You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by da...@apache.org on 2014/10/28 13:23:11 UTC

[1/2] git commit: ISIS-931: isInjectorMethodFor re-impl; ClassDiscoveryService refinement

Repository: isis
Updated Branches:
  refs/heads/master 703a7059c -> 355c1d079


ISIS-931: isInjectorMethodFor re-impl; ClassDiscoveryService refinement


Project: http://git-wip-us.apache.org/repos/asf/isis/repo
Commit: http://git-wip-us.apache.org/repos/asf/isis/commit/29c69d97
Tree: http://git-wip-us.apache.org/repos/asf/isis/tree/29c69d97
Diff: http://git-wip-us.apache.org/repos/asf/isis/diff/29c69d97

Branch: refs/heads/master
Commit: 29c69d97bc736bcb440ec417aa0de6595f250065
Parents: 703a705
Author: Dan Haywood <da...@haywood-associates.co.uk>
Authored: Wed Oct 15 00:36:32 2014 +0100
Committer: Dan Haywood <da...@haywood-associates.co.uk>
Committed: Tue Oct 28 09:18:27 2014 +0000

----------------------------------------------------------------------
 .../applib/fixturescripts/FixtureScripts.java   | 13 +++-
 .../classdiscovery/ClassDiscoveryService2.java  | 39 ++++++++++
 .../ClassDiscoveryServiceUsingReflections.java  | 16 +++-
 .../RemoveInjectMethodsFacetFactory.java        |  7 +-
 .../runtimecontext/RuntimeContextAbstract.java  |  8 +-
 .../runtimecontext/ServicesInjector.java        |  4 +-
 .../noruntime/RuntimeContextNoRuntime.java      | 16 +---
 .../services/ServicesInjectorDefault.java       | 77 +++++++++++---------
 .../metamodel/spec/SpecificationLoader.java     |  4 +
 .../spec/SpecificationLoaderAbstract.java       | 36 +++++++++
 .../metamodel/spec/SpecificationLoaderSpi.java  |  3 -
 .../specloader/ObjectReflectorDefault.java      |  7 +-
 .../metamodel/facets/ProgrammableReflector.java |  5 +-
 .../PersistenceSessionFactoryDelegating.java    |  2 +
 .../internal/RuntimeContextFromSession.java     |  2 +-
 .../system/IsisSystemFixturesHookAbstract.java  | 10 +--
 .../apache/isis/core/webserver/WebServer.java   | 25 +++++--
 .../handlers/DomainObjectInvocationHandler.java |  6 +-
 .../dom/src/main/java/dom/todo/ToDoItem.java    |  2 +-
 19 files changed, 199 insertions(+), 83 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis/blob/29c69d97/core/applib/src/main/java/org/apache/isis/applib/fixturescripts/FixtureScripts.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/fixturescripts/FixtureScripts.java b/core/applib/src/main/java/org/apache/isis/applib/fixturescripts/FixtureScripts.java
index 52bbb2e..b31d723 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/fixturescripts/FixtureScripts.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/fixturescripts/FixtureScripts.java
@@ -32,6 +32,7 @@ import org.apache.isis.applib.ViewModel;
 import org.apache.isis.applib.annotation.*;
 import org.apache.isis.applib.services.bookmark.BookmarkService;
 import org.apache.isis.applib.services.classdiscovery.ClassDiscoveryService;
+import org.apache.isis.applib.services.classdiscovery.ClassDiscoveryService2;
 import org.apache.isis.applib.services.memento.MementoService;
 import org.apache.isis.applib.services.memento.MementoService.Memento;
 import org.apache.isis.applib.util.ObjectContracts;
@@ -192,7 +193,8 @@ public abstract class FixtureScripts extends AbstractService {
     }
 
     private void findAndInstantiateFixtureScripts(List<FixtureScript> fixtureScriptList) {
-        final Set<Class<? extends FixtureScript>> classes = classDiscoveryService.findSubTypesOfClasses(FixtureScript.class);
+        final Set<Class<? extends FixtureScript>> classes =
+                findSubTypesOfClasses();
         for (final Class<? extends FixtureScript> fixtureScriptCls : classes) {
             final String packageName = fixtureScriptCls.getPackage().getName();
             if(!packageName.startsWith(packagePrefix)) {
@@ -211,6 +213,15 @@ public abstract class FixtureScripts extends AbstractService {
         }); 
     }
 
+    private Set<Class<? extends FixtureScript>> findSubTypesOfClasses() {
+        if(classDiscoveryService instanceof ClassDiscoveryService2) {
+            final ClassDiscoveryService2 classDiscoveryService2 = (ClassDiscoveryService2) classDiscoveryService;
+            return classDiscoveryService2.findSubTypesOfClasses(FixtureScript.class, packagePrefix);
+        } else {
+            return classDiscoveryService.findSubTypesOfClasses(FixtureScript.class);
+        }
+    }
+
     private FixtureScript newFixtureScript(Class<? extends FixtureScript> fixtureScriptCls) {
         try {
             final Constructor<? extends FixtureScript> constructor = fixtureScriptCls.getConstructor();

http://git-wip-us.apache.org/repos/asf/isis/blob/29c69d97/core/applib/src/main/java/org/apache/isis/applib/services/classdiscovery/ClassDiscoveryService2.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/classdiscovery/ClassDiscoveryService2.java b/core/applib/src/main/java/org/apache/isis/applib/services/classdiscovery/ClassDiscoveryService2.java
new file mode 100644
index 0000000..8857eb0
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/services/classdiscovery/ClassDiscoveryService2.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.isis.applib.services.classdiscovery;
+
+import java.util.Set;
+import org.apache.isis.applib.annotation.Programmatic;
+
+/**
+ * This utility service supports the dynamic discovery of classes from the classpath.  One service that uses this
+ * is the <tt>FixtureScripts</tt> domain service.
+ *
+ * <p>
+ * Because an implementation of this service (<tt>ClassDiscoveryServiceUsingReflections</tt> is annotated with
+ * {@link org.apache.isis.applib.annotation.DomainService} and is implemented in the core applib, it is automatically
+ * registered and available for use; no configuration is required.
+ * </p>
+ */
+public interface ClassDiscoveryService2 extends ClassDiscoveryService {
+
+    @Programmatic
+    public <T> Set<Class<? extends T>> findSubTypesOfClasses(Class<T> type, String packagePrefix);
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/29c69d97/core/applib/src/main/java/org/apache/isis/applib/services/classdiscovery/ClassDiscoveryServiceUsingReflections.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/classdiscovery/ClassDiscoveryServiceUsingReflections.java b/core/applib/src/main/java/org/apache/isis/applib/services/classdiscovery/ClassDiscoveryServiceUsingReflections.java
index 283f053..68fea39 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/services/classdiscovery/ClassDiscoveryServiceUsingReflections.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/services/classdiscovery/ClassDiscoveryServiceUsingReflections.java
@@ -45,7 +45,7 @@ import org.apache.isis.applib.annotation.DomainService;
 @DomainService
 public class ClassDiscoveryServiceUsingReflections
             extends AbstractService 
-            implements ClassDiscoveryService {
+            implements ClassDiscoveryService2 {
 
 
     @Override
@@ -60,6 +60,19 @@ public class ClassDiscoveryServiceUsingReflections
         return reflections.getSubTypesOf(type);
     }
 
+    @Override
+    public <T> Set<Class<? extends T>> findSubTypesOfClasses(Class<T> type, String packagePrefix) {
+        Vfs.setDefaultURLTypes(getUrlTypes());
+
+        final Reflections reflections = new Reflections(
+                ClasspathHelper.forClassLoader(Thread.currentThread().getContextClassLoader()),
+                ClasspathHelper.forClass(Object.class),
+                ClasspathHelper.forPackage(packagePrefix),
+                new SubTypesScanner(false)
+        );
+        return reflections.getSubTypesOf(type);
+    }
+
     // //////////////////////////////////////
 
     /**
@@ -74,6 +87,7 @@ public class ClassDiscoveryServiceUsingReflections
         return urlTypes;
     }
 
+
     private static class EmptyIfFileEndingsUrlType implements Vfs.UrlType {
 
         private final List<String> fileEndings;

http://git-wip-us.apache.org/repos/asf/isis/blob/29c69d97/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/ignore/javalang/RemoveInjectMethodsFacetFactory.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/ignore/javalang/RemoveInjectMethodsFacetFactory.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/ignore/javalang/RemoveInjectMethodsFacetFactory.java
index 51a1459..8bdf3bd 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/ignore/javalang/RemoveInjectMethodsFacetFactory.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/ignore/javalang/RemoveInjectMethodsFacetFactory.java
@@ -20,12 +20,10 @@
 package org.apache.isis.core.metamodel.facets.object.ignore.javalang;
 
 import java.lang.reflect.Method;
-
 import org.apache.isis.core.metamodel.facetapi.FeatureType;
 import org.apache.isis.core.metamodel.facets.FacetFactoryAbstract;
-import org.apache.isis.core.metamodel.services.ServicesInjectorDefault;
 
-public class RemoveInjectMethodsFacetFactory extends FacetFactoryAbstract {
+public class RemoveInjectMethodsFacetFactory extends FacetFactoryAbstract  {
 
     public RemoveInjectMethodsFacetFactory() {
         super(FeatureType.OBJECTS_ONLY);
@@ -36,12 +34,11 @@ public class RemoveInjectMethodsFacetFactory extends FacetFactoryAbstract {
         for (Class<? extends Object> serviceClass : getSpecificationLoader().getServiceClasses()) {
             Method[] methods = processClassContext.getCls().getMethods();
             for (Method method : methods) {
-                if(ServicesInjectorDefault.isInjectorMethodFor(method, serviceClass)) {
+                if(getSpecificationLoader().isInjectorMethodFor(method, serviceClass)) {
                     processClassContext.removeMethod(method);
                 }
             }
         }
     }
 
-
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/29c69d97/core/metamodel/src/main/java/org/apache/isis/core/metamodel/runtimecontext/RuntimeContextAbstract.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/runtimecontext/RuntimeContextAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/runtimecontext/RuntimeContextAbstract.java
index 1e0243a..333986f 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/runtimecontext/RuntimeContextAbstract.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/runtimecontext/RuntimeContextAbstract.java
@@ -19,6 +19,7 @@
 
 package org.apache.isis.core.metamodel.runtimecontext;
 
+import java.lang.reflect.Method;
 import java.util.Collection;
 import java.util.List;
 import java.util.Properties;
@@ -70,7 +71,7 @@ public abstract class RuntimeContextAbstract implements RuntimeContext, Specific
     }
 
     /**
-     * Is injected into when the reflector is reflector isinitialized.
+     * Is injected into when the reflector is initialized.
      */
     @Override
     public void setSpecificationLoaderSpi(final SpecificationLoaderSpi specificationLoader) {
@@ -135,6 +136,11 @@ public abstract class RuntimeContextAbstract implements RuntimeContext, Specific
             public void invalidateCache(Class<?> domainClass) {
                 specificationLoader.invalidateCache(domainClass);
             }
+
+            @Override
+            public boolean isInjectorMethodFor(Method method, Class<? extends Object> serviceClass) {
+                return specificationLoader.isInjectorMethodFor(method, serviceClass);
+            }
         });
     }
 

http://git-wip-us.apache.org/repos/asf/isis/blob/29c69d97/core/metamodel/src/main/java/org/apache/isis/core/metamodel/runtimecontext/ServicesInjector.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/runtimecontext/ServicesInjector.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/runtimecontext/ServicesInjector.java
index d1bcf08..0676c19 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/runtimecontext/ServicesInjector.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/runtimecontext/ServicesInjector.java
@@ -17,7 +17,7 @@
 package org.apache.isis.core.metamodel.runtimecontext;
 
 import java.util.List;
-
+import org.apache.isis.applib.annotation.Programmatic;
 import org.apache.isis.applib.services.exceprecog.ExceptionRecognizer;
 import org.apache.isis.applib.services.publish.PublishingService;
 import org.apache.isis.core.commons.components.Injectable;
@@ -53,6 +53,7 @@ public interface ServicesInjector extends Injectable {
      * 
      * @see #lookupServices(Class)
      */
+    @Programmatic
     <T> T lookupService(Class<T> serviceClass);
     
     /**
@@ -66,5 +67,6 @@ public interface ServicesInjector extends Injectable {
      * 
      * @see #lookupService(Class)
      */
+    @Programmatic
     <T> List<T> lookupServices(Class<T> serviceClass);
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/29c69d97/core/metamodel/src/main/java/org/apache/isis/core/metamodel/runtimecontext/noruntime/RuntimeContextNoRuntime.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/runtimecontext/noruntime/RuntimeContextNoRuntime.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/runtimecontext/noruntime/RuntimeContextNoRuntime.java
index 30363b5..33c0419 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/runtimecontext/noruntime/RuntimeContextNoRuntime.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/runtimecontext/noruntime/RuntimeContextNoRuntime.java
@@ -21,27 +21,13 @@ package org.apache.isis.core.metamodel.runtimecontext.noruntime;
 
 import java.util.Collections;
 import java.util.List;
-
 import org.apache.isis.applib.profiles.Localization;
 import org.apache.isis.applib.query.Query;
 import org.apache.isis.applib.services.bookmark.Bookmark;
 import org.apache.isis.core.commons.authentication.AuthenticationSession;
 import org.apache.isis.core.commons.authentication.AuthenticationSessionProvider;
 import org.apache.isis.core.commons.authentication.AuthenticationSessionProviderAbstract;
-import org.apache.isis.core.metamodel.adapter.DomainObjectServices;
-import org.apache.isis.core.metamodel.adapter.DomainObjectServicesAbstract;
-import org.apache.isis.core.metamodel.adapter.LocalizationDefault;
-import org.apache.isis.core.metamodel.adapter.LocalizationProvider;
-import org.apache.isis.core.metamodel.adapter.LocalizationProviderAbstract;
-import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
-import org.apache.isis.core.metamodel.adapter.ObjectDirtier;
-import org.apache.isis.core.metamodel.adapter.ObjectDirtierAbstract;
-import org.apache.isis.core.metamodel.adapter.ObjectPersistor;
-import org.apache.isis.core.metamodel.adapter.ObjectPersistorAbstract;
-import org.apache.isis.core.metamodel.adapter.QuerySubmitter;
-import org.apache.isis.core.metamodel.adapter.QuerySubmitterAbstract;
-import org.apache.isis.core.metamodel.adapter.ServicesProvider;
-import org.apache.isis.core.metamodel.adapter.ServicesProviderAbstract;
+import org.apache.isis.core.metamodel.adapter.*;
 import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager;
 import org.apache.isis.core.metamodel.adapter.mgr.AdapterManagerAbstract;
 import org.apache.isis.core.metamodel.adapter.oid.Oid;

http://git-wip-us.apache.org/repos/asf/isis/blob/29c69d97/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/ServicesInjectorDefault.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/ServicesInjectorDefault.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/ServicesInjectorDefault.java
index 2687e1b..74e08f0 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/ServicesInjectorDefault.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/ServicesInjectorDefault.java
@@ -38,27 +38,27 @@ import org.apache.isis.core.commons.lang.ObjectExtensions;
 import org.apache.isis.core.commons.util.ToString;
 import org.apache.isis.core.metamodel.exceptions.MetaModelException;
 import org.apache.isis.core.metamodel.runtimecontext.ServicesInjectorAware;
+import org.apache.isis.core.metamodel.spec.SpecificationLoader;
+import org.apache.isis.core.metamodel.spec.SpecificationLoaderAware;
 
 /**
  * Must be a thread-safe.
  */
-public class ServicesInjectorDefault implements ServicesInjectorSpi {
+public class ServicesInjectorDefault implements ServicesInjectorSpi, SpecificationLoaderAware {
 
     private static final Logger LOG = LoggerFactory.getLogger(ServicesInjectorDefault.class);
 
+    private final List<Object> services = Lists.newArrayList();
+
     /**
      * If no key, not yet searched for type; otherwise the {@link List} indicates
      * whether a service was found.
      */
     private final Map<Class<?>, List<Object>> servicesByType = Maps.newHashMap();
 
-    private final List<Object> services = Lists.newArrayList();
 
-    
-    // /////////////////////////////////////////////////////////
-    // Constructor, init, shutdown
-    // /////////////////////////////////////////////////////////
 
+    //region > init, shutdown
 
     @Override
     public void init() {
@@ -69,9 +69,9 @@ public class ServicesInjectorDefault implements ServicesInjectorSpi {
     public void shutdown() {
     }
 
-    // /////////////////////////////////////////////////////////
-    // Services
-    // /////////////////////////////////////////////////////////
+    //endregion
+
+    //region > setServices, replaceServices
 
     @Override
     public void setServices(final List<Object> services) {
@@ -115,9 +115,9 @@ public class ServicesInjectorDefault implements ServicesInjectorSpi {
         return services.add(service);
     }
 
-    // /////////////////////////////////////////////////////////
-    // Inject Dependencies
-    // /////////////////////////////////////////////////////////
+    //endregion
+
+    //region > injectServicesInto
 
     @Override
     public void injectServicesInto(final Object object) {
@@ -133,9 +133,9 @@ public class ServicesInjectorDefault implements ServicesInjectorSpi {
         }
     }
 
-    // ////////////////////////////////////////////////////////////////////
-    // injectInto
-    // ////////////////////////////////////////////////////////////////////
+    //endregion
+
+    //region > injectInto
 
     /**
      * That is, injecting this injector...
@@ -148,12 +148,11 @@ public class ServicesInjectorDefault implements ServicesInjectorSpi {
         }
     }
 
+    //endregion
 
-    // /////////////////////////////////////////////////////////
-    // Helpers
-    // /////////////////////////////////////////////////////////
+    //region > helpers
 
-    private static void injectServices(final Object object, final List<Object> services) {
+    private void injectServices(final Object object, final List<Object> services) {
         final Class<?> cls = object.getClass();
 
         autowireViaFields(object, services, cls);
@@ -161,7 +160,7 @@ public class ServicesInjectorDefault implements ServicesInjectorSpi {
         autowireViaPrefixedMethods(object, services, cls, "inject");
     }
 
-    private static void autowireViaFields(final Object object, final List<Object> services, final Class<?> cls) {
+    private void autowireViaFields(final Object object, final List<Object> services, final Class<?> cls) {
         final List<Field> fields = Arrays.asList(cls.getDeclaredFields());
         final Iterable<Field> injectFields = Iterables.filter(fields, new Predicate<Field>() {
             @Override
@@ -182,7 +181,7 @@ public class ServicesInjectorDefault implements ServicesInjectorSpi {
         }
     }
 
-    private static void autowire(Object object, Field field, List<Object> services) {
+    private void autowire(Object object, Field field, List<Object> services) {
         for (final Object service : services) {
             final Class<?> serviceClass = service.getClass();
             boolean canInject = isInjectorFieldFor(field, serviceClass);
@@ -194,7 +193,7 @@ public class ServicesInjectorDefault implements ServicesInjectorSpi {
         }
     }
 
-    private static void autowireViaPrefixedMethods(final Object object, final List<Object> services, final Class<?> cls, final String prefix) {
+    private void autowireViaPrefixedMethods(final Object object, final List<Object> services, final Class<?> cls, final String prefix) {
         final List<Method> methods = Arrays.asList(cls.getMethods());
         final Iterable<Method> prefixedMethods = Iterables.filter(methods, new Predicate<Method>(){
             public boolean apply(Method method) {
@@ -208,10 +207,10 @@ public class ServicesInjectorDefault implements ServicesInjectorSpi {
         }
     }
 
-    private static void autowire(Object object, Method prefixedMethod, List<Object> services) {
+    private void autowire(Object object, Method prefixedMethod, List<Object> services) {
         for (final Object service : services) {
             final Class<?> serviceClass = service.getClass();
-            boolean isInjectorMethod = isInjectorMethodFor(prefixedMethod, serviceClass);
+            boolean isInjectorMethod = specificationLoader.isInjectorMethodFor(prefixedMethod, serviceClass);
             if(isInjectorMethod) {
                 prefixedMethod.setAccessible(true);
                 invokeInjectorMethod(prefixedMethod, object, service);
@@ -220,23 +219,13 @@ public class ServicesInjectorDefault implements ServicesInjectorSpi {
         }
     }
 
-    private static boolean isInjectorFieldFor(final Field field, final Class<?> serviceClass) {
+    private boolean isInjectorFieldFor(final Field field, final Class<?> serviceClass) {
         final Class<?> type = field.getType();
         // don't think that type can ever be null, but Javadoc for java.lang.reflect.Field doesn't say
         return type != null && type.isAssignableFrom(serviceClass);
     }
 
-    public static boolean isInjectorMethodFor(Method method, final Class<?> serviceClass) {
-        final String methodName = method.getName();
-        if (methodName.startsWith("set") || methodName.startsWith("inject")) {
-            final Class<?>[] parameterTypes = method.getParameterTypes();
-            if (parameterTypes.length == 1 && parameterTypes[0] != Object.class && parameterTypes[0].isAssignableFrom(serviceClass)) {
-                return true;
-            }
-        }
-        return false;
-    }
-    
+
     private static void invokeMethod(final Method method, final Object target, final Object[] parameters) {
         try {
             method.invoke(target, parameters);
@@ -281,6 +270,11 @@ public class ServicesInjectorDefault implements ServicesInjectorSpi {
         injectServicesInto(this.services);
     }
 
+
+    //endregion
+
+    //region > lookupService, lookupServices
+
     @Override
     public <T> T lookupService(Class<T> serviceClass) {
         List<T> services = lookupServices(serviceClass);
@@ -319,4 +313,15 @@ public class ServicesInjectorDefault implements ServicesInjectorSpi {
         };
     }
 
+    //endregion
+
+    //region > injected dependencies
+
+    private SpecificationLoader specificationLoader;
+
+    public void setSpecificationLookup(SpecificationLoader specificationLoader) {
+        this.specificationLoader = specificationLoader;
+    }
+
+    //endregion
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/29c69d97/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/SpecificationLoader.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/SpecificationLoader.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/SpecificationLoader.java
index a3c5a7c..f7f2a51 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/SpecificationLoader.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/SpecificationLoader.java
@@ -16,6 +16,7 @@
  */
 package org.apache.isis.core.metamodel.spec;
 
+import java.lang.reflect.Method;
 import java.util.Collection;
 import java.util.List;
 
@@ -81,4 +82,7 @@ public interface SpecificationLoader extends Injectable {
 
     void invalidateCache(Class<?> domainClass);
 
+    boolean isInjectorMethodFor(Method method, Class<? extends Object> serviceClass);
+
+
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/29c69d97/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/SpecificationLoaderAbstract.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/SpecificationLoaderAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/SpecificationLoaderAbstract.java
index deb0e0d..8bbead0 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/SpecificationLoaderAbstract.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/SpecificationLoaderAbstract.java
@@ -16,6 +16,10 @@
  */
 package org.apache.isis.core.metamodel.spec;
 
+import java.lang.reflect.Method;
+import java.util.Map;
+import com.google.common.collect.Maps;
+
 public abstract class SpecificationLoaderAbstract implements SpecificationLoader {
 
     @Override
@@ -26,4 +30,36 @@ public abstract class SpecificationLoaderAbstract implements SpecificationLoader
         }
     }
 
+    //region > isInjectorMethodFor
+
+    private final Map<Method, Map<Class<?>, Boolean>> isInjectorMethod = Maps.newConcurrentMap();
+
+    public boolean isInjectorMethodFor(Method method, final Class<?> serviceClass) {
+        Map<Class<?>, Boolean> classBooleanMap = isInjectorMethod.get(method);
+        if(classBooleanMap == null) {
+            synchronized (isInjectorMethod) {
+                classBooleanMap = Maps.newConcurrentMap();
+                isInjectorMethod.put(method, classBooleanMap);
+            }
+        }
+        Boolean result = classBooleanMap.get(serviceClass);
+        if(result == null) {
+            result = determineIsInjectorMethodFor(method, serviceClass);
+            classBooleanMap.put(serviceClass, result);
+        }
+        return result;
+    }
+
+    private static boolean determineIsInjectorMethodFor(Method method, Class<?> serviceClass) {
+        final String methodName = method.getName();
+        if (methodName.startsWith("set") || methodName.startsWith("inject")) {
+            final Class<?>[] parameterTypes = method.getParameterTypes();
+            if (parameterTypes.length == 1 && parameterTypes[0] != Object.class && parameterTypes[0].isAssignableFrom(serviceClass)) {
+                return true;
+            }
+        }
+        return false;
+    }
+    //endregion
+
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/29c69d97/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/SpecificationLoaderSpi.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/SpecificationLoaderSpi.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/SpecificationLoaderSpi.java
index 957ce93..32f44b8 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/SpecificationLoaderSpi.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/SpecificationLoaderSpi.java
@@ -20,11 +20,8 @@
 package org.apache.isis.core.metamodel.spec;
 
 import java.util.List;
-
-import org.apache.isis.applib.DomainObjectContainer;
 import org.apache.isis.core.commons.components.ApplicationScopedComponent;
 import org.apache.isis.core.commons.debug.DebuggableWithTitle;
-import org.apache.isis.core.metamodel.specloader.validator.MetaModelValidator;
 import org.apache.isis.core.metamodel.specloader.validator.ValidationFailures;
 
 public interface SpecificationLoaderSpi extends ApplicationScopedComponent, DebuggableWithTitle, SpecificationLoader {

http://git-wip-us.apache.org/repos/asf/isis/blob/29c69d97/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/ObjectReflectorDefault.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/ObjectReflectorDefault.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/ObjectReflectorDefault.java
index 78a9013..4f27b58 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/ObjectReflectorDefault.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/ObjectReflectorDefault.java
@@ -19,13 +19,13 @@
 
 package org.apache.isis.core.metamodel.specloader;
 
+import java.lang.reflect.Method;
 import java.util.*;
 import com.google.common.base.Function;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import org.apache.isis.applib.DomainObjectContainer;
 import org.apache.isis.core.commons.authentication.AuthenticationSessionProvider;
 import org.apache.isis.core.commons.components.ApplicationScopedComponent;
 import org.apache.isis.core.commons.config.IsisConfiguration;
@@ -361,6 +361,11 @@ public final class ObjectReflectorDefault implements SpecificationLoaderSpi, App
         }
     }
 
+    @Override
+    public boolean isInjectorMethodFor(Method method, Class<? extends Object> serviceClass) {
+        return false;
+    }
+
     private void recache(final ObjectSpecification newSpec) {
         getCache().recache(newSpec);
     }

http://git-wip-us.apache.org/repos/asf/isis/blob/29c69d97/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/ProgrammableReflector.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/ProgrammableReflector.java b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/ProgrammableReflector.java
index 0c553b0..63ca002 100644
--- a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/ProgrammableReflector.java
+++ b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/ProgrammableReflector.java
@@ -21,8 +21,6 @@ package org.apache.isis.core.metamodel.facets;
 
 import java.util.Collection;
 import java.util.List;
-
-import org.apache.isis.applib.DomainObjectContainer;
 import org.apache.isis.core.commons.components.ApplicationScopedComponent;
 import org.apache.isis.core.commons.debug.DebugBuilder;
 import org.apache.isis.core.commons.exceptions.NotYetImplementedException;
@@ -30,11 +28,12 @@ import org.apache.isis.core.metamodel.runtimecontext.RuntimeContext;
 import org.apache.isis.core.metamodel.runtimecontext.RuntimeContextAware;
 import org.apache.isis.core.metamodel.spec.ObjectSpecId;
 import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.spec.SpecificationLoaderAbstract;
 import org.apache.isis.core.metamodel.spec.SpecificationLoaderSpi;
 import org.apache.isis.core.metamodel.specloader.collectiontyperegistry.CollectionTypeRegistry;
 import org.apache.isis.core.metamodel.specloader.validator.ValidationFailures;
 
-public class ProgrammableReflector implements SpecificationLoaderSpi, ApplicationScopedComponent, RuntimeContextAware {
+public class ProgrammableReflector extends SpecificationLoaderAbstract implements SpecificationLoaderSpi, ApplicationScopedComponent, RuntimeContextAware {
 
     @Override
     public void init() {

http://git-wip-us.apache.org/repos/asf/isis/blob/29c69d97/core/runtime/src/main/java/org/apache/isis/core/runtime/persistence/PersistenceSessionFactoryDelegating.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/persistence/PersistenceSessionFactoryDelegating.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/persistence/PersistenceSessionFactoryDelegating.java
index 0c01e96..2efacc2 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/persistence/PersistenceSessionFactoryDelegating.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/persistence/PersistenceSessionFactoryDelegating.java
@@ -122,6 +122,8 @@ public class PersistenceSessionFactoryDelegating implements PersistenceSessionFa
         runtimeContext = persistenceSessionFactoryDelegate.createRuntimeContext(getConfiguration());
         ensureThatState(runtimeContext, is(not(nullValue())));
 
+        // inject the specification loader etc.
+        runtimeContext.injectInto(servicesInjector);
         
         // wire up components
 

http://git-wip-us.apache.org/repos/asf/isis/blob/29c69d97/core/runtime/src/main/java/org/apache/isis/core/runtime/persistence/internal/RuntimeContextFromSession.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/persistence/internal/RuntimeContextFromSession.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/persistence/internal/RuntimeContextFromSession.java
index d7e388c..d5b6d57 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/persistence/internal/RuntimeContextFromSession.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/persistence/internal/RuntimeContextFromSession.java
@@ -304,7 +304,7 @@ public class RuntimeContextFromSession extends RuntimeContextAbstract {
             public <T> List<T> lookupServices(Class<T> serviceClass) {
                 return getPersistenceSession().getServicesInjector().lookupServices(serviceClass);
             }
-            
+
             @Override
             public void injectInto(Object candidate) {
                 if (ServicesInjectorAware.class.isAssignableFrom(candidate.getClass())) {

http://git-wip-us.apache.org/repos/asf/isis/blob/29c69d97/core/runtime/src/main/java/org/apache/isis/core/runtime/system/IsisSystemFixturesHookAbstract.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/IsisSystemFixturesHookAbstract.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/IsisSystemFixturesHookAbstract.java
index 3d98d22..4e09735 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/IsisSystemFixturesHookAbstract.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/IsisSystemFixturesHookAbstract.java
@@ -31,7 +31,6 @@ import org.apache.isis.core.commons.debug.DebuggableWithTitle;
 import org.apache.isis.core.metamodel.adapter.oid.OidMarshaller;
 import org.apache.isis.core.metamodel.facetapi.ClassSubstitutorFactory;
 import org.apache.isis.core.metamodel.facetapi.MetaModelRefiner;
-import org.apache.isis.core.metamodel.services.ServicesInjectorDefault;
 import org.apache.isis.core.metamodel.spec.SpecificationLoaderSpi;
 import org.apache.isis.core.metamodel.specloader.ServiceInitializer;
 import org.apache.isis.core.runtime.about.AboutIsis;
@@ -142,10 +141,11 @@ public abstract class IsisSystemFixturesHookAbstract implements IsisSystem {
 
         final List<Object> services = sessionFactory.getServices();
         
-        // autowire
-        final ServicesInjectorDefault servicesInjector = new ServicesInjectorDefault();
-        servicesInjector.setServices(services);
-        servicesInjector.init();
+//        // autowire
+//        final ServicesInjectorDefault servicesInjector = new ServicesInjectorDefault();
+//        servicesInjector.setSpecificationLookup(sessionFactory.getSpecificationLoader());
+//        servicesInjector.setServices(services);
+//        servicesInjector.init();
 
         // validate 
         final ServiceInitializer serviceInitializer = new ServiceInitializer();

http://git-wip-us.apache.org/repos/asf/isis/blob/29c69d97/core/webserver/src/main/java/org/apache/isis/core/webserver/WebServer.java
----------------------------------------------------------------------
diff --git a/core/webserver/src/main/java/org/apache/isis/core/webserver/WebServer.java b/core/webserver/src/main/java/org/apache/isis/core/webserver/WebServer.java
index 62dc30f..ec067a5 100644
--- a/core/webserver/src/main/java/org/apache/isis/core/webserver/WebServer.java
+++ b/core/webserver/src/main/java/org/apache/isis/core/webserver/WebServer.java
@@ -19,22 +19,19 @@
 
 package org.apache.isis.core.webserver;
 
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
 import java.net.URI;
 import java.util.Formatter;
-
 import org.mortbay.jetty.Connector;
 import org.mortbay.jetty.Server;
 import org.mortbay.jetty.webapp.WebAppContext;
-
 import org.apache.isis.core.commons.config.IsisConfigurationBuilderDefault;
 import org.apache.isis.core.commons.lang.ArrayExtensions;
 import org.apache.isis.core.runtime.runner.Constants;
 import org.apache.isis.core.runtime.runner.IsisRunner;
-import org.apache.isis.core.webserver.internal.OptionHandlerAddress;
-import org.apache.isis.core.webserver.internal.OptionHandlerDeploymentTypeWebServer;
-import org.apache.isis.core.webserver.internal.OptionHandlerPort;
-import org.apache.isis.core.webserver.internal.OptionHandlerResourceBase;
-import org.apache.isis.core.webserver.internal.OptionHandlerStartupMode;
+import org.apache.isis.core.webserver.internal.*;
 
 public class WebServer {
 
@@ -65,9 +62,23 @@ public class WebServer {
     private Server jettyServer;
 
     public static void main(final String[] args) {
+//        System.out.println("press any key to start...");
+//        readLine();
         new WebServer().run(ArrayExtensions.append(args, "--" + Constants.NO_SPLASH_LONG_OPT));
     }
 
+    private static void readLine() {
+        try{
+            BufferedReader br =
+                    new BufferedReader(new InputStreamReader(System.in));
+
+            br.readLine();
+        } catch(IOException io){
+            io.printStackTrace();
+            System.exit(1);
+        }
+    }
+
     /**
      * Originally introduced to allow the WebServer to be used by tests.
      */

http://git-wip-us.apache.org/repos/asf/isis/blob/29c69d97/core/wrapper/src/main/java/org/apache/isis/core/wrapper/handlers/DomainObjectInvocationHandler.java
----------------------------------------------------------------------
diff --git a/core/wrapper/src/main/java/org/apache/isis/core/wrapper/handlers/DomainObjectInvocationHandler.java b/core/wrapper/src/main/java/org/apache/isis/core/wrapper/handlers/DomainObjectInvocationHandler.java
index e5594c9..314021e 100644
--- a/core/wrapper/src/main/java/org/apache/isis/core/wrapper/handlers/DomainObjectInvocationHandler.java
+++ b/core/wrapper/src/main/java/org/apache/isis/core/wrapper/handlers/DomainObjectInvocationHandler.java
@@ -125,8 +125,10 @@ public class DomainObjectInvocationHandler<T> extends DelegatingInvocationHandle
             __isis_executionMode = WrapperObject.class.getMethod("__isis_executionMode", new Class[]{});
             saveMethod = WrapperObject.class.getMethod("save", new Class[] {});
             wrappedMethod = WrapperObject.class.getMethod("wrapped", new Class[] {});
-        } catch (final NoSuchMethodException e) {
-            throw new IllegalStateException("Could not locate reserved declared methods in the WrappingObject and WrappedObject interfaces");
+        } catch (final NoSuchMethodException nsme) {
+            throw new IllegalStateException(
+                    "Could not locate reserved declared methods in the WrappingObject and WrappedObject interfaces",
+                    nsme);
         }
     }
 

http://git-wip-us.apache.org/repos/asf/isis/blob/29c69d97/example/application/todoapp/dom/src/main/java/dom/todo/ToDoItem.java
----------------------------------------------------------------------
diff --git a/example/application/todoapp/dom/src/main/java/dom/todo/ToDoItem.java b/example/application/todoapp/dom/src/main/java/dom/todo/ToDoItem.java
index 09955e1..a5b4a02 100644
--- a/example/application/todoapp/dom/src/main/java/dom/todo/ToDoItem.java
+++ b/example/application/todoapp/dom/src/main/java/dom/todo/ToDoItem.java
@@ -597,7 +597,7 @@ public class ToDoItem implements Categorized, Comparable<ToDoItem> {
         container.informUser("Deleted " + container.titleOf(this));
         
         // invalid to return 'this' (cannot render a deleted object)
-        return toDoItems.notYetComplete(); 
+        return toDoItems.notYetComplete();
     }
     //endregion
 


[2/2] git commit: ISIS-931: extracted out InjectorMethodEvaluator (for testing, single responsibility principle).

Posted by da...@apache.org.
ISIS-931: extracted out InjectorMethodEvaluator (for testing, single responsibility principle).


Project: http://git-wip-us.apache.org/repos/asf/isis/repo
Commit: http://git-wip-us.apache.org/repos/asf/isis/commit/355c1d07
Tree: http://git-wip-us.apache.org/repos/asf/isis/tree/355c1d07
Diff: http://git-wip-us.apache.org/repos/asf/isis/diff/355c1d07

Branch: refs/heads/master
Commit: 355c1d07954cbde2c86b70dde84066ff74ac94ca
Parents: 29c69d9
Author: Dan Haywood <da...@haywood-associates.co.uk>
Authored: Tue Oct 28 12:22:43 2014 +0000
Committer: Dan Haywood <da...@haywood-associates.co.uk>
Committed: Tue Oct 28 12:22:43 2014 +0000

----------------------------------------------------------------------
 .../RemoveInjectMethodsFacetFactory.java        |  4 +-
 .../services/ServicesInjectorDefault.java       | 27 +++++++--
 .../metamodel/spec/InjectorMethodEvaluator.java | 26 ++++++++
 .../metamodel/spec/SpecificationLoader.java     |  8 +--
 .../spec/SpecificationLoaderAbstract.java       | 31 ----------
 .../spec/SpecificationLoaderDelegator.java      |  7 ++-
 .../InjectorMethodEvaluatorDefault.java         | 62 ++++++++++++++++++++
 .../specloader/ObjectReflectorDefault.java      |  9 ++-
 .../metamodel/facets/ProgrammableReflector.java | 12 ++++
 .../services/ServicesInjectorDefaultTest.java   |  9 ++-
 .../PersistenceSessionObjectStoreTest.java      |  3 +-
 11 files changed, 146 insertions(+), 52 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis/blob/355c1d07/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/ignore/javalang/RemoveInjectMethodsFacetFactory.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/ignore/javalang/RemoveInjectMethodsFacetFactory.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/ignore/javalang/RemoveInjectMethodsFacetFactory.java
index 8bdf3bd..69df125 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/ignore/javalang/RemoveInjectMethodsFacetFactory.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/ignore/javalang/RemoveInjectMethodsFacetFactory.java
@@ -20,6 +20,7 @@
 package org.apache.isis.core.metamodel.facets.object.ignore.javalang;
 
 import java.lang.reflect.Method;
+import java.util.List;
 import org.apache.isis.core.metamodel.facetapi.FeatureType;
 import org.apache.isis.core.metamodel.facets.FacetFactoryAbstract;
 
@@ -31,7 +32,8 @@ public class RemoveInjectMethodsFacetFactory extends FacetFactoryAbstract  {
 
     @Override
     public void process(final ProcessClassContext processClassContext) {
-        for (Class<? extends Object> serviceClass : getSpecificationLoader().getServiceClasses()) {
+        final List<Class<?>> serviceClasses = getSpecificationLoader().getServiceClasses();
+        for (Class<? extends Object> serviceClass : serviceClasses) {
             Method[] methods = processClassContext.getCls().getMethods();
             for (Method method : methods) {
                 if(getSpecificationLoader().isInjectorMethodFor(method, serviceClass)) {

http://git-wip-us.apache.org/repos/asf/isis/blob/355c1d07/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/ServicesInjectorDefault.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/ServicesInjectorDefault.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/ServicesInjectorDefault.java
index 74e08f0..5a2b3de 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/ServicesInjectorDefault.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/ServicesInjectorDefault.java
@@ -38,6 +38,7 @@ import org.apache.isis.core.commons.lang.ObjectExtensions;
 import org.apache.isis.core.commons.util.ToString;
 import org.apache.isis.core.metamodel.exceptions.MetaModelException;
 import org.apache.isis.core.metamodel.runtimecontext.ServicesInjectorAware;
+import org.apache.isis.core.metamodel.spec.InjectorMethodEvaluator;
 import org.apache.isis.core.metamodel.spec.SpecificationLoader;
 import org.apache.isis.core.metamodel.spec.SpecificationLoaderAware;
 
@@ -56,9 +57,24 @@ public class ServicesInjectorDefault implements ServicesInjectorSpi, Specificati
      */
     private final Map<Class<?>, List<Object>> servicesByType = Maps.newHashMap();
 
+    public ServicesInjectorDefault() {
+        this(null);
+    }
 
+    /**
+     * For testing.  
+     * 
+     * <p>
+     *     In production code, {@link #setSpecificationLookup(org.apache.isis.core.metamodel.spec.SpecificationLoader)}
+     *     Pis used instead.
+     * </p>
+     * @param injectorMethodEvaluator
+     */
+    public ServicesInjectorDefault(InjectorMethodEvaluator injectorMethodEvaluator) {
+        this.injectorMethodEvaluator = injectorMethodEvaluator;
+    }
 
-    //region > init, shutdown
+//region > init, shutdown
 
     @Override
     public void init() {
@@ -210,7 +226,7 @@ public class ServicesInjectorDefault implements ServicesInjectorSpi, Specificati
     private void autowire(Object object, Method prefixedMethod, List<Object> services) {
         for (final Object service : services) {
             final Class<?> serviceClass = service.getClass();
-            boolean isInjectorMethod = specificationLoader.isInjectorMethodFor(prefixedMethod, serviceClass);
+            boolean isInjectorMethod = injectorMethodEvaluator.isInjectorMethodFor(prefixedMethod, serviceClass);
             if(isInjectorMethod) {
                 prefixedMethod.setAccessible(true);
                 invokeInjectorMethod(prefixedMethod, object, service);
@@ -317,10 +333,11 @@ public class ServicesInjectorDefault implements ServicesInjectorSpi, Specificati
 
     //region > injected dependencies
 
-    private SpecificationLoader specificationLoader;
+    private InjectorMethodEvaluator injectorMethodEvaluator;
 
-    public void setSpecificationLookup(SpecificationLoader specificationLoader) {
-        this.specificationLoader = specificationLoader;
+    @Override
+    public void setSpecificationLookup(SpecificationLoader specificationLookup) {
+        injectorMethodEvaluator = specificationLookup;
     }
 
     //endregion

http://git-wip-us.apache.org/repos/asf/isis/blob/355c1d07/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/InjectorMethodEvaluator.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/InjectorMethodEvaluator.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/InjectorMethodEvaluator.java
new file mode 100644
index 0000000..f67f585
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/InjectorMethodEvaluator.java
@@ -0,0 +1,26 @@
+/**
+ *  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.isis.core.metamodel.spec;
+
+import java.lang.reflect.Method;
+
+public interface InjectorMethodEvaluator {
+
+    boolean isInjectorMethodFor(Method method, Class<? extends Object> serviceClass);
+
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/355c1d07/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/SpecificationLoader.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/SpecificationLoader.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/SpecificationLoader.java
index f7f2a51..4bf99c1 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/SpecificationLoader.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/SpecificationLoader.java
@@ -16,15 +16,13 @@
  */
 package org.apache.isis.core.metamodel.spec;
 
-import java.lang.reflect.Method;
 import java.util.Collection;
 import java.util.List;
-
 import org.apache.isis.core.commons.components.Injectable;
 import org.apache.isis.core.metamodel.facets.FacetFactory;
 import org.apache.isis.core.metamodel.facets.object.autocomplete.AutoCompleteFacet;
 
-public interface SpecificationLoader extends Injectable {
+public interface SpecificationLoader extends Injectable, InjectorMethodEvaluator {
 
     ObjectSpecification lookupBySpecId(ObjectSpecId objectSpecId);
 
@@ -33,7 +31,8 @@ public interface SpecificationLoader extends Injectable {
      * 
      * <p>
      * It is possible for this method to return <tt>null</tt>, for example if
-     * the configured {@link #getClassSubstitutor()} has filtered out the class.
+     * the configured {@link org.apache.isis.core.metamodel.specloader.classsubstitutor.ClassSubstitutor}
+     * has filtered out the class.
      */
     ObjectSpecification loadSpecification(String fullyQualifiedClassName);
 
@@ -82,7 +81,6 @@ public interface SpecificationLoader extends Injectable {
 
     void invalidateCache(Class<?> domainClass);
 
-    boolean isInjectorMethodFor(Method method, Class<? extends Object> serviceClass);
 
 
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/355c1d07/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/SpecificationLoaderAbstract.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/SpecificationLoaderAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/SpecificationLoaderAbstract.java
index 8bbead0..7d0e79b 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/SpecificationLoaderAbstract.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/SpecificationLoaderAbstract.java
@@ -30,36 +30,5 @@ public abstract class SpecificationLoaderAbstract implements SpecificationLoader
         }
     }
 
-    //region > isInjectorMethodFor
-
-    private final Map<Method, Map<Class<?>, Boolean>> isInjectorMethod = Maps.newConcurrentMap();
-
-    public boolean isInjectorMethodFor(Method method, final Class<?> serviceClass) {
-        Map<Class<?>, Boolean> classBooleanMap = isInjectorMethod.get(method);
-        if(classBooleanMap == null) {
-            synchronized (isInjectorMethod) {
-                classBooleanMap = Maps.newConcurrentMap();
-                isInjectorMethod.put(method, classBooleanMap);
-            }
-        }
-        Boolean result = classBooleanMap.get(serviceClass);
-        if(result == null) {
-            result = determineIsInjectorMethodFor(method, serviceClass);
-            classBooleanMap.put(serviceClass, result);
-        }
-        return result;
-    }
-
-    private static boolean determineIsInjectorMethodFor(Method method, Class<?> serviceClass) {
-        final String methodName = method.getName();
-        if (methodName.startsWith("set") || methodName.startsWith("inject")) {
-            final Class<?>[] parameterTypes = method.getParameterTypes();
-            if (parameterTypes.length == 1 && parameterTypes[0] != Object.class && parameterTypes[0].isAssignableFrom(serviceClass)) {
-                return true;
-            }
-        }
-        return false;
-    }
-    //endregion
 
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/355c1d07/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/SpecificationLoaderDelegator.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/SpecificationLoaderDelegator.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/SpecificationLoaderDelegator.java
index ad1ad68..7418f17 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/SpecificationLoaderDelegator.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/SpecificationLoaderDelegator.java
@@ -16,6 +16,7 @@
  */
 package org.apache.isis.core.metamodel.spec;
 
+import java.lang.reflect.Method;
 import java.util.Collection;
 import java.util.List;
 
@@ -79,7 +80,6 @@ public class SpecificationLoaderDelegator extends SpecificationLoaderAbstract {
         return specificationLoaderDelegate.introspectIfRequired(spec);
     }
 
-    
     @Override
     public List<Class<?>> getServiceClasses() {
         return specificationLoaderDelegate.getServiceClasses();
@@ -91,6 +91,11 @@ public class SpecificationLoaderDelegator extends SpecificationLoaderAbstract {
     }
 
     @Override
+    public boolean isInjectorMethodFor(Method method, Class<? extends Object> serviceClass) {
+        return specificationLoaderDelegate.isInjectorMethodFor(method, serviceClass);
+    }
+
+    @Override
     public void injectInto(Object candidate) {
         super.injectInto(candidate);
         if(specificationLoaderDelegate != null) {

http://git-wip-us.apache.org/repos/asf/isis/blob/355c1d07/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/InjectorMethodEvaluatorDefault.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/InjectorMethodEvaluatorDefault.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/InjectorMethodEvaluatorDefault.java
new file mode 100644
index 0000000..03a1c2d
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/InjectorMethodEvaluatorDefault.java
@@ -0,0 +1,62 @@
+/*
+ *  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.isis.core.metamodel.specloader;
+
+import java.lang.reflect.Method;
+import java.util.Map;
+import com.google.common.collect.Maps;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.apache.isis.core.metamodel.spec.InjectorMethodEvaluator;
+
+public final class InjectorMethodEvaluatorDefault implements InjectorMethodEvaluator {
+
+    private final static Logger LOG = LoggerFactory.getLogger(InjectorMethodEvaluatorDefault.class);
+
+    private final Map<Method, Map<Class<?>, Boolean>> isInjectorMethod = Maps.newConcurrentMap();
+
+    public boolean isInjectorMethodFor(Method method, final Class<?> serviceClass) {
+        Map<Class<?>, Boolean> classBooleanMap = isInjectorMethod.get(method);
+        if(classBooleanMap == null) {
+            synchronized (isInjectorMethod) {
+                classBooleanMap = Maps.newConcurrentMap();
+                isInjectorMethod.put(method, classBooleanMap);
+            }
+        }
+        Boolean result = classBooleanMap.get(serviceClass);
+        if(result == null) {
+            result = determineIsInjectorMethodFor(method, serviceClass);
+            classBooleanMap.put(serviceClass, result);
+        }
+        return result;
+    }
+
+    private static boolean determineIsInjectorMethodFor(Method method, Class<?> serviceClass) {
+        final String methodName = method.getName();
+        if (methodName.startsWith("set") || methodName.startsWith("inject")) {
+            final Class<?>[] parameterTypes = method.getParameterTypes();
+            if (parameterTypes.length == 1 && parameterTypes[0] != Object.class && parameterTypes[0].isAssignableFrom(serviceClass)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/355c1d07/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/ObjectReflectorDefault.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/ObjectReflectorDefault.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/ObjectReflectorDefault.java
index 4f27b58..32716d4 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/ObjectReflectorDefault.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/ObjectReflectorDefault.java
@@ -361,10 +361,13 @@ public final class ObjectReflectorDefault implements SpecificationLoaderSpi, App
         }
     }
 
-    @Override
-    public boolean isInjectorMethodFor(Method method, Class<? extends Object> serviceClass) {
-        return false;
+    //region > isInjectorMethodFor
+    private InjectorMethodEvaluator injectorMethodEvaluator = new InjectorMethodEvaluatorDefault();
+
+    public boolean isInjectorMethodFor(Method method, final Class<?> serviceClass) {
+        return injectorMethodEvaluator.isInjectorMethodFor(method, serviceClass);
     }
+    //endregion
 
     private void recache(final ObjectSpecification newSpec) {
         getCache().recache(newSpec);

http://git-wip-us.apache.org/repos/asf/isis/blob/355c1d07/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/ProgrammableReflector.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/ProgrammableReflector.java b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/ProgrammableReflector.java
index 63ca002..4476261 100644
--- a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/ProgrammableReflector.java
+++ b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/ProgrammableReflector.java
@@ -19,8 +19,11 @@
 
 package org.apache.isis.core.metamodel.facets;
 
+import java.lang.reflect.Method;
 import java.util.Collection;
 import java.util.List;
+import java.util.Map;
+import com.google.common.collect.Maps;
 import org.apache.isis.core.commons.components.ApplicationScopedComponent;
 import org.apache.isis.core.commons.debug.DebugBuilder;
 import org.apache.isis.core.commons.exceptions.NotYetImplementedException;
@@ -98,6 +101,15 @@ public class ProgrammableReflector extends SpecificationLoaderAbstract implement
     public void injectInto(final Object candidate) {
     }
 
+    //region > isInjectorMethodFor
+
+    private final Map<Method, Map<Class<?>, Boolean>> isInjectorMethod = Maps.newConcurrentMap();
+
+    public boolean isInjectorMethodFor(Method method, final Class<?> serviceClass) {
+        return false;
+    }
+    //endregion
+
     @Override
     public void setRuntimeContext(final RuntimeContext runtimeContext) {
         // ignored

http://git-wip-us.apache.org/repos/asf/isis/blob/355c1d07/core/metamodel/src/test/java/org/apache/isis/core/metamodel/services/ServicesInjectorDefaultTest.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/services/ServicesInjectorDefaultTest.java b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/services/ServicesInjectorDefaultTest.java
index 9c0cb1c..361474b 100644
--- a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/services/ServicesInjectorDefaultTest.java
+++ b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/services/ServicesInjectorDefaultTest.java
@@ -20,15 +20,14 @@
 package org.apache.isis.core.metamodel.services;
 
 import java.util.Arrays;
-
 import org.jmock.Expectations;
 import org.jmock.auto.Mock;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
-
 import org.apache.isis.applib.DomainObjectContainer;
+import org.apache.isis.core.metamodel.specloader.InjectorMethodEvaluatorDefault;
 import org.apache.isis.core.unittestsupport.jmocking.JUnitRuleMockery2;
 import org.apache.isis.core.unittestsupport.jmocking.JUnitRuleMockery2.Mode;
 
@@ -45,8 +44,8 @@ public class ServicesInjectorDefaultTest {
     private Service2 mockService2;
     @Mock
     private SomeDomainObject mockDomainObject;
-    
-    private ServicesInjectorSpi injector;
+
+    private ServicesInjectorDefault injector;
 
     public static interface Service1 {
     }
@@ -69,7 +68,7 @@ public class ServicesInjectorDefaultTest {
 
     @Before
     public void setUp() throws Exception {
-        injector = new ServicesInjectorDefault();
+        injector = new ServicesInjectorDefault(new InjectorMethodEvaluatorDefault());
     }
 
     @After

http://git-wip-us.apache.org/repos/asf/isis/blob/355c1d07/core/runtime/src/test/java/org/apache/isis/core/runtime/persistence/objectstore/PersistenceSessionObjectStoreTest.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/test/java/org/apache/isis/core/runtime/persistence/objectstore/PersistenceSessionObjectStoreTest.java b/core/runtime/src/test/java/org/apache/isis/core/runtime/persistence/objectstore/PersistenceSessionObjectStoreTest.java
index 9655f82..7954a1b 100644
--- a/core/runtime/src/test/java/org/apache/isis/core/runtime/persistence/objectstore/PersistenceSessionObjectStoreTest.java
+++ b/core/runtime/src/test/java/org/apache/isis/core/runtime/persistence/objectstore/PersistenceSessionObjectStoreTest.java
@@ -39,6 +39,7 @@ import org.apache.isis.core.metamodel.runtimecontext.RuntimeContext;
 import org.apache.isis.core.metamodel.services.ServicesInjectorDefault;
 import org.apache.isis.core.metamodel.services.container.DomainObjectContainerDefault;
 import org.apache.isis.core.metamodel.spec.SpecificationLoaderSpi;
+import org.apache.isis.core.metamodel.specloader.InjectorMethodEvaluatorDefault;
 import org.apache.isis.core.runtime.persistence.adapter.PojoAdapter;
 import org.apache.isis.core.runtime.persistence.adapter.PojoAdapterFactory;
 import org.apache.isis.core.runtime.persistence.adaptermanager.AdapterManagerDefault;
@@ -152,7 +153,7 @@ public class PersistenceSessionObjectStoreTest {
 
         runtimeContext.injectInto(container);
 
-        servicesInjector = new ServicesInjectorDefault();
+        servicesInjector = new ServicesInjectorDefault(new InjectorMethodEvaluatorDefault());
 
         adapterManager = new AdapterManagerDefault(new PojoRecreatorDefault());
         adapterFactory = new PojoAdapterFactory();