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) {