Here's the patch that implements HIVEMIND-96 and HIVEMIND-45.  Let me know
what you guys think and I'll go ahead and commit them (separately with
appropriate comments of course).

-----Original Message-----
From: James Carman [mailto:[EMAIL PROTECTED] 
Sent: Sunday, February 27, 2005 11:04 AM
To: [email protected]; 'Knut Wannheden'
Subject: RE: AOPAlliance Service Interceptors...

I went to the project level and did a Team -> Update.  Then, I go to the
project level and I do a Team -> Create Patch, but it only recognizes my new
classes.  This is getting on my nerves, because I have both of these issues
resolved with test cases and I would like to check it into the 1.1 codebase
for you folks to check out.

-----Original Message-----
From: Knut Wannheden [mailto:[EMAIL PROTECTED] 
Sent: Sunday, February 27, 2005 11:01 AM
To: [email protected]
Subject: Re: AOPAlliance Service Interceptors...

Sounds strange... Only tips I have:

 - Try resynchronizing the entire project
 - Create the patch on the Project level

Sorry if this doesn't help, but I can't think of anything else...

--knut

On Sun, 27 Feb 2005 10:47:11 -0500, James Carman
<[EMAIL PROTECTED]> wrote:
> Well, I've got it implemented with test cases, but I can't get Eclipse to
> generate a patch for me!  It sees my new classes, but fails to include the
> changes I have made to existing classes/interfaces.  HELP!
> 
> -----Original Message-----
> From: Howard Lewis Ship [mailto:[EMAIL PROTECTED]
> Sent: Sunday, February 27, 2005 10:47 AM
> To: [email protected]
> Subject: Re: AOPAlliance Service Interceptors...
> 
> This works for me.  Having the name default to the service id is a
> perfectly fine idea.
> 
> On Sun, 27 Feb 2005 08:35:50 -0500, James Carman
> <[EMAIL PROTECTED]> wrote:
> >
> >
> >
> > Has anyone else come up with a way to do this cleanly?  I think one big
> step
> > in the right direction would be support for overriding the interceptor's
> > name, replacing the factory's id with something else.  This way, we
could
> > define ONE service interceptor factory which inserts a MethodInterceptor
> > defined elsewhere in the registry (or inline maybe) and the interceptors
> > could still be ordered, since they could have unique names.  We could
> leave
> > it backward compatible, of course, defaulting the interceptor name to
the
> > service id of the interceptor factory.
> >
> >
> >
> > <interceptor service-id="hivemind.lib.MethodInterceptorFactory"
> > name="security">
> >
> >   <impl object="service:mymodule.SecurityInterceptor"; />
> >
> > </interceptor>
> >
> >
> >
> > <interceptor service-id="hivemind.lib.MethodInterceptorFactory"
> > name="logging" before="security">
> >
> >   <impl
> object="instance:com.myco.myproject.interceptor.LoggingInterceptor"
> > />
> >
> > </interceptor>
> >
> >
> >
> > Here, we have defined a service interceptor using another service and
one
> > using just a plain ole object.  What do you guys think?
> >
> >
> >
> >
> >
> > -----Original Message-----
> >  From: James Carman [mailto:[EMAIL PROTECTED]
> >  Sent: Saturday, February 05, 2005 7:35 AM
> >  To: [email protected]
> >  Subject: AOPAlliance Service Interceptors...
> >
> >
> >
> >
> > -->
> >
> >
> > Hello, All.  Since the AOPAlliance Service Interceptors support didn't
> make
> > it into 1.1, when can we expect that to become available?  I would like
to
> > discuss service interceptors in my article, but there is NO WAY that I'm
> > going to try to explain how to do it using Javassist.  I would like to
use
> > the AOPAlliance stuff.
> >
> >
> >
> > James
> 
> --
> Howard M. Lewis Ship
> Independent J2EE / Open-Source Java Consultant
> Creator, Jakarta Tapestry
> Creator, Jakarta HiveMind
> 
> Professional Tapestry training, mentoring, support
> and project work.  http://howardlewisship.com
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [EMAIL PROTECTED]
> For additional commands, e-mail: [EMAIL PROTECTED]
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [EMAIL PROTECTED]
> For additional commands, e-mail: [EMAIL PROTECTED]
> 
>

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



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

Index: .classpath
===================================================================
RCS file: /home/cvs/jakarta-hivemind/.classpath,v
retrieving revision 1.48
diff -u -r1.48 .classpath
--- .classpath  11 Feb 2005 01:55:41 -0000      1.48
+++ .classpath  27 Feb 2005 16:47:50 -0000
@@ -27,5 +27,6 @@
        <classpathentry kind="lib" 
path="ext-package/lib/groovy-all-1.0-beta-9.jar"/>
        <classpathentry kind="lib" path="ext-package/lib/cglib-full-2.0.1.jar"/>
        <classpathentry kind="lib" 
path="ext-package/lib/easymockclassextension-1.1.jar"/>
+       <classpathentry kind="lib" path="ext-package/lib/aopalliance-1.0.jar"/>
        <classpathentry kind="output" path="bin"/>
 </classpath>
Index: 
framework/src/java/org/apache/hivemind/impl/ServiceInterceptorContributionImpl.java
===================================================================
RCS file: 
/home/cvs/jakarta-hivemind/framework/src/java/org/apache/hivemind/impl/ServiceInterceptorContributionImpl.java,v
retrieving revision 1.10
diff -u -r1.10 ServiceInterceptorContributionImpl.java
--- 
framework/src/java/org/apache/hivemind/impl/ServiceInterceptorContributionImpl.java
 6 Jan 2005 01:45:12 -0000       1.10
+++ 
framework/src/java/org/apache/hivemind/impl/ServiceInterceptorContributionImpl.java
 27 Feb 2005 16:47:51 -0000
@@ -47,6 +47,8 @@
 
     private String _followingInterceptorIds;
 
+    private String _name;
+    
     public String toString()
     {
         ToStringBuilder builder = new ToStringBuilder(this);
@@ -54,10 +56,28 @@
         builder.append("parameters", _parameters);
         builder.append("precedingInterceptorIds", _precedingInterceptorIds);
         builder.append("followingInterceptorIds", _followingInterceptorIds);
-
+        builder.append("name", _name );
         return builder.toString();
     }
 
+    
+    /**
+     * @return Returns the _name.
+     */
+    public String getName()
+    {
+        if( _name == null )
+        {
+            return getFactoryServiceId();
+        }
+        return _name;
+    }
+    
+    public void setName( String name )
+    {
+        _name = name;
+    }
+    
     public String getFactoryServiceId()
     {
         return _factoryServiceId;
Index: framework/src/java/org/apache/hivemind/impl/ServicePointImpl.java
===================================================================
RCS file: 
/home/cvs/jakarta-hivemind/framework/src/java/org/apache/hivemind/impl/ServicePointImpl.java,v
retrieving revision 1.11
diff -u -r1.11 ServicePointImpl.java
--- framework/src/java/org/apache/hivemind/impl/ServicePointImpl.java   17 Feb 
2005 19:46:44 -0000      1.11
+++ framework/src/java/org/apache/hivemind/impl/ServicePointImpl.java   27 Feb 
2005 16:47:51 -0000
@@ -282,7 +282,7 @@
             // the interceptor stack we'll apply them in reverse order,
             // building outward from the core service implementation.
 
-            orderer.add(sic, sic.getFactoryServiceId(), 
sic.getPrecedingInterceptorIds(), sic
+            orderer.add(sic, sic.getName(), sic.getPrecedingInterceptorIds(), 
sic
                     .getFollowingInterceptorIds());
         }
 
Index: 
framework/src/java/org/apache/hivemind/internal/ServiceInterceptorContribution.java
===================================================================
RCS file: 
/home/cvs/jakarta-hivemind/framework/src/java/org/apache/hivemind/internal/ServiceInterceptorContribution.java,v
retrieving revision 1.4
diff -u -r1.4 ServiceInterceptorContribution.java
--- 
framework/src/java/org/apache/hivemind/internal/ServiceInterceptorContribution.java
 19 Feb 2005 02:40:54 -0000      1.4
+++ 
framework/src/java/org/apache/hivemind/internal/ServiceInterceptorContribution.java
 27 Feb 2005 16:47:51 -0000
@@ -24,6 +24,8 @@
  */
 public interface ServiceInterceptorContribution extends Locatable
 {
+    public String getName();
+    
     /**
      * Returns the id of the factory that creates the interceptor. Interceptor 
factories are simply
      * another HiveMind service, one that implements
Index: framework/src/java/org/apache/hivemind/parse/DescriptorParser.java
===================================================================
RCS file: 
/home/cvs/jakarta-hivemind/framework/src/java/org/apache/hivemind/parse/DescriptorParser.java,v
retrieving revision 1.48
diff -u -r1.48 DescriptorParser.java
--- framework/src/java/org/apache/hivemind/parse/DescriptorParser.java  19 Feb 
2005 13:42:56 -0000      1.48
+++ framework/src/java/org/apache/hivemind/parse/DescriptorParser.java  27 Feb 
2005 16:47:51 -0000
@@ -935,7 +935,7 @@
 
         id.setBefore(getAttribute("before"));
         id.setAfter(getAttribute("after"));
-
+        id.setName(getAttribute("name" ));
         sd.addInterceptor(id);
 
     }
Index: framework/src/java/org/apache/hivemind/parse/DescriptorParser.properties
===================================================================
RCS file: 
/home/cvs/jakarta-hivemind/framework/src/java/org/apache/hivemind/parse/DescriptorParser.properties,v
retrieving revision 1.18
diff -u -r1.18 DescriptorParser.properties
--- framework/src/java/org/apache/hivemind/parse/DescriptorParser.properties    
10 Feb 2005 01:04:34 -0000      1.18
+++ framework/src/java/org/apache/hivemind/parse/DescriptorParser.properties    
27 Feb 2005 16:47:51 -0000
@@ -38,6 +38,7 @@
 
 required.interceptor.before=false
 required.interceptor.after=false
+required.interceptor.name=false
 required.interceptor.service-id=true
 
 required.element.name=true
Index: framework/src/java/org/apache/hivemind/parse/InterceptorDescriptor.java
===================================================================
RCS file: 
/home/cvs/jakarta-hivemind/framework/src/java/org/apache/hivemind/parse/InterceptorDescriptor.java,v
retrieving revision 1.6
diff -u -r1.6 InterceptorDescriptor.java
--- framework/src/java/org/apache/hivemind/parse/InterceptorDescriptor.java     
5 Jan 2005 18:05:37 -0000       1.6
+++ framework/src/java/org/apache/hivemind/parse/InterceptorDescriptor.java     
27 Feb 2005 16:47:51 -0000
@@ -25,7 +25,8 @@
 {
     private String _before;
     private String _after;
-
+    private String _name;
+    
     public String getAfter()
     {
         return _after;
@@ -46,10 +47,26 @@
         _before = string;
     }
 
+    /**
+     * @return Returns the name.
+     */
+    public String getName()
+    {
+        return _name;
+    }
+    /**
+     * @param name The name to set.
+     */
+    public void setName(String name)
+    {
+        this._name = name;
+    }
+    
     protected void extendDescription(ToStringBuilder builder)
     {
         builder.append("before", _before);
         builder.append("after", _after);
+        builder.append("name", _name);
     }
 
 }
Index: framework/src/test/hivemind/test/parse/GenericModule.xml
===================================================================
RCS file: 
/home/cvs/jakarta-hivemind/framework/src/test/hivemind/test/parse/GenericModule.xml,v
retrieving revision 1.10
diff -u -r1.10 GenericModule.xml
--- framework/src/test/hivemind/test/parse/GenericModule.xml    5 Jan 2005 
21:53:32 -0000       1.10
+++ framework/src/test/hivemind/test/parse/GenericModule.xml    27 Feb 2005 
16:47:52 -0000
@@ -68,11 +68,11 @@
        <service-point id="MyService1" interface="package.MyService">
                Description of MyService1.
                <create-instance class="package.impl.MyServiceImpl"/>
-               <interceptor service-id="MyInterceptor" 
before="OtherInterceptor"/>
-               <interceptor service-id="OtherInterceptor" 
after="MyInterceptor"/>
+               <interceptor service-id="MyInterceptor" 
before="OtherInterceptor" name="MyInterceptorName"/>
+               <interceptor service-id="OtherInterceptor" 
after="MyInterceptorName"/>
        </service-point>
        <implementation service-id="othermodule.OtherService">
-               <interceptor service-id="MyInterceptor"/>
+               <interceptor service-id="MyInterceptor" />
        </implementation>
        <service-point id="MyServiceFactory"
                interface="org.apache.hivemind.ServiceImplementationFactory"
Index: framework/src/test/hivemind/test/parse/TestDescriptorParser.java
===================================================================
RCS file: 
/home/cvs/jakarta-hivemind/framework/src/test/hivemind/test/parse/TestDescriptorParser.java,v
retrieving revision 1.31
diff -u -r1.31 TestDescriptorParser.java
--- framework/src/test/hivemind/test/parse/TestDescriptorParser.java    10 Feb 
2005 01:04:33 -0000      1.31
+++ framework/src/test/hivemind/test/parse/TestDescriptorParser.java    27 Feb 
2005 16:47:52 -0000
@@ -190,10 +190,12 @@
         InterceptorDescriptor id = (InterceptorDescriptor) l.get(0);
         assertEquals("MyInterceptor", id.getFactoryServiceId());
         assertEquals("OtherInterceptor", id.getBefore());
-
+        assertEquals( "MyInterceptorName", id.getName() );
+        
         id = (InterceptorDescriptor) l.get(1);
         assertEquals("OtherInterceptor", id.getFactoryServiceId());
-        assertEquals("MyInterceptor", id.getAfter());
+        assertEquals("MyInterceptorName", id.getAfter());
+        assertNull(id.getName());
     }
 
     public void testImplementation() throws Exception
Index: framework/src/test/org/apache/hivemind/impl/TestServicePoint.java
===================================================================
RCS file: 
/home/cvs/jakarta-hivemind/framework/src/test/org/apache/hivemind/impl/TestServicePoint.java,v
retrieving revision 1.4
diff -u -r1.4 TestServicePoint.java
--- framework/src/test/org/apache/hivemind/impl/TestServicePoint.java   17 Feb 
2005 19:46:45 -0000      1.4
+++ framework/src/test/org/apache/hivemind/impl/TestServicePoint.java   27 Feb 
2005 16:47:52 -0000
@@ -16,6 +16,7 @@
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Locale;
 import java.util.Map;
 
 import org.apache.hivemind.ApplicationRuntimeException;
@@ -41,7 +42,7 @@
 
         result.setClassResolver(new DefaultClassResolver());
         result.setPackageName("");
-
+        result.setRegistry(new RegistryInfrastructureImpl( new 
StrictErrorHandler(), Locale.getDefault()));
         return result;
     }
 
@@ -73,6 +74,90 @@
         verifyControls();
     }
 
+    public void testDefaultInterceptorOrdering()
+    {
+        Location l = fabricateLocation(12);
+        Module module = newModule();
+
+        replayControls();
+
+        ServicePointImpl sp = new ServicePointImpl();
+        sp.setModule(module);
+        sp.setServiceInterfaceName("foo.bar.Baz");
+        sp.setExtensionPointId("zip.zap");
+        sp.setLocation(l);
+        final ServiceInterceptorContributionImpl interceptor1 = new 
ServiceInterceptorContributionImpl();
+        interceptor1.setFactoryServiceId( "SomeFactory1" );
+        sp.addInterceptorContribution( interceptor1 );
+        final ServiceInterceptorContributionImpl interceptor2 = new 
ServiceInterceptorContributionImpl();
+        interceptor2.setFactoryServiceId( "SomeFactory2" );
+        sp.addInterceptorContribution( interceptor2 );
+        sp.setExtensionPointId( "ExtensionPointId" );
+        final List ordered = sp.getOrderedInterceptorContributions();
+        assertNotNull( ordered );
+        assertEquals( 2, ordered.size() );
+        assertEquals( interceptor1, ordered.get( 0 ) );
+        assertEquals( interceptor2, ordered.get( 1 ) );
+        verifyControls();
+    }
+
+    public void testCustomInterceptorOrdering()
+    {
+        Location l = fabricateLocation(12);
+        Module module = newModule();
+
+        replayControls();
+
+        ServicePointImpl sp = new ServicePointImpl();
+        sp.setModule(module);
+        sp.setServiceInterfaceName("foo.bar.Baz");
+        sp.setExtensionPointId("zip.zap");
+        sp.setLocation(l);
+        final ServiceInterceptorContributionImpl interceptor1 = new 
ServiceInterceptorContributionImpl();
+        interceptor1.setFactoryServiceId( "SomeFactory1" );
+        sp.addInterceptorContribution( interceptor1 );
+        final ServiceInterceptorContributionImpl interceptor2 = new 
ServiceInterceptorContributionImpl();
+        interceptor2.setFactoryServiceId( "SomeFactory2" );
+        interceptor2.setFollowingInterceptorIds("SomeFactory1");
+        sp.addInterceptorContribution( interceptor2 );
+        sp.setExtensionPointId( "ExtensionPointId" );
+        final List ordered = sp.getOrderedInterceptorContributions();
+        assertNotNull( ordered );
+        assertEquals( 2, ordered.size() );
+        assertEquals( interceptor2, ordered.get( 0 ) );
+        assertEquals( interceptor1, ordered.get( 1 ) );
+        verifyControls();
+    }
+
+    public void testInterceptorOrderingByName()
+    {
+        Location l = fabricateLocation(12);
+        Module module = newModule();
+
+        replayControls();
+
+        ServicePointImpl sp = new ServicePointImpl();
+        sp.setModule(module);
+        sp.setServiceInterfaceName("foo.bar.Baz");
+        sp.setExtensionPointId("zip.zap");
+        sp.setLocation(l);
+        final ServiceInterceptorContributionImpl interceptor1 = new 
ServiceInterceptorContributionImpl();
+        interceptor1.setFactoryServiceId( "SomeFactory1" );
+        interceptor1.setName( "Interceptor1" );
+        sp.addInterceptorContribution( interceptor1 );
+        final ServiceInterceptorContributionImpl interceptor2 = new 
ServiceInterceptorContributionImpl();
+        interceptor2.setFactoryServiceId( "SomeFactory2" );
+        interceptor2.setFollowingInterceptorIds("Interceptor1");
+        sp.addInterceptorContribution( interceptor2 );
+        sp.setExtensionPointId( "ExtensionPointId" );
+        final List ordered = sp.getOrderedInterceptorContributions();
+        assertNotNull( ordered );
+        assertEquals( 2, ordered.size() );
+        assertEquals( interceptor2, ordered.get( 0 ) );
+        assertEquals( interceptor1, ordered.get( 1 ) );
+        verifyControls();
+    }
+    
     public void testResultNotAssignableToServiceInterface()
     {
         Location l = fabricateLocation(187);
Index: library/build.xml
===================================================================
RCS file: /home/cvs/jakarta-hivemind/library/build.xml,v
retrieving revision 1.15
diff -u -r1.15 build.xml
--- library/build.xml   1 Feb 2005 11:59:01 -0000       1.15
+++ library/build.xml   27 Feb 2005 16:47:52 -0000
@@ -46,7 +46,7 @@
                <ibiblio-dependency artifact="servletapi" version="2.3" 
group="servletapi" use="test"/>                         
                <ibiblio-dependency artifact="oro" version="2.0.6" group="oro" 
use="test"/>                     
                <ibiblio-dependency artifact="easymock" version="1.1" 
group="easymock" use="test"/>
-               
+               <ibiblio-dependency artifact="aopalliance" version="1.0" 
group="aopalliance" />
                <project-dependency artifact="hivemind"/>
                
                <default-compile/>
Index: library/src/descriptor/META-INF/hivemodule.xml
===================================================================
RCS file: 
/home/cvs/jakarta-hivemind/library/src/descriptor/META-INF/hivemodule.xml,v
retrieving revision 1.22
diff -u -r1.22 hivemodule.xml
--- library/src/descriptor/META-INF/hivemodule.xml      10 Feb 2005 01:04:34 
-0000      1.22
+++ library/src/descriptor/META-INF/hivemodule.xml      27 Feb 2005 16:47:53 
-0000
@@ -440,5 +440,22 @@
     </parameters-schema>
     
   </service-point>
-  
+  <service-point id="MethodInterceptorFactory" parameters-occurs="1" 
interface="org.apache.hivemind.ServiceInterceptorFactory">
+    <invoke-factory>
+      <construct class="org.apache.hivemind.lib.impl.MethodInterceptorFactory" 
/>
+    </invoke-factory>
+    
+    <parameters-schema>
+      <element name="impl">
+        <attribute name="object" required="true" translator="object">
+          The implementation object which implements the MethodInterceptor 
interface.
+        </attribute>
+
+               <rules>
+                 <push-attribute attribute="object" />
+                 <invoke-parent method="addElement" />
+               </rules>
+      </element>
+    </parameters-schema>
+  </service-point>
 </module>
Index: 
framework/src/test/org/apache/hivemind/impl/TestServiceInterceptorContributionImpl.java
===================================================================
RCS file: 
framework/src/test/org/apache/hivemind/impl/TestServiceInterceptorContributionImpl.java
diff -N 
framework/src/test/org/apache/hivemind/impl/TestServiceInterceptorContributionImpl.java
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ 
framework/src/test/org/apache/hivemind/impl/TestServiceInterceptorContributionImpl.java
     1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,50 @@
+//Copyright 2004, 2005 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package org.apache.hivemind.impl;
+
+import org.apache.hivemind.test.HiveMindTestCase;
+
+/**
+ * Tests for [EMAIL PROTECTED] ServiceInterceptorContributionImpl}.
+ * @author James Carman
+ */
+public class TestServiceInterceptorContributionImpl extends HiveMindTestCase
+{
+    private static final String NAME = "SomeName";
+    private static final String FACTORY_ID = "SomeFactoryId";
+    
+    /**
+     * Tests to make sure that the name defaults to the factory id.
+     *
+     */
+    public void testNameDefault()
+    {
+        final ServiceInterceptorContributionImpl impl = new 
ServiceInterceptorContributionImpl();
+        impl.setFactoryServiceId( FACTORY_ID );
+        assertEquals( FACTORY_ID, impl.getName() );
+    }
+    
+    /**
+     * Tests to make sure that the name override works.
+     *
+     */
+    public void testNameOverride()
+    {
+        final ServiceInterceptorContributionImpl impl = new 
ServiceInterceptorContributionImpl();
+        impl.setFactoryServiceId( FACTORY_ID );
+        impl.setName( NAME );
+        assertEquals( NAME, impl.getName() );
+    }    
+}
Index: 
library/src/java/org/apache/hivemind/lib/impl/MethodInterceptorFactory.java
===================================================================
RCS file: 
library/src/java/org/apache/hivemind/lib/impl/MethodInterceptorFactory.java
diff -N 
library/src/java/org/apache/hivemind/lib/impl/MethodInterceptorFactory.java
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ library/src/java/org/apache/hivemind/lib/impl/MethodInterceptorFactory.java 
1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,149 @@
+//Copyright 2004, 2005 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package org.apache.hivemind.lib.impl;
+
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.util.List;
+
+import org.aopalliance.intercept.MethodInterceptor;
+import org.aopalliance.intercept.MethodInvocation;
+import org.apache.hivemind.InterceptorStack;
+import org.apache.hivemind.ServiceInterceptorFactory;
+import org.apache.hivemind.internal.Module;
+
+/**
+ * A service interceptor factory supporting the AOP Alliance MethodInterceptor 
interface.
+ * <b>Note:</b>The current implementation uses JDK proxies as opposed to 
Javassist! 
+ * @author James Carman
+ */
+public class MethodInterceptorFactory implements ServiceInterceptorFactory
+{
+
+    /**
+     * 
+     * @see 
org.apache.hivemind.ServiceInterceptorFactory#createInterceptor(org.apache.hivemind.InterceptorStack,
 org.apache.hivemind.internal.Module, java.util.List)
+     */
+    public void createInterceptor(InterceptorStack stack, Module 
invokingModule, List parameters)
+    {
+        final Class[] interfaces = new Class[]{stack.getServiceInterface()};
+        final ClassLoader classLoader = 
invokingModule.getClassResolver().getClassLoader();
+        final InvocationHandler invocationHandler = new 
MethodInterceptorInvocationHandler( ( MethodInterceptor )parameters.get( 0 ), 
stack );
+        stack.push( Proxy.newProxyInstance( classLoader, interfaces, 
invocationHandler ) );
+    }
+    
+    /**
+     * A java proxy InvocationHandler implementation which allows a 
MethodInterceptor to intercept the method invocation.
+     */
+    private final class MethodInterceptorInvocationHandler implements 
InvocationHandler
+    {
+        private final MethodInterceptor methodInterceptor;
+        private final InterceptorStack stack;
+        private final Object target;
+
+        /**
+         * Constructs a MethodInterceptorInvocationHandler
+         *
+         * @param stack       the interceptor stack
+         */
+        public MethodInterceptorInvocationHandler( MethodInterceptor 
methodInterceptor, InterceptorStack stack )
+        {
+            this.stack = stack;
+            this.target = stack.peek();
+            this.methodInterceptor = methodInterceptor;
+        }
+
+        /**
+         * Calls the MethodInterceptor's invoke method.
+         * @param proxy  a reference to the proxy instance
+         * @param method the method being invoked
+         * @param args   the arguments to the method
+         * @return the value returned by the MethodInterceptor
+         * @throws Throwable
+         */
+        public Object invoke( Object proxy, Method method, Object[] args ) 
throws Throwable
+        {
+            return methodInterceptor.invoke( new MethodInvocationImpl( target, 
method, args, stack.peek() ) );
+        }
+    }
+
+    /**
+     * A java reflection-based implementation of a MethodInvocation
+     */
+    private final class MethodInvocationImpl implements MethodInvocation
+    {
+        private final Object next;
+        private final Method method;
+        private final Object[] arguments;
+        private final Object proxy;
+
+        /**
+         * Constructs a MethodInvocationImpl object.
+         *
+         * @param next      the next object
+         * @param method    the method
+         * @param arguments the arguments
+         * @param proxy     the outermost proxy object (allows calling another 
method instead).
+         */
+        public MethodInvocationImpl( Object next, Method method, Object[] 
arguments, Object proxy )
+        {
+            this.next = next;
+            this.method = method;
+            this.arguments = arguments;
+            this.proxy = proxy;
+        }
+
+        /**
+         * Invokes the method on the next object.
+         *
+         * @return value returned by invoking the method on the next object
+         * @throws Throwable throwable thrown by invoking method on the next 
object
+         */
+        public final Object proceed() throws Throwable
+        {
+            try
+            {
+                return method.invoke( next, arguments );
+            }
+            catch( InvocationTargetException e )
+            {
+                throw e.getTargetException();
+            }
+        }
+
+        public final Method getMethod()
+        {
+            return method;
+        }
+
+        public final AccessibleObject getStaticPart()
+        {
+            return method;
+        }
+
+        public final Object getThis()
+        {
+            return proxy;
+        }
+
+        public final Object[] getArguments()
+        {
+            return arguments;
+        }
+    }
+}
Index: library/src/test/org/apache/hivemind/lib/impl/FortuneCookie.java
===================================================================
RCS file: library/src/test/org/apache/hivemind/lib/impl/FortuneCookie.java
diff -N library/src/test/org/apache/hivemind/lib/impl/FortuneCookie.java
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ library/src/test/org/apache/hivemind/lib/impl/FortuneCookie.java    1 Jan 
1970 00:00:00 -0000
@@ -0,0 +1,23 @@
+//Copyright 2004, 2005 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package org.apache.hivemind.lib.impl;
+
+/**
+ * @author James Carman
+ */
+public interface FortuneCookie
+{
+    public String generateFortune();
+}
Index: library/src/test/org/apache/hivemind/lib/impl/FortuneCookieImpl.java
===================================================================
RCS file: library/src/test/org/apache/hivemind/lib/impl/FortuneCookieImpl.java
diff -N library/src/test/org/apache/hivemind/lib/impl/FortuneCookieImpl.java
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ library/src/test/org/apache/hivemind/lib/impl/FortuneCookieImpl.java        
1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,29 @@
+//Copyright 2004, 2005 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package org.apache.hivemind.lib.impl;
+
+/**
+ * @author James Carman
+ */
+public class FortuneCookieImpl implements FortuneCookie
+{
+    public static final String FORTUNE = "You will conquer obstacles to 
achieve success";
+    
+    public String generateFortune()
+    {
+        return FORTUNE;
+    }
+
+}
Index: 
library/src/test/org/apache/hivemind/lib/impl/InstanceMethodInterceptor.xml
===================================================================
RCS file: 
library/src/test/org/apache/hivemind/lib/impl/InstanceMethodInterceptor.xml
diff -N 
library/src/test/org/apache/hivemind/lib/impl/InstanceMethodInterceptor.xml
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ library/src/test/org/apache/hivemind/lib/impl/InstanceMethodInterceptor.xml 
1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,27 @@
+<?xml version="1.0"?>
+<!-- 
+   Copyright 2004, 2005 The Apache Software Foundation
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+-->
+
+<module id="hivemind.lib.test" version="1.0.0">
+  
+  <service-point id="FortuneCookie" 
interface="org.apache.hivemind.lib.impl.FortuneCookie">
+    <create-instance class="org.apache.hivemind.lib.impl.FortuneCookieImpl"/>
+    <interceptor service-id="hivemind.lib.MethodInterceptorFactory">
+      <impl 
object="instance:org.apache.hivemind.lib.impl.SuffixMethodInterceptor" />
+    </interceptor>
+  </service-point>
+  
+</module>
Index: 
library/src/test/org/apache/hivemind/lib/impl/ServiceMethodInterceptor.xml
===================================================================
RCS file: 
library/src/test/org/apache/hivemind/lib/impl/ServiceMethodInterceptor.xml
diff -N 
library/src/test/org/apache/hivemind/lib/impl/ServiceMethodInterceptor.xml
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ library/src/test/org/apache/hivemind/lib/impl/ServiceMethodInterceptor.xml  
1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,31 @@
+<?xml version="1.0"?>
+<!-- 
+   Copyright 2004, 2005 The Apache Software Foundation
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+-->
+
+<module id="hivemind.lib.test" version="1.0.0">
+  
+  <service-point id="FortuneCookie" 
interface="org.apache.hivemind.lib.impl.FortuneCookie">
+    <create-instance class="org.apache.hivemind.lib.impl.FortuneCookieImpl"/>
+    <interceptor service-id="hivemind.lib.MethodInterceptorFactory">
+      <impl object="service:SuffixMethodInterceptor"; />
+    </interceptor>
+  </service-point>
+  
+  <service-point id="SuffixMethodInterceptor" 
interface="org.aopalliance.intercept.MethodInterceptor">
+    <create-instance 
class="org.apache.hivemind.lib.impl.SuffixMethodInterceptor"/>
+  </service-point>
+  
+</module>
Index: 
library/src/test/org/apache/hivemind/lib/impl/SuffixMethodInterceptor.java
===================================================================
RCS file: 
library/src/test/org/apache/hivemind/lib/impl/SuffixMethodInterceptor.java
diff -N 
library/src/test/org/apache/hivemind/lib/impl/SuffixMethodInterceptor.java
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ library/src/test/org/apache/hivemind/lib/impl/SuffixMethodInterceptor.java  
1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,31 @@
+//Copyright 2004, 2005 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package org.apache.hivemind.lib.impl;
+
+import org.aopalliance.intercept.MethodInterceptor;
+import org.aopalliance.intercept.MethodInvocation;
+
+/**
+ * @author James Carman
+ */
+public class SuffixMethodInterceptor implements MethodInterceptor
+{
+    public static final String SUFFIX = " in bed.";
+    
+    public Object invoke(MethodInvocation invocation) throws Throwable
+    {
+        return invocation.proceed() + SUFFIX;
+    }
+}
Index: 
library/src/test/org/apache/hivemind/lib/impl/TestMethodInterceptorFactory.java
===================================================================
RCS file: 
library/src/test/org/apache/hivemind/lib/impl/TestMethodInterceptorFactory.java
diff -N 
library/src/test/org/apache/hivemind/lib/impl/TestMethodInterceptorFactory.java
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ 
library/src/test/org/apache/hivemind/lib/impl/TestMethodInterceptorFactory.java 
    1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,41 @@
+//Copyright 2004, 2005 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package org.apache.hivemind.lib.impl;
+
+import org.apache.hivemind.Registry;
+import org.apache.hivemind.test.HiveMindTestCase;
+
+/**
+ * Tests for [EMAIL PROTECTED] MethodInterceptorFactory}.
+ * 
+ * @author James Carman
+ */
+public class TestMethodInterceptorFactory extends HiveMindTestCase
+{
+
+    public void testWithInstanceMethodInterceptor() throws Exception
+    {
+        Registry registry = 
buildFrameworkRegistry("InstanceMethodInterceptor.xml");
+        final FortuneCookie cookie = (FortuneCookie) 
registry.getService(FortuneCookie.class);
+        assertEquals( FortuneCookieImpl.FORTUNE + 
SuffixMethodInterceptor.SUFFIX, cookie.generateFortune());
+    }
+    
+    public void testWithServiceMethodInterceptor() throws Exception
+    {
+        Registry registry = 
buildFrameworkRegistry("ServiceMethodInterceptor.xml");
+        final FortuneCookie cookie = (FortuneCookie) 
registry.getService(FortuneCookie.class);
+        assertEquals( FortuneCookieImpl.FORTUNE + 
SuffixMethodInterceptor.SUFFIX, cookie.generateFortune());
+    }
+}

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

Reply via email to