I'd like to propose a module level tag, with which it is possible to register Interceptors with all in the Registry Services or all Services which implement a (some) certain interface(s). I've implemented a proposal for this feature and tested it - the diff is attached.

These 'global-interceptors' have some advantages. Ie it would be possible to register (unregister) a Logger for all Services with just a little change to just one module. Also services implementing a certain interface could be given automatically parameters through such an Interceptor (Avalon like) without the need to specify the interceptor in each service. This therefore also reduces the amount of failure because of forgetting the interceptor. The same way a stop-service could be implemented, which informs all loaded Services that implement iE StopInterface when the program exits.

For the code of my proposal I have changed the module xml format to include under <module> the following tag:

<global-interceptor service-id=”id of ServiceInterceptorFactory” order=”interceptor-order”>
<class name=”full.interface.name”/>
<class name=”full.interface.name2”/>
</global-interceptor>


The global-interceptor tag takes the same arguments as the <interceptor> tag. If no <class> tag is specified the interceptor will be registered with all Services in all modules. If there are one ore more <class> tags the Services which are intercepted must implement all the given interface(s) (AND). If there are more <global-interceptor>s with the same ServiceInterceptorFactory-Id than the Interceptor is wrapped if at least one fits (OR)

The ServiceInterceptorFactories specified and the Services requested of the Factory at creation time are never wrapped by global Interceptors (because of circularity – actually the implementation loads all the ServiceInterceptorFactories in RegistryBuilder.constructRegistry() as non deferred).

My implementation works following: First the DescriptorParser builds up GlobalInterceptorDescriptors which are added to the ModuleDescriptor.

In the RegistryBuilder one instance of org....hivemind.impl.GlobalInterceptorRegistry is build up from the Descriptors. There is only one instance - held in an field - per RegistryBuilder (and so per Registry). This instance is used to hold all the mappings of interfaces to ServiceInterceptorContributions. The instance is given to each ServiceExtensionPointImpl when it is constructed. The point will use the instance in addInterceptors() to request the global- mapped Interceptors for itself and add it to it's own interceptors list.

When the Modules are processed in the RegistryBuilder the GlobalInterceptorRegistry is populated but not yet ready to use. As the last step in the RegistryBuilder.constructRegistry() the GlobalInterceptorRegistry is build up. Here some optimizations are done (or better could be done) and all the needed ServiceInterceptorFactories are loaded – non deffered. Till this time the ServiceExtensionPointImpls will not use the GlobalInterceptorRegistry. This way Services (the ServiceInterceptorFactories and there requested Services) loaded by the GlobalInterceptorRegistry itself are not intercepted (except if defined in a Service-Extension), which is important for circularity. After this the GlobalInterceptorRegister is ready to be used by the ServiceExtesionPointImpls and all Service loaded are wrapped if they match.

Finally there are also two Tests which you can see from the diff.

--
Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
Index: src/java/org/apache/commons/hivemind/impl/GlobalInterceptorRegistry.java
===================================================================
RCS file: src/java/org/apache/commons/hivemind/impl/GlobalInterceptorRegistry.java
diff -N src/java/org/apache/commons/hivemind/impl/GlobalInterceptorRegistry.java
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ src/java/org/apache/commons/hivemind/impl/GlobalInterceptorRegistry.java    21 Aug 
2003 17:53:37 -0000
@@ -0,0 +1,334 @@
+package org.apache.commons.hivemind.impl;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.hivemind.ApplicationRuntimeException;
+import org.apache.commons.hivemind.ClassResolver;
+import org.apache.commons.hivemind.HiveMind;
+import org.apache.commons.hivemind.Location;
+import org.apache.commons.hivemind.Module;
+import org.apache.commons.hivemind.Registry;
+import org.apache.commons.hivemind.ServiceExtensionPoint;
+import org.apache.commons.hivemind.ServiceInterceptorContribution;
+import org.apache.commons.hivemind.ServiceInterceptorFactory;
+import org.apache.commons.hivemind.parse.GlobalInterceptorDescriptor;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+
+
+/**
+ * This will hold mappings from Interfaces implemented by CoreServices to 
Interceptors which will than
+ * wrap this interfaces.
+ * 
+ * @author chris
+ */
+public class GlobalInterceptorRegistry
+{
+       private static final Log LOG = 
LogFactory.getLog(GlobalInterceptorRegistry.class);
+
+       /**
+        * Used for storing the mappings internally 
+        * Never used outside this class only for testing.
+        * @author chris
+        */
+       public static final class Mapping {
+               public static final Comparator LIST_SIZE_COMP = new Comparator()
+               {
+                       public int compare(Object o1, Object o2){return 
((Object[])o1).length - ((Object[])o2).length;}
+                       public boolean equals(Object obj){return obj == this;}
+               };
+               
+               public Pattern[][] patterns;
+               //used temporaraly until build; contains arrays of Patterns
+               public List tempPatterns = new ArrayList();
+               
+               public boolean matchesAll = false;
+               
+               public final ServiceInterceptorContribution contribution;
+               
+               public final Location _location;
+               public Mapping(ServiceInterceptorContribution contri,Location 
location){
+                       this.contribution = contri;
+                       this._location = location;
+               }
+               
+               public boolean isMatchingAll(){
+                       return this.matchesAll;
+               }
+               
+               public boolean isApplicable(ServiceExtensionPoint extP){
+                       //if no pattern return true
+                       if(matchesAll)
+                               return true;
+                       
+                       //otherwise check that at least one array matches
+                       for (int i = 0; i < patterns.length; i++)
+                       {
+                               Pattern[] patternsA = patterns[i];
+                               boolean mat = this.matchPatterns(patternsA, extP);
+                               if(mat)
+                                       return true;
+                       }
+                       //if none matched return false
+                       return false;
+               }
+               
+               
+               
+               private boolean matchPatterns(Pattern[] 
patternsA,ServiceExtensionPoint extP){
+                       //we have to check that each fits
+                       for (int i = 0; i < patternsA.length; i++)
+                       {
+                               if(! patternsA[i].matches(extP))
+                                       return false;
+                       }
+                       return true;
+                       
+               }
+               
+               public void addPatterns(Pattern[] patternA){
+                       if(this.matchesAll) //we don't need any patterns anymore
+                               return;
+                       if(patternA == null || patternA.length == 0){
+                               this.tempPatterns = null; //not needed anymore
+                               this.matchesAll = true;                         
+                       }else{
+                               this.tempPatterns.add(patternA);
+                       }
+               }
+               
+               public void build(){
+                       //check if there are still patterns
+                       if(this.matchesAll)
+                               return;
+                       
+                       //build the patterns
+                       //first sort the tempPatterns according to the size of the 
sublist
+                       //(this is for optimization
+                       Collections.sort(tempPatterns, LIST_SIZE_COMP);
+                       
+                       //now create the patterns
+                       int listSize = tempPatterns.size();
+                       this.patterns = new Pattern[listSize][];
+                       for(int i=0;i<listSize;i++){
+                               Pattern[] patternsA = (Pattern[]) tempPatterns.get(i);
+                               this.patterns[i] = patternsA;
+                       }
+                       
+                       //don't need them anymore
+                       tempPatterns = null;
+               }
+       }
+       
+
+       /**
+        * Reprsents one condition to match 
+        * 
+        */
+       public interface Pattern{
+               public boolean matches(ServiceExtensionPoint exP);
+       }
+       
+
+       /**
+        * Represtens an interface to match 
+        */
+       public class ClassPattern implements Pattern {
+               public final Class clazz;
+               
+               public ClassPattern(Class clazz){ 
+                       this.clazz = clazz;
+               }
+                       
+               public boolean matches(ServiceExtensionPoint exP){
+                       return this.clazz.isAssignableFrom(exP.getServiceInterface()); 
 
+               }
+       }
+       
+       //      temporaly used until build contains as key the 
ServiceInterceptorContribution.serviceid 
+       // the value is a Mapping
+       private Map tempMappings = new HashMap(); 
+       // holds the Mappings; produced in build()
+       private Mapping[] mappings;
+       
+       private boolean isReady = false;
+       
+       
+       /**
+        * Constructor for GlobalInterceptorRegister.
+        */
+       public GlobalInterceptorRegistry()
+       {
+               super();
+       }
+       
+       public boolean isReady(){
+               return this.isReady;
+       }
+       
+       /**
+        * only for testing
+        * @return Mapping[]
+        */
+       public Mapping[] getMappings(){
+               return this.mappings;
+       }
+       
+       public void addGlobalInterceptor(GlobalInterceptorDescriptor gid, 
ServiceInterceptorContribution contribution, ClassResolver classResolver){
+               //some vars
+               GlobalInterceptorDescriptor.PatternDesc[] patternDescs = 
gid.getPatternDescriptors();
+               Location location = gid.getLocation();
+               
+               //get the mapping
+               Mapping mapping = (Mapping) 
this.tempMappings.get(contribution.getFactoryId());
+               if(mapping == null){
+                       mapping = new Mapping(contribution,gid.getLocation());
+                       this.tempMappings.put(contribution.getFactoryId(),mapping);
+               }
+               
+               //add only patterns if the mapping is not yet matching all
+               if(!mapping.isMatchingAll()){
+                       //add the patterns to the mapping
+                       if(patternDescs != null && patternDescs.length != 0){
+                               //build the interfaces
+                               int length = patternDescs.length;
+                               Pattern[] patternA = new Pattern[length];
+                               for(int i=0;i<length;i++){
+                                       Pattern pattern;
+                                       if (patternDescs[i] instanceof 
GlobalInterceptorDescriptor.ClassPatternDesc)
+                                       {
+                                               
GlobalInterceptorDescriptor.ClassPatternDesc patternDesc = 
(GlobalInterceptorDescriptor.ClassPatternDesc) patternDescs[i];
+                                               Class clazz = 
this.lookupInterface(patternDesc.className, location, classResolver);
+               
+                                               pattern = new ClassPattern(clazz);
+                                               patternA[i] = pattern;
+               
+                                               continue;
+                                       }
+                               }
+                               mapping.addPatterns(patternA);
+                       }else{
+                               //if no descriptors just add null
+                               mapping.addPatterns(null);
+                       }
+               }
+               
+       }
+       
+       /**
+        * called after all GlobalInterceptors are added to make an array
+        */
+       public void build(Registry registry){
+               mappings = new Mapping[tempMappings.values().size()];
+               mappings = (Mapping[]) tempMappings.values().toArray(mappings);
+               tempMappings = null;
+               
+               //build the mappings
+               for (int i = 0; i < mappings.length; i++)
+               {
+                       mappings[i].build();
+               }
+               
+               //now load all the services you will need in you 
ServiceContributionPoints
+               //this is done now because later it could result in circularities
+               //to realy load the service we also have to set all services as not 
deffereable
+
+               for (int i = 0; i < mappings.length; i++)
+               {
+                       String factoryId = mappings[i].contribution.getFactoryId();
+                       try{
+                               
+                               //TODO: we need a dirty cast here 
+                               ServiceExtensionPointImpl extPoint = 
(ServiceExtensionPointImpl)
+                                       
registry.getModule(RegistryImpl.split(factoryId)).getServiceExtensionPoint(factoryId);
+                               
+                               //set not defferable
+                               extPoint.setDeferrable(false);
+                               
+                               ServiceInterceptorFactory factory =     
(ServiceInterceptorFactory) 
+                                                                               
extPoint.getService(ServiceInterceptorFactory.class);
+
+                       }catch(Exception e){
+                               throw new ApplicationRuntimeException(
+                                       HiveMind.format(
+                                               "GlobalInterceptor.no-interceptor",
+                                               factoryId),
+                                       mappings[i]._location,
+                                       null);
+                       
+                       }
+               }
+               
+               //make yourself ready
+               if(mappings.length > 0)
+                       this.isReady = true;
+       }
+       
+       /**
+        * returns null if none applies otherwise a list of 
ServiceInterceptorContributions
+        * @param extP
+        * @return List
+        */
+       public List getServiceInterceptorContributions(ServiceExtensionPoint extP){
+               List ret = null;
+               
+               //go through all mappings
+               for(int i=0;i<mappings.length;i++){
+                       Mapping mapi = mappings[i];
+               
+                       if(mapi.isApplicable(extP)){
+                               if(ret == null)
+                                       ret = new ArrayList();
+                               ServiceInterceptorContribution contribution = 
mapi.contribution;
+                               
+                               ret.add(mapi.contribution);
+                       }
+               }
+               
+               return ret;
+       }
+       
+       /**
+        * a helper usind in build()
+        * @param name
+        * @param location
+        * @return Class
+        */
+       protected Class lookupInterface(String name, Location location,ClassResolver 
resolver)
+       {
+               Class result = null;
+
+               try
+               {
+                       result = resolver.findClass(name);
+               }
+               catch (Exception ex)
+               {
+                       throw new ApplicationRuntimeException(
+                               HiveMind.format(
+                                       "GlobalInterceptor.bad-interface",
+                                       name),
+                               location,
+                               ex);
+               }
+
+               if (!result.isInterface())
+                       throw new ApplicationRuntimeException(
+                               HiveMind.format(
+                                       "GlobalInterceptor.interface-required",
+                                       name),
+                               location,
+                               null);
+
+               return result;
+       }
+
+       
+
+}
Index: src/java/org/apache/commons/hivemind/impl/RegistryBuilder.java
===================================================================
RCS file: 
/home/cvspublic/jakarta-commons-sandbox/hivemind/src/java/org/apache/commons/hivemind/impl/RegistryBuilder.java,v
retrieving revision 1.22
diff -u -r1.22 RegistryBuilder.java
--- src/java/org/apache/commons/hivemind/impl/RegistryBuilder.java      20 Aug 2003 
20:40:45 -0000      1.22
+++ src/java/org/apache/commons/hivemind/impl/RegistryBuilder.java      21 Aug 2003 
17:53:44 -0000
@@ -79,6 +79,7 @@
 import org.apache.commons.hivemind.parse.ExtendServiceDescriptor;
 import org.apache.commons.hivemind.parse.ExtensionDescriptor;
 import org.apache.commons.hivemind.parse.ExtensionPointDescriptor;
+import org.apache.commons.hivemind.parse.GlobalInterceptorDescriptor;
 import org.apache.commons.hivemind.parse.InstanceBuilder;
 import org.apache.commons.hivemind.parse.InterceptorDescriptor;
 import org.apache.commons.hivemind.parse.ModuleDescriptor;
@@ -159,6 +160,11 @@
      * Parser instance used by all parsing for this builder.
      */
     private DescriptorParser _parser;
+    
+    /**
+     * The only one GlobalInterceptorRegister for the Registry
+     */
+       private GlobalInterceptorRegistry _interceptorRegistry = new 
GlobalInterceptorRegistry();
 
     private static class DefaultErrorHandler implements ErrorHandler
     {
@@ -301,14 +307,39 @@
         module.setLocation(md.getLocation());
         module.setModuleId(id);
         module.setResourceResolver(resolver);
+        
 
         addServiceExtensionPoints(module, md);
 
         addExtensionPoints(module, md);
 
+               addGlobalInterceptors(md,resolver);
+
         _modules.put(id, module);
         _descriptors.add(md);
     }
+       
+       private void addGlobalInterceptors(ModuleDescriptor md, ClassResolver 
classResolver){
+               GlobalInterceptorDescriptor[] descriptors = 
md.getGlobalInterceptorDescriptors();
+               if(descriptors == null)
+                       return;
+               
+               for (int i = 0; i < descriptors.length; i++)
+               {
+                       GlobalInterceptorDescriptor gid = descriptors[i];
+                       
+                       //construct the ServiceInterceptorContribution
+                       InterceptorDescriptor id = gid.getInterceptorDescriptor();
+                       ServiceInterceptorContributionImpl ic = new 
ServiceInterceptorContributionImpl();
+                       ic.setFactoryId(qualify(md.getModuleId(), id.getServiceId()));
+                       ic.setLocation(id.getLocation());
+                       ic.setOrder(id.getOrder());
+                       
+                       
+                       //add to the globalInterCeptorRegister
+                       _interceptorRegistry.addGlobalInterceptor(gid, ic, 
classResolver);
+               }
+       }
 
        private void addServiceExtensionPoints(ModuleImpl module, ModuleDescriptor md)
     {
@@ -337,6 +368,7 @@
             point.setDeferrable(sd.isDeferrable());
             point.setServiceInterfaceName(sd.getInterfaceClassName());
             point.setParametersSchema(sd.getParametersSchema());
+            point.setGlobalInterceptorRegistry(_interceptorRegistry);
 
             module.addServiceExtensionPoint(point);
 
@@ -409,7 +441,8 @@
         long startMillis = System.currentTimeMillis();
 
         // TBD: check dependencies and versions!
-
+               
+               
         int count = _descriptors.size();
 
         for (int i = 0; i < count; i++)
@@ -442,6 +475,9 @@
             module.setRegistry(result);
             result.addModule(module);
         }
+
+               //build the interceptor register
+               _interceptorRegistry.build(result);
 
         long elapsedMillis = System.currentTimeMillis() - startMillis;
 
Index: src/java/org/apache/commons/hivemind/impl/ServiceExtensionPointImpl.java
===================================================================
RCS file: 
/home/cvspublic/jakarta-commons-sandbox/hivemind/src/java/org/apache/commons/hivemind/impl/ServiceExtensionPointImpl.java,v
retrieving revision 1.9
diff -u -r1.9 ServiceExtensionPointImpl.java
--- src/java/org/apache/commons/hivemind/impl/ServiceExtensionPointImpl.java    20 Aug 
2003 20:40:45 -0000      1.9
+++ src/java/org/apache/commons/hivemind/impl/ServiceExtensionPointImpl.java    21 Aug 
2003 17:53:40 -0000
@@ -70,7 +70,9 @@
 import org.apache.commons.hivemind.Registry;
 import org.apache.commons.hivemind.ServiceExtensionPoint;
 import org.apache.commons.hivemind.ServiceImplementationConstructor;
+import org.apache.commons.hivemind.ServiceImplementationFactory;
 import org.apache.commons.hivemind.ServiceInterceptorContribution;
+import org.apache.commons.hivemind.ServiceInterceptorFactory;
 import org.apache.commons.hivemind.schema.Schema;
 import org.apache.commons.hivemind.service.BodyBuilder;
 import org.apache.commons.hivemind.service.ClassFab;
@@ -103,6 +105,7 @@
     private Object _constructedService;
     private boolean _deferrable;
     private Object _deferredProxy;
+    private GlobalInterceptorRegistry _interceptorRegistry;
 
     protected void extendDescription(ToStringBuilder builder)
     {
@@ -308,10 +311,26 @@
 
     private Object addInterceptors(Object core)
     {
+       
+       List contributions; //will contain all the interceptors
+       
+       //first get the normal registered interceptors
         if (_interceptorContributions == null || _interceptorContributions.size() == 
0)
-            return core;
+                       contributions = new ArrayList();
+        else
+                       contributions = new ArrayList(_interceptorContributions);
+        
+        //now find the interceptors from the GlobaleInterceptorRegistry
+        //but only if all the InterceptorFactoryServices used are loaded
+        //this is to prevent recursive calls
+        if(_interceptorRegistry.isReady())
+        {
+                       List foundContributions = 
_interceptorRegistry.getServiceInterceptorContributions(this);
+                       if(foundContributions != null && foundContributions.size() != 
0)
+                               contributions.addAll(foundContributions);
+        }
 
-        List sorted = HiveMind.sortOrderables(_interceptorContributions);
+        List sorted = HiveMind.sortOrderables(contributions);
         int count = sorted.size();
 
         InterceptorStackImpl stack = new InterceptorStackImpl(this, core);
@@ -375,6 +394,14 @@
     public void setDeferrable(boolean b)
     {
         _deferrable = b;
+    }
+    
+    public void setGlobalInterceptorRegistry(GlobalInterceptorRegistry reg){
+       _interceptorRegistry = reg;
+    }
+    
+    public GlobalInterceptorRegistry getGlobalInterceptorRegistry(){
+       return _interceptorRegistry;
     }
 
     /**
Index: src/java/org/apache/commons/hivemind/parse/DescriptorParser.java
===================================================================
RCS file: 
/home/cvspublic/jakarta-commons-sandbox/hivemind/src/java/org/apache/commons/hivemind/parse/DescriptorParser.java,v
retrieving revision 1.25
diff -u -r1.25 DescriptorParser.java
--- src/java/org/apache/commons/hivemind/parse/DescriptorParser.java    20 Aug 2003 
20:40:45 -0000      1.25
+++ src/java/org/apache/commons/hivemind/parse/DescriptorParser.java    21 Aug 2003 
17:53:52 -0000
@@ -165,6 +165,12 @@
     private static final int STATE_ELEMENT = 10;
     private static final int STATE_RULES = 11;
     private static final int STATE_INVOKE_FACTORY = 12;
+       
+       /**
+        * used for global-interceptor
+        */
+       private static final int STATE_GLOBAL_INTERCEPTOR = 13;
+       private static final int STATE_GLOBAL_INTERCEPTOR_CLASS = 14;
 
     /**
      * Represents building Element hierarchy as a light-wieght DOM.
@@ -292,6 +298,15 @@
         SCHEMA_ATTRIBUTES.put("id", Boolean.FALSE);
         SCHEMA_ATTRIBUTES.put("ref-id", Boolean.FALSE);
     }
+    
+    /**
+     * for global-interceptor the same attributes are used as for the normal 
INTERCEPTOR
+     */
+    private static final Map GLOBAL_INTERCEPTOR_ATTRIBUTES = new 
HashMap(INTERCEPTOR_ATTRIBUTES);
+    private static final Map GLOBAL_INTERCEPTOR_CLASS_ATTRIBUTES = new HashMap();
+    static{
+       GLOBAL_INTERCEPTOR_CLASS_ATTRIBUTES.put("name", Boolean.TRUE);
+    }
 
     private static final Map CUSTOM_ATTRIBUTES = new HashMap();
 
@@ -757,6 +772,10 @@
 
                 beginInvokeFactory(qName);
                 break;
+                
+            case STATE_GLOBAL_INTERCEPTOR :
+               beginGlobalInterceptor(qName);
+               break;
 
             default :
 
@@ -902,6 +921,26 @@
 
             return;
         }
+        
+        if ("global-interceptor".equals(elementName)){
+               
+               GlobalInterceptorDescriptor gid = new GlobalInterceptorDescriptor();
+               
+               push(elementName,gid,STATE_GLOBAL_INTERCEPTOR);
+               
+               checkAttributes(GLOBAL_INTERCEPTOR_ATTRIBUTES);
+               
+               InterceptorDescriptor ind = new InterceptorDescriptor();
+               ind.setServiceId(getAttribute("service-id"));
+               if(isAttribute("order"))
+                       ind.setOrder(getIntAttribute("order"));
+               
+               gid.setInterceptorDesc(ind);
+               
+               md.addGlobalInterceptorDescriptor(gid);
+               
+               return;
+        }
 
         // TODO: dependency
 
@@ -1116,6 +1155,24 @@
 
         unexpectedElement(elementName);
     }
+
+       private void beginGlobalInterceptor(String elementName)
+       {
+               GlobalInterceptorDescriptor gid = (GlobalInterceptorDescriptor) 
peekObject();
+
+               if ("class".equals(elementName))
+               {
+                       push(elementName, gid, STATE_GLOBAL_INTERCEPTOR_CLASS);
+
+                       checkAttributes(GLOBAL_INTERCEPTOR_CLASS_ATTRIBUTES);
+
+                       gid.addClassPatternDescriptor(getAttribute("name"));
+
+                       return;
+               }
+
+               unexpectedElement(elementName);
+       }
 
     /**
      * Pushes STATE_ELEMENT onto the stack and creates and returns
Index: src/java/org/apache/commons/hivemind/parse/GlobalInterceptorDescriptor.java
===================================================================
RCS file: src/java/org/apache/commons/hivemind/parse/GlobalInterceptorDescriptor.java
diff -N src/java/org/apache/commons/hivemind/parse/GlobalInterceptorDescriptor.java
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ src/java/org/apache/commons/hivemind/parse/GlobalInterceptorDescriptor.java 21 Aug 
2003 17:53:45 -0000
@@ -0,0 +1,84 @@
+package org.apache.commons.hivemind.parse;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.commons.hivemind.Location;
+import org.apache.commons.hivemind.ServiceExtensionPoint;
+import org.apache.commons.hivemind.ServiceInterceptorContribution;
+import org.apache.commons.hivemind.impl.BaseLocatable;
+import org.apache.commons.hivemind.impl.ServiceInterceptorContributionImpl;
+
+
+/**
+ * An Entry which mapps an Interceptor to a certain Interface, which is implemented 
by a CoreService. 
+ * It is the (only) ExtensionPointElement for InterceptorService 
+ * 
+ * @author chris
+ */
+public class GlobalInterceptorDescriptor extends BaseLocatable
+{
+       public static interface PatternDesc{}
+       
+       public static final class ClassPatternDesc implements PatternDesc {
+               public String className;
+               public ClassPatternDesc(String className) {this.className = className;}
+       }
+       
+       private InterceptorDescriptor interceptor;
+       private List matchPatterns; 
+       /**
+        * Constructor for InterceptorServiceEntry.
+        */
+       public GlobalInterceptorDescriptor()
+       {
+               super();
+       }
+       
+       
+
+       public void setInterceptorDesc(InterceptorDescriptor interc)
+       {
+               this.interceptor = interc;
+               if(interceptor != null)
+                       interceptor.setLocation(this.getLocation());
+       }
+
+       public InterceptorDescriptor getInterceptorDescriptor(){
+               return this.interceptor;
+       }
+
+       private List getMatchPatternsList(){
+               if(this.matchPatterns == null)
+                       this.matchPatterns = new ArrayList();
+               return this.matchPatterns;
+       }
+       /**
+        * adds a class to the classes which the CoreService has to implement in order 
that
+        * an Interceptor is wrapped around it.
+        * @param clazz
+        */
+       public void addClassPatternDescriptor(String clazz){
+               if(clazz == null)
+                       return;
+               this.getMatchPatternsList().add(new ClassPatternDesc(clazz));
+       }
+       
+       public PatternDesc[] getPatternDescriptors(){
+               if(this.matchPatterns == null || this.matchPatterns.size() == 0)
+                       return null;
+               PatternDesc[] ret = (PatternDesc[]) this.matchPatterns.toArray(new 
PatternDesc[this.matchPatterns.size()]);
+               return ret;
+       }
+       
+       /**
+        * @see 
org.apache.commons.hivemind.LocationHolder#setLocation(org.apache.commons.hivemind.Location)
+        */
+       public void setLocation(Location location)
+       {
+               super.setLocation(location);
+               if(this.interceptor != null)
+                       this.interceptor.setLocation(location);
+       }
+
+}
Index: src/java/org/apache/commons/hivemind/parse/ModuleDescriptor.java
===================================================================
RCS file: 
/home/cvspublic/jakarta-commons-sandbox/hivemind/src/java/org/apache/commons/hivemind/parse/ModuleDescriptor.java,v
retrieving revision 1.9
diff -u -r1.9 ModuleDescriptor.java
--- src/java/org/apache/commons/hivemind/parse/ModuleDescriptor.java    8 Aug 2003 
13:51:09 -0000       1.9
+++ src/java/org/apache/commons/hivemind/parse/ModuleDescriptor.java    21 Aug 2003 
17:53:46 -0000
@@ -57,7 +57,9 @@
 
 package org.apache.commons.hivemind.parse;
 
+import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 
 import org.apache.commons.hivemind.HiveMind;
@@ -80,6 +82,7 @@
     private Map _serviceExtensions;
     private Map _extensionPoints;
     private Map _extensions;
+    private List _globalInterceptors;
 
     public String toString()
     {
@@ -91,6 +94,7 @@
         builder.append("serviceExtensions", _serviceExtensions);
         builder.append("extensionPoints", _extensionPoints);
         builder.append("extensions", _extensions);
+        builder.append("globalInterceptors",_globalInterceptors);
 
         return builder.toString();
     }
@@ -170,6 +174,24 @@
             _extensions = new HashMap();
 
         _extensions.put(descriptor.getPointId(), descriptor);
+    }
+    
+    public void addGlobalInterceptorDescriptor(GlobalInterceptorDescriptor descriptor)
+    {
+       if (_globalInterceptors == null)
+                       _globalInterceptors = new ArrayList();
+               _globalInterceptors.add(descriptor);
+    }
+    
+    public GlobalInterceptorDescriptor[] getGlobalInterceptorDescriptors()
+    {
+       GlobalInterceptorDescriptor[] ret;
+       if(_globalInterceptors == null)
+               ret = null;
+       else
+               ret = (GlobalInterceptorDescriptor[]) _globalInterceptors.toArray
+                                                               (new 
GlobalInterceptorDescriptor[_globalInterceptors.size()]);
+       return ret; 
     }
 
        /**
Index: src/test/hivemind/test/parse/GenericModule.xml
===================================================================
RCS file: 
/home/cvspublic/jakarta-commons-sandbox/hivemind/src/test/hivemind/test/parse/GenericModule.xml,v
retrieving revision 1.4
diff -u -r1.4 GenericModule.xml
--- src/test/hivemind/test/parse/GenericModule.xml      1 Aug 2003 19:05:24 -0000      
 1.4
+++ src/test/hivemind/test/parse/GenericModule.xml      21 Aug 2003 17:53:33 -0000
@@ -109,4 +109,11 @@
        </parameters-schema>    
   </service>
 
+  <global-interceptor service-id="MyInterceptor" order="100">
+       <class name="org.apache.commons.hivemind.ServiceImplementationFactory"/>
+       <class name="org.apache.commons.hivemind.Location"/>
+  </global-interceptor>
+  
+  <global-interceptor service-id="MyInterceptor2">
+  </global-interceptor>
 </module>
Index: src/test/hivemind/test/parse/TestDescriptorParser.java
===================================================================
RCS file: 
/home/cvspublic/jakarta-commons-sandbox/hivemind/src/test/hivemind/test/parse/TestDescriptorParser.java,v
retrieving revision 1.20
diff -u -r1.20 TestDescriptorParser.java
--- src/test/hivemind/test/parse/TestDescriptorParser.java      11 Aug 2003 17:45:28 
-0000      1.20
+++ src/test/hivemind/test/parse/TestDescriptorParser.java      21 Aug 2003 17:53:35 
-0000
@@ -74,6 +74,7 @@
 import org.apache.commons.hivemind.parse.ExtendServiceDescriptor;
 import org.apache.commons.hivemind.parse.ExtensionDescriptor;
 import org.apache.commons.hivemind.parse.ExtensionPointDescriptor;
+import org.apache.commons.hivemind.parse.GlobalInterceptorDescriptor;
 import org.apache.commons.hivemind.parse.InterceptorDescriptor;
 import org.apache.commons.hivemind.parse.ModuleDescriptor;
 import org.apache.commons.hivemind.parse.ServiceDescriptor;
@@ -379,4 +380,34 @@
                 "Missing required attribute 'name' in element 
module/extension-point/schema/element");
         }
     }
+
+       public void testGlobalInterceptor() throws Exception
+       {
+               ModuleDescriptor md = parse("GenericModule.xml");
+               GlobalInterceptorDescriptor[] gids = 
md.getGlobalInterceptorDescriptors();
+
+               assertEquals(2,gids.length);
+               
+               //make the first interceptor
+               
assertEquals("MyInterceptor",gids[0].getInterceptorDescriptor().getServiceId());
+               assertNotNull(gids[0].getInterceptorDescriptor().getLocation());
+               
+               GlobalInterceptorDescriptor.PatternDesc[] patternDescs = 
gids[0].getPatternDescriptors();
+               assertEquals(2,patternDescs.length);
+               assertTrue(patternDescs[0] instanceof 
GlobalInterceptorDescriptor.ClassPatternDesc);
+               GlobalInterceptorDescriptor.ClassPatternDesc patternDesc = 
+                       (GlobalInterceptorDescriptor.ClassPatternDesc) patternDescs[0];
+               
assertEquals("org.apache.commons.hivemind.ServiceImplementationFactory",patternDesc.className);
+               assertTrue(patternDescs[1] instanceof 
GlobalInterceptorDescriptor.ClassPatternDesc);
+               patternDesc =(GlobalInterceptorDescriptor.ClassPatternDesc) 
patternDescs[1];
+               
assertEquals("org.apache.commons.hivemind.Location",patternDesc.className);
+               
+               //the second interceptor
+               
assertEquals("MyInterceptor2",gids[1].getInterceptorDescriptor().getServiceId());
+               assertNotNull(gids[1].getInterceptorDescriptor().getLocation());
+               
+               assertNull(gids[1].getPatternDescriptors());
+       }
+
+
 }
Index: src/test/hivemind/test/services/DemoSerializeService.java
===================================================================
RCS file: src/test/hivemind/test/services/DemoSerializeService.java
diff -N src/test/hivemind/test/services/DemoSerializeService.java
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ src/test/hivemind/test/services/DemoSerializeService.java   21 Aug 2003 17:53:31 
-0000
@@ -0,0 +1,14 @@
+package hivemind.test.services;
+
+import java.io.Serializable;
+
+
+/**
+ * 
+ * 
+ * @author chris
+ */
+public interface DemoSerializeService extends SimpleSerializeService, DemoService
+{
+
+}
Index: src/test/hivemind/test/services/GlobalInterceptor.xml
===================================================================
RCS file: src/test/hivemind/test/services/GlobalInterceptor.xml
diff -N src/test/hivemind/test/services/GlobalInterceptor.xml
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ src/test/hivemind/test/services/GlobalInterceptor.xml       21 Aug 2003 17:53:31 
-0000
@@ -0,0 +1,157 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+       
+<module id="hivemind.test.services.globalinterceptor" version="0.0.1">
+       
+       <!-- the interface hierarchy:
+               (java.io.Serializable(Ser))                SimpleService (Simple)
+                       |                                                        |
+                       |____________________________|
+                       |                                                        |
+               SimpleSerializeService(SimpleSer)    DemoService (Demo)
+                       |                                                        |
+                       |____________________________|
+                                                                                |
+                                                                   
DemoSerializeService (DemoSer)
+                  
+                  All interfaces are implemented by the class DemoSerializeServiceImpl
+     -->
+
+
+       <!-- use differnt inverceptor-factories  and their global interceptors-->
+       
+       <!-- this must be on SimpleS, SimpleSerS, DemoS and DemoSerS-->
+       <service id="Simple"
+               interface="org.apache.commons.hivemind.ServiceInterceptorFactory">
+               <invoke-factory service-id="hivemind.BuilderFactory">
+                       <construct class="hivemind.test.services.impl.TrackerFactory">
+                               <set property="name" value="Simple"/>
+                       </construct>
+               </invoke-factory>
+       </service>
+       <global-interceptor service-id="Simple" order="10">
+               <class name="hivemind.test.services.SimpleService"/>
+       </global-interceptor>
+       <global-interceptor service-id="Simple" order="10"><!-- check each interceptor 
only once -->
+               <class name="hivemind.test.services.SimpleService"/>
+       </global-interceptor>
+       
+       <!-- this must be on SimpleSerS and DemoSerS -->
+       <service id="SimpleSer"
+               interface="org.apache.commons.hivemind.ServiceInterceptorFactory">
+               <invoke-factory service-id="hivemind.BuilderFactory">
+                       <construct class="hivemind.test.services.impl.TrackerFactory">
+                               <set property="name" value="SimpleSer"/>
+                       </construct>
+               </invoke-factory>
+       </service>
+       <global-interceptor service-id="SimpleSer" order="20">
+               <class name="hivemind.test.services.SimpleSerializeService"/>
+       </global-interceptor>
+
+       <!-- this must be on DemoS and DemoSerS -->
+       <service id="Demo"
+               interface="org.apache.commons.hivemind.ServiceInterceptorFactory">
+               <invoke-factory service-id="hivemind.BuilderFactory">
+                       <construct class="hivemind.test.services.impl.TrackerFactory">
+                               <set property="name" value="Demo"/>
+                       </construct>
+               </invoke-factory>
+       </service>
+       <global-interceptor service-id="Demo" order="30">
+               <class name="hivemind.test.services.DemoService"/>
+       </global-interceptor>
+
+       <!-- this must only be on DemoSerS -->
+       <service id="DemoSer"
+               interface="org.apache.commons.hivemind.ServiceInterceptorFactory">
+               <invoke-factory service-id="hivemind.BuilderFactory">
+                       <construct class="hivemind.test.services.impl.TrackerFactory">
+                               <set property="name" value="DemoSer"/>
+                       </construct>
+               </invoke-factory>
+       </service>
+       <global-interceptor service-id="DemoSer" order="40">
+               <class name="hivemind.test.services.DemoSerializeService"/>
+       </global-interceptor>
+
+       <!-- this must be an SimpleSerS and DemoSerS -->
+       <service id="Ser"
+               interface="org.apache.commons.hivemind.ServiceInterceptorFactory">
+               <invoke-factory service-id="hivemind.BuilderFactory">
+                       <construct class="hivemind.test.services.impl.TrackerFactory">
+                               <set property="name" value="Ser"/>
+                       </construct>
+               </invoke-factory>
+       </service>
+       <global-interceptor service-id="Ser" order="50">
+               <class name="java.io.Serializable"/>
+       </global-interceptor>
+
+       <!-- this must be on SimpleS, SimpleSerS, DemoS and DemoSerS (on all) -->
+       <service id="All"
+               interface="org.apache.commons.hivemind.ServiceInterceptorFactory">
+               <invoke-factory service-id="hivemind.BuilderFactory">
+                       <construct class="hivemind.test.services.impl.TrackerFactory">
+                               <set property="name" value="All"/>
+                       </construct>
+               </invoke-factory>
+       </service>
+       <global-interceptor service-id="All" order="60">
+       </global-interceptor>
+       <global-interceptor service-id="All" order="30"> <!-- also check that not 
double-->
+               <class name="java.io.Serializable"/>
+       </global-interceptor>
+       
+       <!-- this must only be on DemoSerS-->
+       <service id="Ser_Demo"
+               interface="org.apache.commons.hivemind.ServiceInterceptorFactory">
+               <invoke-factory service-id="hivemind.BuilderFactory">
+                       <construct class="hivemind.test.services.impl.TrackerFactory">
+                               <set property="name" value="Ser_Demo"/>
+                       </construct>
+               </invoke-factory>
+       </service>
+       <global-interceptor service-id="Ser_Demo" order="70">
+               <class name="hivemind.test.services.DemoService"/>
+               <class name="java.io.Serializable"/>
+       </global-interceptor>
+
+       <!-- this must be on all Serializable and on all Demo. (= SimpleSerS, DemoS 
and DemoSerS) -->
+       <service id="Ser_Demo_OR"
+               interface="org.apache.commons.hivemind.ServiceInterceptorFactory">
+               <invoke-factory service-id="hivemind.BuilderFactory">
+                       <construct class="hivemind.test.services.impl.TrackerFactory">
+                               <set property="name" value="Ser_Demo_OR"/>
+                       </construct>
+               </invoke-factory>
+       </service>
+       <global-interceptor service-id="Ser_Demo_OR" order="80">
+               <class name="hivemind.test.services.DemoService"/>
+       </global-interceptor>
+       <global-interceptor service-id="Ser_Demo_OR" order="80">
+               <class name="java.io.Serializable"/>
+       </global-interceptor>
+       
+
+       <!-- four Services for each interface -->
+       
+       <!-- should be registered: All, Simple-->
+       <service id="SimpleS" interface="hivemind.test.services.SimpleService">
+         <create-instance 
class="hivemind.test.services.impl.DemoSerializeServiceImpl"/>
+       </service>
+
+       <!-- should be registered: Ser_Demo_OR, All, Ser, SimpleSer, Simple-->
+       <service id="SimpleSerS" 
interface="hivemind.test.services.SimpleSerializeService">
+         <create-instance 
class="hivemind.test.services.impl.DemoSerializeServiceImpl"/>
+       </service>
+       
+       <!-- should be registered: Ser_Demo_OR, All, Demo, Simple-->
+       <service id="DemoS" interface="hivemind.test.services.DemoService">
+         <create-instance 
class="hivemind.test.services.impl.DemoSerializeServiceImpl"/>
+       </service>
+       <!-- shoud be retistered: Ser_Demo_OR, Ser_Demo, All, Ser, DemoSer,Demo, 
SimpleSer, Simple-->
+       <service id="DemoSerS" interface="hivemind.test.services.DemoSerializeService">
+         <create-instance 
class="hivemind.test.services.impl.DemoSerializeServiceImpl"/>
+       </service>
+</module>
Index: src/test/hivemind/test/services/SimpleSerializeService.java
===================================================================
RCS file: src/test/hivemind/test/services/SimpleSerializeService.java
diff -N src/test/hivemind/test/services/SimpleSerializeService.java
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ src/test/hivemind/test/services/SimpleSerializeService.java 21 Aug 2003 17:53:30 
-0000
@@ -0,0 +1,15 @@
+package hivemind.test.services;
+
+import java.io.Serializable;
+
+
+/**
+ * 
+ * 
+ * @author chris
+ */
+public interface SimpleSerializeService extends SimpleService, Serializable
+{
+
+
+}
Index: src/test/hivemind/test/services/TestServices.java
===================================================================
RCS file: 
/home/cvspublic/jakarta-commons-sandbox/hivemind/src/test/hivemind/test/services/TestServices.java,v
retrieving revision 1.21
diff -u -r1.21 TestServices.java
--- src/test/hivemind/test/services/TestServices.java   20 Aug 2003 20:40:45 -0000     
 1.21
+++ src/test/hivemind/test/services/TestServices.java   21 Aug 2003 17:53:30 -0000
@@ -175,6 +175,50 @@
             TrackerFactory.getInvocations().toArray());
 
     }
+    
+    //we have to build for each interceptor-chain a new test
+    public void testGlobalInterceptorSimpleS() throws Exception 
+    {
+       String[] list = {"All:add","Simple:add"};
+               this.globalInterceptorHelper("SimpleS", SimpleService.class, list);
+    }
+    
+       public void testGlobalInterceptorSimpleSerS() throws Exception 
+       {
+               String[] list = 
{"Ser_Demo_OR:add","All:add","Ser:add","SimpleSer:add","Simple:add"};
+               this.globalInterceptorHelper("SimpleSerS", 
SimpleSerializeService.class, list);
+       }
+
+       public void testGlobalInterceptorDemoS() throws Exception 
+       {
+               String[] list = {"Ser_Demo_OR:add","All:add","Demo:add","Simple:add"};
+               this.globalInterceptorHelper("DemoS", DemoService.class, list);
+       }
+
+       public void testGlobalInterceptorDemoSerS() throws Exception 
+       {
+               String[] list = 
{"Ser_Demo_OR:add","Ser_Demo:add","All:add","Ser:add","DemoSer:add","Demo:add","SimpleSer:add","Simple:add"};
+               this.globalInterceptorHelper("DemoSerS", DemoSerializeService.class, 
list);
+       }
+
+    private void globalInterceptorHelper(String serviceId, Class serviceClass, 
String[] list)
+       throws Exception
+    {
+               Registry r =
+                       buildRegistry("GlobalInterceptor.xml");
+
+               SimpleService s = (SimpleService) 
r.getService("hivemind.test.services.globalinterceptor."
+                                                                                      
                 +serviceId, serviceClass);
+
+               TrackerFactory.reset();
+
+               assertEquals(11, s.add(4, 7));
+
+               checkList(
+                       list,
+                       TrackerFactory.getInvocations().toArray());
+       
+    }
 
     public void testInitialize() throws Exception
     {
Index: src/test/hivemind/test/services/impl/DemoSerializeServiceImpl.java
===================================================================
RCS file: src/test/hivemind/test/services/impl/DemoSerializeServiceImpl.java
diff -N src/test/hivemind/test/services/impl/DemoSerializeServiceImpl.java
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ src/test/hivemind/test/services/impl/DemoSerializeServiceImpl.java  21 Aug 2003 
17:53:32 -0000
@@ -0,0 +1,16 @@
+package hivemind.test.services.impl;
+
+import hivemind.test.services.DemoSerializeService;
+import hivemind.test.services.DemoService;
+
+
+/**
+ * 
+ * 
+ * @author chris
+ */
+public class DemoSerializeServiceImpl extends DemoServiceImpl implements 
DemoSerializeService
+{
+
+
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to