Return-Path: Delivered-To: apmail-tapestry-dev-archive@www.apache.org Received: (qmail 63246 invoked from network); 29 Mar 2011 17:25:01 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.3) by minotaur.apache.org with SMTP; 29 Mar 2011 17:25:01 -0000 Received: (qmail 70137 invoked by uid 500); 29 Mar 2011 17:25:01 -0000 Delivered-To: apmail-tapestry-dev-archive@tapestry.apache.org Received: (qmail 70097 invoked by uid 500); 29 Mar 2011 17:25:01 -0000 Mailing-List: contact commits-help@tapestry.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@tapestry.apache.org Delivered-To: mailing list commits@tapestry.apache.org Received: (qmail 70090 invoked by uid 99); 29 Mar 2011 17:25:01 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 29 Mar 2011 17:25:01 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 29 Mar 2011 17:24:56 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id 84F192388A70; Tue, 29 Mar 2011 17:24:36 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1086644 [1/5] - in /tapestry/tapestry5/trunk: ./ plastic/ plastic/src/ plastic/src/main/ plastic/src/main/java/ plastic/src/main/java/org/ plastic/src/main/java/org/apache/ plastic/src/main/java/org/apache/tapestry5/ plastic/src/main/java/... Date: Tue, 29 Mar 2011 17:24:35 -0000 To: commits@tapestry.apache.org From: hlship@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20110329172436.84F192388A70@eris.apache.org> Author: hlship Date: Tue Mar 29 17:24:31 2011 New Revision: 1086644 URL: http://svn.apache.org/viewvc?rev=1086644&view=rev Log: Initial import of Plastic as a Tapestry sub-project Added: tapestry/tapestry5/trunk/plastic/ tapestry/tapestry5/trunk/plastic/build.gradle tapestry/tapestry5/trunk/plastic/src/ tapestry/tapestry5/trunk/plastic/src/main/ tapestry/tapestry5/trunk/plastic/src/main/java/ tapestry/tapestry5/trunk/plastic/src/main/java/org/ tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/ tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/ tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/ tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/ tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/AbstractAnnotationBuilder.java tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/AbstractMethodInvocation.java tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/AnnotationBuilder.java tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/Cache.java tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/ClassInstantiatorImpl.java tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/ClassLoaderDelegate.java tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/EmptyAnnotationAccess.java tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/FailureMethodInvocationResult.java tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/FieldHandleImpl.java tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/FieldState.java tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/InstructionBuilderImpl.java tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/InstructionBuilderState.java tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/LocalVariable.java tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/Lockable.java tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/MethodBundle.java tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/MethodHandleImpl.java tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/NameCache.java tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/NoopDelegate.java tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/PlasticClassHandleShim.java tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/PlasticClassImpl.java tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/PlasticClassLoader.java tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/PlasticClassPool.java tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/PlasticClassTransformation.java tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/PlasticInternalUtils.java tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/PrimitiveType.java tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/StandardDelegate.java tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/StaticContext.java tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/SuccessMethodInvocationResult.java tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/SwitchBlockImpl.java tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/TryCatchBlockImpl.java tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/TypeCategory.java tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/plastic/ tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/plastic/AnnotationAccess.java tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/plastic/ClassInstantiator.java tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/plastic/ComputedValue.java tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/plastic/FieldConduit.java tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/plastic/FieldHandle.java tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/plastic/InstanceContext.java tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/plastic/InstructionBuilder.java tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/plastic/InstructionBuilderCallback.java tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/plastic/MethodAdvice.java tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/plastic/MethodDescription.java tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/plastic/MethodHandle.java tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/plastic/MethodInvocation.java tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/plastic/MethodInvocationResult.java tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/plastic/MethodParameter.java tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/plastic/Opcodes.java tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/plastic/PlasticClass.java tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/plastic/PlasticClassTransformer.java tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/plastic/PlasticField.java tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/plastic/PlasticManager.java tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/plastic/PlasticManagerDelegate.java tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/plastic/PlasticMethod.java tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/plastic/PlasticUtils.java tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/plastic/PropertyAccessType.java tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/plastic/SwitchBlock.java tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/plastic/SwitchCallback.java tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/plastic/TryCatchBlock.java tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/plastic/TryCatchCallback.java tapestry/tapestry5/trunk/plastic/src/test/ tapestry/tapestry5/trunk/plastic/src/test/groovy/ tapestry/tapestry5/trunk/plastic/src/test/groovy/org/ tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/ tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/ tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/internal/ tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/internal/plastic/ tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/internal/plastic/ClassInstantiatorTests.groovy tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/internal/plastic/PlasticUtilsTests.groovy tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/ tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/AbstractPlasticSpecification.groovy tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/ArrayAttributeAnnotations.groovy tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/ClassAnnotationAccess.groovy tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/FieldAnnotationAccess.groovy tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/FieldClaiming.groovy tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/FieldConduitTests.groovy tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/FieldHandleTests.groovy tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/FieldInjection.groovy tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/FieldPropertyMethodCreation.groovy tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/IntroduceFieldTests.groovy tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/MethodAdviceTests.groovy tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/MethodAnnotationAccess.groovy tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/MethodHandleAccess.groovy tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/MethodImplementationTests.groovy tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/MethodIntroduction.groovy tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/MethodProxying.groovy tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/ObtainPlasticClass.groovy tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/ParameterAnnotationsTest.groovy tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/SimpleClassLoading.groovy tapestry/tapestry5/trunk/plastic/src/test/groovy/org/apache/tapestry5/plastic/ToStringTests.groovy tapestry/tapestry5/trunk/plastic/src/test/java/ tapestry/tapestry5/trunk/plastic/src/test/java/org/ tapestry/tapestry5/trunk/plastic/src/test/java/org/apache/ tapestry/tapestry5/trunk/plastic/src/test/java/org/apache/tapestry5/ tapestry/tapestry5/trunk/plastic/src/test/java/org/apache/tapestry5/plastic/ tapestry/tapestry5/trunk/plastic/src/test/java/org/apache/tapestry5/plastic/test/ tapestry/tapestry5/trunk/plastic/src/test/java/org/apache/tapestry5/plastic/test/NoopAdvice.java tapestry/tapestry5/trunk/plastic/src/test/java/org/apache/tapestry5/plastic/test/TestInject.java tapestry/tapestry5/trunk/plastic/src/test/java/testsubjects/ tapestry/tapestry5/trunk/plastic/src/test/java/testsubjects/AlternateConstructor.java tapestry/tapestry5/trunk/plastic/src/test/java/testsubjects/AnnotationSubject.java tapestry/tapestry5/trunk/plastic/src/test/java/testsubjects/ArrayAnnotation.java tapestry/tapestry5/trunk/plastic/src/test/java/testsubjects/ArrayAttributesSubject.java tapestry/tapestry5/trunk/plastic/src/test/java/testsubjects/BaseClass.java tapestry/tapestry5/trunk/plastic/src/test/java/testsubjects/ChildClass.java tapestry/tapestry5/trunk/plastic/src/test/java/testsubjects/ContextCatcher.java tapestry/tapestry5/trunk/plastic/src/test/java/testsubjects/CreateAccessorsSubject.java tapestry/tapestry5/trunk/plastic/src/test/java/testsubjects/Empty.java tapestry/tapestry5/trunk/plastic/src/test/java/testsubjects/ExplicityEmptyArrayAttributesSubject.java tapestry/tapestry5/trunk/plastic/src/test/java/testsubjects/HasToString.java tapestry/tapestry5/trunk/plastic/src/test/java/testsubjects/InjectFieldSubject.java tapestry/tapestry5/trunk/plastic/src/test/java/testsubjects/InjectionSubject.java tapestry/tapestry5/trunk/plastic/src/test/java/testsubjects/InjectionSubjectSubclass.java tapestry/tapestry5/trunk/plastic/src/test/java/testsubjects/IntFieldHolder.java tapestry/tapestry5/trunk/plastic/src/test/java/testsubjects/LongFieldHolder.java tapestry/tapestry5/trunk/plastic/src/test/java/testsubjects/Maybe.java tapestry/tapestry5/trunk/plastic/src/test/java/testsubjects/Memory.java tapestry/tapestry5/trunk/plastic/src/test/java/testsubjects/MethodAdviceTarget.java tapestry/tapestry5/trunk/plastic/src/test/java/testsubjects/MethodHandleSubject.java tapestry/tapestry5/trunk/plastic/src/test/java/testsubjects/MethodReimplementationSubject.java tapestry/tapestry5/trunk/plastic/src/test/java/testsubjects/MiddleClass.java tapestry/tapestry5/trunk/plastic/src/test/java/testsubjects/MultipleFields.java tapestry/tapestry5/trunk/plastic/src/test/java/testsubjects/MultipleMethods.java tapestry/tapestry5/trunk/plastic/src/test/java/testsubjects/NonPrivateInstanceField.java tapestry/tapestry5/trunk/plastic/src/test/java/testsubjects/Outer.java tapestry/tapestry5/trunk/plastic/src/test/java/testsubjects/ParameterAnnotationsSubject.java tapestry/tapestry5/trunk/plastic/src/test/java/testsubjects/PrimitiveValues.java tapestry/tapestry5/trunk/plastic/src/test/java/testsubjects/Property.java tapestry/tapestry5/trunk/plastic/src/test/java/testsubjects/ScratchPad.java tapestry/tapestry5/trunk/plastic/src/test/java/testsubjects/SimpleAnnotation.java tapestry/tapestry5/trunk/plastic/src/test/java/testsubjects/SingleField.java tapestry/tapestry5/trunk/plastic/src/test/java/testsubjects/SingleMethod.java tapestry/tapestry5/trunk/plastic/src/test/java/testsubjects/StaticFields.java tapestry/tapestry5/trunk/plastic/src/test/java/testsubjects/StaticMethodsIgnored.java tapestry/tapestry5/trunk/plastic/src/test/java/testsubjects/StringHolder.java tapestry/tapestry5/trunk/plastic/src/test/java/testsubjects/StringPropertyHolder.java tapestry/tapestry5/trunk/plastic/src/test/java/testsubjects/TestInjectTransformer.java tapestry/tapestry5/trunk/plastic/src/test/java/testsubjects/Truth.java tapestry/tapestry5/trunk/plastic/src/test/java/testsubjects/WillNotDoubleException.java Modified: tapestry/tapestry5/trunk/settings.gradle Added: tapestry/tapestry5/trunk/plastic/build.gradle URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/plastic/build.gradle?rev=1086644&view=auto ============================================================================== --- tapestry/tapestry5/trunk/plastic/build.gradle (added) +++ tapestry/tapestry5/trunk/plastic/build.gradle Tue Mar 29 17:24:31 2011 @@ -0,0 +1,11 @@ +description = "Plastic core framework" + +dependencies { + compile "asm:asm-all:3.3.1" + + testCompile "org.spockframework:spock-core:0.5-groovy-1.7" +} + +test { + useJUnit() +} \ No newline at end of file Added: tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/AbstractAnnotationBuilder.java URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/AbstractAnnotationBuilder.java?rev=1086644&view=auto ============================================================================== --- tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/AbstractAnnotationBuilder.java (added) +++ tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/AbstractAnnotationBuilder.java Tue Mar 29 17:24:31 2011 @@ -0,0 +1,140 @@ +// Copyright 2011 The Apache Software Foundation +// +// Licensed 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.tapestry5.internal.plastic; + +import java.lang.reflect.Array; +import java.util.ArrayList; +import java.util.List; + +import org.objectweb.asm.AnnotationVisitor; +import org.objectweb.asm.Type; + +@SuppressWarnings( +{ "rawtypes", "unchecked" }) +public abstract class AbstractAnnotationBuilder implements AnnotationVisitor +{ + protected final PlasticClassPool pool; + + public AbstractAnnotationBuilder(PlasticClassPool pool) + { + this.pool = pool; + } + + protected abstract void store(String name, Object value); + + protected Class elementTypeForArrayAttribute(String name) + { + throw new IllegalStateException("elementTypeForArrayAttribute() may not be invoked here."); + } + + public void visit(String name, Object value) + { + if (value instanceof Type) + { + Type type = (Type) value; + + Class valueType = pool.loadClass(type.getClassName()); + store(name, valueType); + return; + } + + store(name, value); + } + + public void visitEnum(String name, String desc, String value) + { + + try + { + String enumClassName = PlasticInternalUtils.objectDescriptorToClassName(desc); + + Class enumClass = pool.loader.loadClass(enumClassName); + + Object enumValue = Enum.valueOf(enumClass, value); + + store(name, enumValue); + } + catch (Exception ex) + { + throw new IllegalArgumentException(String.format("Unable to convert enum annotation attribute %s %s: %s", + value, desc, PlasticInternalUtils.toMessage(ex)), ex); + } + } + + public AnnotationVisitor visitAnnotation(final String name, String desc) + { + final AbstractAnnotationBuilder outerBuilder = this; + + final Class nestedAnnotationType = pool.loadClass(PlasticInternalUtils.objectDescriptorToClassName(desc)); + + // Return a nested builder that constructs the inner annotation and, at the end of + // construction, pushes the final Annotation object into this builder's attributes. + + return new AnnotationBuilder(nestedAnnotationType, pool) + { + @Override + public void visitEnd() + { + outerBuilder.store(name, createAnnotation()); + }; + }; + } + + /** + * Because of how ASM works, this should only be invoked when the array values are not + * primitives and not Class/Type; i.e. the inner values will be either Class/Type, enum, or + * nested annotations. All the arrays of strings and primitives are handled by ASM and become + * a single call to {@link #visit(String, Object)}. + */ + public AnnotationVisitor visitArray(final String name) + { + final List values = new ArrayList(); + + final Class componentType = elementTypeForArrayAttribute(name); + + final AbstractAnnotationBuilder outerBuilder = this; + + return new AbstractAnnotationBuilder(pool) + { + @Override + protected void store(String name, Object value) + { + values.add(value); + } + + @Override + public void visitEnd() + { + Object array = Array.newInstance(componentType, values.size()); + + // Now, empty arrays may be primitive types and will not cast to Object[], but + // non empty arrays indicate that it was a Class/Enum/Annotation, which can cast + // to Object[] + + if (values.size() != 0) + array = values.toArray((Object[]) array); + + outerBuilder.store(name, array); + } + }; + } + + public void visitEnd() + { + // Nothing to do here. Subclasses use this as a chance to store a value into an outer + // builder. + } + +} Added: tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/AbstractMethodInvocation.java URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/AbstractMethodInvocation.java?rev=1086644&view=auto ============================================================================== --- tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/AbstractMethodInvocation.java (added) +++ tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/AbstractMethodInvocation.java Tue Mar 29 17:24:31 2011 @@ -0,0 +1,89 @@ +// Copyright 2011 The Apache Software Foundation +// +// Licensed 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.tapestry5.internal.plastic; + +import org.apache.tapestry5.plastic.InstanceContext; +import org.apache.tapestry5.plastic.MethodAdvice; +import org.apache.tapestry5.plastic.MethodInvocation; + +public abstract class AbstractMethodInvocation implements MethodInvocation +{ + private final Object instance; + + private final InstanceContext instanceContext; + + private final MethodAdvice[] advice; + + private int adviceIndex; + + protected AbstractMethodInvocation(Object instance, InstanceContext instanceContext, MethodAdvice[] advice) + { + this.instance = instance; + this.instanceContext = instanceContext; + this.advice = advice; + } + + private Exception checkedException; + + public void rethrow() + { + if (checkedException != null) + throw new RuntimeException(checkedException); + } + + public boolean didThrowCheckedException() + { + return checkedException != null; + } + + public T getCheckedException(Class exceptionType) + { + assert exceptionType != null; + + if (exceptionType.isInstance(checkedException)) + return exceptionType.cast(checkedException); + + return null; + } + + public Object getInstance() + { + return instance; + } + + public InstanceContext getInstanceContext() + { + return instanceContext; + } + + public MethodInvocation proceed() + { + if (adviceIndex == advice.length) + proceedToAdvisedMethod(); + else + advice[adviceIndex++].advise(this); + + return this; + } + + public MethodInvocation setCheckedException(Exception exception) + { + checkedException = exception; + + return this; + } + + protected abstract void proceedToAdvisedMethod(); +} Added: tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/AnnotationBuilder.java URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/AnnotationBuilder.java?rev=1086644&view=auto ============================================================================== --- tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/AnnotationBuilder.java (added) +++ tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/AnnotationBuilder.java Tue Mar 29 17:24:31 2011 @@ -0,0 +1,118 @@ +// Copyright 2011 The Apache Software Foundation +// +// Licensed 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.tapestry5.internal.plastic; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.util.Map; + +@SuppressWarnings( +{ "rawtypes", "unchecked" }) +public class AnnotationBuilder extends AbstractAnnotationBuilder +{ + private static final class AnnotationValueHandler implements InvocationHandler + { + private final Class annotationType; + + private final Map attributes; + + public AnnotationValueHandler(final Class annotationType, Map attributes) + { + this.annotationType = annotationType; + this.attributes = attributes; + } + + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable + { + // args is null for no-arguments methods + if (args == null) + { + String attributeName = method.getName(); + + if (attributes.containsKey(attributeName)) { return attributes.get(attributeName); } + } + + // TODO: Handling of equals() and hashCode() and toString(), plus other methods + // inherited from Object + + throw new RuntimeException(String.format("Annotation proxy for class %s does not handle method %s.", + annotationType.getName(), method)); + } + } + + private final Class annotationType; + + final Map attributes = PlasticInternalUtils.newMap(); + + public AnnotationBuilder(Class annotationType, PlasticClassPool pool) + { + super(pool); + + this.annotationType = annotationType; + + attributes.put("annotationType", annotationType); + + // Annotation attributes are represented as methods, and for each method there may be a + // default value. Preload the default values, which may be overwritten by explicit + // values. + + for (Method m : annotationType.getMethods()) + { + Object defaultValue = m.getDefaultValue(); + + if (defaultValue != null) + attributes.put(m.getName(), defaultValue); + } + } + + protected void store(String name, Object value) + { + attributes.put(name, value); + } + + protected Class elementTypeForArrayAttribute(String name) + { + try + { + return annotationType.getMethod(name).getReturnType().getComponentType(); + } + catch (Exception ex) + { + throw new RuntimeException(String.format( + "Unable to determine element type for attribute '%s' of annotation %s: %s", name, + annotationType.getName(), PlasticInternalUtils.toMessage(ex)), ex); + } + } + + public Object createAnnotation() + { + // Use a static inner class to keep the AnnotationBuilder from being retained + + InvocationHandler handler = new AnnotationValueHandler(annotationType, attributes); + + try + { + return Proxy.newProxyInstance(pool.loader, new Class[] + { annotationType }, handler); + } + catch (IllegalArgumentException ex) + { + throw new IllegalArgumentException(String.format("Unable to create instance of annotation type %s: %s", + annotationType.getName(), PlasticInternalUtils.toMessage(ex)), ex); + } + } + +} Added: tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/Cache.java URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/Cache.java?rev=1086644&view=auto ============================================================================== --- tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/Cache.java (added) +++ tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/Cache.java Tue Mar 29 17:24:31 2011 @@ -0,0 +1,45 @@ +// Copyright 2011 The Apache Software Foundation +// +// Licensed 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.tapestry5.internal.plastic; + +import java.util.HashMap; +import java.util.Map; + +/** + * Quick and dirty key/value cache that is subclassed to provide the logic that generates the value for + * a missing key. + * + * @param + * @param + */ +public abstract class Cache +{ + private Map innerCache = new HashMap(); + + public T get(S input) + { + T result = innerCache.get(input); + + if (result == null) + { + result = convert(input); + innerCache.put(input, result); + } + + return result; + } + + protected abstract T convert(S input); +} Added: tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/ClassInstantiatorImpl.java URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/ClassInstantiatorImpl.java?rev=1086644&view=auto ============================================================================== --- tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/ClassInstantiatorImpl.java (added) +++ tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/ClassInstantiatorImpl.java Tue Mar 29 17:24:31 2011 @@ -0,0 +1,107 @@ +// Copyright 2011 The Apache Software Foundation +// +// Licensed 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.tapestry5.internal.plastic; + +import java.lang.reflect.Constructor; +import java.util.HashMap; +import java.util.Map; + +import org.apache.tapestry5.plastic.ClassInstantiator; +import org.apache.tapestry5.plastic.InstanceContext; + +@SuppressWarnings("all") +public class ClassInstantiatorImpl implements ClassInstantiator, InstanceContext +{ + private final Class clazz; + + private final Constructor ctor; + + private final StaticContext staticContext; + + // Keeping a whole HashMap around for just one or two values feels wasteful, perhaps + // come up with something else later. + + private final Map instanceContextMap; + + ClassInstantiatorImpl(Class clazz, Constructor ctor, StaticContext staticContext) + { + this(clazz, ctor, staticContext, null); + } + + private ClassInstantiatorImpl(Class clazz, Constructor ctor, StaticContext staticContext, Map instanceContextMap) + { + this.clazz = clazz; + this.ctor = ctor; + this.staticContext = staticContext; + this.instanceContextMap = instanceContextMap; + } + + public ClassInstantiator with(Class valueType, T instanceContextValue) + { + assert valueType != null; + assert instanceContextValue != null; + + Object existing = getFromMap(valueType); + + if (existing != null) + throw new IllegalStateException(String.format( + "An instance context value of type %s has already been added.", valueType.getName())); + + Map newMap = instanceContextMap == null ? new HashMap() : new HashMap(instanceContextMap); + + newMap.put(valueType, instanceContextValue); + + return new ClassInstantiatorImpl(clazz, ctor, staticContext, newMap); + } + + public T get(Class valueType) + { + T result = getFromMap(valueType); + + if (result == null) + throw new IllegalArgumentException(String.format( + "Instance context for class %s does not contain a value for type %s.", clazz.getName(), valueType)); + + return result; + } + + private T getFromMap(Class valueType) + { + return instanceContextMap == null ? null : valueType.cast(instanceContextMap.get(valueType)); + } + + public Object newInstance() + { + try + { + return ctor.newInstance(staticContext, this); + } + catch (Throwable ex) + { + throw new RuntimeException(String.format("Unable to instantiate instance of transformed class %s: %s", + clazz.getName(), PlasticInternalUtils.toMessage(ex)), ex); + } + } + + public Class getInstanceType() + { + return clazz; + } + + public String toString() + { + return String.format("ClassInstantiator[%s]", clazz.getName()); + } +} Added: tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/ClassLoaderDelegate.java URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/ClassLoaderDelegate.java?rev=1086644&view=auto ============================================================================== --- tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/ClassLoaderDelegate.java (added) +++ tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/ClassLoaderDelegate.java Tue Mar 29 17:24:31 2011 @@ -0,0 +1,41 @@ +// Copyright 2011 The Apache Software Foundation +// +// Licensed 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.tapestry5.internal.plastic; + +/** + * Externalizes the logic for defining which classes will be loaded (and possibly transformed) by the class loader, and + * which will be loaded by the parent class loader. + */ +public interface ClassLoaderDelegate +{ + /** + * Identifies which classes are to be loaded. + * + * @param className + * fully qualified class name + * @return true if the class should be intercepted, false to let parent class loader load class + */ + boolean shouldInterceptClassLoading(String className); + + /** + * Load the class, transforming it as necessary. + * + * @param className + * binary class name + * @return loaded and (if not an inner class) transformed class + * @throws ClassNotFoundException + */ + Class loadAndTransformClass(String className) throws ClassNotFoundException; +} Added: tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/EmptyAnnotationAccess.java URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/EmptyAnnotationAccess.java?rev=1086644&view=auto ============================================================================== --- tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/EmptyAnnotationAccess.java (added) +++ tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/EmptyAnnotationAccess.java Tue Mar 29 17:24:31 2011 @@ -0,0 +1,38 @@ +// Copyright 2011 The Apache Software Foundation +// +// Licensed 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.tapestry5.internal.plastic; + +import java.lang.annotation.Annotation; + +import org.apache.tapestry5.plastic.AnnotationAccess; + +public class EmptyAnnotationAccess implements AnnotationAccess +{ + public static final AnnotationAccess SINGLETON = new EmptyAnnotationAccess(); + + private EmptyAnnotationAccess() + { + } + + public boolean hasAnnotation(Class annotationType) + { + return false; + } + + public T getAnnotation(Class annotationType) + { + return null; + } +} Added: tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/FailureMethodInvocationResult.java URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/FailureMethodInvocationResult.java?rev=1086644&view=auto ============================================================================== --- tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/FailureMethodInvocationResult.java (added) +++ tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/FailureMethodInvocationResult.java Tue Mar 29 17:24:31 2011 @@ -0,0 +1,53 @@ +// Copyright 2011 The Apache Software Foundation +// +// Licensed 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.tapestry5.internal.plastic; + +import org.apache.tapestry5.plastic.MethodInvocationResult; + +public class FailureMethodInvocationResult implements MethodInvocationResult +{ + private final Throwable thrown; + + public FailureMethodInvocationResult(Throwable thrown) + { + assert thrown != null; + + this.thrown = thrown; + } + + public Object getReturnValue() + { + return null; + } + + public void rethrow() + { + throw new RuntimeException(thrown); + } + + public boolean didThrowCheckedException() + { + return true; + } + + public T getCheckedException(Class exceptionType) + { + if (exceptionType.isInstance(thrown)) + return exceptionType.cast(thrown); + + return null; + } + +} Added: tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/FieldHandleImpl.java URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/FieldHandleImpl.java?rev=1086644&view=auto ============================================================================== --- tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/FieldHandleImpl.java (added) +++ tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/FieldHandleImpl.java Tue Mar 29 17:24:31 2011 @@ -0,0 +1,61 @@ +// Copyright 2011 The Apache Software Foundation +// +// Licensed 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.tapestry5.internal.plastic; + +import org.apache.tapestry5.plastic.FieldHandle; + +public class FieldHandleImpl implements FieldHandle +{ + private final String className, fieldName; + + private final int fieldIndex; + + protected volatile PlasticClassHandleShim shim; + + public FieldHandleImpl(String className, String fieldName, int fieldIndex) + { + this.className = className; + this.fieldName = fieldName; + this.fieldIndex = fieldIndex; + } + + @Override + public String toString() + { + return String.format("FieldHandle[%s#%s]", className, fieldName); + } + + public Object get(Object instance) + { + checkNullInstance(instance, "get"); + + return shim.get(instance, fieldIndex); + } + + private void checkNullInstance(Object instance, String action) + { + if (instance == null) + throw new NullPointerException(String.format( + "Unable to %s value of field %s of class %s, as provided instance is null.", action, fieldName, + className)); + } + + public void set(Object instance, Object newValue) + { + checkNullInstance(instance, "set"); + + shim.set(instance, fieldIndex, newValue); + } +} Added: tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/FieldState.java URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/FieldState.java?rev=1086644&view=auto ============================================================================== --- tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/FieldState.java (added) +++ tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/FieldState.java Tue Mar 29 17:24:31 2011 @@ -0,0 +1,27 @@ +// Copyright 2011 The Apache Software Foundation +// +// Licensed 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.tapestry5.internal.plastic; + +public enum FieldState +{ + INITIAL("in initial state"), INJECTED("has an injection"), CONDUIT("has a FieldConduit"); + + private FieldState(String description) + { + this.description = description; + } + + public final String description; +} Added: tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/InstructionBuilderImpl.java URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/InstructionBuilderImpl.java?rev=1086644&view=auto ============================================================================== --- tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/InstructionBuilderImpl.java (added) +++ tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/InstructionBuilderImpl.java Tue Mar 29 17:24:31 2011 @@ -0,0 +1,574 @@ +// Copyright 2011 The Apache Software Foundation +// +// Licensed 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.tapestry5.internal.plastic; + +import org.apache.tapestry5.plastic.InstructionBuilder; +import org.apache.tapestry5.plastic.InstructionBuilderCallback; +import org.apache.tapestry5.plastic.MethodDescription; +import org.apache.tapestry5.plastic.SwitchCallback; +import org.apache.tapestry5.plastic.TryCatchCallback; +import org.objectweb.asm.Label; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.Type; + +@SuppressWarnings("rawtypes") +public class InstructionBuilderImpl extends Lockable implements Opcodes, InstructionBuilder +{ + private static final int[] DUPE_OPCODES = new int[] + { DUP, DUP_X1, DUP_X2 }; + + protected final InstructionBuilderState state; + + protected final MethodVisitor v; + + protected final NameCache cache; + + InstructionBuilderImpl(MethodDescription description, MethodVisitor visitor, NameCache cache) + { + this(new InstructionBuilderState(description, visitor, cache)); + } + + InstructionBuilderImpl(InstructionBuilderState state) + { + this.state = state; + + // These are conveniences for values stored inside the state. In fact, + // these fields predate the InstructionBuilderState type. + this.v = state.visitor; + this.cache = state.nameCache; + } + + public InstructionBuilder returnDefaultValue() + { + check(); + + PrimitiveType type = PrimitiveType.getByName(state.description.returnType); + + if (type == null) + { + v.visitInsn(ACONST_NULL); + v.visitInsn(ARETURN); + } + else + { + switch (type) + { + case VOID: + break; + + case LONG: + v.visitInsn(LCONST_0); + break; + + case FLOAT: + v.visitInsn(FCONST_0); + break; + + case DOUBLE: + v.visitInsn(DCONST_0); + break; + + default: + v.visitInsn(ICONST_0); + break; + } + + v.visitInsn(type.returnOpcode); + } + + return this; + } + + public InstructionBuilder loadThis() + { + check(); + + v.visitVarInsn(ALOAD, 0); + + return this; + } + + public InstructionBuilder loadNull() + { + check(); + + v.visitInsn(ACONST_NULL); + + return this; + } + + public InstructionBuilder loadArgument(int index) + { + check(); + + PrimitiveType type = PrimitiveType.getByName(state.description.argumentTypes[index]); + + int opcode = type == null ? ALOAD : type.loadOpcode; + + // TODO: May need to adjust offset for static (0) vs. instance (1) method. + + v.visitVarInsn(opcode, index + 1); + + return this; + } + + public InstructionBuilder loadArguments() + { + check(); + + for (int i = 0; i < state.description.argumentTypes.length; i++) + { + loadArgument(i); + } + + return this; + } + + public InstructionBuilder invokeSpecial(String containingClassName, MethodDescription description) + { + check(); + + doInvoke(INVOKESPECIAL, containingClassName, description); + + return this; + } + + public InstructionBuilder invokeVirtual(String className, String returnType, String methodName, + String... argumentTypes) + { + check(); + + doInvoke(INVOKEVIRTUAL, className, returnType, methodName, argumentTypes); + + return this; + } + + public InstructionBuilder invokeInterface(String interfaceName, String returnType, String methodName, + String... argumentTypes) + { + check(); + + doInvoke(INVOKEINTERFACE, interfaceName, returnType, methodName, argumentTypes); + + return this; + } + + private void doInvoke(int opcode, String className, String returnType, String methodName, String... argumentTypes) + { + v.visitMethodInsn(opcode, cache.toInternalName(className), methodName, + cache.toMethodDescriptor(returnType, argumentTypes)); + } + + private void doInvoke(int opcode, Class clazz, Class returnType, String methodName, Class... argumentTypes) + { + doInvoke(opcode, clazz.getName(), cache.toTypeName(returnType), methodName, + PlasticInternalUtils.toTypeNames(argumentTypes)); + } + + public InstructionBuilder invoke(Class clazz, Class returnType, String methodName, Class... argumentTypes) + { + check(); + + doInvoke(clazz.isInterface() ? INVOKEINTERFACE : INVOKEVIRTUAL, clazz, returnType, methodName, argumentTypes); + + return this; + } + + private void doInvoke(int opcode, String containingClassName, MethodDescription description) + { + v.visitMethodInsn(opcode, cache.toInternalName(containingClassName), description.methodName, + cache.toDesc(description)); + } + + public InstructionBuilder returnResult() + { + check(); + + PrimitiveType type = PrimitiveType.getByName(state.description.returnType); + + int opcode = type == null ? ARETURN : type.returnOpcode; + + v.visitInsn(opcode); + + return this; + } + + public InstructionBuilder boxPrimitive(String typeName) + { + check(); + + PrimitiveType type = PrimitiveType.getByName(typeName); + + if (type != null && type != PrimitiveType.VOID) + { + v.visitMethodInsn(INVOKESTATIC, type.wrapperInternalName, "valueOf", type.valueOfMethodDescriptor); + } + + return this; + } + + public InstructionBuilder unboxPrimitive(String typeName) + { + check(); + + PrimitiveType type = PrimitiveType.getByName(typeName); + + if (type != null) + { + doUnbox(type); + } + + return this; + } + + private void doUnbox(PrimitiveType type) + { + v.visitMethodInsn(INVOKEVIRTUAL, type.wrapperInternalName, type.toValueMethodName, type.toValueMethodDescriptor); + } + + public InstructionBuilder getField(String className, String fieldName, String typeName) + { + check(); + + v.visitFieldInsn(GETFIELD, cache.toInternalName(className), fieldName, cache.toDesc(typeName)); + + return this; + } + + public InstructionBuilder putField(String className, String fieldName, String typeName) + { + check(); + + v.visitFieldInsn(PUTFIELD, cache.toInternalName(className), fieldName, cache.toDesc(typeName)); + + return this; + } + + public InstructionBuilder putField(String className, String fieldName, Class fieldType) + { + check(); + + return putField(className, fieldName, cache.toTypeName(fieldType)); + } + + public InstructionBuilder getField(String className, String fieldName, Class fieldType) + { + check(); + + return getField(className, fieldName, fieldType.getName()); + } + + public InstructionBuilder loadArrayElement(int index, String elementType) + { + check(); + + v.visitLdcInsn(index); + + PrimitiveType type = PrimitiveType.getByName(elementType); + + if (type == null) + { + v.visitInsn(AALOAD); + } + else + { + throw new RuntimeException("Access to non-object arrays is not yet supported."); + } + + return this; + } + + public InstructionBuilder checkcast(String className) + { + check(); + + // Found out the hard way that array names are handled differently; you cast to the descriptor, not the internal + // name. + + String internalName = className.contains("[") ? cache.toDesc(className) : cache.toInternalName(className); + + v.visitTypeInsn(CHECKCAST, internalName); + + return this; + } + + public InstructionBuilder checkcast(Class clazz) + { + check(); + + return checkcast(cache.toTypeName(clazz)); + } + + public InstructionBuilder startTryCatch(TryCatchCallback callback) + { + check(); + + new TryCatchBlockImpl(state).doCallback(callback); + + return this; + } + + public InstructionBuilder newInstance(String className) + { + check(); + + v.visitTypeInsn(NEW, cache.toInternalName(className)); + + return this; + } + + public InstructionBuilder newInstance(Class clazz) + { + check(); + + return newInstance(clazz.getName()); + } + + public InstructionBuilder invokeConstructor(String className, String... argumentTypes) + { + check(); + + doInvoke(INVOKESPECIAL, className, "void", "", argumentTypes); + + return this; + } + + public InstructionBuilder invokeConstructor(Class clazz, Class... argumentTypes) + { + check(); + + return invokeConstructor(clazz.getName(), PlasticInternalUtils.toTypeNames(argumentTypes)); + } + + public InstructionBuilder dupe(int depth) + { + check(); + + if (depth < 0 || depth >= DUPE_OPCODES.length) + throw new IllegalArgumentException(String.format( + "Dupe depth %d is invalid; values from 0 to %d are allowed.", depth, DUPE_OPCODES.length - 1)); + + v.visitInsn(DUPE_OPCODES[depth]); + + return this; + } + + public InstructionBuilder pop() + { + check(); + + v.visitInsn(POP); + + return this; + } + + public InstructionBuilder swap() + { + check(); + + v.visitInsn(SWAP); + + return this; + } + + public InstructionBuilder loadConstant(Object constant) + { + check(); + + v.visitLdcInsn(constant); + + return this; + } + + public InstructionBuilder loadTypeConstant(String typeName) + { + check(); + + Type type = Type.getType(cache.toDesc(typeName)); + + v.visitLdcInsn(type); + + return this; + } + + public InstructionBuilder loadTypeConstant(Class clazz) + { + check(); + + Type type = Type.getType(clazz); + + v.visitLdcInsn(type); + + return this; + } + + public InstructionBuilder castOrUnbox(String typeName) + { + check(); + + PrimitiveType type = PrimitiveType.getByName(typeName); + + if (type == null) + return checkcast(typeName); + + v.visitTypeInsn(CHECKCAST, type.wrapperInternalName); + doUnbox(type); + + return this; + } + + public InstructionBuilder throwException(String className, String message) + { + check(); + + newInstance(className); + dupe(0); + loadConstant(message); + invokeConstructor(className, "java.lang.String"); + v.visitInsn(ATHROW); + + return this; + } + + public InstructionBuilder throwException(Class exceptionType, String message) + { + check(); + + return throwException(cache.toTypeName(exceptionType), message); + } + + public InstructionBuilder throwException() + { + check(); + + v.visitInsn(ATHROW); + + return this; + } + + public InstructionBuilder startSwitch(int min, int max, SwitchCallback callback) + { + check(); + + assert callback != null; + + new SwitchBlockImpl(state, min, max).doCallback(callback); + + return this; + } + + public InstructionBuilder startVariable(String name, String type, InstructionBuilderCallback callback) + { + check(); + + Label start = state.newLabel(); + Label end = new Label(); + + LocalVariable var = new LocalVariable(name, type, state.localIndex++); + + v.visitLocalVariable(name, cache.toDesc(type), null, start, end, var.index); + + LocalVariable prior = state.locals.put(name, var); + + new InstructionBuilderImpl(state).doCallback(callback); + + v.visitLabel(end); + + state.localIndex--; + + // Restore the original variable with this name, probably just null though. + + state.locals.put(name, prior); + + return this; + } + + public InstructionBuilder storeVariable(String name) + { + check(); + + LocalVariable var = state.locals.get(name); + + PrimitiveType type = PrimitiveType.getByName(var.type); + + int opcode = type == null ? ASTORE : type.storeOpcode; + + v.visitVarInsn(opcode, var.index); + + return this; + } + + public InstructionBuilder loadVariable(String name) + { + check(); + + LocalVariable var = state.locals.get(name); + + PrimitiveType type = PrimitiveType.getByName(var.type); + + int opcode = type == null ? ALOAD : type.loadOpcode; + + v.visitVarInsn(opcode, var.index); + + return this; + } + + public InstructionBuilder ifZero(InstructionBuilderCallback ifTrue, InstructionBuilderCallback ifFalse) + { + doConditional(IFEQ, ifTrue, ifFalse); + + return this; + } + + public InstructionBuilder ifNull(InstructionBuilderCallback ifTrue, InstructionBuilderCallback ifFalse) + { + doConditional(IFNULL, ifTrue, ifFalse); + + return this; + } + + private void doConditional(int opcode, InstructionBuilderCallback ifTrueCallback, + InstructionBuilderCallback ifFalseCallback) + { + check(); + + Label ifTrueLabel = new Label(); + Label endIfLabel = new Label(); + + // Kind of clumsy code, but it will work. + + v.visitJumpInsn(opcode, ifTrueLabel); + + new InstructionBuilderImpl(state).doCallback(ifFalseCallback); + + v.visitJumpInsn(GOTO, endIfLabel); + v.visitLabel(ifTrueLabel); + + new InstructionBuilderImpl(state).doCallback(ifTrueCallback); + + v.visitLabel(endIfLabel); + } + + void doCallback(InstructionBuilderCallback callback) + { + check(); + + if (callback != null) + callback.doBuild(this); + + lock(); + } +} Added: tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/InstructionBuilderState.java URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/InstructionBuilderState.java?rev=1086644&view=auto ============================================================================== --- tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/InstructionBuilderState.java (added) +++ tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/InstructionBuilderState.java Tue Mar 29 17:24:31 2011 @@ -0,0 +1,58 @@ +// Copyright 2011 The Apache Software Foundation +// +// Licensed 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.tapestry5.internal.plastic; + +import java.util.Map; + +import org.apache.tapestry5.plastic.MethodDescription; +import org.objectweb.asm.Label; +import org.objectweb.asm.MethodVisitor; + +/** + * Stores information about the method whose instructions are being constructed, to make it easier + * to share data across multiple instances. + */ +public class InstructionBuilderState +{ + final MethodDescription description; + + final MethodVisitor visitor; + + final NameCache nameCache; + + int localIndex; + + final Map locals = PlasticInternalUtils.newMap(); + + protected InstructionBuilderState(MethodDescription description, MethodVisitor visitor, NameCache nameCache) + { + this.description = description; + this.visitor = visitor; + this.nameCache = nameCache; + + // TODO: Account for static methods? + + localIndex = 1 + description.argumentTypes.length; + } + + Label newLabel() + { + Label result = new Label(); + + visitor.visitLabel(result); + + return result; + } +} Added: tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/LocalVariable.java URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/LocalVariable.java?rev=1086644&view=auto ============================================================================== --- tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/LocalVariable.java (added) +++ tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/LocalVariable.java Tue Mar 29 17:24:31 2011 @@ -0,0 +1,32 @@ +// Copyright 2011 The Apache Software Foundation +// +// Licensed 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.tapestry5.internal.plastic; + +public class LocalVariable +{ + final String name; + + final String type; + + // Adjusted index i.e., 1 + # of args + var index + final int index; + + LocalVariable(String name, String type, int index) + { + this.name = name; + this.type = type; + this.index = index; + } +} Added: tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/Lockable.java URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/Lockable.java?rev=1086644&view=auto ============================================================================== --- tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/Lockable.java (added) +++ tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/Lockable.java Tue Mar 29 17:24:31 2011 @@ -0,0 +1,38 @@ +// Copyright 2011 The Apache Software Foundation +// +// Licensed 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.tapestry5.internal.plastic; + +/** + * An object that can be locked, at which point most of its functionality is disabled. This conforms to general + * builder approach used throughout Plastic where objects have an active construction phase, but are then locked + * (to encourage user code to discard them after they are no longer of any use). + */ +public class Lockable +{ + private boolean locked; + + protected void check() + { + if (locked) + throw new IllegalStateException(toString() + " has been locked and can no longer be used."); + } + + protected void lock() + { + check(); + + locked = true; + } +} Added: tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/MethodBundle.java URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/MethodBundle.java?rev=1086644&view=auto ============================================================================== --- tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/MethodBundle.java (added) +++ tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/MethodBundle.java Tue Mar 29 17:24:31 2011 @@ -0,0 +1,115 @@ +// Copyright 2011 The Apache Software Foundation +// +// Licensed 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.tapestry5.internal.plastic; + +import java.util.HashSet; +import java.util.Set; + +/** + * Used to track which methods are implemented by a base class, which is often needed when transforming + * a subclass. + */ +public class MethodBundle +{ + private final MethodBundle parent; + + private final Set methods = new HashSet(); + + // TODO: So far, this is just a placeholder until we figure out what the API should look like. + // TODO: Possibly, rename this class and have it store additional information, such as the name of a + // (protected final) field storing the InstanceContext. + + public MethodBundle() + { + this(null); + } + + private MethodBundle(MethodBundle parent) + { + this.parent = parent; + } + + /** + * Is this bundle for a transformed class, or for a base class (typically Object)? + * + * @return + * true if this bundle is for transformed class, false otherwise + */ + public boolean isTransformed() + { + return parent != null; + } + + /** + * Returns a new MethodBundle that represents the methods of a child class + * of this bundle. The returned bundle will always be {@linkplain #isTransformed() transformed}. + * + * @param childClassName + * name of subclass + * @return new method bundle + */ + public MethodBundle createChild(String childClassName) + { + return new MethodBundle(this); + } + + /** + * Adds a new instance method. Only non-private, non-abstract methods should be added (that is, methods which might + * be overridden in subclasses). This can later be queried to see if any base class implements the method. + * + * @param name + * name of method + * @param desc + * method descriptor + */ + public void addMethod(String name, String desc) + { + String value = toValue(name, desc); + + methods.add(value); + } + + /** + * Returns true if a transformed parent class contains the indicated method. + * + * @param name + * method name + * @param desc + * method descriptor + * @return the internal name of the implementing base class for this method, + * or null if no base class implements the method + */ + public boolean isImplemented(String name, String desc) + { + return checkForMethod(toValue(name, desc)); + } + + private boolean checkForMethod(String value) + { + if (methods.contains(value)) + return true; + + return parent == null ? false : parent.checkForMethod(value); + } + + /** + * Combines a method name and its desc (which describes parameter types and return value) to form + * a value, which is how methods are tracked. + */ + private String toValue(String name, String desc) + { + return name + ":" + desc; + } +} Added: tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/MethodHandleImpl.java URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/MethodHandleImpl.java?rev=1086644&view=auto ============================================================================== --- tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/MethodHandleImpl.java (added) +++ tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/MethodHandleImpl.java Tue Mar 29 17:24:31 2011 @@ -0,0 +1,51 @@ +// Copyright 2011 The Apache Software Foundation +// +// Licensed 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.tapestry5.internal.plastic; + +import org.apache.tapestry5.plastic.MethodHandle; +import org.apache.tapestry5.plastic.MethodInvocationResult; + +public class MethodHandleImpl implements MethodHandle +{ + private final String className, methodDescription; + + private final int methodIndex; + + protected volatile PlasticClassHandleShim shim; + + public MethodHandleImpl(String className, String methodDescription, int methodIndex) + { + this.className = className; + this.methodDescription = methodDescription; + this.methodIndex = methodIndex; + } + + public String toString() + { + return String.format("MethodHandle[%s %s]", className, methodDescription); + } + + public MethodInvocationResult invoke(Object instance, Object... arguments) + { + + if (instance == null) + throw new NullPointerException(String.format( + "Unable to invoke method %s of class %s, as provided instance is null.", methodDescription, + className)); + + return shim.invoke(instance, methodIndex, arguments); + } + +} Added: tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/NameCache.java URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/NameCache.java?rev=1086644&view=auto ============================================================================== --- tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/NameCache.java (added) +++ tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/NameCache.java Tue Mar 29 17:24:31 2011 @@ -0,0 +1,125 @@ +// Copyright 2011 The Apache Software Foundation +// +// Licensed 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.tapestry5.internal.plastic; + +import org.apache.tapestry5.plastic.MethodDescription; + +/** + * A cache of translations from type names to internal names and descriptors, as well as a cache from MethodDescription + * to method descriptor. + */ +@SuppressWarnings("rawtypes") +public class NameCache +{ + private final Cache class2internal = new Cache() + { + + @Override + protected String convert(String className) + { + return PlasticInternalUtils.toInternalName(className); + } + }; + + private final Cache type2internal = new Cache() + { + @Override + protected String convert(Class input) + { + return toInternalName(input.getName()); + }; + }; + + private final Cache md2desc = new Cache() + { + @Override + protected String convert(MethodDescription methodDescription) + { + return toMethodDescriptor(methodDescription.returnType, methodDescription.argumentTypes); + } + }; + + private final Cache type2desc = new Cache() + { + @Override + protected String convert(String typeName) + { + return PlasticInternalUtils.toDescriptor(typeName); + } + }; + + private final Cache typeToTypeName = new Cache() + { + @Override + protected String convert(Class type) + { + return PlasticInternalUtils.toTypeName(type); + }; + }; + + public String toInternalName(String className) + { + return class2internal.get(className); + } + + public String toInternalName(Class type) + { + return type2internal.get(type); + } + + public String toDesc(MethodDescription md) + { + return md2desc.get(md); + } + + public String toDesc(String typeName) + { + return type2desc.get(typeName); + } + + public String toTypeName(Class type) + { + return typeToTypeName.get(type); + } + + public String[] toTypeNames(Class... types) + { + String[] result = new String[types.length]; + + for (int i = 0; i < result.length; i++) + result[i] = toTypeName(types[i]); + + return result; + } + + public String toMethodDescriptor(Class returnType, Class... argumentTypes) + { + return toMethodDescriptor(toTypeName(returnType), toTypeNames(argumentTypes)); + } + + public String toMethodDescriptor(String returnType, String... argumentTypes) + { + StringBuilder builder = new StringBuilder("("); + + for (String argumentType : argumentTypes) + { + builder.append(toDesc(argumentType)); + } + + builder.append(")").append(toDesc(returnType)); + + return builder.toString(); + } +} Added: tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/NoopDelegate.java URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/NoopDelegate.java?rev=1086644&view=auto ============================================================================== --- tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/NoopDelegate.java (added) +++ tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/NoopDelegate.java Tue Mar 29 17:24:31 2011 @@ -0,0 +1,32 @@ +// Copyright 2011 The Apache Software Foundation +// +// Licensed 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.tapestry5.internal.plastic; + +import org.apache.tapestry5.plastic.ClassInstantiator; +import org.apache.tapestry5.plastic.PlasticClass; +import org.apache.tapestry5.plastic.PlasticManagerDelegate; + +public class NoopDelegate implements PlasticManagerDelegate +{ + public void transform(PlasticClass plasticClass) + { + } + + public ClassInstantiator configureInstantiator(String className, ClassInstantiator instantiator) + { + return instantiator; + } + +} Added: tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/PlasticClassHandleShim.java URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/PlasticClassHandleShim.java?rev=1086644&view=auto ============================================================================== --- tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/PlasticClassHandleShim.java (added) +++ tapestry/tapestry5/trunk/plastic/src/main/java/org/apache/tapestry5/internal/plastic/PlasticClassHandleShim.java Tue Mar 29 17:24:31 2011 @@ -0,0 +1,74 @@ +// Copyright 2011 The Apache Software Foundation +// +// Licensed 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.tapestry5.internal.plastic; + +import org.apache.tapestry5.plastic.FieldHandle; +import org.apache.tapestry5.plastic.MethodHandle; +import org.apache.tapestry5.plastic.MethodInvocationResult; +import org.apache.tapestry5.plastic.PlasticClass; + +/** + * The interface for a "shim" class that provides the necessary hooks needed + * by {@link FieldHandle} and {@link MethodHandle} implementations for a particular, + * instantiated {@link PlasticClass}. + */ +public abstract class PlasticClassHandleShim +{ + /** + * Gets the field at the given index. + * + * @param instance + * object to read instance field from + * @param fieldIndex + * assigned index for the field + * @return the field's value + * @see FieldHandle#get(Object) + */ + public Object get(Object instance, int fieldIndex) + { + return null; + } + + /** + * Sets the value of a field. + * + * @param instance + * object to update instance field in + * @param fieldIndex + * assigned index for the field + * @param newValue + * new value for field + * @see FieldHandle#set(Object, Object) + */ + public void set(Object instance, int fieldIndex, Object newValue) + { + } + + /** + * Invokes a method. + * + * @param instance + * object to invoke a method upon + * @param methodIndex + * assigned index for the method + * @param arguments + * arguments to pass to the method + * @return result of invoking the method + */ + public MethodInvocationResult invoke(Object instance, int methodIndex, Object[] arguments) + { + return null; + } +}