You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@polygene.apache.org by pa...@apache.org on 2017/05/16 18:51:24 UTC
[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
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 <ni...@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 <ni...@hedhman.org>
Authored: Mon May 15 19:35:33 2017 +0800
Committer: niclas <ni...@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 );
};
}