You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pivot.apache.org by gb...@apache.org on 2009/06/10 22:43:49 UTC

svn commit: r783501 [2/2] - in /incubator/pivot/trunk: demos/src/pivot/demos/decorator/ demos/src/pivot/demos/dnd/ demos/src/pivot/demos/dom/ demos/src/pivot/demos/million/ demos/src/pivot/demos/roweditor/ demos/src/pivot/demos/rss/ demos/src/pivot/dem...

Modified: incubator/pivot/trunk/wtk/src/pivot/wtkx/BindException.java
URL: http://svn.apache.org/viewvc/incubator/pivot/trunk/wtk/src/pivot/wtkx/BindException.java?rev=783501&r1=783500&r2=783501&view=diff
==============================================================================
--- incubator/pivot/trunk/wtk/src/pivot/wtkx/BindException.java (original)
+++ incubator/pivot/trunk/wtk/src/pivot/wtkx/BindException.java Wed Jun 10 20:43:48 2009
@@ -21,8 +21,8 @@
  *
  * @author gbrown
  */
-public class BindException extends RuntimeException {
-    private static final long serialVersionUID = 7977199368589467986L;
+public class BindException extends Exception {
+    private static final long serialVersionUID = 0;
 
     public BindException() {
         super();

Modified: incubator/pivot/trunk/wtk/src/pivot/wtkx/BindProcessor.java
URL: http://svn.apache.org/viewvc/incubator/pivot/trunk/wtk/src/pivot/wtkx/BindProcessor.java?rev=783501&r1=783500&r2=783501&view=diff
==============================================================================
--- incubator/pivot/trunk/wtk/src/pivot/wtkx/BindProcessor.java (original)
+++ incubator/pivot/trunk/wtk/src/pivot/wtkx/BindProcessor.java Wed Jun 10 20:43:48 2009
@@ -35,7 +35,6 @@
 import pivot.collections.List;
 import pivot.collections.Map;
 
-import com.sun.tools.javac.code.Flags;
 import com.sun.tools.javac.processing.JavacProcessingEnvironment;
 import com.sun.tools.javac.tree.JCTree.*;
 import com.sun.tools.javac.tree.TreeTranslator;
@@ -260,15 +259,6 @@
                 buf.append("ObjectHierarchy> objectHierarchies) {");
                 buf.append("super.bind(objectHierarchies);");
 
-                // Process @Load fields (and their associated @Bind fields)
-                if (loadGroups != null) {
-                    for (String loadFieldName : loadGroups) {
-                        AnnotationDossier.LoadGroup loadGroup = loadGroups.get(loadFieldName);
-                        JCVariableDecl loadField = loadGroup.loadField;
-                        processLoad(buf, classDeclaration, loadField, loadGroup.bindFields);
-                    }
-                }
-
                 // Process @Bind fields bound to superclass @Load fields
                 if (strandedBindFields != null) {
                     processStrandedBinds(buf, strandedBindFields);
@@ -302,21 +292,9 @@
         public void visitVarDef(JCVariableDecl field) {
             super.visitVarDef(field);
 
-            JCAnnotation loadAnnotation = getLoadAnnotation(field);
             JCAnnotation bindAnnotation = getBindAnnotation(field);
 
-            if (loadAnnotation != null
-                && bindAnnotation != null) {
-                processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR,
-                    "Cannot combine " + Bindable.Load.class.getName()
-                    + " and " + Bindable.Bind.class.getName() + " annotations.");
-            } else if (loadAnnotation != null) {
-                AnnotationDossier annotationDossier = stack.peek();
-                annotationDossier.createLoadGroup(field);
-
-                // Increment the tally for reporting purposes
-                loadTally++;
-            } else if (bindAnnotation != null) {
+            if (bindAnnotation != null) {
                 AnnotationDossier annotationDossier = stack.peek();
                 annotationDossier.addToLoadGroup(field);
 
@@ -326,129 +304,6 @@
         }
 
         /**
-         * Processes an <tt>@Load</tt> field and associated <tt>@Bind</tt>
-         * fields into runtime code.
-         *
-         * @param buf
-         * The buffer into which to write the source code
-         *
-         * @param classDeclaration
-         * The AST node of the class that contains the <tt>@Load</tt> field
-         *
-         * @param loadField
-         * The AST node with the <tt>@Load</tt> annotation
-         *
-         * @param bindFields
-         * List of AST nodes with the <tt>@Bind</tt> annotations that are
-         * associated with the load field
-         */
-        private void processLoad(StringBuilder buf, JCClassDecl classDeclaration,
-            JCVariableDecl loadField, ArrayList<JCVariableDecl> bindFields) {
-            String loadFieldName = loadField.name.toString();
-
-            // Open local scope for variable name protection
-            buf.append("{");
-
-            // Get annotation properties
-            JCAnnotation loadAnnotation = getLoadAnnotation(loadField);
-            String resourceName = getAnnotationProperty(loadAnnotation, "resourceName");
-            String baseName = getAnnotationProperty(loadAnnotation, "resources");
-            String language = getAnnotationProperty(loadAnnotation, "locale");
-
-            // Default the Resources baseName to the class name
-            boolean defaultResources = false;
-            if (baseName == null) {
-                defaultResources = true;
-                if (!classDeclaration.name.isEmpty()) {
-                    baseName = classDeclaration.name.toString();
-                }
-            }
-
-            buf.append("Object object = null;");
-            buf.append("ObjectHierarchy objectHierarchy = null;");
-            buf.append(String.format
-                ("Class<ObjectHierarchy> compiledClass = pivot.wtkx.Compiler.getClass(getClass(), \"%s\");",
-                resourceName));
-
-            // Load the WTKX resource via the compiled class
-            buf.append("if (compiledClass != null) {");
-            buf.append("try {");
-            buf.append("objectHierarchy = compiledClass.newInstance();");
-            buf.append("object = objectHierarchy.getRootObject();");
-            buf.append("} catch (Exception ex) {");
-            buf.append("throw new pivot.wtkx.BindException(ex);");
-            buf.append("}");
-            buf.append("} else {");
-
-            // Attempt to load the resource bundle
-            buf.append("pivot.util.Resources resources = null;");
-            if (baseName != null) {
-                if (language == null) {
-                    buf.append("java.util.Locale locale = java.util.Locale.getDefault();");
-                } else {
-                    buf.append(String.format
-                        ("java.util.Locale locale = new java.util.Locale(\"%s\");", language));
-                }
-                buf.append("try {");
-                buf.append(String.format
-                    ("resources = new pivot.util.Resources(%s, locale, \"UTF8\");",
-                    defaultResources ? (baseName + ".class.getName()") : ("\"" + baseName + "\"")));
-                buf.append("} catch(java.io.IOException ex) {");
-                buf.append("throw new pivot.wtkx.BindException(ex);");
-                buf.append("} catch (pivot.serialization.SerializationException ex) {");
-                buf.append("throw new pivot.wtkx.BindException(ex);");
-                buf.append("} catch (java.util.MissingResourceException ex) {");
-                if (!defaultResources) {
-                    buf.append("throw new pivot.wtkx.BindException(ex);");
-                }
-                buf.append("}");
-            }
-
-            // Load the WTKX resource via serialization
-            buf.append("pivot.wtkx.WTKXSerializer wtkxSerializer = new pivot.wtkx.WTKXSerializer(resources);");
-            buf.append(String.format("java.net.URL location = getClass().getResource(\"%s\");", resourceName));
-            buf.append("try {");
-            buf.append("object = wtkxSerializer.readObject(location);");
-            buf.append("} catch (Exception ex) {");
-            buf.append("throw new pivot.wtkx.BindException(ex);");
-            buf.append("}");
-            buf.append("objectHierarchy = wtkxSerializer;");
-            buf.append("}");
-
-            // Bind the resource to the field
-            buf.append(String.format
-                ("%s = (%s)object;", loadFieldName, loadField.vartype.toString()));
-
-            // Public and protected fields get kept for subclasses
-            if ((loadField.mods.flags & (Flags.PUBLIC | Flags.PROTECTED)) != 0) {
-                buf.append(String.format
-                    ("objectHierarchies.put(\"%s\", objectHierarchy);", loadFieldName));
-            }
-
-            // Process @Bind variables
-            for (JCVariableDecl bindField : bindFields) {
-                String bindFieldName = bindField.name.toString();
-                JCAnnotation bindAnnotation = getBindAnnotation(bindField);
-
-                String id = getAnnotationProperty(bindAnnotation, "id");
-                if (id == null) {
-                    // The bind name defaults to the field name
-                    id = bindFieldName;
-                }
-
-                buf.append(String.format
-                    ("%s = objectHierarchy.getObjectByID(\"%s\");", bindFieldName, id));
-                buf.append(String.format
-                    ("if (%s == null) ", bindFieldName));
-                buf.append(String.format
-                    ("throw new pivot.wtkx.BindException(\"Element not found: %s.\");", id));
-            }
-
-            // Close local scope
-            buf.append("}");
-        }
-
-        /**
          * Processes a list of <tt>@Bind</tt> fields that were not associated
          * with any <tt>@Load</tt> field in their class. Such fields are called
          * stranded bind fields and are assumed to be associated with an
@@ -604,21 +459,6 @@
     }
 
     /**
-     * Gets the <tt>Load</tt> AST annotation node that's associated with
-     * the specified AST variable declaration node.
-     *
-     * @param field
-     * The AST variable declaration node
-     *
-     * @return
-     * The AST annotation node, or <tt>null</tt> if no such annotation is
-     * associated with the variable declaration
-     */
-    private static JCAnnotation getLoadAnnotation(JCVariableDecl field) {
-        return getAnnotation(field, Bindable.Load.class.getSimpleName());
-    }
-
-    /**
      * Gets the <tt>Bind</tt> AST annotation node that's associated with
      * the specified AST variable declaration node.
      *
@@ -630,7 +470,7 @@
      * associated with the variable declaration
      */
     private static JCAnnotation getBindAnnotation(JCVariableDecl field) {
-        return getAnnotation(field, Bindable.Bind.class.getSimpleName());
+        return getAnnotation(field, WTKX.class.getSimpleName());
     }
 
     /**

Modified: incubator/pivot/trunk/wtk/src/pivot/wtkx/Compiler.java
URL: http://svn.apache.org/viewvc/incubator/pivot/trunk/wtk/src/pivot/wtkx/Compiler.java?rev=783501&r1=783500&r2=783501&view=diff
==============================================================================
--- incubator/pivot/trunk/wtk/src/pivot/wtkx/Compiler.java (original)
+++ incubator/pivot/trunk/wtk/src/pivot/wtkx/Compiler.java Wed Jun 10 20:43:48 2009
@@ -125,41 +125,4 @@
 
         return name;
     }
-
-    /**
-     * Gets the compiled class created from a WTKX resource. This assumes that
-     * the class is named according to the {@linkplain
-     * #getPreferredClassName(Class,String) preferred class name} for
-     * compiled WTKX resources. If a compiled version of the resource exists
-     * but is named differently, this method will not discover it.
-     *
-     * @param referenceClass
-     * The class relative to which the WTKX resource will be considered.
-     * Use <tt>null</tt> to specify that the WTKX resource is relative to no
-     * class.
-     *
-     * @param resourceName
-     * A path name that identifies the WTKX resource. The path name should be
-     * of the form defined by {@link Class#getResource(String)} and is relative
-     * to the reference class. Note that this is the same form as is defined in
-     * {@link Bindable.Load#resourceName()}.
-     *
-     * @return
-     * The compiled WTKX class, or <tt>null</tt> if no such class was
-     * discovered.
-     */
-    @SuppressWarnings("unchecked")
-    public static Class<Bindable.ObjectHierarchy> getClass(Class<?> referenceClass,
-        String resourceName) {
-        Class<Bindable.ObjectHierarchy> result = null;
-
-        String className = getPreferredClassName(referenceClass, resourceName);
-        try {
-            result = (Class<Bindable.ObjectHierarchy>)Class.forName(className);
-        } catch (ClassNotFoundException ex) {
-            // No-op
-        }
-
-        return result;
-    }
 }

Added: incubator/pivot/trunk/wtk/src/pivot/wtkx/WTKX.java
URL: http://svn.apache.org/viewvc/incubator/pivot/trunk/wtk/src/pivot/wtkx/WTKX.java?rev=783501&view=auto
==============================================================================
--- incubator/pivot/trunk/wtk/src/pivot/wtkx/WTKX.java (added)
+++ incubator/pivot/trunk/wtk/src/pivot/wtkx/WTKX.java Wed Jun 10 20:43:48 2009
@@ -0,0 +1,23 @@
+package pivot.wtkx;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Annotation that causes a loaded WTKX element to be bound to the annotated
+ * field.
+ *
+ * @author gbrown
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.FIELD)
+public @interface WTKX {
+    /**
+     * The ID of the WTKX variable that references the element to bind. It
+     * should be a valid <tt>wtkx:id</tt> from the loaded WTKX resource. If
+     * unspecified, the name of the annotated field will be used.
+     */
+    public String id() default "\0";
+}

Modified: incubator/pivot/trunk/wtk/src/pivot/wtkx/WTKXSerializer.java
URL: http://svn.apache.org/viewvc/incubator/pivot/trunk/wtk/src/pivot/wtkx/WTKXSerializer.java?rev=783501&r1=783500&r2=783501&view=diff
==============================================================================
--- incubator/pivot/trunk/wtk/src/pivot/wtkx/WTKXSerializer.java (original)
+++ incubator/pivot/trunk/wtk/src/pivot/wtkx/WTKXSerializer.java Wed Jun 10 20:43:48 2009
@@ -26,6 +26,7 @@
 import java.lang.reflect.Field;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
 import java.net.MalformedURLException;
 import java.net.URL;
 
@@ -52,7 +53,7 @@
  *
  * @author gbrown
  */
-public class WTKXSerializer implements Serializer<Object>, Bindable.ObjectHierarchy {
+public class WTKXSerializer implements Serializer<Object> {
     private static class Element  {
         public enum Type {
             INSTANCE,
@@ -257,8 +258,8 @@
         return resources;
     }
 
-    public Object readObject(String resourceName) throws IOException,
-        SerializationException {
+    public Object readObject(String resourceName)
+        throws IOException, SerializationException {
         if (resourceName == null) {
             throw new IllegalArgumentException("resourceName is null.");
         }
@@ -274,8 +275,34 @@
         return readObject(location);
     }
 
-    public Object readObject(URL location) throws IOException,
-        SerializationException {
+    public Object readObject(Object baseObject, String resourceName)
+        throws IOException, SerializationException {
+        if (baseObject == null) {
+            throw new IllegalArgumentException("baseObject is null.");
+        }
+
+        if (resourceName == null) {
+            throw new IllegalArgumentException("resourceName is null.");
+        }
+
+        return readObject(baseObject.getClass(), resourceName);
+    }
+
+    public Object readObject(Class<?> baseType, String resourceName)
+        throws IOException, SerializationException {
+        if (baseType == null) {
+            throw new IllegalArgumentException("baseType is null.");
+        }
+
+        if (resourceName == null) {
+            throw new IllegalArgumentException("resourceName is null.");
+        }
+
+        return readObject(baseType.getResource(resourceName));
+    }
+
+    public Object readObject(URL location)
+        throws IOException, SerializationException {
         if (location == null) {
             throw new IllegalArgumentException("location is null.");
         }
@@ -290,8 +317,8 @@
     }
 
     @SuppressWarnings({"unchecked"})
-    public Object readObject(InputStream inputStream) throws IOException,
-        SerializationException {
+    public Object readObject(InputStream inputStream)
+        throws IOException, SerializationException {
         if (inputStream == null) {
             throw new IllegalArgumentException("inputStream is null.");
         }
@@ -775,7 +802,7 @@
      *
      * @param id
      * The ID of the object, relative to this loader. The object's ID is the
-     * concatentation of its parent IDs and its ID, separated by periods
+     * concatenation of its parent IDs and its ID, separated by periods
      * (e.g. "foo.bar.baz").
      *
      * @return The named object, or <tt>null</tt> if an object with the given
@@ -800,6 +827,78 @@
     }
 
     /**
+     * Applies WTKX binding annotations to an object.
+     * <p>
+     * If this method will be called by untrusted code, a bind processor must
+     * be applied at compile time. See {@link BindProcessor} for more
+     * information.
+     *
+     * @throws BindException
+     * If an error occurs during binding
+     */
+    public void bind(Object object) throws BindException {
+        Class<?> type = object.getClass();
+
+        Method __bindMethod = null;
+        try {
+            __bindMethod = type.getDeclaredMethod("__bind", new Class<?>[] {type});
+        } catch(NoSuchMethodException exception) {
+            // No-op
+        }
+
+        if (__bindMethod == null) {
+            Field[] fields = type.getDeclaredFields();
+
+            // Process bind annotations
+            for (int j = 0, n = fields.length; j < n; j++) {
+                Field field = fields[j];
+                String fieldName = field.getName();
+                int fieldModifiers = field.getModifiers();
+
+                WTKX wtkxAnnotation = field.getAnnotation(WTKX.class);
+                if (wtkxAnnotation != null) {
+                    // Ensure that we can write to the field
+                    if ((fieldModifiers & Modifier.FINAL) > 0) {
+                        throw new BindException(fieldName + " is final.");
+                    }
+
+                    if ((fieldModifiers & Modifier.PUBLIC) == 0) {
+                        try {
+                            field.setAccessible(true);
+                        } catch(SecurityException exception) {
+                            throw new BindException(fieldName + " is not accessible.");
+                        }
+                    }
+
+                    String id = wtkxAnnotation.id();
+                    if (id.equals("\0")) {
+                        id = field.getName();
+                    }
+
+                    // TODO Use containsKey() here
+                    Object value = getObjectByID(id);
+                    if (value != null) {
+                        // Set the value into the field
+                        try {
+                            field.set(object, value);
+                        } catch (IllegalAccessException exception) {
+                            throw new BindException(exception);
+                        }
+                    }
+                }
+            }
+        } else {
+            try {
+                __bindMethod.invoke(null, new Object[] {object});
+            } catch(IllegalAccessException exception) {
+                throw new RuntimeException(exception);
+            } catch(InvocationTargetException exception) {
+                throw new RuntimeException(exception);
+            }
+        }
+    }
+
+    /**
      * Resolves an attribute value. If the property type is a primitive or
      * primitive wrapper, converts the string value to the primitive type.
      * Otherwise, resolves the value as either a URL, resource value, or

Modified: incubator/pivot/trunk/wtk/test/pivot/wtk/test/AccordionTest.java
URL: http://svn.apache.org/viewvc/incubator/pivot/trunk/wtk/test/pivot/wtk/test/AccordionTest.java?rev=783501&r1=783500&r2=783501&view=diff
==============================================================================
--- incubator/pivot/trunk/wtk/test/pivot/wtk/test/AccordionTest.java (original)
+++ incubator/pivot/trunk/wtk/test/pivot/wtk/test/AccordionTest.java Wed Jun 10 20:43:48 2009
@@ -21,14 +21,15 @@
 import pivot.wtk.DesktopApplicationContext;
 import pivot.wtk.Display;
 import pivot.wtk.Frame;
-import pivot.wtkx.Bindable;
+import pivot.wtkx.WTKXSerializer;
 
-public class AccordionTest extends Bindable implements Application {
-    @Load(resourceName="accordion_test.wtkx") private Frame frame;
+public class AccordionTest implements Application {
+    private Frame frame = null;
 
     public void startup(Display display, Dictionary<String, String> properties)
         throws Exception {
-        bind();
+        WTKXSerializer wtkxSerializer = new WTKXSerializer();
+        frame = (Frame)wtkxSerializer.readObject(this, "accordion_test.wtkx");
         frame.open(display);
     }
 

Modified: incubator/pivot/trunk/wtk/test/pivot/wtk/test/CardPaneTest.java
URL: http://svn.apache.org/viewvc/incubator/pivot/trunk/wtk/test/pivot/wtk/test/CardPaneTest.java?rev=783501&r1=783500&r2=783501&view=diff
==============================================================================
--- incubator/pivot/trunk/wtk/test/pivot/wtk/test/CardPaneTest.java (original)
+++ incubator/pivot/trunk/wtk/test/pivot/wtk/test/CardPaneTest.java Wed Jun 10 20:43:48 2009
@@ -27,24 +27,27 @@
 import pivot.wtk.FlowPane;
 import pivot.wtk.Frame;
 import pivot.wtk.Sheet;
-import pivot.wtkx.Bindable;
+import pivot.wtkx.WTKX;
+import pivot.wtkx.WTKXSerializer;
 
-public class CardPaneTest extends Bindable implements Application {
+public class CardPaneTest implements Application {
     private Frame frame = null;
+    private Sheet sheet = null;
 
-    @Load(resourceName="card_pane_test.wtkx") private Sheet sheet;
-    @Bind(fieldName="sheet") private CardPane cardPane;
+    @WTKX private CardPane cardPane;
 
     public void startup(Display display, Dictionary<String, String> properties)
         throws Exception {
-        bind();
-
         frame = new Frame(new FlowPane());
         frame.getStyles().put("padding", 0);
         frame.setTitle("Component Pane Test");
         frame.setPreferredSize(800, 600);
         frame.setLocation(20, 20);
 
+        WTKXSerializer wtkxSerializer = new WTKXSerializer();
+        sheet = (Sheet)wtkxSerializer.readObject(this, "card_pane_test.wtkx");
+        wtkxSerializer.bind(this);
+
         Button.Group sizeGroup = Button.getGroup("sizeGroup");
         sizeGroup.getGroupListeners().add(new Button.GroupListener() {
             public void selectionChanged(Button.Group buttonGroup, Button previousSelection) {