You are viewing a plain text version of this content. The canonical link for it is here.
Posted to server-dev@james.apache.org by ad...@apache.org on 2016/10/07 12:11:35 UTC
[06/10] james-project git commit: JAMES-1738 Import Onami-test code
in order to not depend on a SNAPSHOT
JAMES-1738 Import Onami-test code in order to not depend on a SNAPSHOT
Project: http://git-wip-us.apache.org/repos/asf/james-project/repo
Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/a37176fb
Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/a37176fb
Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/a37176fb
Branch: refs/heads/master
Commit: a37176fb07ed3f3c0b106340db5c31b20c7137f4
Parents: e8ef39c
Author: Benoit Tellier <bt...@linagora.com>
Authored: Wed Oct 5 12:38:20 2016 +0200
Committer: Benoit Tellier <bt...@linagora.com>
Committed: Wed Oct 5 14:57:39 2016 +0200
----------------------------------------------------------------------
mpt/onami-test/pom.xml | 82 +++
.../james/mpt/onami/test/GuiceMockModule.java | 182 +++++++
.../james/mpt/onami/test/MockEngineFactory.java | 66 +++
.../james/mpt/onami/test/OnamiRunner.java | 510 +++++++++++++++++++
.../apache/james/mpt/onami/test/OnamiSuite.java | 464 +++++++++++++++++
.../mpt/onami/test/annotation/GuiceModules.java | 42 ++
.../test/annotation/GuiceProvidedModules.java | 44 ++
.../james/mpt/onami/test/annotation/Mock.java | 77 +++
.../onami/test/annotation/MockFramework.java | 40 ++
.../mpt/onami/test/annotation/MockObjType.java | 48 ++
.../mpt/onami/test/annotation/MockType.java | 39 ++
.../onami/test/guice/MockMembersInjector.java | 79 +++
.../mpt/onami/test/guice/MockTypeListener.java | 87 ++++
.../handler/GuiceInjectableClassHandler.java | 84 +++
.../onami/test/handler/GuiceModuleHandler.java | 77 +++
.../handler/GuiceProvidedModuleHandler.java | 137 +++++
.../test/handler/MockFrameworkHandler.java | 72 +++
.../mpt/onami/test/handler/MockHandler.java | 178 +++++++
.../james/mpt/onami/test/mock/MockEngine.java | 50 ++
.../test/mock/framework/EasyMockFramework.java | 65 +++
.../test/mock/framework/MockitoFramework.java | 55 ++
.../test/reflection/AnnotationHandler.java | 45 ++
.../mpt/onami/test/reflection/ClassHandler.java | 33 ++
.../mpt/onami/test/reflection/ClassVisitor.java | 110 ++++
.../mpt/onami/test/reflection/FieldHandler.java | 34 ++
.../onami/test/reflection/HandleException.java | 66 +++
.../onami/test/reflection/MethodHandler.java | 34 ++
.../mpt/onami/test/AbstractEmptyTestCase.java | 42 ++
.../mpt/onami/test/AbstractMockTestCase.java | 40 ++
.../mpt/onami/test/AbstractMockitoTestCase.java | 45 ++
.../james/mpt/onami/test/AbstractTestCase.java | 83 +++
.../test/InjectDependingMockObjectTestCase.java | 87 ++++
.../test/InjectFromSuperClassTestCase.java | 57 +++
.../test/InjectJSR330ModuleClassTestCase.java | 54 ++
.../onami/test/InjectMockObjectTestCase.java | 97 ++++
.../onami/test/InjectModuleClassTestCase.java | 53 ++
.../onami/test/InjectStaticSimpleTestCase.java | 70 +++
.../james/mpt/onami/test/MockTypeTestCase.java | 43 ++
.../onami/test/MockitoFrameworkTestCase.java | 60 +++
.../james/mpt/onami/test/OnamiSuiteTest.java | 29 ++
.../mpt/onami/test/ServiceMockProviderTest.java | 43 ++
.../apache/james/mpt/onami/test/SimpleTest.java | 56 ++
.../mpt/onami/test/data/ComplexModule.java | 41 ++
.../mpt/onami/test/data/HelloWordAnnotated.java | 46 ++
.../james/mpt/onami/test/data/HelloWorld.java | 65 +++
.../james/mpt/onami/test/data/Service.java | 29 ++
.../james/mpt/onami/test/data/ServiceImpl.java | 36 ++
.../onami/test/data/ServiceMockProvider.java | 33 ++
.../mpt/onami/test/data/ServiceModule.java | 35 ++
.../james/mpt/onami/test/data/SimpleModule.java | 34 ++
.../mpt/onami/test/data/TelephonService.java | 27 +
.../onami/test/data/TelephonServiceImpl.java | 31 ++
.../mpt/onami/test/data/TestAnnotation.java | 32 ++
.../mpt/onami/test/data/TestAnnotation2.java | 32 ++
.../apache/james/mpt/onami/test/data/WhoIm.java | 37 ++
.../test/guice/MockAnnotatedWithTestCase.java | 76 +++
.../test/guice/TestCustomInjectionTest.java | 82 +++
.../src/test/resources/log4j.properties | 46 ++
mpt/pom.xml | 1 +
59 files changed, 4342 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/james-project/blob/a37176fb/mpt/onami-test/pom.xml
----------------------------------------------------------------------
diff --git a/mpt/onami-test/pom.xml b/mpt/onami-test/pom.xml
new file mode 100644
index 0000000..930450d
--- /dev/null
+++ b/mpt/onami-test/pom.xml
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you 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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <artifactId>apache-james-mpt</artifactId>
+ <groupId>org.apache.james</groupId>
+ <version>3.0.0-beta5-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>apache-james-mpt-onami-test</artifactId>
+ <packaging>jar</packaging>
+
+ <name>Apache James :: MPT :: Onami-test</name>
+ <description>MPT tooling from Onami project</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>com.google.inject</groupId>
+ <artifactId>guice</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymock</artifactId>
+ <version>3.2</version>
+ <scope>provided</scope>
+ <optional>true</optional>
+ </dependency>
+
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ <version>16.0.1</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-core</artifactId>
+ <version>1.9.5</version>
+ <scope>provided</scope>
+ <optional>true</optional>
+ </dependency>
+
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <extensions>true</extensions>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/james-project/blob/a37176fb/mpt/onami-test/src/main/java/org/apache/james/mpt/onami/test/GuiceMockModule.java
----------------------------------------------------------------------
diff --git a/mpt/onami-test/src/main/java/org/apache/james/mpt/onami/test/GuiceMockModule.java b/mpt/onami-test/src/main/java/org/apache/james/mpt/onami/test/GuiceMockModule.java
new file mode 100644
index 0000000..645e57f
--- /dev/null
+++ b/mpt/onami-test/src/main/java/org/apache/james/mpt/onami/test/GuiceMockModule.java
@@ -0,0 +1,182 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you 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.james.mpt.onami.test;
+
+import static com.google.common.base.Preconditions.checkState;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.apache.james.mpt.onami.test.annotation.Mock;
+
+import com.google.common.collect.HashMultimap;
+import com.google.common.collect.Multimap;
+import com.google.inject.AbstractModule;
+import com.google.inject.TypeLiteral;
+import com.google.inject.name.Names;
+
+/**
+ * <p>
+ * This class creates the binding for all mock objects found.
+ * </p>
+ * <p>
+ * Method {@link GuiceMockModule#configure()} creates a binding for each {@link Mock} annotation found. The binding will
+ * be created <b>if and only if</b> there is no types conflict between {@link Mock} caught.
+ * <p>
+ * <p>
+ * <b>A type conflict</b> is detected if two or more field are annotated with the same {@link Mock} and no different
+ * {@link Mock#annotatedWith} parameter are specified, or two o more equals {@link Mock#annotatedWith} parameter are
+ * specified for the same type field.
+ * </p>
+ * <p>
+ * If a conflict is detected the binding will not create for the conflicted type, moreover the field will be injected
+ * into the test class.
+ * </p>
+ */
+public class GuiceMockModule
+ extends AbstractModule
+{
+
+ private static final Logger LOGGER = Logger.getLogger( GuiceMockModule.class.getName() );
+
+ final Map<Field, Object> mockedFields;
+
+ /**
+ * Costructor.
+ *
+ * @param mockedFields the map of mock fileds.
+ */
+
+ public GuiceMockModule( final Map<Field, Object> mockedFields )
+ {
+ this.mockedFields = mockedFields;
+ }
+
+ @SuppressWarnings( "unchecked" )
+ @Override
+ protected void configure()
+ {
+ final Multimap<Type, Field> fieldsByType = HashMultimap.create();
+
+ for ( final Entry<Field, Object> entry : this.mockedFields.entrySet() )
+ {
+ fieldsByType.put( entry.getKey().getGenericType(), entry.getKey() );
+ }
+
+ for ( final Type type : fieldsByType.keySet() )
+ {
+ final Collection<Field> fields = fieldsByType.get( type );
+
+ boolean isTypeConflicts = false;
+ if ( fields.size() != 1 )
+ {
+ isTypeConflicts = checkTypeConflict( fields );
+ }
+
+ checkState( !isTypeConflicts, " Found multiple annotation @%s for type: %s; binding skipped!.",
+ Mock.class.getSimpleName(), type );
+ for ( final Field field : fields )
+ {
+ final TypeLiteral literal = TypeLiteral.get( type );
+ final Mock annoBy = field.getAnnotation( Mock.class );
+ final Object mock = this.mockedFields.get( field );
+ if ( annoBy.annotatedWith() != Mock.NoAnnotation.class )
+ {
+ bind( literal ).annotatedWith( annoBy.annotatedWith() ).toInstance( mock );
+ }
+ else if ( !"".equals( annoBy.namedWith() ) )
+ {
+ bind( literal ).annotatedWith( Names.named( annoBy.namedWith() ) ).toInstance( mock );
+ }
+ else
+ {
+ bind( literal ).toInstance( mock );
+ }
+ if ( LOGGER.isLoggable( Level.FINER ) )
+ {
+ LOGGER.finer( " Created binding for: " + type + " " + annoBy );
+ }
+ }
+ }
+ }
+
+ /**
+ * @param fields
+ * @return
+ */
+ private boolean checkTypeConflict( Collection<Field> fields )
+ {
+ final List<Class<?>> listAnnotatedType = new ArrayList<Class<?>>();
+ final List<String> listNamedType = new ArrayList<String>();
+ int numOfSimpleType = 0;
+
+ for ( Field field : fields )
+ {
+ final Mock annoBy = field.getAnnotation( Mock.class );
+
+ if ( annoBy.annotatedWith() == Mock.NoAnnotation.class && "".equals( annoBy.namedWith() ) )
+ {
+ numOfSimpleType++;
+ }
+ if ( numOfSimpleType > 1 )
+ {
+ LOGGER.finer( "Found multiple simple type" );
+ return true;
+ }
+
+ if ( annoBy.annotatedWith() != Mock.NoAnnotation.class )
+ {
+ if ( !listAnnotatedType.contains( annoBy.annotatedWith() ) )
+ {
+ listAnnotatedType.add( annoBy.annotatedWith() );
+ }
+ else
+ {
+ // found two fields with same annotation
+ LOGGER.finer( "Found multiple annotatedBy type" );
+ return true;
+ }
+ }
+
+ if ( !"".equals( annoBy.namedWith() ) )
+ {
+ if ( !listNamedType.contains( annoBy.namedWith() ) )
+ {
+ listNamedType.add( annoBy.namedWith() );
+ }
+ else
+ {
+ // found two fields with same named annotation
+ LOGGER.finer( "Found multiple namedWith type" );
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/james-project/blob/a37176fb/mpt/onami-test/src/main/java/org/apache/james/mpt/onami/test/MockEngineFactory.java
----------------------------------------------------------------------
diff --git a/mpt/onami-test/src/main/java/org/apache/james/mpt/onami/test/MockEngineFactory.java b/mpt/onami-test/src/main/java/org/apache/james/mpt/onami/test/MockEngineFactory.java
new file mode 100644
index 0000000..ad10daf
--- /dev/null
+++ b/mpt/onami-test/src/main/java/org/apache/james/mpt/onami/test/MockEngineFactory.java
@@ -0,0 +1,66 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you 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.james.mpt.onami.test;
+
+import org.apache.james.mpt.onami.test.annotation.MockType;
+import org.apache.james.mpt.onami.test.mock.MockEngine;
+import org.apache.james.mpt.onami.test.mock.framework.EasyMockFramework;
+import org.apache.james.mpt.onami.test.mock.framework.MockitoFramework;
+
+/**
+ * Factory class to create the mock framework.
+ *
+ * @see org.apache.onami.test.annotation.MockFramework
+ */
+final class MockEngineFactory
+{
+
+ /**
+ * Hidden constructor, this class must not be instantiated directly.
+ */
+ private MockEngineFactory()
+ {
+ // do nothing
+ }
+
+ /**
+ * Mock factory constructor. <br>
+ * Supported framewors: <li> {@link MockType}.EASY_MOCK <li> {@link MockType}.MOCKITO <br>
+ *
+ * @see MockType
+ * @param type of mock framework to create.
+ * @return An instance of mock framework.
+ */
+ public static MockEngine getMockEngine(MockType type )
+ {
+ switch ( type )
+ {
+ case EASY_MOCK:
+ return new EasyMockFramework();
+
+ case MOCKITO:
+ return new MockitoFramework();
+
+ default:
+ throw new IllegalArgumentException( "Unrecognized MockType '" + type.name() + "'" );
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/james-project/blob/a37176fb/mpt/onami-test/src/main/java/org/apache/james/mpt/onami/test/OnamiRunner.java
----------------------------------------------------------------------
diff --git a/mpt/onami-test/src/main/java/org/apache/james/mpt/onami/test/OnamiRunner.java b/mpt/onami-test/src/main/java/org/apache/james/mpt/onami/test/OnamiRunner.java
new file mode 100644
index 0000000..3ca9f6c
--- /dev/null
+++ b/mpt/onami-test/src/main/java/org/apache/james/mpt/onami/test/OnamiRunner.java
@@ -0,0 +1,510 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you 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.james.mpt.onami.test;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.apache.james.mpt.onami.test.annotation.GuiceModules;
+import org.apache.james.mpt.onami.test.annotation.GuiceProvidedModules;
+import org.apache.james.mpt.onami.test.annotation.Mock;
+import org.apache.james.mpt.onami.test.annotation.MockFramework;
+import org.apache.james.mpt.onami.test.annotation.MockType;
+import org.apache.james.mpt.onami.test.guice.MockTypeListener;
+import org.apache.james.mpt.onami.test.handler.GuiceInjectableClassHandler;
+import org.apache.james.mpt.onami.test.handler.GuiceModuleHandler;
+import org.apache.james.mpt.onami.test.handler.GuiceProvidedModuleHandler;
+import org.apache.james.mpt.onami.test.handler.MockFrameworkHandler;
+import org.apache.james.mpt.onami.test.handler.MockHandler;
+import org.apache.james.mpt.onami.test.mock.MockEngine;
+import org.apache.james.mpt.onami.test.reflection.ClassVisitor;
+import org.apache.james.mpt.onami.test.reflection.HandleException;
+import org.junit.runner.notification.RunNotifier;
+import org.junit.runners.BlockJUnit4ClassRunner;
+import org.junit.runners.model.FrameworkMethod;
+import org.junit.runners.model.InitializationError;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Guice;
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+import com.google.inject.Module;
+import com.google.inject.matcher.Matchers;
+import com.google.inject.util.Modules;
+
+/**
+ * <p>
+ * It's a {@link BlockJUnit4ClassRunner} runner.
+ * </p>
+ * <p>
+ * This class creates a Google Guice {@link Injector} configured by {@link GuiceModules} annotation (only fr modules
+ * with default constructor) and {@link GuiceProvidedModules} annotation and {@link Mock}.
+ * </p>
+ * <p>
+ * <b>Example #1:</b> <br>
+ *
+ * <pre>
+ *
+ * @org.junit.runner.RunWith( OnamiRunner.class )
+ * @GuiceModules( SimpleModule.class )
+ * public class AcmeTestCase
+ * {
+ *
+ * @GuiceProvidedModules
+ * static public Module getProperties()
+ * {
+
+import org.apache.onami.test.reflection.AnnotationHandler;
+import org.apache.onami.test.reflection.HandleException;
+ * ...
+ * return Modules.combine(new ComplexModule( loadProperies() ), ... );
+ * }
+ *
+ * </pre>
+ *
+ * </p>
+ * <p>
+ * <b>Example #2:</b> <br>
+ *
+ * <pre>
+ *
+ * @org.junit.runner.RunWith( OnamiRunner.class )
+ * public class AcmeTestCase
+ * extends com.google.inject.AbstractModule
+ * {
+ *
+ * public void configure()
+ * {
+ * // Configure your proper modules
+ * ...
+ * bind( Service.class ).annotatedWith( TestAnnotation.class ).to( ServiceTestImpl.class );
+ * ...
+ * }
+ *
+ * @Mock
+ * private AnotherService serviceMock;
+ *
+ * @Inject
+ * private Service serviceTest;
+ *
+ * @org.junit.Test
+ * public void test()
+ * {
+ * assertNotNull( serviceMock );
+ * assertNotNull( serviceTest );
+ * }
+ * </pre>
+ *
+ * </p>
+ *
+ * @see GuiceMockModule
+ */
+public class OnamiRunner
+ extends BlockJUnit4ClassRunner
+{
+
+ private static final Logger LOGGER = Logger.getLogger( OnamiRunner.class.getName() );
+
+ private Injector injector;
+
+ private final List<Module> allModules;
+
+ private final Map<Field, Object> mocked = new HashMap<Field, Object>( 1 );
+
+ private MockType mockFramework = MockType.EASY_MOCK;
+
+ /**
+ * OnamiRunner constructor to create the core JUnice class.
+ *
+ * @see org.junit.runner.RunWith
+ * @param klass The test case class to run.
+ * @throws org.junit.runners.model.InitializationError if any error occurs.
+ */
+ public OnamiRunner( Class<?> klass )
+ throws InitializationError
+ {
+ super( klass );
+
+ try
+ {
+ if ( LOGGER.isLoggable( Level.FINER ) )
+ {
+ LOGGER.finer( "Inizializing injector for test class: " + klass.getName() );
+ }
+
+ this.allModules = inizializeInjector( klass );
+
+ if ( LOGGER.isLoggable( Level.FINER ) )
+ {
+ LOGGER.finer( "done..." );
+ }
+ }
+ catch ( Exception e )
+ {
+ final List<Throwable> throwables = new LinkedList<Throwable>();
+ throwables.add( e );
+ throw new InitializationError( throwables );
+ }
+ }
+
+ /**
+ * OnamiRunner constructor to create the runner needed
+ * by the OnamiSuite class.
+ *
+ * @see org.junit.runner.RunWith
+ * @param suite The suite test case class to run.
+ * @param test The test case class to run.
+ * @throws org.junit.runners.model.InitializationError if any error occurs.
+ */
+ public OnamiRunner( Class<?> suite, Class<?> test )
+ throws InitializationError
+ {
+ super( test );
+
+ try
+ {
+ if ( LOGGER.isLoggable( Level.FINER ) )
+ {
+ LOGGER.finer( "Inizializing injector for test class: " + test.getName() );
+ }
+
+ this.allModules = inizializeInjector( suite, test );
+
+ if ( LOGGER.isLoggable( Level.FINER ) )
+ {
+ LOGGER.finer( "done..." );
+ }
+ }
+ catch ( Exception e )
+ {
+ final List<Throwable> throwables = new LinkedList<Throwable>();
+ throwables.add( e );
+ throw new InitializationError( throwables );
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void run( final RunNotifier notifier )
+ {
+ if ( LOGGER.isLoggable( Level.FINER ) )
+ {
+ LOGGER.finer( " ### Run test case: " + getTestClass().getJavaClass() + " ### " );
+ LOGGER.finer( " #### Creating injector ####" );
+ }
+
+ this.injector = createInjector( allModules );
+ super.run( notifier );
+ this.flush();
+
+ if ( LOGGER.isLoggable( Level.FINER ) )
+ {
+ LOGGER.finer( " ### End test case: " + getTestClass().getJavaClass().getName() + " ### " );
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ private void flush()
+ {
+ this.injector = null;
+ this.allModules.clear();
+ this.mocked.clear();
+ }
+
+ @Override
+ protected void runChild( FrameworkMethod method, RunNotifier notifier )
+ {
+ if ( LOGGER.isLoggable( Level.FINER ) )
+ {
+ LOGGER.finer( " +++ invoke test method: " + method.getName() + " +++ " );
+ }
+
+ super.runChild( method, notifier );
+ resetAllResetAfterMocks();
+
+ if ( LOGGER.isLoggable( Level.FINER ) )
+ {
+ LOGGER.finer( " --- end test method: " + method.getName() + " --- " );
+ }
+ }
+
+ /**
+ * Creates test instance via Google-Guice to inject all not-static dependencies.
+ * @return The instance of the test case.
+ * @throws Exception when an error occurs.
+ */
+ @Override
+ protected Object createTest()
+ throws Exception
+ {
+ if ( LOGGER.isLoggable( Level.FINER ) )
+ {
+ LOGGER.finer( " Create and inject test class: " + getTestClass().getJavaClass() );
+ }
+ return this.injector.getInstance( getTestClass().getJavaClass() );
+ }
+
+ /**
+ * Shortcut to create the Injector given a list of Modules.
+ *
+ * @param modules the list of modules have to be load
+ * @return an Injector instance built using the input Module list
+ */
+ protected Injector createInjector( List<Module> modules )
+ {
+ return Guice.createInjector( modules );
+ }
+
+ /**
+ * This method collects modules from {@link GuiceModules}, {@link GuiceProvidedModules}, {@link Mock}
+ * and {@ OnamiSuite}.
+ *
+ * @param <T> whatever input type is accepted
+ * @param suite the input suite to be analyzed
+ * @param test the input class has to be analyzed
+ * @return a List of Guice Modules built after input class analysis.
+ * @throws IllegalAccessException when a n error occurs.
+ * @throws InstantiationException when a n error occurs.
+ * @throws HandleException when a n error occurs.
+ */
+ protected <T> List<Module> inizializeInjector( Class<?> suite, Class<T> test)
+ throws HandleException, InstantiationException, IllegalAccessException
+ {
+ final List<Module> modules = inizializeInjector(test);
+ Module m = visitClass( suite );
+ if ( m != null )
+ {
+ modules.add( m );
+ }
+ return modules;
+ }
+
+ /**
+ * This method collects modules from {@link GuiceModules}, {@link GuiceProvidedModules}, {@link Mock}.
+ *
+ * @param <T> whatever input type is accepted
+ * @param clazz the input class has to be analyzed
+ * @return a List of Guice Modules built after input class analysis.
+ * @throws IllegalAccessException when a n error occurs.
+ * @throws InstantiationException when a n error occurs.
+ * @throws HandleException when a n error occurs.
+ */
+ protected <T> List<Module> inizializeInjector( Class<T> clazz )
+ throws HandleException, InstantiationException, IllegalAccessException
+ {
+ final List<Module> modules = new ArrayList<Module>();
+ Module m = visitClass( clazz );
+ if ( m != null )
+ {
+ modules.add( m );
+ }
+ return modules;
+ }
+
+ private void resetAllResetAfterMocks()
+ {
+ for ( Entry<Field, Object> entry : mocked.entrySet() )
+ {
+ final Mock mockAnnotation = entry.getKey().getAnnotation( Mock.class );
+ if ( mockAnnotation.resetAfter() )
+ {
+ MockEngine mockEngine = MockEngineFactory.getMockEngine( mockFramework );
+ mockEngine.resetMock( entry.getValue() );
+ }
+ }
+ }
+
+ /**
+ * @throws HandleException
+ * @throws IllegalAccessException
+ * @throws InstantiationException
+ */
+ private <T> Module visitClass( final Class<T> clazz )
+ throws HandleException, InstantiationException, IllegalAccessException
+ {
+ try
+ {
+ if ( LOGGER.isLoggable( Level.FINER ) )
+ {
+ LOGGER.finer( " Start introspecting class: " + clazz.getName() );
+ }
+ final List<Module> allModules = new ArrayList<Module>();
+
+ // Setup the handlers
+ final GuiceProvidedModuleHandler guiceProvidedModuleHandler = new GuiceProvidedModuleHandler();
+ final GuiceModuleHandler guiceModuleHandler = new GuiceModuleHandler();
+ final GuiceInjectableClassHandler<Inject> guiceInjectableClassHandler = new GuiceInjectableClassHandler<com.google.inject.Inject>();
+ final GuiceInjectableClassHandler<javax.inject.Inject> jsr330InjectableClassHandler = new GuiceInjectableClassHandler<javax.inject.Inject>();
+
+ final MockHandler mockHandler = new MockHandler();
+ final MockFrameworkHandler mockFrameworkHandler = new MockFrameworkHandler();
+
+ // Visit class and super-classes
+ new ClassVisitor()
+ .registerHandler( GuiceProvidedModules.class, guiceProvidedModuleHandler )
+ .registerHandler( GuiceModules.class, guiceModuleHandler )
+ .registerHandler( Mock.class, mockHandler )
+ .registerHandler( MockFramework.class, mockFrameworkHandler )
+ .registerHandler( com.google.inject.Inject.class, guiceInjectableClassHandler )
+ .registerHandler( javax.inject.Inject.class, jsr330InjectableClassHandler )
+ .visit( clazz );
+
+ // Retrieve mock framework
+ if ( mockFrameworkHandler.getMockType() != null )
+ {
+ this.mockFramework = mockFrameworkHandler.getMockType();
+ }
+
+ // retrieve the modules founded
+ allModules.addAll( guiceProvidedModuleHandler.getModules() );
+ allModules.addAll( guiceModuleHandler.getModules() );
+ MockEngine engine = MockEngineFactory.getMockEngine( this.mockFramework );
+ this.mocked.putAll( mockHandler.getMockedObject( engine ) );
+ if ( !this.mocked.isEmpty() )
+ {
+ // Replace all real module binding with Mocked moduled.
+ Module m = Modules.override( allModules ).with( new GuiceMockModule( this.mocked ) );
+ allModules.clear();
+ allModules.add( m );
+ }
+
+ // Add only clasess that have got the Inject annotation
+ final Class<?>[] guiceInjectableClasses = guiceInjectableClassHandler.getClasses();
+ final Class<?>[] jsr330InjectableClasses = jsr330InjectableClassHandler.getClasses();
+
+ final AbstractModule statcInjector = new AbstractModule()
+ {
+ @Override
+ protected void configure()
+ {
+ // inject all STATIC dependencies
+ if ( guiceInjectableClasses.length != 0 )
+ {
+ requestStaticInjection( guiceInjectableClasses );
+ }
+
+ if ( jsr330InjectableClasses.length != 0 )
+ {
+ requestStaticInjection( jsr330InjectableClasses );
+ }
+
+
+ }
+ };
+ if ( guiceInjectableClasses.length != 0 || jsr330InjectableClasses.length != 0 )
+ {
+ allModules.add( statcInjector );
+ }
+
+ // Check if the class is itself a Google Module.
+ if ( Module.class.isAssignableFrom( getTestClass().getJavaClass() ) )
+ {
+ if ( LOGGER.isLoggable( Level.FINER ) )
+ {
+ LOGGER.finer( " creating module from test class " + getTestClass().getJavaClass() );
+ }
+ final Module classModule = (Module) getTestClass().getJavaClass().newInstance();
+ allModules.add( classModule );
+ }
+
+ // create MockTypeListenerModule
+ if ( this.mocked.size() != 0 )
+ {
+ final AbstractModule mockTypeListenerModule = new AbstractModule()
+ {
+ @Override
+ protected void configure()
+ {
+ bindListener( Matchers.any(), new MockTypeListener( mocked ) );
+ }
+ };
+
+ // BEGIN patch for issue: google-guice: #452
+ for ( Entry<Field, Object> entry : mocked.entrySet() )
+ {
+ final Field field = entry.getKey();
+ final Object mock = entry.getValue();
+ if ( Modifier.isStatic( field.getModifiers() ) )
+ {
+ if ( LOGGER.isLoggable( Level.FINER ) )
+ {
+ LOGGER.finer( " inject static mock field: " + field.getName() );
+ }
+
+ AccessController.doPrivileged( new PrivilegedAction<Void>()
+ {
+
+ public Void run()
+ {
+ field.setAccessible( true );
+ return null;
+ }
+
+ } );
+ field.set( field.getDeclaringClass(), mock );
+ }
+ }
+ // END patch for issue: google-guice: #452
+
+ allModules.add( mockTypeListenerModule );
+ }
+
+ if ( allModules.size() != 0 )
+ {
+ if ( LOGGER.isLoggable( Level.FINER ) )
+ {
+ StringBuilder builder = new StringBuilder();
+ builder.append( " Collected modules: " );
+ builder.append( "\n" );
+ for ( Module module : allModules )
+ {
+ builder.append( " " ).append( module );
+ builder.append( "\n" );
+ }
+ LOGGER.finer( builder.toString() );
+ }
+ return Modules.combine( allModules );
+ }
+ return null;
+ }
+ finally
+ {
+ if ( LOGGER.isLoggable( Level.FINER ) )
+ {
+ LOGGER.finer( " ...done" );
+ }
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/james-project/blob/a37176fb/mpt/onami-test/src/main/java/org/apache/james/mpt/onami/test/OnamiSuite.java
----------------------------------------------------------------------
diff --git a/mpt/onami-test/src/main/java/org/apache/james/mpt/onami/test/OnamiSuite.java b/mpt/onami-test/src/main/java/org/apache/james/mpt/onami/test/OnamiSuite.java
new file mode 100644
index 0000000..cb7835e
--- /dev/null
+++ b/mpt/onami-test/src/main/java/org/apache/james/mpt/onami/test/OnamiSuite.java
@@ -0,0 +1,464 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you 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.james.mpt.onami.test;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.apache.james.mpt.onami.test.annotation.GuiceModules;
+import org.apache.james.mpt.onami.test.annotation.GuiceProvidedModules;
+import org.apache.james.mpt.onami.test.annotation.Mock;
+import org.apache.james.mpt.onami.test.annotation.MockFramework;
+import org.apache.james.mpt.onami.test.annotation.MockType;
+import org.apache.james.mpt.onami.test.guice.MockTypeListener;
+import org.apache.james.mpt.onami.test.handler.GuiceInjectableClassHandler;
+import org.apache.james.mpt.onami.test.handler.GuiceModuleHandler;
+import org.apache.james.mpt.onami.test.handler.GuiceProvidedModuleHandler;
+import org.apache.james.mpt.onami.test.handler.MockFrameworkHandler;
+import org.apache.james.mpt.onami.test.handler.MockHandler;
+import org.apache.james.mpt.onami.test.mock.MockEngine;
+import org.apache.james.mpt.onami.test.reflection.ClassVisitor;
+import org.apache.james.mpt.onami.test.reflection.HandleException;
+import org.junit.runner.Runner;
+import org.junit.runner.notification.RunNotifier;
+import org.junit.runners.Suite;
+import org.junit.runners.model.InitializationError;
+import org.junit.runners.model.RunnerBuilder;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Guice;
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+import com.google.inject.Module;
+import com.google.inject.matcher.Matchers;
+import com.google.inject.util.Modules;
+
+/**
+ * <p>
+ * It's a {@link Suite} runner.
+ * </p>
+ * <p>
+ * This class creates a Google Guice {@link Injector} configured by {@link GuiceModules} annotation (only fr modules
+ * with default constructor) and {@link GuiceProvidedModules} annotation and {@link Mock}.
+ * </p>
+ * <p>
+ * <b>Example #1:</b> <br>
+ *
+ * <pre>
+ *
+ * @org.junit.runner.RunWith( OnamiSuite.class )
+ * @GuiceModules( SimpleModule.class )
+ * @SuiteClasses({ .class })
+ * public class AcmeTestCase
+ * {
+ *
+ * @GuiceProvidedModules
+ * static public Module getProperties()
+ * {
+ * ...
+ * return Modules.combine(new ComplexModule( loadProperies() ), ... );
+ * }
+ *
+ * </pre>
+ *
+ * </p>
+ * <p>
+ * <b>Example #2:</b> <br>
+ *
+ * <pre>
+ *
+ * @org.junit.runner.RunWith( OnamiSuite.class )
+ * public class AcmeTestCase
+ * extends com.google.inject.AbstractModule
+ * {
+ *
+ * public void configure()
+ * {
+ * // Configure your proper modules
+ * ...
+ * bind( Service.class ).annotatedWith( TestAnnotation.class ).to( ServiceTestImpl.class );
+ * ...
+ * }
+ *
+ * @Mock
+ * private AnotherService serviceMock;
+ *
+ * @Inject
+ * private Service serviceTest;
+ *
+ * @org.junit.Test
+ * public void test()
+ * {
+ * assertNotNull( serviceMock );
+ * assertNotNull( serviceTest );
+ * }
+ * </pre>
+ *
+ * </p>
+ *
+ * @see GuiceMockModule
+ */
+public class OnamiSuite
+ extends Suite
+{
+
+ private static final Logger LOGGER = Logger.getLogger( OnamiSuite.class.getName() );
+
+ private Injector injector;
+
+ private final List<Module> allModules;
+
+ private final Map<Field, Object> mocked = new HashMap<Field, Object>( 1 );
+
+ private MockType mockFramework = MockType.EASY_MOCK;
+
+ private static Class<?>[] getAnnotatedClasses(Class<?> klass) throws InitializationError {
+ SuiteClasses annotation= klass.getAnnotation(SuiteClasses.class);
+ if (annotation == null)
+ throw new InitializationError(String.format("class '%s' must have a SuiteClasses annotation", klass.getName()));
+ return annotation.value();
+ }
+
+ /**
+ * OnamiRunner constructor to create the core JUnice class.
+ *
+ * @see org.junit.runner.RunWith
+ * @param klass The test case class to run.
+ * @throws org.junit.runners.model.InitializationError if any error occurs.
+ */
+ public OnamiSuite( Class<?> klass, RunnerBuilder builder )
+ throws InitializationError
+ {
+ this(builder, klass, getAnnotatedClasses(klass));
+
+ }
+
+ /**
+ * Called by this class and subclasses once the classes making up the suite have been determined
+ *
+ * @param builder builds runners for classes in the suite
+ * @param klass the root of the suite
+ * @param suiteClasses the classes in the suite
+ * @throws InitializationError
+ */
+ protected OnamiSuite( RunnerBuilder builder, Class<?> suite, Class<?>[] suiteClasses )
+ throws InitializationError
+ {
+ super( suite, runners( suite, suiteClasses ) );
+ try
+ {
+ if ( LOGGER.isLoggable( Level.FINER ) )
+ {
+ LOGGER.finer( "Inizializing injector for siote class: " + suite.getName() );
+ }
+
+ this.allModules = inizializeInjector( suite );
+
+ if ( LOGGER.isLoggable( Level.FINER ) )
+ {
+ LOGGER.finer( "done..." );
+ }
+ }
+ catch ( Exception e )
+ {
+ final List<Throwable> throwables = new LinkedList<Throwable>();
+ throwables.add( e );
+ throw new InitializationError( throwables );
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void run( final RunNotifier notifier )
+ {
+ if ( LOGGER.isLoggable( Level.FINER ) )
+ {
+ LOGGER.finer( " ### Run test case: " + getTestClass().getJavaClass() + " ### " );
+ LOGGER.finer( " #### Creating injector ####" );
+ }
+
+ this.injector = createInjector( allModules );
+ super.run( notifier );
+ this.flush();
+
+ if ( LOGGER.isLoggable( Level.FINER ) )
+ {
+ LOGGER.finer( " ### End test case: " + getTestClass().getJavaClass().getName() + " ### " );
+ }
+ }
+
+ private static List<Runner> runners( Class<?> suite, Class<?>[] children ) throws InitializationError {
+ ArrayList<Runner> runners= new ArrayList<Runner>();
+ for (Class<?> each : children) {
+ Runner childRunner= new OnamiRunner( suite, each );
+ if (childRunner != null)
+ runners.add(childRunner);
+ }
+ return runners;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ private void flush()
+ {
+ this.injector = null;
+ this.allModules.clear();
+ this.mocked.clear();
+ }
+
+ @Override
+ protected void runChild( Runner runner, RunNotifier notifier )
+ {
+ if ( LOGGER.isLoggable( Level.FINER ) )
+ {
+ LOGGER.finer( " +++ invoke runner: " + runner + " +++ " );
+ }
+
+ super.runChild( runner, notifier );
+ resetAllResetAfterMocks();
+
+ if ( LOGGER.isLoggable( Level.FINER ) )
+ {
+ LOGGER.finer( " --- end runner: " + runner + " --- " );
+ }
+ }
+
+ /**
+ * Shortcut to create the Injector given a list of Modules.
+ *
+ * @param modules the list of modules have to be load
+ * @return an Injector instance built using the input Module list
+ */
+ protected Injector createInjector( List<Module> modules )
+ {
+ return Guice.createInjector( modules );
+ }
+
+ /**
+ * This method collects modules from {@link GuiceModules}, {@link GuiceProvidedModules}, {@link Mock}.
+ *
+ * @param <T> whatever input type is accepted
+ * @param clazz the input class has to be analyzed
+ * @return a List of Guice Modules built after input class analysis.
+ * @throws IllegalAccessException when a n error occurs.
+ * @throws InstantiationException when a n error occurs.
+ * @throws HandleException when a n error occurs.
+ */
+ protected <T> List<Module> inizializeInjector( Class<T> clazz )
+ throws HandleException, InstantiationException, IllegalAccessException
+ {
+ final List<Module> modules = new ArrayList<Module>();
+ Module m = visitClass( clazz );
+ if ( m != null )
+ {
+ modules.add( m );
+ }
+ return modules;
+ }
+
+ private void resetAllResetAfterMocks()
+ {
+ for ( Entry<Field, Object> entry : mocked.entrySet() )
+ {
+ final Mock mockAnnotation = entry.getKey().getAnnotation( Mock.class );
+ if ( mockAnnotation.resetAfter() )
+ {
+ MockEngine mockEngine = MockEngineFactory.getMockEngine( mockFramework );
+ mockEngine.resetMock( entry.getValue() );
+ }
+ }
+ }
+
+ /**
+ * @throws HandleException
+ * @throws IllegalAccessException
+ * @throws InstantiationException
+ */
+ private <T> Module visitClass( final Class<T> clazz )
+ throws HandleException, InstantiationException, IllegalAccessException
+ {
+ try
+ {
+ if ( LOGGER.isLoggable( Level.FINER ) )
+ {
+ LOGGER.finer( " Start introspecting class: " + clazz.getName() );
+ }
+ final List<Module> allModules = new ArrayList<Module>();
+
+ // Setup the handlers
+ final GuiceProvidedModuleHandler guiceProvidedModuleHandler = new GuiceProvidedModuleHandler();
+ final GuiceModuleHandler guiceModuleHandler = new GuiceModuleHandler();
+ final GuiceInjectableClassHandler<Inject> guiceInjectableClassHandler = new GuiceInjectableClassHandler<Inject>();
+ final GuiceInjectableClassHandler<javax.inject.Inject> jsr330InjectableClassHandler = new GuiceInjectableClassHandler<javax.inject.Inject>();
+
+ final MockHandler mockHandler = new MockHandler();
+ final MockFrameworkHandler mockFrameworkHandler = new MockFrameworkHandler();
+
+ // Visit class and super-classes
+ new ClassVisitor()
+ .registerHandler( GuiceProvidedModules.class, guiceProvidedModuleHandler )
+ .registerHandler( GuiceModules.class, guiceModuleHandler )
+ .registerHandler( Mock.class, mockHandler )
+ .registerHandler( MockFramework.class, mockFrameworkHandler )
+ .registerHandler( Inject.class, guiceInjectableClassHandler )
+ .registerHandler( javax.inject.Inject.class, jsr330InjectableClassHandler )
+ .visit( clazz );
+
+ // Retrieve mock framework
+ if ( mockFrameworkHandler.getMockType() != null )
+ {
+ this.mockFramework = mockFrameworkHandler.getMockType();
+ }
+
+ // retrieve the modules founded
+ allModules.addAll( guiceProvidedModuleHandler.getModules() );
+ allModules.addAll( guiceModuleHandler.getModules() );
+ MockEngine engine = MockEngineFactory.getMockEngine( this.mockFramework );
+ this.mocked.putAll( mockHandler.getMockedObject( engine ) );
+ if ( !this.mocked.isEmpty() )
+ {
+ // Replace all real module binding with Mocked moduled.
+ Module m = Modules.override( allModules ).with( new GuiceMockModule( this.mocked ) );
+ allModules.clear();
+ allModules.add( m );
+ }
+
+ // Add only clasess that have got the Inject annotation
+ final Class<?>[] guiceInjectableClasses = guiceInjectableClassHandler.getClasses();
+ final Class<?>[] jsr330InjectableClasses = jsr330InjectableClassHandler.getClasses();
+
+ final AbstractModule statcInjector = new AbstractModule()
+ {
+ @Override
+ protected void configure()
+ {
+ // inject all STATIC dependencies
+ if ( guiceInjectableClasses.length != 0 )
+ {
+ requestStaticInjection( guiceInjectableClasses );
+ }
+
+ if ( jsr330InjectableClasses.length != 0 )
+ {
+ requestStaticInjection( jsr330InjectableClasses );
+ }
+
+
+ }
+ };
+ if ( guiceInjectableClasses.length != 0 || jsr330InjectableClasses.length != 0 )
+ {
+ allModules.add( statcInjector );
+ }
+
+ // Check if the class is itself a Google Module.
+ if ( Module.class.isAssignableFrom( getTestClass().getJavaClass() ) )
+ {
+ if ( LOGGER.isLoggable( Level.FINER ) )
+ {
+ LOGGER.finer( " creating module from test class " + getTestClass().getJavaClass() );
+ }
+ final Module classModule = (Module) getTestClass().getJavaClass().newInstance();
+ allModules.add( classModule );
+ }
+
+ // create MockTypeListenerModule
+ if ( this.mocked.size() != 0 )
+ {
+ final AbstractModule mockTypeListenerModule = new AbstractModule()
+ {
+ @Override
+ protected void configure()
+ {
+ bindListener( Matchers.any(), new MockTypeListener( mocked ) );
+ }
+ };
+
+ // BEGIN patch for issue: google-guice: #452
+ for ( Entry<Field, Object> entry : mocked.entrySet() )
+ {
+ final Field field = entry.getKey();
+ final Object mock = entry.getValue();
+ if ( Modifier.isStatic( field.getModifiers() ) )
+ {
+ if ( LOGGER.isLoggable( Level.FINER ) )
+ {
+ LOGGER.finer( " inject static mock field: " + field.getName() );
+ }
+
+ AccessController.doPrivileged( new PrivilegedAction<Void>()
+ {
+
+ public Void run()
+ {
+ field.setAccessible( true );
+ return null;
+ }
+
+ } );
+ field.set( field.getDeclaringClass(), mock );
+ }
+ }
+ // END patch for issue: google-guice: #452
+
+ allModules.add( mockTypeListenerModule );
+ }
+
+ if ( allModules.size() != 0 )
+ {
+ if ( LOGGER.isLoggable( Level.FINER ) )
+ {
+ StringBuilder builder = new StringBuilder();
+ builder.append( " Collected modules: " );
+ builder.append( "\n" );
+ for ( Module module : allModules )
+ {
+ builder.append( " " ).append( module );
+ builder.append( "\n" );
+ }
+ LOGGER.finer( builder.toString() );
+ }
+ return Modules.combine( allModules );
+ }
+ return null;
+ }
+ finally
+ {
+ if ( LOGGER.isLoggable( Level.FINER ) )
+ {
+ LOGGER.finer( " ...done" );
+ }
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/james-project/blob/a37176fb/mpt/onami-test/src/main/java/org/apache/james/mpt/onami/test/annotation/GuiceModules.java
----------------------------------------------------------------------
diff --git a/mpt/onami-test/src/main/java/org/apache/james/mpt/onami/test/annotation/GuiceModules.java b/mpt/onami-test/src/main/java/org/apache/james/mpt/onami/test/annotation/GuiceModules.java
new file mode 100644
index 0000000..fe98e07
--- /dev/null
+++ b/mpt/onami-test/src/main/java/org/apache/james/mpt/onami/test/annotation/GuiceModules.java
@@ -0,0 +1,42 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you 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.james.mpt.onami.test.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import com.google.inject.Module;
+
+/**
+ * Annotate your class to define a list of Google Guice {@link Module} whit default constructor.
+ */
+@Retention( RetentionPolicy.RUNTIME )
+@Target( ElementType.TYPE )
+public @interface GuiceModules
+{
+
+ /**
+ * List of Google Guice {@link Module}.
+ */
+ Class<? extends Module>[] value();
+
+}
http://git-wip-us.apache.org/repos/asf/james-project/blob/a37176fb/mpt/onami-test/src/main/java/org/apache/james/mpt/onami/test/annotation/GuiceProvidedModules.java
----------------------------------------------------------------------
diff --git a/mpt/onami-test/src/main/java/org/apache/james/mpt/onami/test/annotation/GuiceProvidedModules.java b/mpt/onami-test/src/main/java/org/apache/james/mpt/onami/test/annotation/GuiceProvidedModules.java
new file mode 100644
index 0000000..bd36d22
--- /dev/null
+++ b/mpt/onami-test/src/main/java/org/apache/james/mpt/onami/test/annotation/GuiceProvidedModules.java
@@ -0,0 +1,44 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you 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.james.mpt.onami.test.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * <p>
+ * Annotate a <b>public static</b> method to create a Google Guice {@link com.google.inject.Module} provider.
+ * </p>
+ * <p>
+ * The method return type must be one of:
+ * <ul>
+ * <li>com.google.inject.Module</li>
+ * <li>Iterable<com.google.inject.Module></li>
+ * <li>com.google.inject.Module[]</li>
+ * </p>
+ */
+@Retention( RetentionPolicy.RUNTIME )
+@Target( ElementType.METHOD )
+public @interface GuiceProvidedModules
+{
+
+}
http://git-wip-us.apache.org/repos/asf/james-project/blob/a37176fb/mpt/onami-test/src/main/java/org/apache/james/mpt/onami/test/annotation/Mock.java
----------------------------------------------------------------------
diff --git a/mpt/onami-test/src/main/java/org/apache/james/mpt/onami/test/annotation/Mock.java b/mpt/onami-test/src/main/java/org/apache/james/mpt/onami/test/annotation/Mock.java
new file mode 100644
index 0000000..5695e51
--- /dev/null
+++ b/mpt/onami-test/src/main/java/org/apache/james/mpt/onami/test/annotation/Mock.java
@@ -0,0 +1,77 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you 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.james.mpt.onami.test.annotation;
+
+import java.lang.annotation.Annotation;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Annotate your filed into which {@link org.apache.onami.test.GuiceMockModule} will create and inject the mock object.
+ */
+@Retention( RetentionPolicy.RUNTIME )
+@Target( ElementType.FIELD )
+@Inherited
+public @interface Mock
+{
+
+ /**
+ * Annotation class used to mark that no annotation binding is defined.
+ */
+ public static @interface NoAnnotation
+ {
+ }
+
+ /**
+ * Indicates if this mock object has to be resetted after each test method Default: true
+ */
+ boolean resetAfter() default true;
+
+ /**
+ * The name of the method that provides to mock creation.
+ */
+ String providedBy() default "";
+
+ /**
+ * The {@link Class} that contains the method {@link Mock#providedBy()}. By default: the filed declaring class.
+ */
+ Class<?> providerClass() default Object.class;
+
+ /**
+ * Specifies an annotation {@link Class} that will be used in the <em>Google Guice</em> binder to execute the literal
+ * annotating binding.
+ */
+ Class<? extends Annotation> annotatedWith() default NoAnnotation.class;
+
+ /**
+ * Specifies an {@link String} annotation that will be used in the <em>Google Guice</em> binder to execute the
+ * literal annotating binding via {@link com.google.inject.name.Named} class.
+ */
+ String namedWith() default "";
+
+ /**
+ * Specifies TODO
+ */
+ MockObjType type() default MockObjType.DEFAULT;
+
+}
http://git-wip-us.apache.org/repos/asf/james-project/blob/a37176fb/mpt/onami-test/src/main/java/org/apache/james/mpt/onami/test/annotation/MockFramework.java
----------------------------------------------------------------------
diff --git a/mpt/onami-test/src/main/java/org/apache/james/mpt/onami/test/annotation/MockFramework.java b/mpt/onami-test/src/main/java/org/apache/james/mpt/onami/test/annotation/MockFramework.java
new file mode 100644
index 0000000..d695453
--- /dev/null
+++ b/mpt/onami-test/src/main/java/org/apache/james/mpt/onami/test/annotation/MockFramework.java
@@ -0,0 +1,40 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you 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.james.mpt.onami.test.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Annotate test class to specify you favorite mock framework.
+ */
+@Retention( RetentionPolicy.RUNTIME )
+@Target( ElementType.TYPE )
+public @interface MockFramework
+{
+
+ /**
+ * Type of mock that JUnice has to create.
+ */
+ MockType value();
+
+}
http://git-wip-us.apache.org/repos/asf/james-project/blob/a37176fb/mpt/onami-test/src/main/java/org/apache/james/mpt/onami/test/annotation/MockObjType.java
----------------------------------------------------------------------
diff --git a/mpt/onami-test/src/main/java/org/apache/james/mpt/onami/test/annotation/MockObjType.java b/mpt/onami-test/src/main/java/org/apache/james/mpt/onami/test/annotation/MockObjType.java
new file mode 100644
index 0000000..e3e4eac
--- /dev/null
+++ b/mpt/onami-test/src/main/java/org/apache/james/mpt/onami/test/annotation/MockObjType.java
@@ -0,0 +1,48 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you 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.james.mpt.onami.test.annotation;
+
+/**
+ * Enumeration class to specifies the preferred mock object.
+ */
+public enum MockObjType
+{
+
+ /**
+ * @see EasyMock.createMock
+ */
+ EASY_MOCK_NORMAL,
+
+ /**
+ * @see EasyMock.createStrictMock
+ */
+ EASY_MOCK_STRICT,
+
+ /**
+ * @see EasyMock.createNiceMock
+ */
+ EASY_MOCK_NICE,
+
+ /**
+ * Use default mock creation mode
+ */
+ DEFAULT
+
+}
http://git-wip-us.apache.org/repos/asf/james-project/blob/a37176fb/mpt/onami-test/src/main/java/org/apache/james/mpt/onami/test/annotation/MockType.java
----------------------------------------------------------------------
diff --git a/mpt/onami-test/src/main/java/org/apache/james/mpt/onami/test/annotation/MockType.java b/mpt/onami-test/src/main/java/org/apache/james/mpt/onami/test/annotation/MockType.java
new file mode 100644
index 0000000..57f2810
--- /dev/null
+++ b/mpt/onami-test/src/main/java/org/apache/james/mpt/onami/test/annotation/MockType.java
@@ -0,0 +1,39 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you 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.james.mpt.onami.test.annotation;
+
+/**
+ * Enumeration class to specifies your preferred mock framework.
+ *
+ * @see MockFramework
+ */
+public enum MockType
+{
+ /**
+ * Identify the Easy Mock framework
+ */
+ EASY_MOCK,
+
+ /**
+ * Identify the Mockito framework
+ */
+ MOCKITO
+
+}
http://git-wip-us.apache.org/repos/asf/james-project/blob/a37176fb/mpt/onami-test/src/main/java/org/apache/james/mpt/onami/test/guice/MockMembersInjector.java
----------------------------------------------------------------------
diff --git a/mpt/onami-test/src/main/java/org/apache/james/mpt/onami/test/guice/MockMembersInjector.java b/mpt/onami-test/src/main/java/org/apache/james/mpt/onami/test/guice/MockMembersInjector.java
new file mode 100644
index 0000000..d8f05ce
--- /dev/null
+++ b/mpt/onami-test/src/main/java/org/apache/james/mpt/onami/test/guice/MockMembersInjector.java
@@ -0,0 +1,79 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you 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.james.mpt.onami.test.guice;
+
+import java.lang.reflect.Field;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.Map;
+
+import com.google.inject.MembersInjector;
+
+/**
+ * Class to inject via google-guice mock members into test cases classes.
+ *
+ * @param <T> type to inject members of
+ */
+public class MockMembersInjector<T>
+ implements MembersInjector<T>
+{
+
+ private final Field field;
+
+ private final Map<Field, Object> mockedObjects;
+
+ /**
+ * Create a new instance.
+ *
+ * @param field the field that has to be injected.
+ * @param mockedObjects the map of mocked object.
+ */
+ public MockMembersInjector( final Field field, Map<Field, Object> mockedObjects )
+ {
+ this.field = field;
+ this.mockedObjects = mockedObjects;
+ AccessController.doPrivileged( new PrivilegedAction<Void>()
+ {
+
+ public Void run()
+ {
+ field.setAccessible( true );
+ return null;
+ }
+
+ } );
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void injectMembers( T t )
+ {
+ try
+ {
+ field.set( t, mockedObjects.get( field ) );
+ }
+ catch ( IllegalAccessException e )
+ {
+ throw new RuntimeException( e );
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/james-project/blob/a37176fb/mpt/onami-test/src/main/java/org/apache/james/mpt/onami/test/guice/MockTypeListener.java
----------------------------------------------------------------------
diff --git a/mpt/onami-test/src/main/java/org/apache/james/mpt/onami/test/guice/MockTypeListener.java b/mpt/onami-test/src/main/java/org/apache/james/mpt/onami/test/guice/MockTypeListener.java
new file mode 100644
index 0000000..427fab8
--- /dev/null
+++ b/mpt/onami-test/src/main/java/org/apache/james/mpt/onami/test/guice/MockTypeListener.java
@@ -0,0 +1,87 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you 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.james.mpt.onami.test.guice;
+
+import java.lang.reflect.Field;
+import java.util.Map;
+
+import org.apache.james.mpt.onami.test.annotation.Mock;
+import org.apache.james.mpt.onami.test.reflection.AnnotationHandler;
+import org.apache.james.mpt.onami.test.reflection.ClassVisitor;
+import org.apache.james.mpt.onami.test.reflection.HandleException;
+
+import com.google.inject.TypeLiteral;
+import com.google.inject.spi.TypeEncounter;
+import com.google.inject.spi.TypeListener;
+
+/**
+ * <p>
+ * {@link TypeListener} implementation.
+ * </p>
+ * <p>
+ * Creates a specific {@link MockMembersInjector} for each {@link Mock} annotation found.
+ * </p>
+ *
+ * @see MockMembersInjector
+ * @see Mock
+ */
+public class MockTypeListener
+ implements TypeListener
+{
+
+ private final Map<Field, Object> mockedObjects;
+
+ /**
+ * Creates a new {@code MockTypeListener} instance given a map of mocked objects.
+ *
+ * @param mockedObjects a map of mocked objects
+ */
+ public MockTypeListener( Map<Field, Object> mockedObjects )
+ {
+ this.mockedObjects = mockedObjects;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public <I> void hear( final TypeLiteral<I> typeLiteral, final TypeEncounter<I> typeEncounter )
+ {
+ try
+ {
+ new ClassVisitor()
+ .registerHandler( Mock.class, new AnnotationHandler<Mock, Field>()
+ {
+
+ public void handle( Mock annotation, Field field )
+ throws HandleException
+ {
+ typeEncounter.register( new MockMembersInjector<I>( field, mockedObjects ) );
+ }
+
+ } )
+ .visit( typeLiteral.getRawType() );
+ }
+ catch ( HandleException e )
+ {
+ typeEncounter.addError( e );
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/james-project/blob/a37176fb/mpt/onami-test/src/main/java/org/apache/james/mpt/onami/test/handler/GuiceInjectableClassHandler.java
----------------------------------------------------------------------
diff --git a/mpt/onami-test/src/main/java/org/apache/james/mpt/onami/test/handler/GuiceInjectableClassHandler.java b/mpt/onami-test/src/main/java/org/apache/james/mpt/onami/test/handler/GuiceInjectableClassHandler.java
new file mode 100644
index 0000000..936e4ed
--- /dev/null
+++ b/mpt/onami-test/src/main/java/org/apache/james/mpt/onami/test/handler/GuiceInjectableClassHandler.java
@@ -0,0 +1,84 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you 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.james.mpt.onami.test.handler;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Member;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.apache.james.mpt.onami.test.reflection.AnnotationHandler;
+import org.apache.james.mpt.onami.test.reflection.HandleException;
+
+/**
+ * Handler class to handle all {@link com.google.inject.Inject} and {@link javax.inject.Inject} annotations.
+ *
+ * @param <A> whatever annotation type
+ * @see org.apache.onami.test.reflection.ClassVisitor
+ */
+public final class GuiceInjectableClassHandler<A extends Annotation>
+ implements AnnotationHandler<A, AccessibleObject>
+{
+
+ private static final Logger LOGGER = Logger.getLogger( GuiceInjectableClassHandler.class.getName() );
+
+ /**
+ * Contains the guice injectable classes founded, after inspection.
+ */
+ protected final Set<Class<?>> classes = new HashSet<Class<?>>();
+
+ /**
+ * Return all {@link Class} that contains at last one {@link com.google.inject.Inject} or
+ * {@link javax.inject.Inject} annotation.
+ *
+ * @return {@link Class} array.
+ */
+ public Class<?>[] getClasses()
+ {
+ return classes.toArray( new Class<?>[classes.size()] );
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void handle( A annotation, AccessibleObject element )
+ throws HandleException
+ {
+ Class<?> type = null;
+
+ if ( element instanceof Member )
+ {
+ type = ( (Member) element ).getDeclaringClass();
+ }
+
+ if ( type != null && !classes.contains( type ) )
+ {
+ if ( LOGGER.isLoggable( Level.FINER ) )
+ {
+ LOGGER.finer( " Found injectable type: " + type );
+ }
+ classes.add( type );
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/james-project/blob/a37176fb/mpt/onami-test/src/main/java/org/apache/james/mpt/onami/test/handler/GuiceModuleHandler.java
----------------------------------------------------------------------
diff --git a/mpt/onami-test/src/main/java/org/apache/james/mpt/onami/test/handler/GuiceModuleHandler.java b/mpt/onami-test/src/main/java/org/apache/james/mpt/onami/test/handler/GuiceModuleHandler.java
new file mode 100644
index 0000000..718604d
--- /dev/null
+++ b/mpt/onami-test/src/main/java/org/apache/james/mpt/onami/test/handler/GuiceModuleHandler.java
@@ -0,0 +1,77 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you 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.james.mpt.onami.test.handler;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.apache.james.mpt.onami.test.annotation.GuiceModules;
+import org.apache.james.mpt.onami.test.reflection.ClassHandler;
+import org.apache.james.mpt.onami.test.reflection.HandleException;
+
+import com.google.inject.Module;
+
+/**
+ * Handler class to handle all {@link GuiceModules} annotations.
+ *
+ * @see org.apache.onami.test.reflection.ClassVisitor
+ */
+public final class GuiceModuleHandler
+ implements ClassHandler<GuiceModules>
+{
+
+ private static final Logger LOGGER = Logger.getLogger( GuiceModuleHandler.class.getName() );
+
+ private final List<Module> modules = new ArrayList<Module>();
+
+ /**
+ * @return the modules
+ */
+ public List<Module> getModules()
+ {
+ return modules;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void handle( GuiceModules annotation, Class<?> element )
+ throws HandleException
+ {
+ for ( Class<? extends Module> module : annotation.value() )
+ {
+ if ( LOGGER.isLoggable( Level.FINER ) )
+ {
+ LOGGER.finer( " Try to create module: " + module );
+ }
+ try
+ {
+ modules.add( module.newInstance() );
+ }
+ catch ( Exception e )
+ {
+ throw new HandleException( e );
+ }
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/james-project/blob/a37176fb/mpt/onami-test/src/main/java/org/apache/james/mpt/onami/test/handler/GuiceProvidedModuleHandler.java
----------------------------------------------------------------------
diff --git a/mpt/onami-test/src/main/java/org/apache/james/mpt/onami/test/handler/GuiceProvidedModuleHandler.java b/mpt/onami-test/src/main/java/org/apache/james/mpt/onami/test/handler/GuiceProvidedModuleHandler.java
new file mode 100644
index 0000000..9c7b365
--- /dev/null
+++ b/mpt/onami-test/src/main/java/org/apache/james/mpt/onami/test/handler/GuiceProvidedModuleHandler.java
@@ -0,0 +1,137 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you 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.james.mpt.onami.test.handler;
+
+import static java.lang.String.format;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.apache.james.mpt.onami.test.annotation.GuiceProvidedModules;
+import org.apache.james.mpt.onami.test.reflection.HandleException;
+import org.apache.james.mpt.onami.test.reflection.MethodHandler;
+
+import com.google.inject.Module;
+import com.google.inject.TypeLiteral;
+
+/**
+ * Handler class to handle all {@link GuiceProvidedModules} annotations.
+ *
+ * @see org.apache.onami.test.reflection.ClassVisitor
+ * @see GuiceProvidedModules
+ */
+public final class GuiceProvidedModuleHandler
+ implements MethodHandler<GuiceProvidedModules>
+{
+
+ private static final Logger LOGGER = Logger.getLogger( GuiceProvidedModuleHandler.class.getName() );
+
+ private final List<Module> modules = new ArrayList<Module>();
+
+ /**
+ * @return the guiceProviderModuleRegistry
+ */
+ public List<Module> getModules()
+ {
+ return modules;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @SuppressWarnings( "unchecked" )
+ public void handle( GuiceProvidedModules annotation, Method method )
+ throws HandleException
+ {
+ final Class<?> returnType = method.getReturnType();
+
+ if ( LOGGER.isLoggable( Level.FINER ) )
+ {
+ LOGGER.finer( format( " Found %s annotated method, checking if return type '%s' is one of ( %s | Iterable<%s> | %s[] )",
+ GuiceProvidedModules.class.getSimpleName(),
+ returnType.getName(),
+ Module.class.getName(),
+ Module.class.getName(),
+ Module.class.getName() ) );
+ }
+
+ if ( !Modifier.isPublic( method.getModifiers() ) || !Modifier.isStatic( method.getModifiers() ) )
+ {
+ throw new HandleException( "Impossible to invoke method: " + method + ", it has to be static and public" );
+ }
+
+ final Class<?> type = method.getDeclaringClass();
+
+ try
+ {
+ if ( Module.class.isAssignableFrom( returnType ) )
+ {
+ modules.add( (Module) method.invoke( type ) );
+ }
+ else if ( new TypeLiteral<Iterable<Module>>()
+ {
+ }.getRawType().isAssignableFrom( returnType ) )
+ {
+ addModules( (Iterable<Module>) method.invoke( type ) );
+ }
+ else if ( new TypeLiteral<Module[]>()
+ {
+ }.getRawType().isAssignableFrom( returnType ) )
+ {
+ addModules( (Module[]) method.invoke( type ) );
+ }
+ else
+ {
+ throw new ClassCastException( format( " Incompatible return type: %s.\nThe return type must be one of ( %s | Iterable<%s> | %s[] )",
+ returnType.getName(),
+ Module.class.getName(),
+ Module.class.getName(),
+ Module.class.getName() ) );
+ }
+
+ if ( LOGGER.isLoggable( Level.FINER ) )
+ {
+ LOGGER.finer( " Invoked method: " + method.toGenericString() );
+ }
+ }
+ catch ( Exception e )
+ {
+ throw new HandleException( e );
+ }
+ }
+
+ private void addModules( Iterable<Module> modules )
+ {
+ for ( Module module : modules )
+ {
+ this.modules.add( module );
+ }
+ }
+
+ private void addModules( Module... modules )
+ {
+ Collections.addAll( this.modules, modules );
+ }
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org