KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jacorb > notification > filter > AbstractFilter


1 package org.jacorb.notification.filter;
2
3 /*
4  * JacORB - a free Java ORB
5  *
6  * Copyright (C) 1999-2004 Gerald Brose
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public
19  * License along with this library; if not, write to the Free
20  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21  *
22  */

23
24 import java.lang.reflect.Constructor JavaDoc;
25 import java.lang.reflect.InvocationTargetException JavaDoc;
26 import java.util.ArrayList JavaDoc;
27 import java.util.Date JavaDoc;
28 import java.util.HashMap JavaDoc;
29 import java.util.Iterator JavaDoc;
30 import java.util.LinkedList JavaDoc;
31 import java.util.List JavaDoc;
32 import java.util.Map JavaDoc;
33 import java.util.NoSuchElementException JavaDoc;
34
35 import org.apache.avalon.framework.configuration.Configurable;
36 import org.apache.avalon.framework.configuration.Configuration;
37 import org.apache.avalon.framework.configuration.ConfigurationException;
38 import org.apache.avalon.framework.logger.Logger;
39 import org.jacorb.notification.AbstractMessage;
40 import org.jacorb.notification.EventTypeWrapper;
41 import org.jacorb.notification.MessageFactory;
42 import org.jacorb.notification.conf.Attributes;
43 import org.jacorb.notification.conf.Default;
44 import org.jacorb.notification.interfaces.Disposable;
45 import org.jacorb.notification.interfaces.EvaluationContextFactory;
46 import org.jacorb.notification.interfaces.GCDisposable;
47 import org.jacorb.notification.interfaces.Message;
48 import org.jacorb.notification.servant.ManageableServant;
49 import org.jacorb.notification.util.DisposableManager;
50 import org.jacorb.notification.util.LogUtil;
51 import org.jacorb.notification.util.WildcardMap;
52 import org.jacorb.util.ObjectUtil;
53 import org.omg.CORBA.Any JavaDoc;
54 import org.omg.CORBA.ORB JavaDoc;
55 import org.omg.CosNotification.EventType;
56 import org.omg.CosNotification.Property;
57 import org.omg.CosNotification.StructuredEvent;
58 import org.omg.CosNotifyComm.NotifySubscribe;
59 import org.omg.CosNotifyFilter.ConstraintExp;
60 import org.omg.CosNotifyFilter.ConstraintInfo;
61 import org.omg.CosNotifyFilter.ConstraintNotFound;
62 import org.omg.CosNotifyFilter.Filter;
63 import org.omg.CosNotifyFilter.FilterOperations;
64 import org.omg.CosNotifyFilter.FilterPOATie;
65 import org.omg.CosNotifyFilter.InvalidConstraint;
66 import org.omg.CosNotifyFilter.UnsupportedFilterableData;
67 import org.omg.PortableServer.POA JavaDoc;
68 import org.omg.PortableServer.POAPackage.ObjectNotActive JavaDoc;
69 import org.omg.PortableServer.POAPackage.ServantNotActive JavaDoc;
70 import org.omg.PortableServer.POAPackage.WrongPolicy JavaDoc;
71
72 import EDU.oswego.cs.dl.util.concurrent.ReadWriteLock;
73 import EDU.oswego.cs.dl.util.concurrent.Sync;
74 import EDU.oswego.cs.dl.util.concurrent.SynchronizedBoolean;
75 import EDU.oswego.cs.dl.util.concurrent.SynchronizedInt;
76 import EDU.oswego.cs.dl.util.concurrent.WriterPreferenceReadWriteLock;
77
78 /**
79  * The Filter interface defines the behaviors supported by objects which encapsulate constraints
80  * used by the proxy objects associated with an event channel in order to determine which events
81  * they receive will be forwarded, and which will be discarded. Each object supporting the Filter
82  * interface can encapsulate a sequence of any number of constraints. Each event received by a proxy
83  * object which has one or more objects supporting the Filter interface associated with it must
84  * satisfy at least one of the constraints associated with one of its associated Filter objects in
85  * order to be forwarded (either to another proxy object or to the consumer, depending on the type
86  * of proxy the filter is associated with), otherwise it will be discarded. <br>
87  * Each constraint encapsulated by a filter object is a structure comprised of two main components.
88  * The first component is a sequence of data structures, each of which indicates an event type
89  * comprised of a domain and a type name. The second component is a boolean expression over the
90  * properties of an event, expressed in some constraint grammar (more on this below). For a given
91  * constraint, the sequence of event type structures in the first component nominates a set of event
92  * types to which the constraint expression in the second component applies. Each element of the
93  * sequence can contain strings which will be matched for equality against the domain_name and
94  * type_name fields of each event being evaluated by the filter object, or it could contain strings
95  * with wildcard symbols (*), indicating a pattern match should be performed against the type
96  * contained in each event, rather than a comparison for equality when determining if the boolean
97  * expression should be applied to the event, or the event should simply be discarded without even
98  * attempting to apply the boolean expression. Note that an empty sequence included as the first
99  * component of a constraint implies that the associated expression applies to all types of events,
100  * as does a sequence comprised of a single element whose domain and type name are both set to
101  * either the empty string or else the wildcard symbol alone contained in quotes. <br>
102  * The constraint expressions associated with a particular object supporting the Filter interface
103  * are expressed as strings which obey the syntax of a particular constraint grammar (i.e., a BNF).
104  * Every conformant implementation of this service must support constraint expressions expressed in
105  * the default constraint grammar described in Section 2.4, "The Default Filter Constraint
106  * Language," on page 2-23. In addition, implementations may support other constraint grammars,
107  * and/or users of this service may implement their own filter objects which allow constraints to be
108  * expressed in terms of an alternative constraint grammar. As long as such user-defined filter
109  * objects support the Filter interface, they can be attached to Proxy or Admin objects in the same
110  * fashion as the default Filter objects supported by the implementation of the service are, and the
111  * channel should be able to use them to filter events in the same fashion. <br>
112  * The Filter interface supports the operations required to manage the constraints associated with
113  * an object instance which supports the interface, along with a readonly attribute which identifies
114  * the particular constraint grammar in which the constraints encapsulated by this object have
115  * meaning. In addition, the Filter interface supports three variants of the match operation which
116  * can be invoked by an associated proxy object upon receipt of an event (the specific variant
117  * selected depends upon whether the event is received in the form of an Any, a Structured Event, or
118  * a Typed Event), to determine if the event should be forwarded or discarded, based on whether or
119  * not the event satisfies at least one criteria encapsulated by the filter object. The Filter
120  * interface also supports operations which enable a client to associate with the target filter
121  * object any number of "callbacks" which are notified each time there is a change to the list of
122  * event types which the constraints encapsulated by the filter object could potentially cause
123  * proxies to which the filter is attached to receive. Operations are also defined to support
124  * administration of this callback list by unique identifier. <br>
125  *
126  * @author Alphonse Bendt
127  * @author John Farrell
128  * @version $Id: AbstractFilter.java,v 1.4 2005/04/10 14:21:32 alphonse.bendt Exp $
129  */

130
131 public abstract class AbstractFilter implements GCDisposable, ManageableServant, Configurable,
132         FilterOperations
133 {
134     final static RuntimeException JavaDoc NOT_SUPPORTED = new UnsupportedOperationException JavaDoc(
135             "this operation is not supported");
136
137     public static final int NO_CONSTRAINTS_MATCH = -2;
138
139     public static final int CONSTRAINTS_EMPTY = -1;
140
141     private static final String JavaDoc EMPTY_EVENT_TYPE_CONSTRAINT_KEY = AbstractMessage
142             .calcConstraintKey("*", "*");
143
144     // //////////////////////////////////////
145

146     private final FilterPOATie servant_;
147
148     private final DisposableManager disposables_ = new DisposableManager();
149
150     private final CallbackManager callbackManager_ = new CallbackManager();
151
152     /**
153      * contains the associated constraints. as access to constraints_ is controlled by
154      * constraintsLock_ its safe to use unsynchronized HashMap here
155      */

156     protected final Map JavaDoc constraints_ = new HashMap JavaDoc();
157
158     protected final WildcardMap wildcardMap_;
159
160     protected final ReadWriteLock constraintsLock_;
161
162     private final SynchronizedInt constraintIdPool_ = new SynchronizedInt(0);
163
164     protected final MessageFactory messageFactory_;
165
166     private final FilterUsageDecorator filterUsageDecorator_;
167
168     private final POA JavaDoc poa_;
169
170     private final ORB JavaDoc orb_;
171
172     private Filter thisRef_;
173
174     private final Logger logger_;
175
176     private final EvaluationContextFactory evaluationContextFactory_;
177
178     private final SynchronizedBoolean isActivated = new SynchronizedBoolean(false);
179
180     private static final ConstraintInfo[] EMPTY_CONSTRAINT_INFO = new ConstraintInfo[0];
181
182     private final long maxIdleTime_;
183
184     // //////////////////////////////////////
185

186     protected AbstractFilter(Configuration config,
187             EvaluationContextFactory evaluationContextFactory, MessageFactory messageFactory,
188             ORB JavaDoc orb, POA JavaDoc poa) throws ConfigurationException
189     {
190         super();
191
192         orb_ = orb;
193         poa_ = poa;
194         logger_ = LogUtil.getLogger(config, getClass().getName());
195
196         if (logger_.isInfoEnabled())
197         {
198             logger_.info("Created filter for Grammar: " + constraint_grammar());
199         }
200
201         messageFactory_ = messageFactory;
202
203         evaluationContextFactory_ = evaluationContextFactory;
204
205         constraintsLock_ = new WriterPreferenceReadWriteLock();
206
207         wildcardMap_ = newWildcardMap(config);
208
209         disposables_.addDisposable(callbackManager_);
210
211         filterUsageDecorator_ = new FilterUsageDecorator(this);
212
213         servant_ = new FilterPOATie(filterUsageDecorator_.getFilterOperations());
214
215         maxIdleTime_ = config.getAttributeAsLong(Attributes.DEAD_FILTER_INTERVAL,
216                 Default.DEFAULT_DEAD_FILTER_INTERVAL);
217     }
218
219     // //////////////////////////////////////
220

221     private WildcardMap newWildcardMap(Configuration config) throws ConfigurationException
222     {
223         String JavaDoc wildcardMapImpl = config.getAttribute(Attributes.WILDCARDMAP_CLASS,
224                 Default.DEFAULT_WILDCARDMAP_IMPL);
225
226         try
227         {
228             Class JavaDoc wildcardMapClazz = ObjectUtil.classForName(wildcardMapImpl);
229
230             Constructor JavaDoc ctor = wildcardMapClazz.getConstructor(new Class JavaDoc[0]);
231
232             return (WildcardMap) ctor.newInstance(new Object JavaDoc[0]);
233         } catch (ClassNotFoundException JavaDoc e)
234         {
235             // ignore
236
} catch (IllegalArgumentException JavaDoc e)
237         {
238             // ignore
239
} catch (InstantiationException JavaDoc e)
240         {
241             // ignore
242
} catch (IllegalAccessException JavaDoc e)
243         {
244             // ignore
245
} catch (InvocationTargetException JavaDoc e)
246         {
247             // ignore
248
} catch (SecurityException JavaDoc e)
249         {
250             // ignore
251
} catch (NoSuchMethodException JavaDoc e)
252         {
253             // ignore
254
}
255
256         throw new ConfigurationException(wildcardMapImpl
257                 + " is no valid WildcardMap Implementation");
258     }
259
260     public final void configure(Configuration conf)
261     {
262         // config is fetched via c'tor.
263
}
264
265     public org.omg.CORBA.Object JavaDoc activate()
266     {
267         if (thisRef_ == null)
268         {
269             thisRef_ = servant_._this(orb_);
270
271             isActivated.set(true);
272         }
273
274         return thisRef_;
275     }
276
277     public void deactivate()
278     {
279         try
280         {
281             poa_.deactivate_object(poa_.servant_to_id(servant_));
282         } catch (WrongPolicy JavaDoc e)
283         {
284             logger_.fatalError("error deactivating object", e);
285         } catch (ObjectNotActive JavaDoc e)
286         {
287             logger_.fatalError("error deactivating object", e);
288         } catch (ServantNotActive JavaDoc e)
289         {
290             logger_.fatalError("error deactivating object", e);
291         }
292     }
293
294     protected int newConstraintId()
295     {
296         return constraintIdPool_.increment();
297     }
298
299     /**
300      * The <code>add_constraints</code> operation is invoked by a client in order to associate one
301      * or more new constraints with the target filter object. The operation accepts as input a
302      * sequence of constraint data structures, each element of which consists of a sequence of event
303      * type structures (described in Section 3.2.1, "The Filter Interface," on page 3-14) and a
304      * constraint expressed within the constraint grammar supported by the target object. Upon
305      * processing each constraint, the target object associates a numeric identifier with the
306      * constraint that is unique among all constraints it encapsulates. If any of the constraints in
307      * the input sequence is not a valid expression within the supported constraint grammar, the
308      * InvalidConstraint exception is raised. This exception contains as data the specific
309      * constraint expression that was determined to be invalid. Upon successful processing of all
310      * input constraint expressions, the <code>add_constraints</code> operation returns a sequence
311      * in which each element will be a structure including one of the input constraint expressions,
312      * along with the unique identifier assigned to it by the target filter object. <br>
313      * Note that the semantics of the <code>add_constraints</code> operation are such that its
314      * sideeffects are performed atomically upon the target filter object. Once
315      * <code>add_constraints</code> is invoked by a client, the target filter object is
316      * temporarily disabled from usage by any proxy object it may be associated with. The operation
317      * is then carried out, either successfully adding all of the input constraints to the target
318      * object or none of them (in the case one of the input expressions was invalid). Upon
319      * completion of the operation, the target filter object is effectively re-enabled and can once
320      * again be used by associated filter objects in order to make event forwarding decisions.
321      */

322     public ConstraintInfo[] add_constraints(ConstraintExp[] constraintExp) throws InvalidConstraint
323     {
324         FilterConstraint[] _arrayFilterConstraint = newFilterConstraints(constraintExp);
325
326         try
327         {
328             // access writeonly lock
329
constraintsLock_.writeLock().acquire();
330
331             try
332             {
333                 return add_constraint(constraintExp, _arrayFilterConstraint);
334             } finally
335             {
336                 // give up the lock
337
constraintsLock_.writeLock().release();
338             }
339         } catch (InterruptedException JavaDoc ie)
340         {
341             // propagate without throwing
342
Thread.currentThread().interrupt();
343
344             return EMPTY_CONSTRAINT_INFO;
345         }
346     }
347
348     private ConstraintInfo[] add_constraint(ConstraintExp[] constraintExp,
349             FilterConstraint[] filterConstraints) throws InterruptedException JavaDoc
350     {
351         final ConstraintInfo[] _arrayConstraintInfo = new ConstraintInfo[filterConstraints.length];
352
353         for (int _x = 0; _x < constraintExp.length; _x++)
354         {
355             int _constraintId = newConstraintId();
356
357             _arrayConstraintInfo[_x] = new ConstraintInfo(constraintExp[_x], _constraintId);
358
359             ConstraintEntry _entry = new ConstraintEntry(filterConstraints[_x],
360                     _arrayConstraintInfo[_x]);
361
362             addEventTypeMappingsForConstraint(_entry);
363
364             constraints_.put(new Integer JavaDoc(_constraintId), _entry);
365
366             notifyCallbacks();
367         }
368
369         return _arrayConstraintInfo;
370     }
371
372     private void addEventTypeMappingsForConstraint(ConstraintEntry entry)
373     {
374         int _eventTypeCount = entry.getEventTypeCount();
375
376         if (_eventTypeCount == 0)
377         {
378             addConstraintEntryToWildcardMap(EMPTY_EVENT_TYPE_CONSTRAINT_KEY, entry);
379         }
380         else
381         {
382             for (int _y = 0; _y < _eventTypeCount; ++_y)
383             {
384                 EventTypeWrapper _eventTypeWrapper = entry.getEventTypeWrapper(_y);
385
386                 addConstraintEntryToWildcardMap(_eventTypeWrapper.getConstraintKey(), entry);
387             }
388         }
389     }
390
391     private void addConstraintEntryToWildcardMap(String JavaDoc constraintKey,
392             ConstraintEntry constraintEntry)
393     {
394         List JavaDoc _listOfConstraintEntry = (List JavaDoc) wildcardMap_.getNoExpansion(constraintKey);
395
396         if (_listOfConstraintEntry == null)
397         {
398             _listOfConstraintEntry = new LinkedList JavaDoc();
399
400             wildcardMap_.put(constraintKey, _listOfConstraintEntry);
401         }
402
403         _listOfConstraintEntry.add(constraintEntry);
404     }
405
406     private FilterConstraint[] newFilterConstraints(ConstraintExp[] constraintExp)
407             throws InvalidConstraint
408     {
409         FilterConstraint[] _arrayFilterConstraint = new FilterConstraint[constraintExp.length];
410
411         // creation of the FilterConstraint's may cause a
412
// InvalidConstraint Exception. Note that the State of the
413
// Filter has not been changed yet.
414
for (int _x = 0; _x < constraintExp.length; _x++)
415         {
416             _arrayFilterConstraint[_x] = newFilterConstraint(constraintExp[_x]);
417         }
418
419         return _arrayFilterConstraint;
420     }
421
422     protected abstract FilterConstraint newFilterConstraint(ConstraintExp constraintExp)
423             throws InvalidConstraint;
424
425     // //////////
426

427     public void modify_constraints(int[] deleteIds, ConstraintInfo[] constraintInfo)
428             throws ConstraintNotFound, InvalidConstraint
429     {
430         try
431         {
432             // write lock
433
constraintsLock_.writeLock().acquire();
434
435             try
436             {
437                 Integer JavaDoc[] _deleteKeys = checkConstraintsToBeDeleted(deleteIds);
438
439                 FilterConstraint[] _arrayConstraintEvaluator = checkConstraintsToBeModified(constraintInfo);
440
441                 deleteConstraints(_deleteKeys);
442
443                 modifyConstraints(constraintInfo, _arrayConstraintEvaluator);
444
445                 notifyCallbacks();
446             } finally
447             {
448                 constraintsLock_.writeLock().release();
449             }
450         } catch (InterruptedException JavaDoc ie)
451         {
452             Thread.currentThread().interrupt();
453         }
454     }
455
456     private void modifyConstraints(ConstraintInfo[] constraintInfo,
457             FilterConstraint[] filterConstraints)
458     {
459         for (int _x = 0; _x < constraintInfo.length; _x++)
460         {
461             Integer JavaDoc _key = new Integer JavaDoc(constraintInfo[_x].constraint_id);
462
463             ConstraintEntry _updatedEntry = new ConstraintEntry(filterConstraints[_x],
464                     constraintInfo[_x]);
465
466             // overwrite existing entry
467
constraints_.put(_key, _updatedEntry);
468
469             int _eventTypeCount = _updatedEntry.getEventTypeCount();
470
471             for (int _y = 0; _y < _eventTypeCount; ++_y)
472             {
473                 EventTypeIdentifier _eventTypeIdentifier = _updatedEntry.getEventTypeWrapper(_y);
474
475                 List JavaDoc _listOfConstraintEvaluator = (List JavaDoc) wildcardMap_
476                         .getNoExpansion(_eventTypeIdentifier.getConstraintKey());
477
478                 // list should NEVER be null as the constraint is modified and therefor
479
// should have existed before.
480
_listOfConstraintEvaluator.add(_updatedEntry);
481             }
482         }
483     }
484
485     private FilterConstraint[] checkConstraintsToBeModified(ConstraintInfo[] constraintInfo)
486             throws InvalidConstraint, ConstraintNotFound
487     {
488         FilterConstraint[] _arrayConstraintEvaluator = new FilterConstraint[constraintInfo.length];
489
490         for (int _x = 0; _x < constraintInfo.length; ++_x)
491         {
492             if (constraints_.containsKey(new Integer JavaDoc(constraintInfo[_x].constraint_id)))
493             {
494                 _arrayConstraintEvaluator[_x] = newFilterConstraint(constraintInfo[_x].constraint_expression);
495             }
496             else
497             {
498                 throw new ConstraintNotFound(constraintInfo[_x].constraint_id);
499             }
500         }
501         return _arrayConstraintEvaluator;
502     }
503
504     private Integer JavaDoc[] checkConstraintsToBeDeleted(int[] idsToBeDeleted) throws ConstraintNotFound
505     {
506         final Integer JavaDoc[] _deleteKeys = new Integer JavaDoc[idsToBeDeleted.length];
507
508         for (int _x = 0; _x < idsToBeDeleted.length; ++_x)
509         {
510             _deleteKeys[_x] = new Integer JavaDoc(idsToBeDeleted[_x]);
511
512             if (!constraints_.containsKey(_deleteKeys[_x]))
513             {
514                 throw new ConstraintNotFound(idsToBeDeleted[_x]);
515             }
516         }
517         return _deleteKeys;
518     }
519
520     private void deleteConstraints(Integer JavaDoc[] keys)
521     {
522         for (int _x = 0; _x < keys.length; ++_x)
523         {
524             ConstraintEntry _deletedEntry = (ConstraintEntry) constraints_.remove(keys[_x]);
525
526             removeEventTypeMappingForConstraint(keys[_x], _deletedEntry);
527         }
528     }
529
530     private void removeEventTypeMappingForConstraint(Integer JavaDoc key, ConstraintEntry deletedEntry)
531     {
532         int _eventTypeCount = deletedEntry.getEventTypeCount();
533
534         for (int _y = 0; _y < _eventTypeCount; ++_y)
535         {
536             EventTypeIdentifier _eventTypeIdentifier = deletedEntry.getEventTypeWrapper(_y);
537
538             List JavaDoc _listOfConstraintEvaluator = (List JavaDoc) wildcardMap_
539                     .getNoExpansion(_eventTypeIdentifier.getConstraintKey());
540
541             Iterator JavaDoc _i = _listOfConstraintEvaluator.iterator();
542
543             // traverse list of wildcard mappings. as a sideeffect mappings for deleted
544
// constraints are removed.
545
while (_i.hasNext())
546             {
547                 ConstraintEntry _constraint = (ConstraintEntry) _i.next();
548
549                 if (_constraint.getConstraintId() == key.intValue())
550                 {
551                     _i.remove();
552                     break;
553                 }
554             }
555         }
556     }
557
558     public ConstraintInfo[] get_constraints(int[] ids) throws ConstraintNotFound
559     {
560         final Sync _lock = constraintsLock_.readLock();
561
562         try
563         {
564             _lock.acquire();
565             try
566             {
567                 final ConstraintInfo[] _constraintInfo = new ConstraintInfo[ids.length];
568
569                 for (int _x = 0; _x < ids.length; ++_x)
570                 {
571                     Integer JavaDoc _key = new Integer JavaDoc(ids[_x]);
572
573                     if (constraints_.containsKey(_key))
574                     {
575                         _constraintInfo[_x] = ((ConstraintEntry) constraints_.get(_key))
576                                 .getConstraintInfo();
577                     }
578                     else
579                     {
580                         throw new ConstraintNotFound(ids[_x]);
581                     }
582                 }
583
584                 return _constraintInfo;
585             } finally
586             {
587                 _lock.release();
588             }
589         } catch (InterruptedException JavaDoc ie)
590         {
591             Thread.currentThread().interrupt();
592
593             return EMPTY_CONSTRAINT_INFO;
594         }
595     }
596
597     public ConstraintInfo[] get_all_constraints()
598     {
599         try
600         {
601             constraintsLock_.readLock().acquire();
602
603             try
604             {
605                 ConstraintInfo[] _constraintInfo = new ConstraintInfo[constraints_.size()];
606
607                 Iterator JavaDoc _i = constraints_.values().iterator();
608
609                 for (int i = 0; i < _constraintInfo.length; i++)
610                 {
611                     _constraintInfo[i] = ((ConstraintEntry) _i.next()).getConstraintInfo();
612                 }
613
614                 return _constraintInfo;
615             } finally
616             {
617                 constraintsLock_.readLock().release();
618             }
619         } catch (InterruptedException JavaDoc ie)
620         {
621             Thread.currentThread().interrupt();
622
623             return EMPTY_CONSTRAINT_INFO;
624         }
625     }
626
627     public void remove_all_constraints()
628     {
629         try
630         {
631             constraintsLock_.writeLock().acquire();
632
633             try
634             {
635                 constraints_.clear();
636
637                 wildcardMap_.clear();
638
639                 notifyCallbacks();
640             } finally
641             {
642                 constraintsLock_.writeLock().release();
643             }
644         } catch (InterruptedException JavaDoc ie)
645         {
646             Thread.currentThread().interrupt();
647         }
648     }
649
650     public void destroy()
651     {
652         dispose();
653     }
654
655     /**
656      * call and use this Iterator inside a acquired read lock section only.
657      */

658     private Iterator JavaDoc getConstraintsForEvent(Message event)
659     {
660         String JavaDoc _key = event.getConstraintKey();
661
662         return getIterator(_key);
663     }
664
665     public Iterator JavaDoc getIterator(Object JavaDoc key)
666     {
667         Object JavaDoc[] _entries = wildcardMap_.getWithExpansion(key);
668
669         return new ConstraintIterator(_entries);
670     }
671
672     /**
673      * Iterator over an Array of Lists. If a List is depleted this Iterator will switch
674      * transparently to the next available list.
675      */

676     static private class ConstraintIterator implements Iterator JavaDoc
677     {
678         final Object JavaDoc[] arrayOfLists_;
679
680         Iterator JavaDoc current_;
681
682         int currentListIdx_ = 0;
683
684         ConstraintIterator(Object JavaDoc[] arrayOfLists)
685         {
686             arrayOfLists_ = arrayOfLists;
687
688             if (arrayOfLists_.length == 0)
689             {
690                 current_ = null;
691             }
692             else
693             {
694                 switchIterator();
695             }
696         }
697
698         private void switchIterator()
699         {
700             current_ = ((List JavaDoc) arrayOfLists_[currentListIdx_]).iterator();
701         }
702
703         public boolean hasNext()
704         {
705             return current_ != null && current_.hasNext();
706         }
707
708         public Object JavaDoc next()
709         {
710             if (current_ == null)
711             {
712                 throw new NoSuchElementException JavaDoc();
713             }
714
715             Object JavaDoc _ret = current_.next();
716
717             if (!current_.hasNext() && currentListIdx_ < arrayOfLists_.length - 1)
718             {
719                 ++currentListIdx_;
720
721                 switchIterator();
722             }
723
724             return _ret;
725         }
726
727         public void remove()
728         {
729             throw NOT_SUPPORTED;
730         }
731     }
732
733     /**
734      * generic version of the match operation
735      */

736     private int match_ReadLock(EvaluationContext evaluationContext, Message event)
737             throws UnsupportedFilterableData
738     {
739         try
740         {
741             constraintsLock_.readLock().acquire();
742
743             try
744             {
745                 return match_NoLock(evaluationContext, event);
746             } finally
747             {
748                 constraintsLock_.readLock().release();
749             }
750         } catch (InterruptedException JavaDoc ie)
751         {
752             Thread.currentThread().interrupt();
753
754             return NO_CONSTRAINTS_MATCH;
755         }
756     }
757
758     private int match_NoLock(EvaluationContext evaluationContext, Message event)
759             throws UnsupportedFilterableData
760     {
761         if (!constraints_.isEmpty())
762         {
763             Iterator JavaDoc _entries = getConstraintsForEvent(event);
764
765             while (_entries.hasNext())
766             {
767                 ConstraintEntry _entry = (ConstraintEntry) _entries.next();
768                 try
769                 {
770                     boolean _result = _entry.getFilterConstraint().evaluate(evaluationContext,
771                             event).getBool();
772
773                     if (_result)
774                     {
775                         return _entry.getConstraintId();
776                     }
777                 } catch (PropertyDoesNotExistException e)
778                 {
779                     // non critical exception. ignore
780
// and continue with next Constraint
781
logger_.info("tried to access non existing Property", e);
782                 } catch (EvaluationException e)
783                 {
784                     logger_.fatalError("Error evaluating filter", e);
785
786                     throw new UnsupportedFilterableData(e.getMessage());
787                 }
788             }
789
790             return NO_CONSTRAINTS_MATCH;
791         }
792         
793         logger_.info("Filter has no Expressions");
794
795         return CONSTRAINTS_EMPTY;
796     }
797
798     public boolean match(Any JavaDoc anyEvent) throws UnsupportedFilterableData
799     {
800         return match_internal(anyEvent) >= 0;
801     }
802
803     /**
804      * match Any to associated constraints. return the id of the first matching filter or
805      * NO_CONSTRAINT.
806      */

807     protected int match_internal(Any JavaDoc anyEvent) throws UnsupportedFilterableData
808     {
809         final EvaluationContext _evaluationContext = evaluationContextFactory_
810                 .newEvaluationContext();
811
812         try
813         {
814             final Message _event = messageFactory_.newMessage(anyEvent);
815
816             try
817             {
818                 return match_ReadLock(_evaluationContext, _event);
819             } finally
820             {
821                 _event.dispose();
822             }
823         } finally
824         {
825             _evaluationContext.dispose();
826         }
827     }
828
829     public boolean match_structured(StructuredEvent structuredevent)
830             throws UnsupportedFilterableData
831     {
832         return match_structured_internal(structuredevent) >= 0;
833     }
834
835     /**
836      * match the StructuredEvent to the associated constraints. return the id of the first matching
837      * filter or NO_CONSTRAINT.
838      */

839     protected int match_structured_internal(StructuredEvent structuredEvent)
840             throws UnsupportedFilterableData
841     {
842         final EvaluationContext _evaluationContext = evaluationContextFactory_
843                 .newEvaluationContext();
844
845         try
846         {
847             final Message _event = messageFactory_.newMessage(structuredEvent);
848
849             try
850             {
851                 return match_ReadLock(_evaluationContext, _event);
852             } finally
853             {
854                 _event.dispose();
855             }
856         } finally
857         {
858             _evaluationContext.dispose();
859         }
860     }
861
862     /**
863      * match the TypedEvent to the associated constraints. return the id of the first matching
864      * filter or NO_CONSTRAINT.
865      */

866     protected int match_typed_internal(Property[] typedEvent) throws UnsupportedFilterableData
867     {
868         final EvaluationContext _evaluationContext = evaluationContextFactory_
869                 .newEvaluationContext();
870
871         try
872         {
873             final Message _event = messageFactory_.newMessage(typedEvent);
874
875             try
876             {
877                 return match_ReadLock(_evaluationContext, _event);
878             } finally
879             {
880                 _event.dispose();
881             }
882         } finally
883         {
884             _evaluationContext.dispose();
885         }
886     }
887
888     public boolean match_typed(Property[] properties) throws UnsupportedFilterableData
889     {
890         return match_typed_internal(properties) >= 0;
891     }
892
893     public int attach_callback(NotifySubscribe notifySubscribe)
894     {
895         return callbackManager_.attach_callback(notifySubscribe);
896     }
897
898     public void detach_callback(int id)
899     {
900         callbackManager_.detach_callback(id);
901     }
902
903     public int[] get_callbacks()
904     {
905         return callbackManager_.get_callbacks();
906     }
907
908     private void notifyCallbacks() throws InterruptedException JavaDoc
909     {
910         final Iterator JavaDoc i = constraints_.keySet().iterator();
911         final List JavaDoc eventTypes = new ArrayList JavaDoc();
912
913         while (i.hasNext())
914         {
915             Object JavaDoc key = i.next();
916
917             ConstraintEntry value = (ConstraintEntry) constraints_.get(key);
918
919             int ets = value.getEventTypeCount();
920
921             for (int j = 0; j < ets; ++j)
922             {
923                 EventTypeWrapper et = value.getEventTypeWrapper(j);
924
925                 eventTypes.add(et.getEventType());
926             }
927         }
928
929         callbackManager_.replaceWith((EventType[]) eventTypes
930                 .toArray(EventTypeWrapper.EMPTY_EVENT_TYPE_ARRAY));
931     }
932
933     public POA JavaDoc _default_POA()
934     {
935         return poa_;
936     }
937
938     public void dispose()
939     {
940         if (isActivated.get())
941         {
942             deactivate();
943
944             isActivated.set(false);
945         }
946
947         disposables_.dispose();
948     }
949
950     public void addDisposeHook(Disposable disposeHook)
951     {
952         disposables_.addDisposable(disposeHook);
953     }
954
955     public Date JavaDoc getLastUsage()
956     {
957         return filterUsageDecorator_.getLastUsage();
958     }
959
960     public void attemptDispose()
961     {
962         attemptDispose(this, getLastUsage(), maxIdleTime_);
963     }
964
965     static void attemptDispose(Disposable disposable, Date JavaDoc lastUsage, long maxIdleTime)
966     {
967         if (maxIdleTime <= 0)
968         {
969             return;
970         }
971
972         if (lastUsage.getTime() + maxIdleTime < System.currentTimeMillis())
973         {
974             disposable.dispose();
975         }
976     }
977 }
Popular Tags