polygene-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From nic...@apache.org
Subject [12/81] [abbrv] [partial] zest-java git commit: ZEST-195 ; Replace all "zest" with "polygene"
Date Sat, 17 Dec 2016 10:27:48 GMT
http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/composite/FragmentClassLoader.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/FragmentClassLoader.java b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/FragmentClassLoader.java
new file mode 100644
index 0000000..774bea7
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/FragmentClassLoader.java
@@ -0,0 +1,847 @@
+/*
+ *  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.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.polygene.api.entity.Lifecycle;
+import org.apache.polygene.api.mixin.Initializable;
+import org.apache.polygene.api.util.Classes;
+import org.apache.polygene.api.util.Methods;
+import org.objectweb.asm.ClassWriter;
+import org.objectweb.asm.Label;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.Type;
+
+import static org.apache.polygene.api.util.Classes.interfacesOf;
+import static org.objectweb.asm.Opcodes.AASTORE;
+import static org.objectweb.asm.Opcodes.ACC_PRIVATE;
+import static org.objectweb.asm.Opcodes.ACC_PUBLIC;
+import static org.objectweb.asm.Opcodes.ACC_STATIC;
+import static org.objectweb.asm.Opcodes.ACC_SUPER;
+import static org.objectweb.asm.Opcodes.ACONST_NULL;
+import static org.objectweb.asm.Opcodes.ALOAD;
+import static org.objectweb.asm.Opcodes.ANEWARRAY;
+import static org.objectweb.asm.Opcodes.ARETURN;
+import static org.objectweb.asm.Opcodes.ASTORE;
+import static org.objectweb.asm.Opcodes.ATHROW;
+import static org.objectweb.asm.Opcodes.BIPUSH;
+import static org.objectweb.asm.Opcodes.CHECKCAST;
+import static org.objectweb.asm.Opcodes.DLOAD;
+import static org.objectweb.asm.Opcodes.DRETURN;
+import static org.objectweb.asm.Opcodes.DUP;
+import static org.objectweb.asm.Opcodes.FLOAD;
+import static org.objectweb.asm.Opcodes.FRETURN;
+import static org.objectweb.asm.Opcodes.GETFIELD;
+import static org.objectweb.asm.Opcodes.GETSTATIC;
+import static org.objectweb.asm.Opcodes.GOTO;
+import static org.objectweb.asm.Opcodes.ICONST_0;
+import static org.objectweb.asm.Opcodes.ICONST_1;
+import static org.objectweb.asm.Opcodes.ICONST_2;
+import static org.objectweb.asm.Opcodes.ICONST_3;
+import static org.objectweb.asm.Opcodes.ICONST_4;
+import static org.objectweb.asm.Opcodes.ICONST_5;
+import static org.objectweb.asm.Opcodes.ILOAD;
+import static org.objectweb.asm.Opcodes.INVOKEINTERFACE;
+import static org.objectweb.asm.Opcodes.INVOKESPECIAL;
+import static org.objectweb.asm.Opcodes.INVOKESTATIC;
+import static org.objectweb.asm.Opcodes.INVOKEVIRTUAL;
+import static org.objectweb.asm.Opcodes.IRETURN;
+import static org.objectweb.asm.Opcodes.LLOAD;
+import static org.objectweb.asm.Opcodes.LRETURN;
+import static org.objectweb.asm.Opcodes.POP;
+import static org.objectweb.asm.Opcodes.PUTSTATIC;
+import static org.objectweb.asm.Opcodes.RETURN;
+import static org.objectweb.asm.Type.getInternalName;
+
+/**
+ * Generate subclasses of mixins/modifiers that implement all interfaces not in the class itself
+ * and which delegates those calls to a given composite invoker.
+ */
+@SuppressWarnings( "raw" )
+public class FragmentClassLoader
+    extends ClassLoader
+{
+    private static final int JDK_VERSION;
+    public static final String GENERATED_POSTFIX = "_Stub";
+
+    static
+    {
+        String jdkString = System.getProperty( "java.specification.version" );
+        switch( jdkString )
+        {
+        case "1.8":
+            JDK_VERSION = Opcodes.V1_8;
+            break;
+        case "1.7":
+        default:
+            JDK_VERSION = Opcodes.V1_7;
+            break;
+        }
+    }
+
+    public FragmentClassLoader( ClassLoader parent )
+    {
+        super( parent );
+    }
+
+    @Override
+    protected Class findClass( String name )
+        throws ClassNotFoundException
+    {
+        if( name.endsWith( GENERATED_POSTFIX ) )
+        {
+            Class baseClass;
+            String baseName = name.substring( 0, name.length() - 5 );
+            try
+            {
+                baseClass = loadClass( baseName );
+            }
+            catch( ClassNotFoundException e )
+            {
+                // Try replacing the last _ with $
+                while( true )
+                {
+                    int idx = baseName.lastIndexOf( "_" );
+                    if( idx != -1 )
+                    {
+                        baseName = baseName.substring( 0, idx ) + "$" + baseName.substring( idx + 1 );
+                        try
+                        {
+                            baseClass = loadClass( baseName );
+                            break;
+                        }
+                        catch( ClassNotFoundException e1 )
+                        {
+                            // Try again
+                        }
+                    }
+                    else
+                    {
+                        throw e;
+                    }
+                }
+            }
+            //  To Allow JDK classes to be composed.
+            if( name.startsWith( "java." ) )
+            {
+                name = "polygene." + name;
+            }
+
+            byte[] b = generateClass( name, baseClass );
+            return defineClass( name, b, 0, b.length, baseClass.getProtectionDomain() );
+        }
+
+        // Try the classloader of this classloader -> get classes in Polygene such as CompositeInvoker
+        return getClass().getClassLoader().loadClass( name );
+    }
+
+    public byte[] generateClass( String name, Class baseClass )
+        throws ClassNotFoundException
+    {
+        String classSlash = name.replace( '.', '/' );
+        String baseClassSlash = getInternalName( baseClass );
+
+        ClassWriter cw = new ClassWriter( ClassWriter.COMPUTE_MAXS );
+
+        // Class definition start
+        cw.visit( JDK_VERSION, ACC_PUBLIC + ACC_SUPER, classSlash, null, baseClassSlash, null );
+
+        // Composite reference
+        {
+            cw.visitField( ACC_PUBLIC, "_instance", "Lorg/apache/polygene/api/composite/CompositeInvoker;", null, null )
+                .visitEnd();
+        }
+
+        // Static Method references
+        boolean hasProxyMethods = false;
+        {
+            int idx = 1;
+            for( Method method : baseClass.getMethods() )
+            {
+                if( isOverridden( method, baseClass ) )
+                {
+                    cw.visitField( ACC_PRIVATE + ACC_STATIC, "m" + idx++, "Ljava/lang/reflect/Method;", null, null )
+                        .visitEnd();
+                    hasProxyMethods = true;
+                }
+            }
+        }
+
+        // Constructors
+        for( Constructor constructor : baseClass.getDeclaredConstructors() )
+        {
+            if( Modifier.isPublic( constructor.getModifiers() ) || Modifier.isProtected( constructor.getModifiers() ) )
+            {
+                String desc = org.objectweb.asm.commons.Method.getMethod( constructor ).getDescriptor();
+                MethodVisitor mv = cw.visitMethod( ACC_PUBLIC, "<init>", desc, null, null );
+                mv.visitCode();
+                mv.visitVarInsn( ALOAD, 0 );
+
+                int idx = 1;
+                for( Class aClass : constructor.getParameterTypes() )
+                {
+                    final int opcode;
+                    if( aClass.equals( Integer.TYPE ) )
+                    {
+                        opcode = ILOAD;
+                    }
+                    else if( aClass.equals( Long.TYPE ) )
+                    {
+                        opcode = LLOAD;
+                    }
+                    else if( aClass.equals( Float.TYPE ) )
+                    {
+                        opcode = FLOAD;
+                    }
+                    else if( aClass.equals( Double.TYPE ) )
+                    {
+                        opcode = DLOAD;
+                    }
+                    else
+                    {
+                        opcode = ALOAD;
+                    }
+                    mv.visitVarInsn( opcode, idx++ );
+                }
+
+                mv.visitMethodInsn( INVOKESPECIAL, baseClassSlash, "<init>", desc, false );
+                mv.visitInsn( RETURN );
+                mv.visitMaxs( idx, idx );
+                mv.visitEnd();
+            }
+        }
+
+        // Overloaded and unimplemented methods
+        if( hasProxyMethods )
+        {
+            Method[] methods = baseClass.getMethods();
+            int idx = 0;
+            List<Label> exceptionLabels = new ArrayList<>();
+            for( Method method : methods )
+            {
+                if( isOverridden( method, baseClass ) )
+                {
+                    idx++;
+                    String methodName = method.getName();
+                    String desc = org.objectweb.asm.commons.Method.getMethod( method ).getDescriptor();
+
+                    String[] exceptions = null;
+                    {
+                        MethodVisitor mv = cw.visitMethod( ACC_PUBLIC, methodName, desc, null, null );
+                        if( isInternalPolygeneMethod( method, baseClass ) )
+                        {
+                            // generate a NoOp method...
+                            mv.visitInsn( RETURN );
+                        }
+                        else
+                        {
+                            Label endLabel = null; // Use this if return type is void
+                            if( method.getExceptionTypes().length > 0 )
+                            {
+                                exceptions = new String[ method.getExceptionTypes().length ];
+                                for( int i = 0; i < method.getExceptionTypes().length; i++ )
+                                {
+                                    Class<?> aClass = method.getExceptionTypes()[ i ];
+                                    exceptions[ i ] = getInternalName( aClass );
+                                }
+                            }
+                            mv.visitCode();
+                            Label l0 = new Label();
+                            Label l1 = new Label();
+
+                            exceptionLabels.clear();
+                            for( Class<?> declaredException : method.getExceptionTypes() )
+                            {
+                                Label ld = new Label();
+                                mv.visitTryCatchBlock( l0, l1, ld, getInternalName( declaredException ) );
+                                exceptionLabels.add( ld ); // Reuse this further down for the catch
+                            }
+
+                            Label lruntime = new Label();
+                            mv.visitTryCatchBlock( l0, l1, lruntime, "java/lang/RuntimeException" );
+                            Label lerror = new Label();
+                            mv.visitTryCatchBlock( l0, l1, lerror, "java/lang/Throwable" );
+
+                            mv.visitLabel( l0 );
+                            mv.visitVarInsn( ALOAD, 0 );
+                            mv.visitFieldInsn( GETFIELD, classSlash, "_instance",
+                                               "Lorg/apache/polygene/api/composite/CompositeInvoker;" );
+                            mv.visitFieldInsn( GETSTATIC, classSlash, "m" + idx, "Ljava/lang/reflect/Method;" );
+
+                            int paramCount = method.getParameterTypes().length;
+                            int stackIdx = 0;
+                            if( paramCount == 0 )
+                            {
+                                // Send in null as parameter
+                                mv.visitInsn( ACONST_NULL );
+                            }
+                            else
+                            {
+                                insn( mv, paramCount );
+                                mv.visitTypeInsn( ANEWARRAY, "java/lang/Object" );
+                                int pidx = 0;
+                                for( Class<?> aClass : method.getParameterTypes() )
+                                {
+                                    mv.visitInsn( DUP );
+                                    insn( mv, pidx++ );
+                                    stackIdx = wrapParameter( mv, aClass, stackIdx + 1 );
+                                    mv.visitInsn( AASTORE );
+                                }
+                            }
+
+                            // Call method
+                            mv.visitMethodInsn( INVOKEINTERFACE, "org/apache/zest/api/composite/CompositeInvoker",
+                                                "invokeComposite",
+                                                "(Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;", true );
+
+                            // Return value
+                            if( !method.getReturnType().equals( Void.TYPE ) )
+                            {
+                                unwrapResult( mv, method.getReturnType(), l1 );
+                            }
+                            else
+                            {
+                                mv.visitInsn( POP );
+                                mv.visitLabel( l1 );
+                                endLabel = new Label();
+                                mv.visitJumpInsn( GOTO, endLabel );
+                            }
+
+                            // Increase stack to beyond method args
+                            stackIdx++;
+
+                            // Declared exceptions
+                            int exceptionIdx = 0;
+                            for( Class<?> aClass : method.getExceptionTypes() )
+                            {
+                                mv.visitLabel( exceptionLabels.get( exceptionIdx++ ) );
+                                mv.visitFrame( Opcodes.F_SAME1, 0, null, 1, new Object[]{ getInternalName( aClass ) } );
+                                mv.visitVarInsn( ASTORE, stackIdx );
+                                mv.visitVarInsn( ALOAD, stackIdx );
+                                mv.visitInsn( ATHROW );
+                            }
+
+                            // RuntimeException and Error catch-all
+                            mv.visitLabel( lruntime );
+                            mv.visitFrame( Opcodes.F_SAME1, 0, null, 1, new Object[]{ "java/lang/RuntimeException" } );
+                            mv.visitVarInsn( ASTORE, stackIdx );
+                            mv.visitVarInsn( ALOAD, stackIdx );
+                            mv.visitInsn( ATHROW );
+
+                            mv.visitLabel( lerror );
+                            mv.visitFrame( Opcodes.F_SAME1, 0, null, 1, new Object[]{ "java/lang/Throwable" } );
+                            mv.visitVarInsn( ASTORE, stackIdx );
+                            mv.visitVarInsn( ALOAD, stackIdx );
+                            mv.visitTypeInsn( CHECKCAST, "java/lang/Error" );
+                            mv.visitInsn( ATHROW );
+
+                            // Return type = void
+                            if( endLabel != null )
+                            {
+                                mv.visitLabel( endLabel );
+                                mv.visitFrame( Opcodes.F_SAME, 0, null, 0, null );
+                                mv.visitInsn( RETURN );
+                            }
+
+                            mv.visitMaxs( 0, 0 );
+                            mv.visitEnd();
+                        }
+                    }
+
+                    if( !Modifier.isAbstract( method.getModifiers() ) )
+                    {
+                        // Add method with _ as prefix
+                        MethodVisitor mv = cw.visitMethod( ACC_PUBLIC, "_" + method.getName(), desc, null, exceptions );
+                        mv.visitCode();
+                        mv.visitVarInsn( ALOAD, 0 );
+
+                        // Parameters
+                        int stackIdx = 1;
+                        for( Class<?> aClass : method.getParameterTypes() )
+                        {
+                            stackIdx = loadParameter( mv, aClass, stackIdx ) + 1;
+                        }
+
+                        // Call method
+                        mv.visitMethodInsn( INVOKESPECIAL, baseClassSlash, method.getName(), desc, false );
+
+                        // Return value
+                        if( !method.getReturnType().equals( Void.TYPE ) )
+                        {
+                            returnResult( mv, method.getReturnType() );
+                        }
+                        else
+                        {
+                            mv.visitInsn( RETURN );
+                        }
+
+                        mv.visitMaxs( 1, 1 );
+                        mv.visitEnd();
+                    }
+                }
+            }
+
+            // Class initializer
+            {
+                MethodVisitor mv = cw.visitMethod( ACC_STATIC, "<clinit>", "()V", null, null );
+                mv.visitCode();
+                Label l0 = new Label();
+                Label l1 = new Label();
+                Label l2 = new Label();
+                mv.visitTryCatchBlock( l0, l1, l2, "java/lang/NoSuchMethodException" );
+                mv.visitLabel( l0 );
+
+                // Lookup methods and store in static variables
+                int midx = 0;
+                for( Method method : methods )
+                {
+                    if( isOverridden( method, baseClass ) )
+                    {
+                        method.setAccessible( true );
+                        Class methodClass;
+                        if( Modifier.isAbstract( method.getModifiers() ) )
+                        {
+                            methodClass = method.getDeclaringClass();
+                        }
+                        else
+                        {
+                            try
+                            {
+                                methodClass = getInterfaceMethodDeclaration( method,
+                                                                             baseClass ); // Overridden method lookup
+                            }
+                            catch( NoSuchMethodException e )
+                            {
+                                throw new ClassNotFoundException( name, e );
+                            }
+                        }
+
+                        midx++;
+
+                        mv.visitLdcInsn( Type.getType( methodClass ) );
+                        mv.visitLdcInsn( method.getName() );
+                        insn( mv, method.getParameterTypes().length );
+                        mv.visitTypeInsn( ANEWARRAY, "java/lang/Class" );
+
+                        int pidx = 0;
+                        for( Class<?> aClass : method.getParameterTypes() )
+                        {
+                            mv.visitInsn( DUP );
+                            insn( mv, pidx++ );
+                            type( mv, aClass );
+                            mv.visitInsn( AASTORE );
+                        }
+
+                        mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/Class", "getMethod",
+                                            "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;", false );
+                        mv.visitFieldInsn( PUTSTATIC, classSlash, "m" + midx, "Ljava/lang/reflect/Method;" );
+                    }
+                }
+
+                mv.visitLabel( l1 );
+                Label l3 = new Label();
+                mv.visitJumpInsn( GOTO, l3 );
+                mv.visitLabel( l2 );
+                mv.visitFrame( Opcodes.F_SAME1, 0, null, 1, new Object[]{ "java/lang/NoSuchMethodException" } );
+                mv.visitVarInsn( ASTORE, 0 );
+                mv.visitVarInsn( ALOAD, 0 );
+                mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/NoSuchMethodException", "printStackTrace", "()V", false );
+                mv.visitLabel( l3 );
+                mv.visitFrame( Opcodes.F_SAME, 0, null, 0, null );
+                mv.visitInsn( RETURN );
+                mv.visitMaxs( 6, 1 );
+                mv.visitEnd();
+            }
+        }
+        cw.visitEnd();
+        return cw.toByteArray();
+    }
+
+    private static boolean isOverridden( Method method, Class baseClass )
+    {
+        if( Modifier.isAbstract( method.getModifiers() ) )
+        {
+            return true; // Implement all abstract methods
+        }
+
+        if( Modifier.isFinal( method.getModifiers() ) )
+        {
+            return false; // Cannot override final methods
+        }
+
+        if( isInterfaceMethod( method, baseClass ) )
+        {
+            // if() used for clarity.
+            //noinspection RedundantIfStatement
+            if( isInternalPolygeneMethod( method, baseClass ) )
+            {
+                return false; // Skip methods in Polygene-internal interfaces
+            }
+            else
+            {
+                return true;
+            }
+        }
+        else
+        {
+            return false;
+        }
+    }
+
+    private static boolean isInternalPolygeneMethod( Method method, Class baseClass )
+    {
+        return isDeclaredIn( method, Initializable.class, baseClass )
+               || isDeclaredIn( method, Lifecycle.class, baseClass );
+    }
+
+    private static boolean isDeclaredIn( Method method, Class<?> clazz, Class<?> baseClass )
+    {
+        return clazz.isAssignableFrom( baseClass ) && checkForMethod( method, clazz );
+    }
+
+    private static Class getInterfaceMethodDeclaration( Method method, Class clazz )
+        throws NoSuchMethodException
+    {
+        return interfacesOf( clazz )
+            .map( Classes.RAW_CLASS )
+            .filter( intface -> checkForMethod( method, intface ) )
+            .findFirst()
+            .orElseThrow( () -> new NoSuchMethodException( method.getName() ) );
+    }
+
+    private static boolean isInterfaceMethod( Method method, Class<?> baseClass )
+    {
+        return interfacesOf( baseClass )
+            .map( Classes.RAW_CLASS )
+            .filter( Methods.HAS_METHODS )
+            .anyMatch( intface -> checkForMethod( method, intface ));
+    }
+
+    private static boolean checkForMethod( Method method, Class<?> intface )
+    {
+        try
+        {
+            Method m = intface.getMethod( method.getName(), method.getParameterTypes() );
+            m.setAccessible( true );
+            return true;
+        }
+        catch( NoSuchMethodException e )
+        {
+            return false;
+        }
+    }
+
+    private static void type( MethodVisitor mv, Class<?> aClass )
+    {
+        if( aClass.equals( Integer.TYPE ) )
+        {
+            mv.visitFieldInsn( GETSTATIC, "java/lang/Integer", "TYPE", "Ljava/lang/Class;" );
+        }
+        else if( aClass.equals( Long.TYPE ) )
+        {
+            mv.visitFieldInsn( GETSTATIC, "java/lang/Long", "TYPE", "Ljava/lang/Class;" );
+        }
+        else if( aClass.equals( Short.TYPE ) )
+        {
+            mv.visitFieldInsn( GETSTATIC, "java/lang/Short", "TYPE", "Ljava/lang/Class;" );
+        }
+        else if( aClass.equals( Byte.TYPE ) )
+        {
+            mv.visitFieldInsn( GETSTATIC, "java/lang/Byte", "TYPE", "Ljava/lang/Class;" );
+        }
+        else if( aClass.equals( Double.TYPE ) )
+        {
+            mv.visitFieldInsn( GETSTATIC, "java/lang/Double", "TYPE", "Ljava/lang/Class;" );
+        }
+        else if( aClass.equals( Float.TYPE ) )
+        {
+            mv.visitFieldInsn( GETSTATIC, "java/lang/Float", "TYPE", "Ljava/lang/Class;" );
+        }
+        else if( aClass.equals( Boolean.TYPE ) )
+        {
+            mv.visitFieldInsn( GETSTATIC, "java/lang/Boolean", "TYPE", "Ljava/lang/Class;" );
+        }
+        else if( aClass.equals( Character.TYPE ) )
+        {
+            mv.visitFieldInsn( GETSTATIC, "java/lang/Character", "TYPE", "Ljava/lang/Class;" );
+        }
+        else
+        {
+            mv.visitLdcInsn( Type.getType( aClass ) );
+        }
+    }
+
+    private static int wrapParameter( MethodVisitor mv, Class<?> aClass, int idx )
+    {
+        if( aClass.equals( Integer.TYPE ) )
+        {
+            mv.visitVarInsn( ILOAD, idx );
+            mv.visitMethodInsn( INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", false );
+        }
+        else if( aClass.equals( Long.TYPE ) )
+        {
+            mv.visitVarInsn( LLOAD, idx );
+            mv.visitMethodInsn( INVOKESTATIC, "java/lang/Long", "valueOf", "(J)Ljava/lang/Long;", false );
+            idx++; // Extra jump
+        }
+        else if( aClass.equals( Short.TYPE ) )
+        {
+            mv.visitVarInsn( ILOAD, idx );
+            mv.visitMethodInsn( INVOKESTATIC, "java/lang/Short", "valueOf", "(S)Ljava/lang/Short;", false );
+        }
+        else if( aClass.equals( Byte.TYPE ) )
+        {
+            mv.visitVarInsn( ILOAD, idx );
+            mv.visitMethodInsn( INVOKESTATIC, "java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;", false );
+        }
+        else if( aClass.equals( Double.TYPE ) )
+        {
+            mv.visitVarInsn( DLOAD, idx );
+            idx++; // Extra jump
+            mv.visitMethodInsn( INVOKESTATIC, "java/lang/Double", "valueOf", "(D)Ljava/lang/Double;", false );
+        }
+        else if( aClass.equals( Float.TYPE ) )
+        {
+            mv.visitVarInsn( FLOAD, idx );
+            mv.visitMethodInsn( INVOKESTATIC, "java/lang/Float", "valueOf", "(F)Ljava/lang/Float;", false );
+        }
+        else if( aClass.equals( Boolean.TYPE ) )
+        {
+            mv.visitVarInsn( ILOAD, idx );
+            mv.visitMethodInsn( INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;", false );
+        }
+        else if( aClass.equals( Character.TYPE ) )
+        {
+            mv.visitVarInsn( ILOAD, idx );
+            mv.visitMethodInsn( INVOKESTATIC, "java/lang/Character", "valueOf", "(C)Ljava/lang/Character;", false );
+        }
+        else
+        {
+            mv.visitVarInsn( ALOAD, idx );
+        }
+
+        return idx;
+    }
+
+    private static void unwrapResult( MethodVisitor mv, Class<?> aClass, Label label )
+    {
+        if( aClass.equals( Integer.TYPE ) )
+        {
+            mv.visitTypeInsn( CHECKCAST, "java/lang/Integer" );
+            mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I", false );
+            mv.visitLabel( label );
+            mv.visitInsn( IRETURN );
+        }
+        else if( aClass.equals( Long.TYPE ) )
+        {
+            mv.visitTypeInsn( CHECKCAST, "java/lang/Long" );
+            mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/Long", "longValue", "()J", false );
+            mv.visitLabel( label );
+            mv.visitInsn( LRETURN );
+        }
+        else if( aClass.equals( Short.TYPE ) )
+        {
+            mv.visitTypeInsn( CHECKCAST, "java/lang/Short" );
+            mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/Short", "shortValue", "()S", false );
+            mv.visitLabel( label );
+            mv.visitInsn( IRETURN );
+        }
+        else if( aClass.equals( Byte.TYPE ) )
+        {
+            mv.visitTypeInsn( CHECKCAST, "java/lang/Byte" );
+            mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/Byte", "byteValue", "()B", false );
+            mv.visitLabel( label );
+            mv.visitInsn( IRETURN );
+        }
+        else if( aClass.equals( Double.TYPE ) )
+        {
+            mv.visitTypeInsn( CHECKCAST, "java/lang/Double" );
+            mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/Double", "doubleValue", "()D", false );
+            mv.visitLabel( label );
+            mv.visitInsn( DRETURN );
+        }
+        else if( aClass.equals( Float.TYPE ) )
+        {
+            mv.visitTypeInsn( CHECKCAST, "java/lang/Float" );
+            mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/Float", "floatValue", "()F", false );
+            mv.visitLabel( label );
+            mv.visitInsn( FRETURN );
+        }
+        else if( aClass.equals( Boolean.TYPE ) )
+        {
+            mv.visitTypeInsn( CHECKCAST, "java/lang/Boolean" );
+            mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/Boolean", "booleanValue", "()Z", false );
+            mv.visitLabel( label );
+            mv.visitInsn( IRETURN );
+        }
+        else if( aClass.equals( Character.TYPE ) )
+        {
+            mv.visitTypeInsn( CHECKCAST, "java/lang/Character" );
+            mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/Character", "charValue", "()C", false );
+            mv.visitLabel( label );
+            mv.visitInsn( IRETURN );
+        }
+        else
+        {
+            mv.visitTypeInsn( CHECKCAST, getInternalName( aClass ) );
+            mv.visitLabel( label );
+            mv.visitInsn( ARETURN );
+        }
+    }
+
+    private static int loadParameter( MethodVisitor mv, Class<?> aClass, int idx )
+    {
+        if( aClass.equals( Integer.TYPE ) )
+        {
+            mv.visitVarInsn( ILOAD, idx );
+        }
+        else if( aClass.equals( Long.TYPE ) )
+        {
+            mv.visitVarInsn( LLOAD, idx );
+            idx++; // Extra jump
+        }
+        else if( aClass.equals( Short.TYPE ) )
+        {
+            mv.visitVarInsn( ILOAD, idx );
+        }
+        else if( aClass.equals( Byte.TYPE ) )
+        {
+            mv.visitVarInsn( ILOAD, idx );
+        }
+        else if( aClass.equals( Double.TYPE ) )
+        {
+            mv.visitVarInsn( DLOAD, idx );
+            idx++; // Extra jump
+        }
+        else if( aClass.equals( Float.TYPE ) )
+        {
+            mv.visitVarInsn( FLOAD, idx );
+        }
+        else if( aClass.equals( Boolean.TYPE ) )
+        {
+            mv.visitVarInsn( ILOAD, idx );
+        }
+        else if( aClass.equals( Character.TYPE ) )
+        {
+            mv.visitVarInsn( ILOAD, idx );
+        }
+        else
+        {
+            mv.visitVarInsn( ALOAD, idx );
+        }
+
+        return idx;
+    }
+
+    private static void returnResult( MethodVisitor mv, Class<?> aClass )
+    {
+        if( aClass.equals( Integer.TYPE ) )
+        {
+            mv.visitInsn( IRETURN );
+        }
+        else if( aClass.equals( Long.TYPE ) )
+        {
+            mv.visitInsn( LRETURN );
+        }
+        else if( aClass.equals( Short.TYPE ) )
+        {
+            mv.visitInsn( IRETURN );
+        }
+        else if( aClass.equals( Byte.TYPE ) )
+        {
+            mv.visitInsn( IRETURN );
+        }
+        else if( aClass.equals( Double.TYPE ) )
+        {
+            mv.visitInsn( DRETURN );
+        }
+        else if( aClass.equals( Float.TYPE ) )
+        {
+            mv.visitInsn( FRETURN );
+        }
+        else if( aClass.equals( Boolean.TYPE ) )
+        {
+            mv.visitInsn( IRETURN );
+        }
+        else if( aClass.equals( Character.TYPE ) )
+        {
+            mv.visitInsn( IRETURN );
+        }
+        else
+        {
+            mv.visitTypeInsn( CHECKCAST, getInternalName( aClass ) );
+            mv.visitInsn( ARETURN );
+        }
+    }
+
+    private static void insn( MethodVisitor mv, int length )
+    {
+        switch( length )
+        {
+        case 0:
+            mv.visitInsn( ICONST_0 );
+            return;
+        case 1:
+            mv.visitInsn( ICONST_1 );
+            return;
+        case 2:
+            mv.visitInsn( ICONST_2 );
+            return;
+        case 3:
+            mv.visitInsn( ICONST_3 );
+            return;
+        case 4:
+            mv.visitInsn( ICONST_4 );
+            return;
+        case 5:
+            mv.visitInsn( ICONST_5 );
+            return;
+        default:
+            mv.visitIntInsn( BIPUSH, length );
+        }
+    }
+
+    public static boolean isGenerated( Class clazz )
+    {
+        return clazz.getName().endsWith( GENERATED_POSTFIX );
+    }
+
+    public static boolean isGenerated( Object object )
+    {
+        return object.getClass().getName().endsWith( GENERATED_POSTFIX );
+    }
+
+    public Class loadFragmentClass( Class fragmentClass )
+        throws ClassNotFoundException
+    {
+        return loadClass( fragmentClass.getName().replace( '$', '_' ) + GENERATED_POSTFIX );
+    }
+
+    public static Class getSourceClass( Class fragmentClass )
+    {
+        return fragmentClass.getName().endsWith( GENERATED_POSTFIX ) ? fragmentClass.getSuperclass() : fragmentClass;
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/composite/FragmentInvocationHandler.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/FragmentInvocationHandler.java b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/FragmentInvocationHandler.java
new file mode 100644
index 0000000..f0dfca6
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/FragmentInvocationHandler.java
@@ -0,0 +1,137 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *
+ */
+package org.apache.polygene.runtime.composite;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+
+/**
+ * JAVADOC
+ */
+abstract class FragmentInvocationHandler
+    implements InvocationHandler
+{
+    private static final String COMPACT_TRACE = "polygene.compacttrace";
+
+    private static final CompactLevel compactLevel;
+
+    static
+    {
+        compactLevel = CompactLevel.valueOf( System.getProperty( COMPACT_TRACE, "proxy" ) );
+    }
+
+    protected Object fragment;
+    protected Method method;
+
+    void setFragment( Object fragment )
+    {
+        this.fragment = fragment;
+    }
+
+    public void setMethod( Method method )
+    {
+        this.method = method;
+    }
+
+    protected Throwable cleanStackTrace( Throwable throwable, Object proxy, Method method )
+    {
+        if( compactLevel == CompactLevel.off )
+        {
+            return throwable;
+        }
+
+        StackTraceElement[] trace = throwable.getStackTrace();
+
+        // Check if exception originated within Polygene or JDK - if so then skip compaction
+        if( trace.length == 0 || !isApplicationClass( trace[ 0 ].getClassName() ) )
+        {
+            return throwable;
+        }
+
+        int count = 0;
+        for( int i = 0; i < trace.length; i++ )
+        {
+            StackTraceElement stackTraceElement = trace[ i ];
+            if( !isApplicationClass( stackTraceElement.getClassName() ) )
+            {
+                // TODO: Should find stack entry outside Runtime, and compact beyond that
+                trace[ i ] = null;
+                count++;
+            }
+            else
+            {
+                boolean classOrigin = stackTraceElement.getClassName().equals( proxy.getClass().getSimpleName() );
+                boolean methodOrigin = stackTraceElement.getMethodName().equals( method.getName() );
+                if( classOrigin && methodOrigin && compactLevel == CompactLevel.proxy )
+                {
+                    // Stop removing if the originating method call has been located in the stack.
+                    // For 'semi' and 'extensive' compaction, we don't and do the entire stack instead.
+                    trace[ i ] = new StackTraceElement( proxy.getClass()
+                                                            .getInterfaces()[ 0 ].getName(), method.getName(), null, -1 );
+                    break; // Stop compacting this trace
+                }
+            }
+        }
+
+        // Create new trace array
+        int idx = 0;
+        StackTraceElement[] newTrace = new StackTraceElement[ trace.length - count ];
+        for( StackTraceElement stackTraceElement : trace )
+        {
+            if( stackTraceElement != null )
+            {
+                newTrace[ idx++ ] = stackTraceElement;
+            }
+        }
+        throwable.setStackTrace( newTrace );
+
+        Throwable nested = throwable.getCause();
+        if( nested != null )
+        {
+            //noinspection ThrowableResultOfMethodCallIgnored
+            cleanStackTrace( nested, proxy, method );
+        }
+        for( Throwable suppressed : throwable.getSuppressed() )
+        {
+            //noinspection ThrowableResultOfMethodCallIgnored
+            cleanStackTrace( suppressed, proxy, method );
+        }
+        return throwable;
+    }
+
+    private boolean isApplicationClass( String className )
+    {
+        if( compactLevel == CompactLevel.semi )
+        {
+            return !isJdkInternals( className );
+        }
+        return !( className.endsWith( FragmentClassLoader.GENERATED_POSTFIX ) ||
+                  className.startsWith( "org.apache.polygene.runtime" ) ||
+                  isJdkInternals( className ) );
+    }
+
+    private boolean isJdkInternals( String className )
+    {
+        return className.startsWith( "java.lang.reflect" )
+               || className.startsWith( "jdk.internal.reflect" )
+               || className.startsWith( "com.sun.proxy" )
+               || className.startsWith( "sun.reflect" );
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/composite/FunctionStateResolver.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/FunctionStateResolver.java b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/FunctionStateResolver.java
new file mode 100644
index 0000000..1357568
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/FunctionStateResolver.java
@@ -0,0 +1,115 @@
+/*
+ *  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.util.Map;
+import java.util.function.Function;
+import java.util.stream.Stream;
+import org.apache.polygene.api.association.AssociationDescriptor;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.property.PropertyDescriptor;
+import org.apache.polygene.runtime.entity.EntityModel;
+import org.apache.polygene.spi.entity.EntityState;
+import org.apache.polygene.spi.entity.ManyAssociationState;
+import org.apache.polygene.spi.entity.NamedAssociationState;
+
+/**
+ * Function based StateResolver.
+ */
+public class FunctionStateResolver
+    implements StateResolver
+{
+    final Function<PropertyDescriptor, Object> propertyFunction;
+    final Function<AssociationDescriptor, EntityReference> associationFunction;
+    final Function<AssociationDescriptor, Stream<EntityReference>> manyAssociationFunction;
+    final Function<AssociationDescriptor, Stream<Map.Entry<String, EntityReference>>> namedAssociationFunction;
+
+    public FunctionStateResolver( Function<PropertyDescriptor, Object> propertyFunction,
+                                  Function<AssociationDescriptor, EntityReference> associationFunction,
+                                  Function<AssociationDescriptor, Stream<EntityReference>> manyAssociationFunction,
+                                  Function<AssociationDescriptor, Stream<Map.Entry<String, EntityReference>>> namedAssociationFunction )
+    {
+        this.propertyFunction = propertyFunction;
+        this.associationFunction = associationFunction;
+        this.manyAssociationFunction = manyAssociationFunction;
+        this.namedAssociationFunction = namedAssociationFunction;
+    }
+
+    @Override
+    public Object getPropertyState( PropertyDescriptor propertyDescriptor )
+    {
+        return propertyFunction.apply( propertyDescriptor );
+    }
+
+    @Override
+    public EntityReference getAssociationState( AssociationDescriptor associationDescriptor )
+    {
+        return associationFunction.apply( associationDescriptor );
+    }
+
+    @Override
+    public Stream<EntityReference> getManyAssociationState( AssociationDescriptor associationDescriptor )
+    {
+        return manyAssociationFunction.apply( associationDescriptor );
+    }
+
+    @Override
+    public Stream<Map.Entry<String, EntityReference>> getNamedAssociationState(
+        AssociationDescriptor associationDescriptor )
+    {
+        return namedAssociationFunction.apply( associationDescriptor );
+    }
+
+    public void populateState( EntityModel model, EntityState state )
+    {
+        model.state().properties().forEach(
+            propDesc ->
+            {
+                Object value = getPropertyState( propDesc );
+                state.setPropertyValue( propDesc.qualifiedName(), value );
+            } );
+        model.state().associations().forEach(
+            assDesc ->
+            {
+                EntityReference ref = getAssociationState( assDesc );
+                state.setAssociationValue( assDesc.qualifiedName(), ref );
+            } );
+        model.state().manyAssociations().forEach(
+            manyAssDesc ->
+            {
+                ManyAssociationState associationState = state.manyAssociationValueOf( manyAssDesc.qualifiedName() );
+                // First clear existing ones
+                associationState.forEach( associationState::remove );
+                // then add the new ones.
+                getManyAssociationState( manyAssDesc )
+                    .forEach( ref -> associationState.add( 0, ref ) );
+            } );
+        model.state().namedAssociations().forEach(
+            namedAssDesc ->
+            {
+                NamedAssociationState associationState = state.namedAssociationValueOf( namedAssDesc.qualifiedName() );
+                // First clear existing ones
+                associationState.forEach( associationState::remove );
+                // then add the new ones.
+                getNamedAssociationState( namedAssDesc )
+                    .forEach( entry -> associationState.put( entry.getKey(), entry.getValue() ) );
+            } );
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/composite/GenericFragmentInvocationHandler.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/GenericFragmentInvocationHandler.java b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/GenericFragmentInvocationHandler.java
new file mode 100644
index 0000000..44259e8
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/GenericFragmentInvocationHandler.java
@@ -0,0 +1,51 @@
+/*
+ *  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.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+/**
+ * JAVADOC
+ */
+public final class GenericFragmentInvocationHandler
+    extends FragmentInvocationHandler
+{
+    // InvocationHandler implementation ------------------------------
+
+    @Override
+    public Object invoke( Object proxy, Method method, Object[] args )
+        throws Throwable
+    {
+        try
+        {
+            return ( (InvocationHandler) fragment ).invoke( proxy, method, args );
+        }
+        catch( InvocationTargetException throwable )
+        {
+            throw cleanStackTrace( throwable.getTargetException(), proxy, method );
+        }
+        catch( Throwable throwable )
+        {
+            throw cleanStackTrace( throwable, proxy, method );
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/composite/Genericpredicate.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/Genericpredicate.java b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/Genericpredicate.java
new file mode 100644
index 0000000..e8c5cea
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/Genericpredicate.java
@@ -0,0 +1,38 @@
+/*
+ *  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.reflect.InvocationHandler;
+import java.util.function.Predicate;
+
+/**
+ * Specification that checks whether a given class implements InvocationHandler or not.
+ */
+public class Genericpredicate
+    implements Predicate<Class<?>>
+{
+    public static final Genericpredicate INSTANCE = new Genericpredicate();
+
+    @Override
+    public boolean test( Class<?> item )
+    {
+        return InvocationHandler.class.isAssignableFrom( item );
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/composite/InstancePool.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/InstancePool.java b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/InstancePool.java
new file mode 100644
index 0000000..0eec577
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/InstancePool.java
@@ -0,0 +1,30 @@
+/*
+ *  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;
+
+/**
+ * JAVADOC
+ */
+public interface InstancePool<T>
+{
+    public T obtainInstance();
+
+    public void releaseInstance( T instance );
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/composite/MixinModel.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/MixinModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/MixinModel.java
new file mode 100644
index 0000000..37722e6
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/MixinModel.java
@@ -0,0 +1,184 @@
+/*
+ *  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.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import org.apache.polygene.api.common.ConstructionException;
+import org.apache.polygene.api.composite.CompositeInstance;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.mixin.Initializable;
+import org.apache.polygene.api.mixin.InitializationException;
+import org.apache.polygene.api.mixin.MixinDescriptor;
+import org.apache.polygene.api.property.StateHolder;
+import org.apache.polygene.api.util.HierarchicalVisitor;
+import org.apache.polygene.api.util.VisitableHierarchy;
+import org.apache.polygene.runtime.injection.Dependencies;
+import org.apache.polygene.runtime.injection.DependencyModel;
+import org.apache.polygene.runtime.injection.InjectedFieldsModel;
+import org.apache.polygene.runtime.injection.InjectedMethodsModel;
+import org.apache.polygene.runtime.injection.InjectionContext;
+
+/**
+ * JAVADOC
+ */
+public final class MixinModel
+    implements MixinDescriptor, VisitableHierarchy<Object, Object>, Dependencies
+{
+    private final Class<?> mixinClass;
+    private final Class<?> instantiationClass;
+    private final ConstructorsModel constructorsModel;
+    private final InjectedFieldsModel injectedFieldsModel;
+    private final InjectedMethodsModel injectedMethodsModel;
+    private final List<Class<?>> thisMixinTypes;
+
+    public MixinModel( Class<?> declaredMixinClass, Class<?> instantiationClass )
+    {
+        injectedFieldsModel = new InjectedFieldsModel( declaredMixinClass );
+        injectedMethodsModel = new InjectedMethodsModel( declaredMixinClass );
+
+        this.mixinClass = declaredMixinClass;
+        this.instantiationClass = instantiationClass;
+        constructorsModel = new ConstructorsModel( instantiationClass );
+
+        thisMixinTypes = buildThisMixinTypes();
+    }
+
+    @Override
+    public Class<?> mixinClass()
+    {
+        return mixinClass;
+    }
+
+    public Class<?> instantiationClass()
+    {
+        return instantiationClass;
+    }
+
+    public boolean isGeneric()
+    {
+        return InvocationHandler.class.isAssignableFrom( mixinClass );
+    }
+
+    public Stream<DependencyModel> dependencies()
+    {
+        Stream<? extends Dependencies> models = Stream.of( constructorsModel, injectedFieldsModel, injectedMethodsModel );
+        return models.flatMap( Dependencies::dependencies );
+    }
+
+    @Override
+    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> visitor )
+        throws ThrowableType
+    {
+        if( visitor.visitEnter( this ) )
+        {
+            if( constructorsModel.accept( visitor ) )
+            {
+                if( injectedFieldsModel.accept( visitor ) )
+                {
+                    injectedMethodsModel.accept( visitor );
+                }
+            }
+        }
+        return visitor.visitLeave( this );
+    }
+
+    // Context
+    public Object newInstance( CompositeInstance compositeInstance, StateHolder state, UsesInstance uses )
+    {
+        InjectionContext injectionContext = new InjectionContext( compositeInstance, uses, state );
+        return newInstance( injectionContext );
+    }
+
+    public Object newInstance( InjectionContext injectionContext )
+    {
+        Object mixin;
+        CompositeInstance compositeInstance = injectionContext.compositeInstance();
+
+        mixin = constructorsModel.newInstance( injectionContext );
+
+        if( FragmentClassLoader.isGenerated( instantiationClass ) )
+        {
+            try
+            {
+                instantiationClass.getDeclaredField( "_instance" ).set( mixin,
+                                                                        injectionContext.compositeInstance() );
+            }
+            catch( IllegalAccessException | NoSuchFieldException e )
+            {
+                e.printStackTrace();
+            }
+        }
+
+        injectedFieldsModel.inject( injectionContext, mixin );
+        injectedMethodsModel.inject( injectionContext, mixin );
+        if( mixin instanceof Initializable )
+        {
+            try
+            {
+                ( (Initializable) mixin ).initialize();
+            }
+            catch( Exception e )
+            {
+                List<Class<?>> compositeType = compositeInstance.types().collect( Collectors.toList() );
+                String message = "Unable to initialize " + mixinClass + " in composite " + compositeType;
+                throw new ConstructionException( new InitializationException( message, e ) );
+            }
+        }
+        return mixin;
+    }
+
+    public Iterable<Class<?>> thisMixinTypes()
+    {
+        return thisMixinTypes;
+    }
+
+    private List<Class<?>> buildThisMixinTypes()
+    {
+        return dependencies()
+            .filter( new DependencyModel.ScopeSpecification( This.class ) )
+            .distinct()
+            .map( DependencyModel::rawInjectionType )
+            .collect( Collectors.toList() );
+    }
+
+    protected FragmentInvocationHandler newInvocationHandler( Method method )
+    {
+        if( InvocationHandler.class.isAssignableFrom( mixinClass )
+            && !method.getDeclaringClass().isAssignableFrom( mixinClass ) )
+        {
+            return new GenericFragmentInvocationHandler();
+        }
+        else
+        {
+            return new TypedModifierInvocationHandler();
+        }
+    }
+
+    @Override
+    public String toString()
+    {
+        return mixinClass.getName();
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/composite/MixinsInstance.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/MixinsInstance.java b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/MixinsInstance.java
new file mode 100644
index 0000000..b26f548
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/MixinsInstance.java
@@ -0,0 +1,35 @@
+/*
+ *  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.reflect.Method;
+
+/**
+ * JAVADOC
+ */
+public interface MixinsInstance
+{
+    Object invoke( Object composite, Object[] params, CompositeMethodInstance methodInstance )
+        throws Throwable;
+
+    Object invokeObject( Object proxy, Object[] args, Method method )
+        throws Throwable;
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/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
new file mode 100644
index 0000000..2f6e333
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/MixinsModel.java
@@ -0,0 +1,234 @@
+/*
+ *  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.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Stream;
+import org.apache.polygene.api.util.Classes;
+import org.apache.polygene.api.util.HierarchicalVisitor;
+import org.apache.polygene.api.util.HierarchicalVisitorAdapter;
+import org.apache.polygene.api.util.VisitableHierarchy;
+import org.apache.polygene.bootstrap.BindingException;
+import org.apache.polygene.runtime.injection.Dependencies;
+import org.apache.polygene.runtime.injection.DependencyModel;
+import org.apache.polygene.runtime.injection.InjectedFieldModel;
+import org.apache.polygene.runtime.model.Binder;
+import org.apache.polygene.runtime.model.Resolution;
+
+import static org.apache.polygene.api.util.Classes.interfacesOf;
+
+/**
+ * Base implementation of model for mixins. This records the mapping between methods in the Composite
+ * and mixin implementations.
+ */
+public class MixinsModel
+    implements Binder, VisitableHierarchy<Object, Object>, Dependencies
+{
+    protected final Map<Method, MixinModel> methodImplementation = new HashMap<Method, MixinModel>();
+    protected final Map<Method, Integer> methodIndex = new HashMap<Method, Integer>();
+    protected List<MixinModel> mixinModels = new ArrayList<MixinModel>();
+
+    private final Map<Class, Integer> mixinIndex = new HashMap<Class, Integer>();
+    private final Set<Class<?>> mixinTypes = new LinkedHashSet<Class<?>>();
+
+    public Stream<Class<?>> mixinTypes()
+    {
+        return mixinTypes.stream();
+    }
+
+    public <T> boolean isImplemented( Class<T> mixinType )
+    {
+        return mixinTypes.contains( mixinType );
+    }
+
+    public List<MixinModel> mixinModels()
+    {
+        return mixinModels;
+    }
+
+    public MixinModel mixinFor( Method method )
+    {
+        return methodImplementation.get( method );
+    }
+
+    public MixinModel getMixinModel( Class mixinClass )
+    {
+        for( MixinModel mixinModel : mixinModels )
+        {
+            if( mixinModel.mixinClass().equals( mixinClass ) )
+            {
+                return mixinModel;
+            }
+        }
+        return null;
+    }
+
+    public void addMixinType( Class mixinType )
+    {
+        Stream<? extends Type> stream = interfacesOf( mixinType );
+        Stream<Class<?>> rawClass = stream.map( Classes.RAW_CLASS );
+        rawClass.forEach( mixinTypes::add );
+    }
+
+    public void addMixinModel( MixinModel mixinModel )
+    {
+        mixinModels.add( mixinModel );
+    }
+
+    public void addMethodMixin( Method method, MixinModel mixinModel )
+    {
+        methodImplementation.put( method, mixinModel );
+    }
+
+    @Override
+    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> visitor )
+        throws ThrowableType
+    {
+        if( visitor.visitEnter( this ) )
+        {
+            for( MixinModel mixinModel : mixinModels )
+            {
+                mixinModel.accept( visitor );
+            }
+        }
+        return visitor.visitLeave( this );
+    }
+
+    // Binding
+    @Override
+    public void bind( final Resolution resolution )
+        throws BindingException
+    {
+        // Order mixins based on @This usages
+        UsageGraph<MixinModel> deps = new UsageGraph<MixinModel>( mixinModels, new Uses(), true );
+        mixinModels = deps.resolveOrder();
+
+        // Populate mappings
+        for( int i = 0; i < mixinModels.size(); i++ )
+        {
+            MixinModel mixinModel = mixinModels.get( i );
+            mixinIndex.put( mixinModel.mixinClass(), i );
+        }
+
+        for( Map.Entry<Method, MixinModel> methodClassEntry : methodImplementation.entrySet() )
+        {
+            methodIndex.put( methodClassEntry.getKey(), mixinIndex.get( methodClassEntry.getValue().mixinClass() ) );
+        }
+
+        for( MixinModel mixinModel : mixinModels )
+        {
+            mixinModel.accept( new HierarchicalVisitorAdapter<Object, Object, BindingException>()
+            {
+                @Override
+                public boolean visitEnter( Object visited )
+                    throws BindingException
+                {
+                    if( visited instanceof InjectedFieldModel )
+                    {
+                        InjectedFieldModel fieldModel = (InjectedFieldModel) visited;
+                        fieldModel.bind( resolution.forField( fieldModel.field() ) );
+                        return false;
+                    }
+                    else if( visited instanceof Binder )
+                    {
+                        Binder constructorsModel = (Binder) visited;
+                        constructorsModel.bind( resolution );
+
+                        return false;
+                    }
+                    return true;
+                }
+
+                @Override
+                public boolean visit( Object visited )
+                    throws BindingException
+                {
+                    if( visited instanceof Binder )
+                    {
+                        ( (Binder) visited ).bind( resolution );
+                    }
+                    return true;
+                }
+            } );
+        }
+    }
+
+    // Context
+
+    public Object[] newMixinHolder()
+    {
+        return new Object[ mixinIndex.size() ];
+    }
+
+    public FragmentInvocationHandler newInvocationHandler( final Method method )
+    {
+        return mixinFor( method ).newInvocationHandler( method );
+    }
+
+    public Stream<DependencyModel> dependencies()
+    {
+        return mixinModels.stream().flatMap( Dependencies::dependencies );
+    }
+
+    public Stream<Method> invocationsFor( final Class<?> mixinClass )
+    {
+        return methodImplementation.entrySet()
+            .stream().filter( entry -> entry.getValue().mixinClass().equals( mixinClass ) )
+            .map( Map.Entry::getKey );
+    }
+
+    private class Uses
+        implements UsageGraph.Use<MixinModel>
+    {
+        @Override
+        public Collection<MixinModel> uses( MixinModel source )
+        {
+            // System.out.println("BEGIN> MixinsModel.Uses.uses( "+source+" )");
+            Iterable<Class<?>> thisMixinTypes = source.thisMixinTypes();
+            List<MixinModel> usedMixinClasses = new ArrayList<MixinModel>();
+            // System.out.println("\tSource Mixin Types and Methods: ");
+            for( Class thisMixinType : thisMixinTypes )
+            {
+                // System.out.println("\t\t"+thisMixinType);
+                for( Method method : thisMixinType.getMethods() )
+                {
+                    // System.out.println("\t\t\t"+method);
+                    if( !Modifier.isStatic( method.getModifiers() ) )
+                    {
+                        MixinModel used = methodImplementation.get( method );
+                        usedMixinClasses.add( used );
+                    }
+                }
+            }
+            // System.out.println( "END>   MixinsModel.Uses.uses( " + source + " )" );
+            return usedMixinClasses;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ProxyGenerator.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ProxyGenerator.java b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ProxyGenerator.java
new file mode 100644
index 0000000..df7a02a
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ProxyGenerator.java
@@ -0,0 +1,35 @@
+/*
+ *  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.reflect.Proxy;
+
+/**
+ * generates proxyclasses
+ */
+public class ProxyGenerator {
+    public static Class<?> createProxyClass(ClassLoader mainTypeClassLoader, Class<?>[] interfaces) {
+        ClassLoader effectiveClassLoader = Thread.currentThread().getContextClassLoader();
+        if (effectiveClassLoader == null) {
+            effectiveClassLoader = mainTypeClassLoader;
+        }
+        return Proxy.getProxyClass(effectiveClassLoader, interfaces);
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ProxyReferenceInvocationHandler.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ProxyReferenceInvocationHandler.java b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ProxyReferenceInvocationHandler.java
new file mode 100644
index 0000000..5d125a2
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ProxyReferenceInvocationHandler.java
@@ -0,0 +1,86 @@
+/*
+ *  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.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.lang.reflect.UndeclaredThrowableException;
+import org.apache.polygene.api.composite.CompositeInvoker;
+
+public final class ProxyReferenceInvocationHandler
+    implements InvocationHandler, CompositeInvoker
+{
+    private Object proxy;
+
+    public Object proxy()
+    {
+        return proxy;
+    }
+
+    public void setProxy( Object proxy )
+    {
+        this.proxy = proxy;
+    }
+
+    public void clearProxy()
+    {
+        proxy = null;
+    }
+
+    @Override
+    public Object invokeComposite( Method method, Object[] args )
+        throws Throwable
+    {
+        try
+        {
+            InvocationHandler invocationHandler = Proxy.getInvocationHandler( this.proxy );
+            return invocationHandler.invoke( this.proxy, method, args );
+        }
+        catch( InvocationTargetException e )
+        {
+            throw e.getTargetException();
+        }
+        catch( UndeclaredThrowableException e )
+        {
+            throw e.getUndeclaredThrowable();
+        }
+    }
+
+    @Override
+    public Object invoke( Object proxy, Method method, Object[] args )
+        throws Throwable
+    {
+        try
+        {
+            InvocationHandler invocationHandler = Proxy.getInvocationHandler( this.proxy );
+            return invocationHandler.invoke( this.proxy, method, args );
+        }
+        catch( InvocationTargetException e )
+        {
+            throw e.getTargetException();
+        }
+        catch( UndeclaredThrowableException e )
+        {
+            throw e.getUndeclaredThrowable();
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/composite/SideEffectInvocationHandlerResult.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/SideEffectInvocationHandlerResult.java b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/SideEffectInvocationHandlerResult.java
new file mode 100644
index 0000000..44c10d5
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/SideEffectInvocationHandlerResult.java
@@ -0,0 +1,59 @@
+/*
+ *  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.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+
+/**
+ * JAVADOC
+ */
+public final class SideEffectInvocationHandlerResult
+    implements InvocationHandler
+{
+    private Object result;
+    private Throwable throwable;
+
+    public SideEffectInvocationHandlerResult()
+    {
+    }
+
+    public void setResult( Object result, Throwable throwable )
+    {
+        this.result = result;
+        this.throwable = throwable;
+    }
+
+    // InvocationHandler implementation ------------------------------
+
+    @Override
+    public Object invoke( Object proxy, Method method, Object[] args )
+        throws Throwable
+    {
+        if( throwable != null )
+        {
+            throw throwable;
+        }
+        else
+        {
+            return result;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/composite/SideEffectModel.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/SideEffectModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/SideEffectModel.java
new file mode 100644
index 0000000..0b19e80
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/SideEffectModel.java
@@ -0,0 +1,36 @@
+/*
+ *  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 org.apache.polygene.api.sideeffect.SideEffectDescriptor;
+
+/**
+ * JAVADOC
+ */
+public final class SideEffectModel
+    extends AbstractModifierModel
+    implements SideEffectDescriptor
+{
+    public SideEffectModel( Class<?> sideEffectClass, Class<?> instantiationClass )
+    {
+        super( sideEffectClass, instantiationClass );
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/composite/SideEffectsInstance.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/SideEffectsInstance.java b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/SideEffectsInstance.java
new file mode 100644
index 0000000..011cd9c
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/SideEffectsInstance.java
@@ -0,0 +1,101 @@
+/*
+ *  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.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.util.List;
+
+/**
+ * JAVADOC
+ */
+public final class SideEffectsInstance
+    implements InvocationHandler
+{
+    private final List<InvocationHandler> sideEffects;
+    private final SideEffectInvocationHandlerResult resultInvocationHandler;
+    private final ProxyReferenceInvocationHandler proxyHandler;
+    private InvocationHandler invoker;
+
+    public SideEffectsInstance( List<InvocationHandler> sideEffects,
+                                SideEffectInvocationHandlerResult resultInvocationHandler,
+                                ProxyReferenceInvocationHandler proxyHandler,
+                                InvocationHandler invoker
+    )
+    {
+        this.sideEffects = sideEffects;
+        this.resultInvocationHandler = resultInvocationHandler;
+        this.proxyHandler = proxyHandler;
+        this.invoker = invoker;
+    }
+
+    @Override
+    public Object invoke( Object proxy, Method method, Object[] args )
+        throws Throwable
+    {
+        try
+        {
+            Object result = invoker.invoke( proxy, method, args );
+            invokeSideEffects( proxy, method, args, result, null );
+            return result;
+        }
+        catch( Throwable throwable )
+        {
+            invokeSideEffects( proxy, method, args, null, throwable );
+            throw throwable;
+        }
+    }
+
+    private void invokeSideEffects( Object proxy,
+                                    Method method,
+                                    Object[] params,
+                                    Object result,
+                                    Throwable originalThrowable
+    )
+        throws Throwable
+    {
+        proxyHandler.setProxy( proxy );
+        resultInvocationHandler.setResult( result, originalThrowable );
+
+        try
+        {
+            for( InvocationHandler sideEffect : sideEffects )
+            {
+                try
+                {
+                    sideEffect.invoke( proxy, method, params );
+                }
+                catch( Throwable throwable )
+                {
+                    if( throwable != originalThrowable )
+                    {
+                        throwable.printStackTrace();
+                    }
+                }
+            }
+        }
+        finally
+        {
+            proxyHandler.clearProxy();
+            resultInvocationHandler.setResult( null, null );
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/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
new file mode 100644
index 0000000..73c910c
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/SideEffectsModel.java
@@ -0,0 +1,87 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *
+ */
+
+package org.apache.polygene.runtime.composite;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Stream;
+import org.apache.polygene.api.sideeffect.SideEffectsDescriptor;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.api.util.HierarchicalVisitor;
+import org.apache.polygene.api.util.VisitableHierarchy;
+import org.apache.polygene.runtime.injection.Dependencies;
+import org.apache.polygene.runtime.injection.DependencyModel;
+
+/**
+ * JAVADOC
+ */
+public final class SideEffectsModel
+    implements SideEffectsDescriptor, Dependencies, VisitableHierarchy<Object, Object>
+{
+    public static final SideEffectsModel EMPTY_SIDEEFFECTS = new SideEffectsModel( Collections.<SideEffectModel>emptyList() );
+
+    private List<SideEffectModel> sideEffectModels = null;
+
+    public SideEffectsModel( List<SideEffectModel> sideEffectModels )
+    {
+        this.sideEffectModels = sideEffectModels;
+    }
+
+    @Override
+    public Stream<DependencyModel> dependencies()
+    {
+        return sideEffectModels.stream().flatMap( Dependencies::dependencies );
+    }
+
+    // Context
+    public SideEffectsInstance newInstance( Method method, ModuleDescriptor module, InvocationHandler invoker )
+    {
+        ProxyReferenceInvocationHandler proxyHandler = new ProxyReferenceInvocationHandler();
+        SideEffectInvocationHandlerResult result = new SideEffectInvocationHandlerResult();
+        List<InvocationHandler> sideEffects = new ArrayList<InvocationHandler>( sideEffectModels.size() );
+        for( SideEffectModel sideEffectModel : sideEffectModels )
+        {
+            InvocationHandler sideEffect = sideEffectModel.newInstance( module, result, proxyHandler, method );
+            sideEffects.add( sideEffect );
+        }
+        return new SideEffectsInstance( sideEffects, result, proxyHandler, invoker );
+    }
+
+    @Override
+    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> modelVisitor )
+        throws ThrowableType
+    {
+        if( modelVisitor.visitEnter( this ) )
+        {
+            for( SideEffectModel sideEffectModel : sideEffectModels )
+            {
+                if( !sideEffectModel.accept( modelVisitor ) )
+                {
+                    break;
+                }
+            }
+        }
+        return modelVisitor.visitLeave( this );
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/composite/StateModel.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/StateModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/StateModel.java
new file mode 100644
index 0000000..9995d1b
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/StateModel.java
@@ -0,0 +1,79 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *
+ */
+package org.apache.polygene.runtime.composite;
+
+import java.lang.reflect.AccessibleObject;
+import java.util.stream.Stream;
+import org.apache.polygene.api.common.QualifiedName;
+import org.apache.polygene.api.composite.StateDescriptor;
+import org.apache.polygene.api.util.HierarchicalVisitor;
+import org.apache.polygene.api.util.VisitableHierarchy;
+import org.apache.polygene.runtime.property.PropertiesModel;
+import org.apache.polygene.runtime.property.PropertyModel;
+
+/**
+ * Base model for Composite state
+ */
+public class StateModel
+    implements StateDescriptor, VisitableHierarchy<Object, Object>
+{
+    protected final PropertiesModel propertiesModel;
+
+    public StateModel( PropertiesModel propertiesModel )
+    {
+        this.propertiesModel = propertiesModel;
+    }
+
+    public PropertyModel propertyModelFor( AccessibleObject accessor )
+    {
+        return propertiesModel.getProperty( accessor );
+    }
+
+    @Override
+    public PropertyModel findPropertyModelByName( String name )
+        throws IllegalArgumentException
+    {
+        return propertiesModel.getPropertyByName( name );
+    }
+
+    @Override
+    public PropertyModel findPropertyModelByQualifiedName( QualifiedName name )
+        throws IllegalArgumentException
+    {
+        return propertiesModel.getPropertyByQualifiedName( name );
+    }
+
+    @Override
+    public Stream<PropertyModel> properties()
+    {
+        return propertiesModel.properties();
+    }
+
+    @Override
+    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> visitor )
+        throws ThrowableType
+    {
+        if( visitor.visitEnter( this ) )
+        {
+            ( (VisitableHierarchy<Object, Object>) propertiesModel ).accept( visitor );
+        }
+        return visitor.visitLeave( this );
+    }
+}


Mime
View raw message