You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tapestry.apache.org by hl...@apache.org on 2006/07/20 22:19:01 UTC

svn commit: r424044 - in /tapestry/tapestry5/tapestry-core/trunk/src: main/aspect/org/apache/tapestry/internal/aspects/ main/java/org/apache/tapestry/internal/annotations/ main/java/org/apache/tapestry/internal/ioc/ main/java/org/apache/tapestry/intern...

Author: hlship
Date: Thu Jul 20 13:19:01 2006
New Revision: 424044

URL: http://svn.apache.org/viewvc?rev=424044&view=rev
Log:
Removed unused interface MethodFab.
Create OneShot annotation and related aspects.
Mark RegistryBuilder and ClassFab as OneShot objects.

Added:
    tapestry/tapestry5/tapestry-core/trunk/src/main/aspect/org/apache/tapestry/internal/aspects/InternalOneShotChecks.aj
    tapestry/tapestry5/tapestry-core/trunk/src/main/aspect/org/apache/tapestry/internal/aspects/OneShotChecks.aj
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/annotations/OneShot.java
    tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/aspects/OneShotChecksAspectTest.java
Removed:
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/services/MethodFab.java
Modified:
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/IOCMessages.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/services/AbstractFab.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/RegistryBuilder.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/transform/MethodSignature.java

Added: tapestry/tapestry5/tapestry-core/trunk/src/main/aspect/org/apache/tapestry/internal/aspects/InternalOneShotChecks.aj
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/aspect/org/apache/tapestry/internal/aspects/InternalOneShotChecks.aj?rev=424044&view=auto
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/aspect/org/apache/tapestry/internal/aspects/InternalOneShotChecks.aj (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/aspect/org/apache/tapestry/internal/aspects/InternalOneShotChecks.aj Thu Jul 20 13:19:01 2006
@@ -0,0 +1,7 @@
+package org.apache.tapestry.internal.aspects;
+
+public aspect InternalOneShotChecks extends OneShotChecks
+{
+    pointcut targetClasses()  :
+        within(org.apache.tapestry..*);
+}

Added: tapestry/tapestry5/tapestry-core/trunk/src/main/aspect/org/apache/tapestry/internal/aspects/OneShotChecks.aj
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/aspect/org/apache/tapestry/internal/aspects/OneShotChecks.aj?rev=424044&view=auto
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/aspect/org/apache/tapestry/internal/aspects/OneShotChecks.aj (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/aspect/org/apache/tapestry/internal/aspects/OneShotChecks.aj Thu Jul 20 13:19:01 2006
@@ -0,0 +1,54 @@
+package org.apache.tapestry.internal.aspects;
+
+import org.apache.tapestry.internal.annotations.OneShot;
+
+/**
+ * Adds checks related to the {@link org.apache.tapestry.internal.annotations.OneShot} annotation.
+ * 
+ * @author Howard M. Lewis Ship
+ */
+
+public abstract aspect OneShotChecks extends AbstractClassTargetting
+perthis(annotatedClasses())
+{
+    private boolean _oneShotLock;
+
+    pointcut annotatedClasses(): targetClasses() && within(@OneShot Object+);
+
+    // Was thinking of adding a warning or error if no method of the class is annotated with @Lockdown.
+    // But since the flag is per instance, a subclass could provide that method. Unless the class
+    // is final, it is reasonable for no method to provide the @Lockdown annotation. Worse, it could be
+    // inherited from a base class itself. So ... no warning, but @OneShot without @Lockdown is
+    // useless.
+    
+    /** Method inherited from java.lang.Object are never locked. */
+    pointcut excludedMethods() :
+        execution(public int hashCode()) ||
+        execution(public boolean equals(Object)) ||
+        execution(public String toString());
+
+    /** Locked methods are within annotated classes, aren't excluded, and are public. */
+    pointcut checkedMethods() :
+        annotatedClasses() && ! excludedMethods() && execution(public * *(..));
+
+    /** Methods with the OneShot.Lockdown annotation will set the lock. */
+    pointcut lockingMethods() : checkedMethods() && execution(@OneShot.Lockdown * *(..));
+
+    // Order here is important. The locked check must occur before
+    // the flag is set (for locking methods, which are also checked methods).
+
+    before() : checkedMethods()
+    {
+        if (_oneShotLock)
+            throw new IllegalStateException("Method " + thisJoinPointStaticPart.getSignature()
+                    + " may no longer be invoked.");
+    }
+
+    // Now, after the check, turn the flag on for locking methods (with the @Lockdown annotation)
+
+    before() : lockingMethods()
+    {
+        _oneShotLock = true;
+    }
+
+}

Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/annotations/OneShot.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/annotations/OneShot.java?rev=424044&view=auto
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/annotations/OneShot.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/annotations/OneShot.java Thu Jul 20 13:19:01 2006
@@ -0,0 +1,49 @@
+// Copyright 2006 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.tapestry.internal.annotations;
+
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Used to mark a class as useable once. In such a class, one or more public methods (marked with
+ * the OneShot.Lockdown annotation) will lock the instance such that no further calls on public
+ * methods are allowed. This can be applied to a number of patterns, such as a factory pattern where
+ * a factory instance is created and configured, and the used to create a desired output class (at
+ * which point, the factory instance is of no futher use).
+ * <p>
+ * Methods inherited from java.lang.Object, such as toString(), are not subject to locking.
+ * 
+ * @author Howard M. Lewis Ship
+ */
+@Target(TYPE)
+@Retention(RUNTIME)
+@Documented
+@Inherited
+public @interface OneShot {
+
+    @Target(METHOD)
+    @Retention(RUNTIME)
+    @Documented
+    public @interface Lockdown {
+
+    }
+}

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/IOCMessages.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/IOCMessages.java?rev=424044&r1=424043&r2=424044&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/IOCMessages.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/IOCMessages.java Thu Jul 20 13:19:01 2006
@@ -22,7 +22,6 @@
 import org.apache.hivemind.Messages;
 import org.apache.hivemind.impl.MessageFormatter;
 import org.apache.tapestry.internal.annotations.Utility;
-import org.apache.tapestry.ioc.IOCUtilities;
 
 /**
  * @author Howard M. Lewis Ship

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/services/AbstractFab.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/services/AbstractFab.java?rev=424044&r1=424043&r2=424044&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/services/AbstractFab.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/services/AbstractFab.java Thu Jul 20 13:19:01 2006
@@ -18,6 +18,7 @@
 
 import java.util.Map;
 
+import org.apache.tapestry.internal.annotations.OneShot;
 import org.apache.tapestry.internal.annotations.SuppressNullCheck;
 
 import javassist.CtClass;
@@ -29,6 +30,7 @@
  * 
  * @author Howard M. Lewis Ship
  */
+@OneShot
 public class AbstractFab
 {
     private final CtClass _ctClass;
@@ -85,6 +87,7 @@
         return result;
     }
 
+    @OneShot.Lockdown
     public Class createClass()
     {
         return _source.createClass(_ctClass);

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/RegistryBuilder.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/RegistryBuilder.java?rev=424044&r1=424043&r2=424044&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/RegistryBuilder.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/RegistryBuilder.java Thu Jul 20 13:19:01 2006
@@ -19,6 +19,7 @@
 import java.util.Map;
 
 import org.apache.commons.logging.Log;
+import org.apache.tapestry.internal.annotations.OneShot;
 import org.apache.tapestry.internal.ioc.DefaultModuleDefImpl;
 import org.apache.tapestry.internal.ioc.IOCMessages;
 import org.apache.tapestry.internal.ioc.RegistryImpl;
@@ -30,6 +31,7 @@
  * 
  * @author Howard M. Lewis Ship
  */
+@OneShot
 public final class RegistryBuilder
 {
     /** Module defs, keyed on module id. */
@@ -39,8 +41,6 @@
 
     private final Log _log;
 
-    private boolean _locked;
-
     private final LogSource _logSource;
 
     public RegistryBuilder()
@@ -62,8 +62,6 @@
 
     public void add(ModuleDef moduleDef)
     {
-        checkLocked();
-
         String id = moduleDef.getModuleId();
 
         if (_modules.containsKey(id))
@@ -98,20 +96,9 @@
         }
     }
 
-    private void checkLocked()
-    {
-        if (_locked)
-            throw new RuntimeException(IOCMessages.builderLocked());
-    }
-
+    @OneShot.Lockdown
     public Registry build()
     {
-        checkLocked();
-
-        _locked = true;
-
-        // TODO: Consistency checks, once we have interceptors and contributions
-
         return new RegistryImpl(_modules.values(), _logSource);
     }
 

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/transform/MethodSignature.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/transform/MethodSignature.java?rev=424044&r1=424043&r2=424044&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/transform/MethodSignature.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/transform/MethodSignature.java Thu Jul 20 13:19:01 2006
@@ -25,7 +25,9 @@
  * visibility), return type, parameter types, and declared exception types.
  * <p>
  * Types are stored as class names (or primitive names) because the MethodSignature is often used in
- * situations where the actual class has not been loaded yet.
+ * situations where the actual class has not been loaded yet. When classes are already loaded (such
+ * as, for use with {@link org.apache.hivemind.service.ClassFab}), then a different implementation
+ * with the same name, {@link org.apache.tapestry.ioc.services.MethodSignature} is used.
  * 
  * @author Howard M. Lewis Ship
  */

Added: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/aspects/OneShotChecksAspectTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/aspects/OneShotChecksAspectTest.java?rev=424044&view=auto
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/aspects/OneShotChecksAspectTest.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/aspects/OneShotChecksAspectTest.java Thu Jul 20 13:19:01 2006
@@ -0,0 +1,184 @@
+// Copyright 2006 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.tapestry.internal.aspects;
+
+import static org.testng.Assert.assertEquals;
+
+import org.apache.tapestry.internal.annotations.OneShot;
+import org.apache.tapestry.test.BaseTestCase;
+import org.testng.annotations.Test;
+
+/**
+ * @author Howard M. Lewis Ship
+ */
+public class OneShotChecksAspectTest extends BaseTestCase
+{
+    @OneShot
+    public static class Subject
+    {
+        public void go()
+        {
+        }
+
+        @OneShot.Lockdown
+        public void done()
+        {
+        }
+
+        public String toString()
+        {
+            return "SUBJECT";
+        }
+    }
+
+    public static class SubjectSubclass extends Subject
+    {
+        public void subclassMethod()
+        {
+
+        }
+
+        @OneShot.Lockdown
+        public void subclassLocker()
+        {
+        }
+
+    }
+
+    @Test
+    public void basic_locking()
+    {
+        Subject s = new Subject();
+
+        s.go();
+
+        s.done();
+
+        try
+        {
+            s.go();
+            unreachable();
+        }
+        catch (IllegalStateException ex)
+        {
+            assertEquals(ex.getMessage(), "Method void " + getClass().getName()
+                    + ".Subject.go() may no longer be invoked.");
+        }
+    }
+
+    @Test
+    public void to_string_not_checked()
+    {
+        Subject s = new Subject();
+
+        assertEquals(s.toString(), "SUBJECT");
+
+        s.done();
+
+        assertEquals(s.toString(), "SUBJECT");
+    }
+
+    @Test
+    public void locking_method_includes_check()
+    {
+        Subject s = new Subject();
+
+        s.go();
+
+        s.done();
+
+        try
+        {
+            s.done();
+            unreachable();
+        }
+        catch (IllegalStateException ex)
+        {
+            assertEquals(ex.getMessage(), "Method void " + getClass().getName()
+                    + ".Subject.done() may no longer be invoked.");
+        }
+    }
+
+    @Test
+    public void lock_is_per_instance()
+    {
+        Subject s1 = new Subject();
+        Subject s2 = new Subject();
+
+        s1.go();
+        s2.go();
+
+        s1.done();
+        s2.go();
+
+        try
+        {
+            s1.go();
+            unreachable();
+        }
+        catch (IllegalStateException ex)
+        {
+            // Expected
+        }
+
+        s2.done();
+
+        try
+        {
+            s2.go();
+            unreachable();
+        }
+        catch (IllegalStateException ex)
+        {
+            // Expected
+        }
+    }
+
+    @Test
+    public void base_class_methods_use_same_lock_as_subclass_methods()
+    {
+        SubjectSubclass ss = new SubjectSubclass();
+
+        ss.subclassLocker();
+
+        try
+        {
+            ss.go();
+            unreachable();
+        }
+        catch (IllegalStateException ex)
+        {
+            // Expected
+        }
+    }
+
+    @Test
+    public void subclass_methods_use_same_lock_as_base_class_methods()
+    {
+        SubjectSubclass ss = new SubjectSubclass();
+
+        ss.done();
+
+        try
+        {
+            ss.subclassMethod();
+            unreachable();
+        }
+        catch (IllegalStateException ex)
+        {
+            // Expected
+        }
+    }
+}