polygene-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From paulmer...@apache.org
Subject [32/50] [abbrv] polygene-java git commit: POLYGENE-251 - Fixed Concerns/SideEffects being invoke on default interface methods (JetBrains call them Extension Methods. Is that from JVM Spec?). Still a question mark if Concerns/SideEffects are present in c
Date Tue, 16 May 2017 18:51:24 GMT
POLYGENE-251 - Fixed Concerns/SideEffects being invoke on default interface methods (JetBrains
call them Extension Methods. Is that from JVM Spec?). Still a question  mark if Concerns/SideEffects
are present in case they are Generic and not Typed.

Signed-off-by: niclas <niclas@hedhman.org>


Project: http://git-wip-us.apache.org/repos/asf/polygene-java/repo
Commit: http://git-wip-us.apache.org/repos/asf/polygene-java/commit/452c7292
Tree: http://git-wip-us.apache.org/repos/asf/polygene-java/tree/452c7292
Diff: http://git-wip-us.apache.org/repos/asf/polygene-java/diff/452c7292

Branch: refs/heads/master
Commit: 452c72929631b1aff6f45d13f253b66fcea2bb6a
Parents: b028f64
Author: niclas <niclas@hedhman.org>
Authored: Mon May 15 19:35:33 2017 +0800
Committer: niclas <niclas@hedhman.org>
Committed: Mon May 15 19:35:33 2017 +0800

----------------------------------------------------------------------
 .../bootstrap/CompositeAssemblyImpl.java        | 104 +++++++++----------
 .../ImplementsMethodAppliesToFilter.java        |   4 +-
 .../runtime/composite/CompositeMethodModel.java |   4 +-
 .../composite/CompositeMethodsModel.java        |  38 +------
 .../runtime/composite/ConcernsModel.java        |   6 +-
 .../composite/InterfaceDefaultMethodsMixin.java |  98 +++++++++++++++++
 .../polygene/runtime/composite/MixinsModel.java |   7 +-
 .../runtime/composite/SideEffectsModel.java     |   4 +-
 .../composite/InterfaceDefaultMethodsTest.java  |  32 +++---
 .../jdbm/JdbmEntityStorePerformanceTest.java    |  20 ++--
 10 files changed, 190 insertions(+), 127 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/polygene-java/blob/452c7292/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/CompositeAssemblyImpl.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/CompositeAssemblyImpl.java
b/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/CompositeAssemblyImpl.java
index 14e6300..543e8cd 100644
--- a/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/CompositeAssemblyImpl.java
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/CompositeAssemblyImpl.java
@@ -84,6 +84,7 @@ import org.apache.polygene.runtime.composite.ConcernsModel;
 import org.apache.polygene.runtime.composite.ConstraintModel;
 import org.apache.polygene.runtime.composite.ConstraintsModel;
 import org.apache.polygene.runtime.composite.GenericPredicate;
+import org.apache.polygene.runtime.composite.InterfaceDefaultMethodsMixin;
 import org.apache.polygene.runtime.composite.MixinModel;
 import org.apache.polygene.runtime.composite.MixinsModel;
 import org.apache.polygene.runtime.composite.SideEffectModel;
@@ -97,6 +98,7 @@ import org.apache.polygene.runtime.property.PropertiesModel;
 import org.apache.polygene.runtime.property.PropertyModel;
 
 import static java.util.stream.Stream.concat;
+import static java.util.stream.Stream.of;
 import static org.apache.polygene.api.composite.InvalidCompositeException.handleInvalidCompositeType;
 import static org.apache.polygene.api.util.Annotations.isType;
 import static org.apache.polygene.api.util.Annotations.typeHasAnnotation;
@@ -113,18 +115,18 @@ import static org.apache.polygene.api.util.Classes.wrapperClass;
 public abstract class CompositeAssemblyImpl
     implements HasTypes
 {
-    protected List<Class<?>> concerns = new ArrayList<>();
-    protected List<Class<?>> sideEffects = new ArrayList<>();
-    protected List<Class<?>> mixins = new ArrayList<>();
-    protected List<Class<?>> types = new ArrayList<>();
-    protected MetaInfo metaInfo = new MetaInfo();
-    protected Visibility visibility = Visibility.module;
-
-    protected boolean immutable;
-    protected PropertiesModel propertiesModel;
-    protected StateModel stateModel;
-    protected MixinsModel mixinsModel;
-    protected CompositeMethodsModel compositeMethodsModel;
+    List<Class<?>> concerns = new ArrayList<>();
+    List<Class<?>> sideEffects = new ArrayList<>();
+    List<Class<?>> mixins = new ArrayList<>();
+    List<Class<?>> types = new ArrayList<>();
+    MetaInfo metaInfo = new MetaInfo();
+    Visibility visibility = Visibility.module;
+
+    private boolean immutable;
+    PropertiesModel propertiesModel;
+    StateModel stateModel;
+    MixinsModel mixinsModel;
+    CompositeMethodsModel compositeMethodsModel;
     private AssemblyHelper helper;
     private StateDeclarations stateDeclarations;
 
@@ -192,7 +194,7 @@ public abstract class CompositeAssemblyImpl
         return stream.collect( Collectors.toList() );
     }
 
-    protected void addAnnotationsMetaInfo( Class<?> type, MetaInfo compositeMetaInfo
)
+    private void addAnnotationsMetaInfo( Class<?> type, MetaInfo compositeMetaInfo
)
     {
         Class[] declaredInterfaces = type.getInterfaces();
         for( int i = declaredInterfaces.length - 1; i >= 0; i-- )
@@ -202,12 +204,12 @@ public abstract class CompositeAssemblyImpl
         compositeMetaInfo.withAnnotations( type );
     }
 
-    protected void implementMixinType( List<? extends Class<?>> types,
-                                       List<Class<?>> constraintClasses,
-                                       List<Class<?>> concernClasses,
-                                       List<Class<?>> sideEffectClasses,
-                                       List<Class<?>> mixinClasses
-                                     )
+    private void implementMixinType( List<? extends Class<?>> types,
+                                     List<Class<?>> constraintClasses,
+                                     List<Class<?>> concernClasses,
+                                     List<Class<?>> sideEffectClasses,
+                                     List<Class<?>> mixinClasses
+                                   )
     {
         List<Throwable> exceptions = new ArrayList<>();
         Set<Class<?>> thisDependencies = new HashSet<>();
@@ -294,7 +296,7 @@ public abstract class CompositeAssemblyImpl
                         mixinsModel
                     );
 
-                    Stream<? extends Dependencies> source = Stream.of( methodComposite,
mixinModel );
+                    Stream<? extends Dependencies> source = of( methodComposite, mixinModel
);
                     source.flatMap( Dependencies::dependencies )
                           .filter( new DependencyModel.ScopeSpecification( This.class ) )
                           .map( DependencyModel::rawInjectionType )
@@ -302,8 +304,8 @@ public abstract class CompositeAssemblyImpl
 
                     interfacesOf( mixinModel.mixinClass() )
                         .map( Classes.RAW_CLASS )
-                        .filter( clazz -> Stream.of( Initializable.class, Lifecycle.class,
InvocationHandler.class )
-                                                .noneMatch( c -> c.equals( clazz ) ) )
+                        .filter( clazz -> of( Initializable.class, Lifecycle.class, InvocationHandler.class
)
+                            .noneMatch( c -> c.equals( clazz ) ) )
                         .forEach( thisDependencies::add );
 
                     compositeMethodsModel.addMethod( methodComposite );
@@ -317,7 +319,7 @@ public abstract class CompositeAssemblyImpl
     }
 
     @SuppressWarnings( "raw" )
-    protected MixinModel implementMethod( Method method, List<Class<?>> mixinDeclarations
)
+    private MixinModel implementMethod( Method method, List<Class<?>> mixinDeclarations
)
     {
         MixinModel implementationModel = mixinsModel.mixinFor( method );
         if( implementationModel != null )
@@ -331,15 +333,12 @@ public abstract class CompositeAssemblyImpl
         }
 
         // Check generic implementations
-        mixinClass = findGenericImplementation( method, mixinDeclarations.stream() );
+        mixinClass = findGenericImplementation( method, concat( mixinDeclarations.stream(),
of( InterfaceDefaultMethodsMixin.class ) ) );
         if( mixinClass != null )
         {
             return implementMethodWithClass( method, mixinClass );
         }
-        if( !method.isDefault() )  // if it is NOT a default method in an interface, we don't
have an implementation.
-        {
-            handleInvalidCompositeType( "No implementation found for method ", null, null,
null, null, method, types );
-        }
+        handleInvalidCompositeType( "No implementation found for method ", null, null, null,
null, method, types );
         return null;
     }
 
@@ -369,13 +368,11 @@ public abstract class CompositeAssemblyImpl
             mixinModel = helper.getMixinModel( mixinClass );
             mixinsModel.addMixinModel( mixinModel );
         }
-
         mixinsModel.addMethodMixin( method, mixinModel );
-
         return mixinModel;
     }
 
-    protected void addState( final List<Class<?>> constraintClasses )
+    private void addState( final List<Class<?>> constraintClasses )
     {
         // Add method state
         compositeMethodsModel.accept( new HierarchicalVisitorAdapter<Object, Object, RuntimeException>()
@@ -420,7 +417,7 @@ public abstract class CompositeAssemblyImpl
         } );
     }
 
-    protected void addStateFor( AccessibleObject accessor, List<Class<?>> constraintClasses
)
+    private void addStateFor( AccessibleObject accessor, List<Class<?>> constraintClasses
)
     {
         String stateName = QualifiedName.fromAccessor( accessor ).name();
 
@@ -467,9 +464,9 @@ public abstract class CompositeAssemblyImpl
         return null;
     }
 
-    protected PropertyModel newPropertyModel( AccessibleObject accessor,
-                                              List<Class<?>> constraintClasses
-                                            )
+    private PropertyModel newPropertyModel( AccessibleObject accessor,
+                                            List<Class<?>> constraintClasses
+                                          )
     {
         List<Annotation> annotations = Annotations.findAccessorAndTypeAnnotationsIn(
accessor );
         boolean optional = annotations.stream().anyMatch( isType( Optional.class ) );
@@ -519,12 +516,12 @@ public abstract class CompositeAssemblyImpl
         {
             Annotation[] parameterAnnotation = parameterAnnotations[ i ];
 
-            Name nameAnnotation = (Name) Stream.of( parameterAnnotation ).filter( isType(
Name.class ) )
-                                               .findFirst().orElse( null );
+            Name nameAnnotation = (Name) of( parameterAnnotation ).filter( isType( Name.class
) )
+                                                                  .findFirst().orElse( null
);
             String name = nameAnnotation == null ? "param" + ( i + 1 ) : nameAnnotation.value();
 
-            boolean optional = Stream.of( parameterAnnotation )
-                                     .anyMatch( isType( Optional.class ) );
+            boolean optional = of( parameterAnnotation )
+                .anyMatch( isType( Optional.class ) );
             ValueConstraintsModel parameterConstraintsModel = constraintsFor(
                 Arrays.stream( parameterAnnotation ),
                 parameterTypes[ i ],
@@ -554,14 +551,14 @@ public abstract class CompositeAssemblyImpl
         }
     }
 
-    protected ValueConstraintsModel constraintsFor(
+    private ValueConstraintsModel constraintsFor(
         Stream<Annotation> constraintAnnotations,
         Type valueType,
         String name,
         boolean optional,
         Iterable<Class<?>> constraintClasses,
         AccessibleObject accessor
-                                                  )
+                                                )
     {
         valueType = wrapperClass( valueType );
 
@@ -578,6 +575,7 @@ public abstract class CompositeAssemblyImpl
             Class<? extends Annotation> annotationType = constraintAnnotation.annotationType();
             for( Class<?> constraint : constraintClasses )
             {
+                @SuppressWarnings( "unchecked" )
                 Class<? extends Constraint<?, ?>> constraintType = (Class<?
extends Constraint<?, ?>>) constraint;
                 if( helper.appliesTo( constraintType, annotationType, valueType ) )
                 {
@@ -819,7 +817,7 @@ public abstract class CompositeAssemblyImpl
     }
 
     @SuppressWarnings( "unchecked" )
-    protected Stream<Class<?>> sideEffectDeclarations( Class<?> type )
+    private Stream<Class<?>> sideEffectDeclarations( Class<?> type )
     {
         Stream<? extends Type> types = getTypes( type );
         return sideEffectDeclarations( types );
@@ -832,10 +830,10 @@ public abstract class CompositeAssemblyImpl
             .flatMap( mixinType -> Arrays.stream( Annotations.annotationOn( mixinType,
SideEffects.class ).value() ) );
     }
 
-    protected Stream<Class<?>> mixinDeclarations( Class<?> type )
+    private Stream<Class<?>> mixinDeclarations( Class<?> type )
     {
         //Stream<? extends Type> types = typesOf( type );
-        return mixinDeclarations( Stream.of( type ) );
+        return mixinDeclarations( of( type ) );
     }
 
     private Stream<Class<?>> mixinDeclarations( Stream<? extends Class>
types )
@@ -862,9 +860,9 @@ public abstract class CompositeAssemblyImpl
         }
     }
 
-    public AssociationModel newAssociationModel( AccessibleObject accessor,
-                                                 List<Class<?>> constraintClasses
-                                               )
+    private AssociationModel newAssociationModel( AccessibleObject accessor,
+                                                  List<Class<?>> constraintClasses
+                                                )
     {
         List<Annotation> annotations = Annotations.findAccessorAndTypeAnnotationsIn(
accessor );
         boolean optional = annotations.stream().anyMatch( isType( Optional.class ) );
@@ -898,9 +896,9 @@ public abstract class CompositeAssemblyImpl
         return new AssociationModel( accessor, valueConstraintsInstance, associationValueConstraintsInstance,
metaInfo );
     }
 
-    public ManyAssociationModel newManyAssociationModel( AccessibleObject accessor,
-                                                         List<Class<?>> constraintClasses
-                                                       )
+    private ManyAssociationModel newManyAssociationModel( AccessibleObject accessor,
+                                                          List<Class<?>> constraintClasses
+                                                        )
     {
         List<Annotation> annotations = Annotations.findAccessorAndTypeAnnotationsIn(
accessor );
         boolean optional = annotations.stream().anyMatch( isType( Optional.class ) );
@@ -925,9 +923,9 @@ public abstract class CompositeAssemblyImpl
         return new ManyAssociationModel( accessor, valueConstraintsInstance, manyValueConstraintsInstance,
metaInfo );
     }
 
-    public NamedAssociationModel newNamedAssociationModel( AccessibleObject accessor,
-                                                           List<Class<?>> constraintClasses
-                                                         )
+    private NamedAssociationModel newNamedAssociationModel( AccessibleObject accessor,
+                                                            List<Class<?>> constraintClasses
+                                                          )
     {
         List<Annotation> annotations = Annotations.findAccessorAndTypeAnnotationsIn(
accessor );
         boolean optional = annotations.stream().anyMatch( isType( Optional.class ) );

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/452c7292/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/ImplementsMethodAppliesToFilter.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/ImplementsMethodAppliesToFilter.java
b/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/ImplementsMethodAppliesToFilter.java
index fd5b04c..a188253 100644
--- a/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/ImplementsMethodAppliesToFilter.java
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/ImplementsMethodAppliesToFilter.java
@@ -35,8 +35,8 @@ final class ImplementsMethodAppliesToFilter
     {
         try
         {
-            return !Modifier.isAbstract( fragmentClass.getMethod( method.getName(), method.getParameterTypes()
)
-                                             .getModifiers() );
+            Method fragmentMethod = fragmentClass.getMethod( method.getName(), method.getParameterTypes()
);
+            return !Modifier.isAbstract( fragmentMethod.getModifiers() );
         }
         catch( NoSuchMethodException e )
         {

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/452c7292/core/runtime/src/main/java/org/apache/polygene/runtime/composite/CompositeMethodModel.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/CompositeMethodModel.java
b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/CompositeMethodModel.java
index e0e9b98..d290f97 100644
--- a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/CompositeMethodModel.java
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/CompositeMethodModel.java
@@ -93,7 +93,9 @@ public final class CompositeMethodModel
     @SuppressWarnings( "unchecked" )
     public Stream<DependencyModel> dependencies()
     {
-        return Stream.of( concerns, sideEffects ).filter( Objects::nonNull ).flatMap( Dependencies::dependencies
);
+        Stream<? extends Dependencies> concerns = Stream.of( this.concerns, sideEffects
);
+        Stream<? extends Dependencies> filteredNonNull = concerns.filter( Objects::nonNull
);
+        return filteredNonNull.flatMap( Dependencies::dependencies );
     }
 
     // Context

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/452c7292/core/runtime/src/main/java/org/apache/polygene/runtime/composite/CompositeMethodsModel.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/CompositeMethodsModel.java
b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/CompositeMethodsModel.java
index 25b98f7..2223091 100644
--- a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/CompositeMethodsModel.java
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/CompositeMethodsModel.java
@@ -19,16 +19,10 @@
  */
 package org.apache.polygene.runtime.composite;
 
-import java.lang.invoke.MethodHandle;
-import java.lang.invoke.MethodHandles;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.util.Collection;
 import java.util.LinkedHashMap;
 import java.util.Objects;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 import org.apache.polygene.api.composite.Composite;
@@ -45,7 +39,6 @@ import org.apache.polygene.runtime.injection.DependencyModel;
 public final class CompositeMethodsModel
     implements VisitableHierarchy<Object, Object>, Dependencies
 {
-    private final ConcurrentMap<Method, MethodCallHandler> methodHandleCache = new
ConcurrentHashMap<>();
     private final LinkedHashMap<Method, CompositeMethodModel> methods;
     private final MixinsModel mixinsModel;
 
@@ -103,8 +96,7 @@ public final class CompositeMethodsModel
             {
                 if( proxy instanceof Composite )
                 {
-                    MethodCallHandler callHandler = forMethod( method );
-                    return callHandler.invoke( proxy, args );
+                    throw new InternalError( "This shouldn't happen!" );
                 }
                 // Does this next line actually make any sense? Can we have a default method
on an interface where the instance is not a Composite? Maybe... Let's try to trap a usecase
by disallowing it.
 //                return method.invoke( proxy, args );
@@ -166,32 +158,4 @@ public final class CompositeMethodsModel
         return methods().toString();
     }
 
-    private MethodCallHandler forMethod( Method method )
-    {
-        return methodHandleCache.computeIfAbsent( method, this::createMethodCallHandler );
-    }
-
-    private MethodCallHandler createMethodCallHandler( Method method )
-    {
-        Class<?> declaringClass = method.getDeclaringClass();
-        try
-        {
-            Constructor<MethodHandles.Lookup> constructor = MethodHandles.Lookup.class.getDeclaredConstructor(
Class.class, int.class );
-            constructor.setAccessible( true );
-            MethodHandles.Lookup lookup = constructor.newInstance( declaringClass, MethodHandles.Lookup.PRIVATE
);
-            MethodHandle handle = lookup.unreflectSpecial( method, declaringClass );
-            return ( proxy, args ) -> handle.bindTo( proxy ).invokeWithArguments( args
);
-        }
-        catch( IllegalAccessException | NoSuchMethodException | InstantiationException |
InvocationTargetException e )
-        {
-            throw new RuntimeException( e );
-        }
-    }
-
-    @FunctionalInterface
-    private interface MethodCallHandler
-    {
-        Object invoke( Object proxy, Object[] args )
-            throws Throwable;
-    }
 }

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/452c7292/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ConcernsModel.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ConcernsModel.java
b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ConcernsModel.java
index 9c16505..5dde8ce 100644
--- a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ConcernsModel.java
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ConcernsModel.java
@@ -17,7 +17,6 @@
  *
  *
  */
-
 package org.apache.polygene.runtime.composite;
 
 import java.lang.reflect.InvocationHandler;
@@ -55,18 +54,15 @@ public final class ConcernsModel
 
     // Context
     public ConcernsInstance newInstance( Method method, ModuleDescriptor module,
-                                         FragmentInvocationHandler mixinInvocationHandler
-    )
+                                         FragmentInvocationHandler mixinInvocationHandler
)
     {
         ProxyReferenceInvocationHandler proxyHandler = new ProxyReferenceInvocationHandler();
         InvocationHandler nextConcern = mixinInvocationHandler;
         for( int i = concernsFor.size() - 1; i >= 0; i-- )
         {
             ConcernModel concernModel = concernsFor.get( i );
-
             nextConcern = concernModel.newInstance( module, nextConcern, proxyHandler, method
);
         }
-
         return new ConcernsInstance( nextConcern, mixinInvocationHandler, proxyHandler );
     }
 

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/452c7292/core/runtime/src/main/java/org/apache/polygene/runtime/composite/InterfaceDefaultMethodsMixin.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/InterfaceDefaultMethodsMixin.java
b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/InterfaceDefaultMethodsMixin.java
new file mode 100644
index 0000000..b150a86
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/InterfaceDefaultMethodsMixin.java
@@ -0,0 +1,98 @@
+/*
+ *  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.polygene.runtime.composite;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import org.apache.polygene.api.common.AppliesTo;
+import org.apache.polygene.api.common.AppliesToFilter;
+import org.apache.polygene.api.composite.Composite;
+import org.apache.polygene.api.injection.scope.This;
+
+@AppliesTo( { InterfaceDefaultMethodsMixin.DefaultMethodsFilter.class } )
+public class InterfaceDefaultMethodsMixin
+    implements InvocationHandler
+{
+    // TODO (niclas): We have one instance of this class per mixin, so it seems a bit wasteful
to have a ConcurrentHashMap. Maybe a small array 3 elements, which is changed to a Map is
run out of space? Tricky concurrency on that, so leave it for later (a.k.a. will forget about
it)
+    private final ConcurrentMap<Method, MethodCallHandler> methodHandleCache = new
ConcurrentHashMap<>();
+
+    @This
+    private Composite me;
+
+    @Override
+    public Object invoke( Object proxy, Method method, Object[] args )
+        throws Throwable
+    {
+        if( method.isDefault() )
+        {
+            // Call the interface's default method
+            MethodCallHandler callHandler = forMethod( method );
+            return callHandler.invoke( proxy, args );
+        }
+        // call the composite's method instead.
+        return method.invoke( me, args );
+    }
+
+    /**
+     * Filter Default Interface Methods to apply generic Mixin.
+     */
+    public static class DefaultMethodsFilter
+        implements AppliesToFilter
+    {
+        @Override
+        public boolean appliesTo( Method method, Class<?> mixin, Class<?> compositeType,
Class<?> modifierClass )
+        {
+            return method.isDefault();
+        }
+    }
+
+    private MethodCallHandler forMethod( Method method )
+    {
+        return methodHandleCache.computeIfAbsent( method, this::createMethodCallHandler );
+    }
+
+    private MethodCallHandler createMethodCallHandler( Method method )
+    {
+        Class<?> declaringClass = method.getDeclaringClass();
+        try
+        {
+            Constructor<MethodHandles.Lookup> constructor = MethodHandles.Lookup.class.getDeclaredConstructor(
Class.class, int.class );
+            constructor.setAccessible( true );
+            MethodHandles.Lookup lookup = constructor.newInstance( declaringClass, MethodHandles.Lookup.PRIVATE
);
+            MethodHandle handle = lookup.unreflectSpecial( method, declaringClass );
+            return ( proxy, args ) -> handle.bindTo( proxy ).invokeWithArguments( args
);
+        }
+        catch( IllegalAccessException | NoSuchMethodException | InstantiationException |
InvocationTargetException e )
+        {
+            throw new RuntimeException( e );
+        }
+    }
+
+    @FunctionalInterface
+    private interface MethodCallHandler
+    {
+        Object invoke( Object proxy, Object[] args )
+            throws Throwable;
+    }
+}

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/452c7292/core/runtime/src/main/java/org/apache/polygene/runtime/composite/MixinsModel.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/MixinsModel.java
b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/MixinsModel.java
index 8a3390d..35efb9d 100644
--- a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/MixinsModel.java
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/MixinsModel.java
@@ -189,7 +189,12 @@ public class MixinsModel
 
     public FragmentInvocationHandler newInvocationHandler( final Method method )
     {
-        return mixinFor( method ).newInvocationHandler( method );
+        MixinModel mixinModel = mixinFor( method );
+        if( mixinModel == null )
+        {
+            throw new InternalError( "MixinModel can't be found." );
+        }
+        return mixinModel.newInvocationHandler( method );
     }
 
     public Stream<DependencyModel> dependencies()

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/452c7292/core/runtime/src/main/java/org/apache/polygene/runtime/composite/SideEffectsModel.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/SideEffectsModel.java
b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/SideEffectsModel.java
index b56b363..576b188 100644
--- a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/SideEffectsModel.java
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/SideEffectsModel.java
@@ -17,7 +17,6 @@
  *
  *
  */
-
 package org.apache.polygene.runtime.composite;
 
 import java.lang.reflect.InvocationHandler;
@@ -55,7 +54,8 @@ public final class SideEffectsModel
     }
 
     // Context
-    public SideEffectsInstance newInstance( Method method, ModuleDescriptor module, InvocationHandler
invoker )
+    public SideEffectsInstance newInstance( Method method, ModuleDescriptor module,
+                                            InvocationHandler invoker )
     {
         ProxyReferenceInvocationHandler proxyHandler = new ProxyReferenceInvocationHandler();
         SideEffectInvocationHandlerResult result = new SideEffectInvocationHandlerResult();

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/452c7292/core/runtime/src/test/java/org/apache/polygene/runtime/composite/InterfaceDefaultMethodsTest.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/composite/InterfaceDefaultMethodsTest.java
b/core/runtime/src/test/java/org/apache/polygene/runtime/composite/InterfaceDefaultMethodsTest.java
index 76dde88..5a57a82 100644
--- a/core/runtime/src/test/java/org/apache/polygene/runtime/composite/InterfaceDefaultMethodsTest.java
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/composite/InterfaceDefaultMethodsTest.java
@@ -28,12 +28,10 @@ import org.apache.polygene.bootstrap.AssemblyException;
 import org.apache.polygene.bootstrap.ModuleAssembly;
 import org.apache.polygene.library.constraints.annotation.NotEmpty;
 import org.apache.polygene.test.AbstractPolygeneTest;
-import org.junit.Ignore;
 import org.junit.Test;
 
 import static org.hamcrest.Matchers.containsString;
 import static org.hamcrest.Matchers.equalTo;
-import static org.hamcrest.Matchers.is;
 import static org.junit.Assert.assertThat;
 
 /**
@@ -79,18 +77,23 @@ public class InterfaceDefaultMethodsTest extends AbstractPolygeneTest
         }
     }
 
+    @Concerns( DefaultMethodsConcern.class )
     public interface DefaultMethodsConcerns extends DefaultMethods
     {
-        @Concerns( DefaultMethodsConcern.class )
         @Override
         default String sayHello( String name )
         {
             return greeting().get() + ", " + name + '!';
         }
+
+        default String sayGoodBye( String name )
+        {
+            return "Good Bye, " + name + '!';
+        }
     }
 
-    public static abstract class DefaultMethodsConcern extends ConcernOf<DefaultMethods>
-        implements DefaultMethods
+    public static abstract class DefaultMethodsConcern extends ConcernOf<DefaultMethodsConcerns>
+        implements DefaultMethodsConcerns
     {
         @Override
         public String sayHello( String name )
@@ -99,9 +102,9 @@ public class InterfaceDefaultMethodsTest extends AbstractPolygeneTest
         }
     }
 
+    @SideEffects( DefaultMethodsSideEffect.class )
     public interface DefaultMethodsSideEffects extends DefaultMethods
     {
-        @SideEffects( DefaultMethodsSideEffect.class )
         @Override
         default String sayHello( String name )
         {
@@ -112,25 +115,27 @@ public class InterfaceDefaultMethodsTest extends AbstractPolygeneTest
     public static abstract class DefaultMethodsSideEffect extends SideEffectOf<DefaultMethodsSideEffects>
         implements DefaultMethodsSideEffects
     {
-        static boolean invoked = false;
+        static int count;
 
         @Override
         public String sayHello( String name )
         {
-            invoked = true;
+            count++;
             return null;
         }
     }
 
     @Override
-    public void assemble( final ModuleAssembly module ) throws AssemblyException
+    public void assemble( final ModuleAssembly module )
+        throws AssemblyException
     {
         module.transients( DefaultMethods.class,
                            OverrideDefaultMethods.class,
                            MixinDefaultMethods.class,
                            DefaultMethodsConstraints.class,
                            DefaultMethodsConcerns.class,
-                           DefaultMethodsSideEffects.class );
+                           DefaultMethodsSideEffects.class
+                         );
     }
 
     @Test
@@ -168,20 +173,21 @@ public class InterfaceDefaultMethodsTest extends AbstractPolygeneTest
         }
     }
 
-    @Ignore( "POLYGENE-120" )
     @Test
     public void defaultMethodsConcerns()
     {
         DefaultMethodsConcerns composite = transientBuilderFactory.newTransient( DefaultMethodsConcerns.class
);
         assertThat( composite.sayHello( "John" ), equalTo( "Hello, concerned John!" ) );
+        assertThat( composite.sayGoodBye( "John" ), equalTo( "Good Bye, John!" ) );
     }
 
-    @Ignore( "POLYGENE-120" )
     @Test
     public void defaultMethodsSideEffects()
     {
         DefaultMethodsSideEffects composite = transientBuilderFactory.newTransient( DefaultMethodsSideEffects.class
);
         assertThat( composite.sayHello( "John" ), equalTo( "Hello, John!" ) );
-        assertThat( DefaultMethodsSideEffect.invoked, is( true ) );
+        assertThat( composite.sayHello( "John" ), equalTo( "Hello, John!" ) );
+        assertThat( composite.sayHello( "John" ), equalTo( "Hello, John!" ) );
+        assertThat( DefaultMethodsSideEffect.count, equalTo( 3 ) );
     }
 }

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/452c7292/tests/performance/src/perf/java/org/apache/polygene/test/performance/entitystore/jdbm/JdbmEntityStorePerformanceTest.java
----------------------------------------------------------------------
diff --git a/tests/performance/src/perf/java/org/apache/polygene/test/performance/entitystore/jdbm/JdbmEntityStorePerformanceTest.java
b/tests/performance/src/perf/java/org/apache/polygene/test/performance/entitystore/jdbm/JdbmEntityStorePerformanceTest.java
index 006cf85..3b4e179 100644
--- a/tests/performance/src/perf/java/org/apache/polygene/test/performance/entitystore/jdbm/JdbmEntityStorePerformanceTest.java
+++ b/tests/performance/src/perf/java/org/apache/polygene/test/performance/entitystore/jdbm/JdbmEntityStorePerformanceTest.java
@@ -21,7 +21,6 @@ import java.io.File;
 import org.apache.derby.iapi.services.io.FileUtil;
 import org.apache.polygene.api.common.Visibility;
 import org.apache.polygene.bootstrap.Assembler;
-import org.apache.polygene.bootstrap.AssemblyException;
 import org.apache.polygene.bootstrap.ModuleAssembly;
 import org.apache.polygene.cache.ehcache.EhCacheConfiguration;
 import org.apache.polygene.cache.ehcache.EhCachePoolService;
@@ -43,20 +42,15 @@ public class JdbmEntityStorePerformanceTest
 
     private static Assembler createAssembler()
     {
-        return new Assembler()
+        return module ->
         {
-            @Override
-            public void assemble( ModuleAssembly module )
-                throws AssemblyException
-            {
-                new JdbmEntityStoreAssembler().assemble( module );
-                ModuleAssembly configModule = module.layer().module( "Config" );
-                configModule.entities( JdbmConfiguration.class ).visibleIn( Visibility.layer
);
-                new EntityTestAssembler().assemble( configModule );
+            new JdbmEntityStoreAssembler().assemble( module );
+            ModuleAssembly configModule = module.layer().module( "Config" );
+            configModule.entities( JdbmConfiguration.class ).visibleIn( Visibility.layer
);
+            new EntityTestAssembler().assemble( configModule );
 
-                module.services( EhCachePoolService.class );
-                configModule.entities( EhCacheConfiguration.class ).visibleIn( Visibility.layer
);
-            }
+            module.services( EhCachePoolService.class );
+            configModule.entities( EhCacheConfiguration.class ).visibleIn( Visibility.layer
);
         };
     }
 


Mime
View raw message