You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@struts.apache.org by mr...@apache.org on 2005/09/14 18:21:05 UTC

svn commit: r280879 [5/16] - in /struts/sandbox/trunk/ti: ./ jars/compiler-apt/ jars/compiler-apt/src/ jars/compiler-apt/src/java/ jars/compiler-apt/src/java/org/ jars/compiler-apt/src/java/org/apache/ jars/compiler-apt/src/java/org/apache/ti/ jars/com...

Added: struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/AnnotationGrammar.java
URL: http://svn.apache.org/viewcvs/struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/AnnotationGrammar.java?rev=280879&view=auto
==============================================================================
--- struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/AnnotationGrammar.java (added)
+++ struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/AnnotationGrammar.java Wed Sep 14 09:20:05 2005
@@ -0,0 +1,414 @@
+/*
+ * Copyright 2004 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.
+ *
+ * $Header:$
+ */
+package org.apache.ti.compiler.internal;
+
+import org.apache.ti.compiler.internal.typesystem.declaration.AnnotationInstance;
+import org.apache.ti.compiler.internal.typesystem.declaration.AnnotationTypeElementDeclaration;
+import org.apache.ti.compiler.internal.typesystem.declaration.AnnotationValue;
+import org.apache.ti.compiler.internal.typesystem.declaration.Declaration;
+import org.apache.ti.compiler.internal.typesystem.declaration.MemberDeclaration;
+import org.apache.ti.compiler.internal.typesystem.env.AnnotationProcessorEnvironment;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+
+/**
+ * Our base class for customizable annotation tag grammars.  It has stock behavior for basic
+ * things like making sure required attributes exist, and provides plugin points for more
+ * complex checks.
+ */
+public abstract class AnnotationGrammar
+        implements JpfLanguageConstants {
+
+    /**
+     * If this tag requires a particular runtime version...
+     */
+    private String _requiredRuntimeVersion = null;
+    private RuntimeVersionChecker _runtimeVersionChecker;
+    private AnnotationProcessorEnvironment _env;
+    private Diagnostics _diagnostics;
+    private Map _memberGrammars = new HashMap();
+    private Map _memberArrayGrammars = new HashMap();
+    private Map _memberTypes = new HashMap();
+
+
+    /**
+     * @param requiredRuntimeVersion causes an error to be produced if the version in the manifest of beehive-netui-pageflow.jar
+     *                               is not high enough.
+     */
+    protected AnnotationGrammar(AnnotationProcessorEnvironment env, Diagnostics diags, String requiredRuntimeVersion,
+                                RuntimeVersionChecker runtimeVersionChecker) {
+        _env = env;
+        _diagnostics = diags;
+        _runtimeVersionChecker = runtimeVersionChecker;
+        _requiredRuntimeVersion = requiredRuntimeVersion;
+    }
+
+    public final AnnotationProcessorEnvironment getEnv() {
+        return _env;
+    }
+
+    public Diagnostics getDiagnostics() {
+        return _diagnostics;
+    }
+
+    public final Object check(AnnotationInstance annotation, AnnotationInstance[] parentAnnotations,
+                              MemberDeclaration classMember)
+            throws FatalCompileTimeException {
+        return check(annotation, parentAnnotations, classMember, -1);
+    }
+
+    public final Object check(AnnotationInstance annotation, AnnotationInstance[] parentAnnotations,
+                              MemberDeclaration classMember, int annotationArrayIndex)
+            throws FatalCompileTimeException {
+        if (! beginCheck(annotation, parentAnnotations, classMember)) return null;
+
+        Map valuesPresent = annotation.getElementValues();
+        HashSet wasPresent = new HashSet();
+        HashMap checkResults = new HashMap();
+
+        if (parentAnnotations == null) parentAnnotations = new AnnotationInstance[0];
+        int oldLen = parentAnnotations.length;
+        AnnotationInstance[] parentsIncludingMe = new AnnotationInstance[oldLen + 1];
+        System.arraycopy(parentAnnotations, 0, parentsIncludingMe, 0, oldLen);
+        parentsIncludingMe[oldLen] = annotation;
+
+        for (Iterator ii = valuesPresent.entrySet().iterator(); ii.hasNext();) {
+            Map.Entry i = (Map.Entry) ii.next();
+            AnnotationTypeElementDeclaration decl = (AnnotationTypeElementDeclaration) i.getKey();
+            AnnotationValue value = (AnnotationValue) i.getValue();
+            String memberName = decl.getSimpleName();
+
+            wasPresent.add(memberName);
+            onCheckMember(decl, value, annotation, parentAnnotations, classMember);
+            Object grammarOrType = null;
+
+            if ((grammarOrType = _memberGrammars.get(memberName)) != null) {
+                AnnotationGrammar childGrammar = (AnnotationGrammar) grammarOrType;
+
+                if (childGrammar != null)   // it will be non-null unless there are other, more basic, errors
+                {
+                    Object result =
+                            childGrammar.check((AnnotationInstance) value.getValue(), parentsIncludingMe, classMember);
+
+                    if (result != null) {
+                        checkResults.put(memberName, result);
+                    }
+                }
+            } else if ((grammarOrType = _memberArrayGrammars.get(memberName)) != null) {
+                AnnotationGrammar arrayGrammar = (AnnotationGrammar) grammarOrType;
+
+                if (arrayGrammar != null) {
+                    List annotations = CompilerUtils.getAnnotationArray(value);
+
+                    for (int j = 0; j < annotations.size(); ++j) {
+                        AnnotationInstance ann = (AnnotationInstance) annotations.get(j);
+                        arrayGrammar.check(ann, parentsIncludingMe, classMember, j);
+                    }
+                }
+            } else {
+                AnnotationMemberType memberType = (AnnotationMemberType) _memberTypes.get(memberName);
+
+                if (memberType != null)   // it will be non-null unless there are other, more basic, errors
+                {
+                    Object result =
+                            memberType.check(decl, value, parentsIncludingMe, classMember, annotationArrayIndex);
+                    if (result != null) checkResults.put(memberName, result);
+                }
+            }
+        }
+
+        return endCheck(annotation, parentAnnotations, classMember, wasPresent, checkResults);
+    }
+
+    public final boolean beginCheck(AnnotationInstance annotation, AnnotationInstance[] parentAnnotations,
+                                    MemberDeclaration classMember)
+            throws FatalCompileTimeException {
+        //
+        // First check to see if there's a required runtime version.
+        //
+        if (! _runtimeVersionChecker.checkRuntimeVersion(_requiredRuntimeVersion, annotation, _diagnostics,
+                "error.required-runtime-version-annotation", null)) {
+            return false;
+        }
+
+        return onBeginCheck(annotation, parentAnnotations, classMember);  // for derived classes
+    }
+
+    protected void addError(Declaration element, String key) {
+        getDiagnostics().addError(element, key, null);
+    }
+
+    protected void addError(Declaration element, String key, Object[] args) {
+        getDiagnostics().addErrorArrayArgs(element, key, args);
+    }
+
+    protected void addError(Declaration element, String key, Object arg) {
+        getDiagnostics().addError(element, key, arg);
+    }
+
+    protected void addError(Declaration element, String key, Object arg1, Object arg2) {
+        getDiagnostics().addError(element, key, arg1, arg2);
+    }
+
+    protected void addError(Declaration element, String key, Object arg1, Object arg2, Object arg3) {
+        getDiagnostics().addError(element, key, arg1, arg2, arg3);
+    }
+
+    protected void addError(AnnotationValue element, String key) {
+        getDiagnostics().addError(element, key, null);
+    }
+
+    protected void addError(AnnotationValue element, String key, Object[] args) {
+        getDiagnostics().addErrorArrayArgs(element, key, args);
+    }
+
+    protected void addError(AnnotationValue element, String key, Object arg1) {
+        getDiagnostics().addError(element, key, arg1);
+    }
+
+    protected void addError(AnnotationValue element, String key, Object arg1, Object arg2) {
+        getDiagnostics().addError(element, key, arg1, arg2);
+    }
+
+    protected void addError(AnnotationValue element, String key, Object arg1, Object arg2, Object arg3) {
+        getDiagnostics().addError(element, key, arg1, arg2, arg3);
+    }
+
+    protected void addError(AnnotationInstance element, String key) {
+        getDiagnostics().addError(element, key, null);
+    }
+
+    protected void addError(AnnotationInstance element, String key, Object[] args) {
+        getDiagnostics().addErrorArrayArgs(element, key, args);
+    }
+
+    protected void addError(AnnotationInstance element, String key, Object arg1) {
+        getDiagnostics().addError(element, key, arg1);
+    }
+
+    protected void addError(AnnotationInstance element, String key, Object arg1, Object arg2) {
+        getDiagnostics().addError(element, key, arg1, arg2);
+    }
+
+    protected void addError(AnnotationInstance element, String key, Object arg1, Object arg2, Object arg3) {
+        getDiagnostics().addError(element, key, arg1, arg2, arg3);
+    }
+
+    protected void addWarning(Declaration element, String key) {
+        getDiagnostics().addWarning(element, key, null);
+    }
+
+    protected void addWarning(Declaration element, String key, Object[] args) {
+        getDiagnostics().addWarningArrayArgs(element, key, args);
+    }
+
+    protected void addWarning(Declaration element, String key, Object arg) {
+        getDiagnostics().addWarning(element, key, arg);
+    }
+
+    protected void addWarning(Declaration element, String key, Object arg1, Object arg2) {
+        getDiagnostics().addWarning(element, key, arg1, arg2);
+    }
+
+    protected void addWarning(Declaration element, String key, Object arg1, Object arg2, Object arg3) {
+        getDiagnostics().addWarning(element, key, arg1, arg2, arg3);
+    }
+
+    protected void addWarning(AnnotationValue element, String key) {
+        getDiagnostics().addWarning(element, key, null);
+    }
+
+    protected void addWarning(AnnotationValue element, String key, Object[] args) {
+        getDiagnostics().addWarningArrayArgs(element, key, args);
+    }
+
+    protected void addWarning(AnnotationValue element, String key, Object arg1) {
+        getDiagnostics().addWarning(element, key, arg1);
+    }
+
+    protected void addWarning(AnnotationValue element, String key, Object arg1, Object arg2) {
+        getDiagnostics().addWarning(element, key, arg1, arg2);
+    }
+
+    protected void addWarning(AnnotationValue element, String key, Object arg1, Object arg2, Object arg3) {
+        getDiagnostics().addWarning(element, key, arg1, arg2, arg3);
+    }
+
+    protected void addWarning(AnnotationInstance element, String key) {
+        getDiagnostics().addWarning(element, key, null);
+    }
+
+    protected void addWarning(AnnotationInstance element, String key, Object[] args) {
+        getDiagnostics().addWarningArrayArgs(element, key, args);
+    }
+
+    protected void addWarning(AnnotationInstance element, String key, Object arg1) {
+        getDiagnostics().addWarning(element, key, arg1);
+    }
+
+    protected void addWarning(AnnotationInstance element, String key, Object arg1, Object arg2) {
+        getDiagnostics().addWarning(element, key, arg1, arg2);
+    }
+
+    protected void addWarning(AnnotationInstance element, String key, Object arg1, Object arg2, Object arg3) {
+        getDiagnostics().addWarning(element, key, arg1, arg2, arg3);
+    }
+
+    /**
+     * @return a result (any Object) that will be passed back to the parent checker.  May be null</code>.
+     */
+    public final Object endCheck(AnnotationInstance annotation, AnnotationInstance[] parentAnnotations,
+                                 MemberDeclaration classMember, Set wasPresent, Map checkResults) {
+        //
+        // Check mutually-exclusive attributes and child annotations.
+        //
+        String[][] mutuallyExclusiveAttrs = getMutuallyExclusiveAttrs();
+        for (int i = 0; mutuallyExclusiveAttrs != null && i < mutuallyExclusiveAttrs.length; ++i) {
+            String alreadyFound = null;
+
+            for (int j = 0; j < mutuallyExclusiveAttrs[i].length; ++j) {
+                String thisAttr = mutuallyExclusiveAttrs[i][j];
+
+                if (wasPresent.contains(thisAttr)) {
+                    if (alreadyFound == null) {
+                        alreadyFound = thisAttr;
+                    } else {
+                        String errorKey = "error.atmost-one-may-exist-" + mutuallyExclusiveAttrs[i].length;
+                        getDiagnostics().addErrorArrayArgs(annotation, errorKey, mutuallyExclusiveAttrs[i]);
+                    }
+                }
+            }
+        }
+
+        //
+        // Check required attributes and child annotations.
+        //
+        String[][] requiredAttrs = getRequiredAttrs();
+        for (int i = 0; requiredAttrs != null && i < requiredAttrs.length; ++i) {
+            boolean foundOne = false;
+
+            for (int j = 0; j < requiredAttrs[i].length; ++j) {
+                String thisAttr = requiredAttrs[i][j];
+
+                if (wasPresent.contains(thisAttr)) {
+                    foundOne = true;
+                    break;
+                }
+            }
+
+            if (! foundOne) {
+                String errorKey = "error.atleast-one-must-exist-" + requiredAttrs[i].length;
+                getDiagnostics().addErrorArrayArgs(annotation, errorKey, requiredAttrs[i]);
+            }
+        }
+
+        //
+        // Check inter-dependencies for attributes and child annotations.
+        //
+        String[][] attrDependencies = getAttrDependencies();
+        for (int i = 0; attrDependencies != null && i < attrDependencies.length; ++i) {
+            String thisAttr = attrDependencies[i][0];
+
+            if (wasPresent.contains(thisAttr)) {
+                boolean foundOne = false;
+
+                for (int j = 1; j < attrDependencies[i].length; ++j) {
+                    if (wasPresent.contains(attrDependencies[i][j])) {
+                        foundOne = true;
+                        break;
+                    }
+                }
+
+                if (! foundOne) {
+                    String key = "error.attr-dependency-not-found-" + (attrDependencies[i].length - 1);
+                    getDiagnostics().addErrorArrayArgs(annotation, key, attrDependencies[i]);
+                }
+            }
+        }
+
+        return onEndCheck(annotation, parentAnnotations, classMember, checkResults);   // for derived classes
+    }
+
+    protected boolean onBeginCheck(AnnotationInstance annotation, AnnotationInstance[] parentAnnotations,
+                                   MemberDeclaration classMember)
+            throws FatalCompileTimeException {
+        return true;
+    }
+
+    /**
+     * @param checkResults map of member-name (String) -> result-from-checking (Object)
+     * @return a result (any Object) that will be passed back to the parent checker.  May be null</code>.
+     */
+    protected Object onEndCheck(AnnotationInstance annotation, AnnotationInstance[] parentAnnotations,
+                                MemberDeclaration classMember, Map checkResults) {
+        return null;
+    }
+
+    protected void onCheckMember(AnnotationTypeElementDeclaration memberDecl, AnnotationValue member,
+                                 AnnotationInstance annotation, AnnotationInstance[] parentAnnotations,
+                                 MemberDeclaration classMember) {
+    }
+
+    /**
+     * Each entry in this array (a String[]) lists mutually exclusive attributes.
+     */
+    public String[][] getMutuallyExclusiveAttrs() {
+        return null;
+    }
+
+    /**
+     * Each entry in this array (a String[]) lists attributes of which one must exist in this tag.
+     */
+    public String[][] getRequiredAttrs() {
+        return null;
+    }
+
+    /**
+     * Each entry in this array (a String[]) is an array whose first element is an attribute that
+     * requires at least one of the subsequent elements to exist as an attribute.
+     */
+    public String[][] getAttrDependencies() {
+        return null;
+    }
+
+    protected void addMemberGrammar(String memberName, AnnotationGrammar grammar) {
+        _memberGrammars.put(memberName, grammar);
+    }
+
+    protected void addMemberArrayGrammar(String memberName, AnnotationGrammar grammar) {
+        _memberArrayGrammars.put(memberName, grammar);
+    }
+
+    protected void addMemberType(String memberName, AnnotationMemberType type) {
+        _memberTypes.put(memberName, type);
+    }
+
+    public String getRequiredRuntimeVersion() {
+        return _requiredRuntimeVersion;
+    }
+
+    public RuntimeVersionChecker getRuntimeVersionChecker() {
+        return _runtimeVersionChecker;
+    }
+}      

Added: struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/AnnotationMemberType.java
URL: http://svn.apache.org/viewcvs/struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/AnnotationMemberType.java?rev=280879&view=auto
==============================================================================
--- struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/AnnotationMemberType.java (added)
+++ struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/AnnotationMemberType.java Wed Sep 14 09:20:05 2005
@@ -0,0 +1,214 @@
+/*
+ * Copyright 2004 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.
+ *
+ * $Header:$
+ */
+package org.apache.ti.compiler.internal;
+
+import org.apache.ti.compiler.internal.typesystem.declaration.AnnotationInstance;
+import org.apache.ti.compiler.internal.typesystem.declaration.AnnotationTypeElementDeclaration;
+import org.apache.ti.compiler.internal.typesystem.declaration.AnnotationValue;
+import org.apache.ti.compiler.internal.typesystem.declaration.Declaration;
+import org.apache.ti.compiler.internal.typesystem.declaration.MemberDeclaration;
+import org.apache.ti.compiler.internal.typesystem.env.AnnotationProcessorEnvironment;
+
+
+public class AnnotationMemberType
+        implements JpfLanguageConstants {
+
+    /**
+     * set if this entire attribute type requires a particular runtime version.
+     */
+    private String _requiredRuntimeVersion = null;
+    private AnnotationGrammar _parentGrammar;
+    private AnnotationMemberType _nextInChain;
+
+
+    public AnnotationMemberType(String requiredRuntimeVersion, AnnotationGrammar parentGrammar) {
+        _requiredRuntimeVersion = requiredRuntimeVersion;
+        _parentGrammar = parentGrammar;
+    }
+
+    public AnnotationMemberType(String requiredRuntimeVersion, AnnotationGrammar parentGrammar,
+                                AnnotationMemberType nextInChain) {
+        this(requiredRuntimeVersion, parentGrammar);
+        _nextInChain = nextInChain;
+    }
+
+    /**
+     * @return a result (any Object) that will be passed back to the parent checker.  May be null</code>.
+     */
+    public final Object check(AnnotationTypeElementDeclaration valueDecl, AnnotationValue value,
+                              AnnotationInstance[] parentAnnotations, MemberDeclaration classMember,
+                              int annotationArrayIndex)
+            throws FatalCompileTimeException {
+        //
+        // First check to see if this attribute requires a particular runtime version.
+        //
+        String valueName = valueDecl.getSimpleName();
+        Diagnostics diags = _parentGrammar.getDiagnostics();
+        _parentGrammar.getRuntimeVersionChecker().checkRuntimeVersion(
+                _requiredRuntimeVersion, value, diags, "error.required-runtime-version-attribute", null);
+
+        // for derived classes
+        Object retVal = onCheck(valueDecl, value, parentAnnotations, classMember, annotationArrayIndex);
+        if (_nextInChain != null) {
+            return _nextInChain.check(valueDecl, value, parentAnnotations, classMember, annotationArrayIndex);
+        }
+        return retVal;
+    }
+
+    /**
+     * @return a result (any Object) that will be passed back to the parent checker.  May be null</code>.
+     */
+    public Object onCheck(AnnotationTypeElementDeclaration valueDecl, AnnotationValue member,
+                          AnnotationInstance[] parentAnnotations, MemberDeclaration classMember,
+                          int annotationArrayIndex)
+            throws FatalCompileTimeException {
+        return null;
+    }
+
+    protected void addError(Declaration element, String key) {
+        _parentGrammar.addError(element, key, null);
+    }
+
+    protected void addError(Declaration element, String key, Object[] args) {
+        _parentGrammar.addError(element, key, args);
+    }
+
+    protected void addError(Declaration element, String key, Object arg) {
+        _parentGrammar.addError(element, key, new Object[]{arg});
+    }
+
+    protected void addError(Declaration element, String key, Object arg1, Object arg2) {
+        _parentGrammar.addError(element, key, new Object[]{arg1, arg2});
+    }
+
+    protected void addError(Declaration element, String key, Object arg1, Object arg2, Object arg3) {
+        _parentGrammar.addError(element, key, new Object[]{arg1, arg2, arg3});
+    }
+
+    protected void addError(AnnotationValue element, String key) {
+        _parentGrammar.addError(element, key, null);
+    }
+
+    protected void addError(AnnotationValue element, String key, Object[] args) {
+        _parentGrammar.addError(element, key, args);
+    }
+
+    protected void addError(AnnotationValue element, String key, Object arg1) {
+        _parentGrammar.addError(element, key, new Object[]{arg1});
+    }
+
+    protected void addError(AnnotationValue element, String key, Object arg1, Object arg2) {
+        _parentGrammar.addError(element, key, new Object[]{arg1, arg2});
+    }
+
+    protected void addError(AnnotationValue element, String key, Object arg1, Object arg2, Object arg3) {
+        _parentGrammar.addError(element, key, new Object[]{arg1, arg2, arg3});
+    }
+
+    protected void addError(AnnotationInstance element, String key) {
+        _parentGrammar.addError(element, key, null);
+    }
+
+    protected void addError(AnnotationInstance element, String key, Object[] args) {
+        _parentGrammar.addError(element, key, args);
+    }
+
+    protected void addError(AnnotationInstance element, String key, Object arg1) {
+        _parentGrammar.addError(element, key, new Object[]{arg1});
+    }
+
+    protected void addError(AnnotationInstance element, String key, Object arg1, Object arg2) {
+        _parentGrammar.addError(element, key, new Object[]{arg1, arg2});
+    }
+
+    protected void addError(AnnotationInstance element, String key, Object arg1, Object arg2, Object arg3) {
+        _parentGrammar.addError(element, key, new Object[]{arg1, arg2, arg3});
+    }
+
+    protected void addWarning(Declaration element, String key) {
+        _parentGrammar.addWarning(element, key, null);
+    }
+
+    protected void addWarning(Declaration element, String key, Object[] args) {
+        _parentGrammar.addWarning(element, key, args);
+    }
+
+    protected void addWarning(Declaration element, String key, Object arg) {
+        _parentGrammar.addWarning(element, key, new Object[]{arg});
+    }
+
+    protected void addWarning(Declaration element, String key, Object arg1, Object arg2) {
+        _parentGrammar.addWarning(element, key, new Object[]{arg1, arg2});
+    }
+
+    protected void addWarning(Declaration element, String key, Object arg1, Object arg2, Object arg3) {
+        _parentGrammar.addWarning(element, key, new Object[]{arg1, arg2, arg3});
+    }
+
+    protected void addWarning(AnnotationValue element, String key) {
+        _parentGrammar.addWarning(element, key, null);
+    }
+
+    protected void addWarning(AnnotationValue element, String key, Object[] args) {
+        _parentGrammar.addWarning(element, key, args);
+    }
+
+    protected void addWarning(AnnotationValue element, String key, Object arg1) {
+        _parentGrammar.addWarning(element, key, new Object[]{arg1});
+    }
+
+    protected void addWarning(AnnotationValue element, String key, Object arg1, Object arg2) {
+        _parentGrammar.addWarning(element, key, new Object[]{arg1, arg2});
+    }
+
+    protected void addWarning(AnnotationValue element, String key, Object arg1, Object arg2, Object arg3) {
+        _parentGrammar.addWarning(element, key, new Object[]{arg1, arg2, arg3});
+    }
+
+    protected void addWarning(AnnotationInstance element, String key) {
+        _parentGrammar.addWarning(element, key, null);
+    }
+
+    protected void addWarning(AnnotationInstance element, String key, Object[] args) {
+        _parentGrammar.addWarning(element, key, args);
+    }
+
+    protected void addWarning(AnnotationInstance element, String key, Object arg1) {
+        _parentGrammar.addWarning(element, key, new Object[]{arg1});
+    }
+
+    protected void addWarning(AnnotationInstance element, String key, Object arg1, Object arg2) {
+        _parentGrammar.addWarning(element, key, new Object[]{arg1, arg2});
+    }
+
+    protected void addWarning(AnnotationInstance element, String key, Object arg1, Object arg2, Object arg3) {
+        _parentGrammar.addWarning(element, key, new Object[]{arg1, arg2, arg3});
+    }
+
+    protected AnnotationGrammar getParentGrammar() {
+        return _parentGrammar;
+    }
+
+    protected final AnnotationProcessorEnvironment getEnv() {
+        return _parentGrammar.getEnv();
+    }
+
+    protected final Diagnostics getDiagnostics() {
+        return _parentGrammar.getDiagnostics();
+    }
+}

Added: struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/AnnotationToXML.java
URL: http://svn.apache.org/viewcvs/struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/AnnotationToXML.java?rev=280879&view=auto
==============================================================================
--- struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/AnnotationToXML.java (added)
+++ struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/AnnotationToXML.java Wed Sep 14 09:20:05 2005
@@ -0,0 +1,121 @@
+/*
+ * Copyright 2004 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.
+ *
+ * $Header:$
+ */
+package org.apache.ti.compiler.internal;
+
+import org.apache.ti.compiler.internal.model.XWorkModuleConfigModel;
+import org.apache.ti.compiler.internal.typesystem.declaration.AnnotationInstance;
+import org.apache.ti.compiler.internal.typesystem.declaration.AnnotationTypeElementDeclaration;
+import org.apache.ti.compiler.internal.typesystem.declaration.AnnotationValue;
+import org.apache.ti.compiler.internal.typesystem.declaration.MemberDeclaration;
+import org.apache.ti.compiler.internal.typesystem.declaration.TypeDeclaration;
+import org.apache.ti.compiler.internal.typesystem.env.AnnotationProcessorEnvironment;
+import org.apache.ti.compiler.internal.typesystem.type.TypeInstance;
+import org.apache.ti.schema.annotations.AnnotatedElement;
+import org.apache.ti.schema.annotations.AnnotationAttribute;
+import org.apache.ti.schema.annotations.ProcessedAnnotation;
+import org.apache.ti.schema.annotations.ProcessedAnnotationsDocument;
+import org.apache.xmlbeans.XmlOptions;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+public class AnnotationToXML {
+
+    private static final String ANNOTATIONS_FILE_PREFIX = "annotations-";
+
+    private ProcessedAnnotationsDocument _doc;
+    private TypeDeclaration _typeDecl;
+
+    public AnnotationToXML(TypeDeclaration typeDecl) {
+        _doc = ProcessedAnnotationsDocument.Factory.newInstance();
+        _typeDecl = typeDecl;
+        ProcessedAnnotationsDocument.ProcessedAnnotations pa = _doc.addNewProcessedAnnotations();
+        pa.setTypeName(typeDecl.getQualifiedName());
+    }
+
+    public void include(MemberDeclaration memberDecl, AnnotationInstance annotation) {
+        AnnotatedElement element = _doc.getProcessedAnnotations().addNewAnnotatedElement();
+        String name = memberDecl instanceof TypeDeclaration
+                ? ((TypeDeclaration) memberDecl).getQualifiedName()
+                : memberDecl.getSimpleName();
+        element.setElementName(name);
+        ProcessedAnnotation xmlAnnotation = element.addNewAnnotation();
+        include(xmlAnnotation, annotation);
+    }
+
+    private void include(ProcessedAnnotation xmlAnnotation, AnnotationInstance annotation) {
+        xmlAnnotation.setAnnotationName(annotation.getAnnotationType().getAnnotationTypeDeclaration().getQualifiedName());
+
+        Map elementValues = annotation.getElementValues();
+
+        for (Iterator i = elementValues.entrySet().iterator(); i.hasNext();) {
+            Map.Entry entry = (Map.Entry) i.next();
+            AnnotationTypeElementDeclaration elementDecl = (AnnotationTypeElementDeclaration) entry.getKey();
+            AnnotationValue annotationValue = (AnnotationValue) entry.getValue();
+
+            String name = elementDecl.getSimpleName();
+            Object value = annotationValue.getValue();
+            AnnotationAttribute xmlAttr = xmlAnnotation.addNewAnnotationAttribute();
+            xmlAttr.setAttributeName(name);
+
+            if (value instanceof List) {
+                for (Iterator j = ((List) value).iterator(); j.hasNext();) {
+                    Object o = j.next();
+                    assert o instanceof AnnotationValue : o.getClass().getName();
+                    Object listVal = ((AnnotationValue) o).getValue();
+
+                    // we only handle lists of annotations at the moment
+                    assert listVal instanceof AnnotationInstance : listVal.getClass().getName();
+                    include(xmlAttr.addNewAnnotationValue(), (AnnotationInstance) listVal);
+                }
+            } else {
+                // we only support a few types at the moment
+                assert value instanceof TypeInstance || value instanceof String : value.getClass().getName();
+                xmlAttr.setStringValue1(value.toString());
+            }
+        }
+    }
+
+    public void writeXml(Diagnostics diagnostics, AnnotationProcessorEnvironment env) {
+        String typeName = _typeDecl.getQualifiedName();
+        int lastDot = typeName.lastIndexOf('.');
+        String baseName = ANNOTATIONS_FILE_PREFIX + typeName.substring(lastDot + 1);
+        String containingPackage = lastDot != -1 ? typeName.substring(0, lastDot) : null;
+        String outputFilePath = XWorkModuleConfigModel.getOutputFilePath(baseName, containingPackage);
+        File outputFile = new File(outputFilePath);
+
+        try {
+            XmlOptions options = new XmlOptions();
+            options.setSavePrettyPrint();
+            PrintWriter writer = env.getFiler().createTextFile(outputFile);
+            try {
+                _doc.save(writer, options);
+            }
+            finally {
+                writer.close();
+            }
+        }
+        catch (IOException e) {
+            diagnostics.addError(_typeDecl, "error.could-not-generate", outputFilePath, e.getMessage());
+        }
+    }
+}

Added: struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/BaseChecker.java
URL: http://svn.apache.org/viewcvs/struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/BaseChecker.java?rev=280879&view=auto
==============================================================================
--- struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/BaseChecker.java (added)
+++ struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/BaseChecker.java Wed Sep 14 09:20:05 2005
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2004 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.
+ *
+ * $Header:$
+ */
+package org.apache.ti.compiler.internal;
+
+import org.apache.ti.compiler.internal.typesystem.declaration.ClassDeclaration;
+import org.apache.ti.compiler.internal.typesystem.env.AnnotationProcessorEnvironment;
+
+import java.util.Map;
+
+public abstract class BaseChecker {
+
+    private AnnotationProcessorEnvironment _env;
+    private Diagnostics _diagnostics;
+    private RuntimeVersionChecker _runtimeVersionChecker;
+    private SourceFileInfo _sourceFileInfo;
+
+    protected BaseChecker(AnnotationProcessorEnvironment env, SourceFileInfo sourceFileInfo, Diagnostics diagnostics) {
+        _env = env;
+        _diagnostics = diagnostics;
+        _sourceFileInfo = sourceFileInfo;
+    }
+
+    public Map check(ClassDeclaration jclass)
+            throws FatalCompileTimeException {
+        setRuntimeVersionChecker(new RuntimeVersionChecker());
+        return onCheck(jclass);
+    }
+
+    public abstract Map onCheck(ClassDeclaration jclass)
+            throws FatalCompileTimeException;
+
+    protected AnnotationProcessorEnvironment getEnv() {
+        return _env;
+    }
+
+    protected Diagnostics getDiagnostics() {
+        return _diagnostics;
+    }
+
+    protected RuntimeVersionChecker getRuntimeVersionChecker() {
+        return _runtimeVersionChecker;
+    }
+
+    protected void setRuntimeVersionChecker(RuntimeVersionChecker runtimeVersionChecker) {
+        _runtimeVersionChecker = runtimeVersionChecker;
+    }
+
+    protected SourceFileInfo getSourceFileInfo() {
+        return _sourceFileInfo;
+    }
+}

Added: struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/BaseGenerator.java
URL: http://svn.apache.org/viewcvs/struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/BaseGenerator.java?rev=280879&view=auto
==============================================================================
--- struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/BaseGenerator.java (added)
+++ struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/BaseGenerator.java Wed Sep 14 09:20:05 2005
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2004 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.
+ *
+ * $Header:$
+ */
+package org.apache.ti.compiler.internal;
+
+import org.apache.ti.compiler.internal.typesystem.declaration.ClassDeclaration;
+import org.apache.ti.compiler.internal.typesystem.env.AnnotationProcessorEnvironment;
+
+public abstract class BaseGenerator {
+
+    private AnnotationProcessorEnvironment _env;
+    private Diagnostics _diagnostics;
+    private SourceFileInfo _sourceFileInfo;
+
+
+    protected BaseGenerator(AnnotationProcessorEnvironment env, SourceFileInfo sourceFileInfo, Diagnostics diagnostics) {
+        _env = env;
+        _diagnostics = diagnostics;
+        _sourceFileInfo = sourceFileInfo;
+    }
+
+    public abstract void generate(ClassDeclaration publicClass)
+            throws FatalCompileTimeException;
+
+    protected AnnotationProcessorEnvironment getEnv() {
+        return _env;
+    }
+
+    protected Diagnostics getDiagnostics() {
+        return _diagnostics;
+    }
+
+    protected SourceFileInfo getSourceFileInfo() {
+        return _sourceFileInfo;
+    }
+}

Added: struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/CompilerUtils.java
URL: http://svn.apache.org/viewcvs/struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/CompilerUtils.java?rev=280879&view=auto
==============================================================================
--- struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/CompilerUtils.java (added)
+++ struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/CompilerUtils.java Wed Sep 14 09:20:05 2005
@@ -0,0 +1,1125 @@
+/*
+ * Copyright 2004 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.
+ *
+ * $Header:$
+ */
+package org.apache.ti.compiler.internal;
+
+import org.apache.ti.compiler.internal.typesystem.declaration.*;
+import org.apache.ti.compiler.internal.typesystem.env.AnnotationProcessorEnvironment;
+import org.apache.ti.compiler.internal.typesystem.env.Filer;
+import org.apache.ti.compiler.internal.typesystem.env.Messager;
+import org.apache.ti.compiler.internal.typesystem.type.ArrayType;
+import org.apache.ti.compiler.internal.typesystem.type.ClassType;
+import org.apache.ti.compiler.internal.typesystem.type.DeclaredType;
+import org.apache.ti.compiler.internal.typesystem.type.InterfaceType;
+import org.apache.ti.compiler.internal.typesystem.type.ReferenceType;
+import org.apache.ti.compiler.internal.typesystem.type.TypeInstance;
+import org.apache.ti.compiler.internal.typesystem.type.TypeVariable;
+import org.apache.ti.compiler.internal.typesystem.util.SourcePosition;
+
+import java.io.File;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+
+public class CompilerUtils
+        implements JpfLanguageConstants {
+
+    private static final String ERROR_STRING = "<error>";
+    private static final TypeDeclaration ERROR_TYPE_DECLARATION = new ErrorTypeDeclaration();
+
+    public static boolean isJpfAnnotation(AnnotationInstance annotation, String unqualifiedName) {
+        String annotationName = getDeclaration(annotation.getAnnotationType()).getQualifiedName();
+        return annotationName.equals(ANNOTATION_QUALIFIER + unqualifiedName);
+    }
+
+    public static AnnotationInstance getAnnotation(ClassDeclaration decl, String unqualifiedName, boolean inherited) {
+        if (! inherited) return getAnnotation(decl, unqualifiedName);
+
+        do {
+            AnnotationInstance ann = getAnnotation(decl, unqualifiedName);
+            if (ann != null) return ann;
+            ClassType superType = decl.getSuperclass();
+            TypeDeclaration superTypeDecl = getDeclaration(superType);
+            decl = superTypeDecl instanceof ClassDeclaration ? (ClassDeclaration) superTypeDecl : null;
+        } while (decl != null);
+
+        return null;
+    }
+
+    public static AnnotationInstance getAnnotation(Declaration element, String unqualifiedName) {
+        return getAnnotationFullyQualified(element, ANNOTATION_QUALIFIER + unqualifiedName);
+    }
+
+    public static AnnotationInstance getAnnotationFullyQualified(Declaration element, String fullyQualifiedName) {
+        AnnotationInstance[] annotations = element.getAnnotationInstances();
+
+        for (int ii = 0; ii < annotations.length; ii++) {
+            AnnotationInstance i = annotations[ii];
+            String iName = getDeclaration(i.getAnnotationType()).getQualifiedName();
+            if (fullyQualifiedName.equals(iName)) return i;
+        }
+
+        return null;
+    }
+
+    public static AnnotationValue getAnnotationValue(Declaration element, String annotationName, String valueName) {
+        AnnotationInstance ann = getAnnotation(element, annotationName);
+        return ann != null ? getAnnotationValue(ann, valueName, true) : null;
+    }
+
+    /**
+     * If the given annotation exists, assert that the given member is not null</code>, and return it; otherwise,
+     * if the given annotation does not exist, return null</code>.
+     */
+    private static AnnotationValue assertAnnotationValue(Declaration element, String annotationName, String valueName,
+                                                         boolean defaultIsNull) {
+        AnnotationInstance ann = getAnnotation(element, annotationName);
+
+        if (ann == null) {
+            return null;
+        } else {
+            return getAnnotationValue(ann, valueName, defaultIsNull);
+        }
+    }
+
+    public static String getStringValue(Declaration element, String annotationName, String memberName,
+                                        boolean defaultIsNull) {
+        return (String) getValue(element, annotationName, memberName, defaultIsNull);
+    }
+
+    public static AnnotationValue getAnnotationValue(AnnotationInstance annotation, String memberName,
+                                                     boolean defaultIsNull) {
+        Map valuesPresent = annotation.getElementValues();
+
+        for (Iterator ii = valuesPresent.entrySet().iterator(); ii.hasNext();) {
+            Map.Entry i = (Map.Entry) ii.next();
+            if (memberName.equals(((AnnotationTypeElementDeclaration) i.getKey()).getSimpleName())) {
+                return (AnnotationValue) i.getValue();
+            }
+        }
+
+        //
+        // We didn't find it.  If necessary, look for the default value.
+        //
+        if (defaultIsNull) return null;
+
+        AnnotationTypeDeclaration typeDecl = annotation.getAnnotationType().getAnnotationTypeDeclaration();
+        if (typeDecl == null) return null;    // type declaration is null in the case of error type
+
+        AnnotationTypeElementDeclaration[] members = typeDecl.getAnnotationMembers();
+        for (int i = 0; i < members.length; i++) {
+            AnnotationTypeElementDeclaration member = members[i];
+            if (memberName.equals(member.getSimpleName())) return member.getDefaultValue();
+
+        }
+
+        assert false : "Member " + memberName + " not found on annotation type " + getQualifiedName(annotation);
+        return null;
+    }
+
+    public static List getStringArrayValue(Declaration element, String annotationName, String memberName,
+                                           boolean defaultIsNull) {
+        AnnotationValue value = assertAnnotationValue(element, annotationName, memberName, defaultIsNull);
+        if (value == null) return null;
+        ArrayList ret = new ArrayList();
+        getValues(value, ret, false);
+        return ret;
+    }
+
+    public static Boolean getBooleanValue(Declaration element, String annotationName, String memberName,
+                                          boolean defaultIsNull) {
+        AnnotationValue value = assertAnnotationValue(element, annotationName, memberName, defaultIsNull);
+        return value != null ? (Boolean) value.getValue() : null;
+    }
+
+    public static String getString(AnnotationInstance annotation, String memberName, boolean defaultIsNull) {
+        AnnotationValue value = getAnnotationValue(annotation, memberName, defaultIsNull);
+        return value != null ? (String) value.getValue() : (defaultIsNull ? null : "");
+    }
+
+    public static TypeInstance getTypeInstance(AnnotationInstance annotation, String memberName, boolean defaultIsNull) {
+        AnnotationValue value = getAnnotationValue(annotation, memberName, defaultIsNull);
+        if (value == null) return null;
+        Object typeInstance = value.getValue();
+        if (isErrorString(typeInstance)) return new ErrorTypeInstance();
+        return (TypeInstance) typeInstance;
+    }
+
+    public static String getEnumFieldName(AnnotationInstance annotation, String memberName, boolean defaultIsNull) {
+        AnnotationValue value = getAnnotationValue(annotation, memberName, defaultIsNull);
+        return value != null ? getEnumFieldName(value) : null;
+    }
+
+    public static List getStringArray(AnnotationInstance annotation, String memberName, boolean defaultIsNull) {
+        AnnotationValue value = getAnnotationValue(annotation, memberName, defaultIsNull);
+        if (value == null) return null;
+        ArrayList ret = new ArrayList();
+        getValues(value, ret, false);
+        return ret;
+    }
+
+    public static DeclaredType getDeclaredType(AnnotationInstance annotation, String memberName, boolean defaultIsNull) {
+        return (DeclaredType) getReferenceType(annotation, memberName, defaultIsNull);
+    }
+
+    public static ReferenceType getReferenceType(AnnotationInstance annotation, String memberName, boolean defaultIsNull) {
+        AnnotationValue value = getAnnotationValue(annotation, memberName, defaultIsNull);
+
+        // If the type is the string "<error>", it means that there is already an error related to the type itself.
+        if (value != null && isErrorString(value.getValue())) return null;
+
+        return value != null ? (ReferenceType) value.getValue() : null;
+    }
+
+    public static Integer getInteger(AnnotationInstance annotation, String memberName, boolean defaultIsNull) {
+        AnnotationValue value = getAnnotationValue(annotation, memberName, defaultIsNull);
+        if (value == null) return defaultIsNull ? null : new Integer(0);
+        Object result = value.getValue();
+
+        if (result instanceof String) {
+            assert isErrorString(result) : result;
+            return new Integer(0);
+        }
+
+        return (Integer) value.getValue();
+    }
+
+    public static boolean isErrorString(Object str) {
+        return ERROR_STRING.equals(str);
+    }
+
+    public static Long getLong(AnnotationInstance annotation, String memberName, boolean defaultIsNull) {
+        AnnotationValue value = getAnnotationValue(annotation, memberName, defaultIsNull);
+        if (value == null) return defaultIsNull ? null : new Long(0);
+        Object result = value.getValue();
+
+        if (result instanceof String) {
+            assert result.equals(ERROR_STRING) : result;
+            return new Long(0);
+        }
+
+        return (Long) value.getValue();
+    }
+
+    public static Float getFloat(AnnotationInstance annotation, String memberName, boolean defaultIsNull) {
+        AnnotationValue value = getAnnotationValue(annotation, memberName, defaultIsNull);
+        if (value == null) return defaultIsNull ? null : new Float(0);
+        Object result = value.getValue();
+
+        if (result instanceof String) {
+            assert result.equals(ERROR_STRING) : result;
+            return new Float(0);
+        }
+
+        return (Float) value.getValue();
+    }
+
+    public static Double getDouble(AnnotationInstance annotation, String memberName, boolean defaultIsNull) {
+        AnnotationValue value = getAnnotationValue(annotation, memberName, defaultIsNull);
+        if (value == null) return defaultIsNull ? null : new Double(0);
+        Object result = value.getValue();
+
+        if (result instanceof String) {
+            assert result.equals(ERROR_STRING) : result;
+            return new Double(0);
+        }
+
+        return (Double) value.getValue();
+    }
+
+    public static Boolean getBoolean(AnnotationInstance annotation, String memberName, boolean defaultIsNull) {
+        AnnotationValue value = getAnnotationValue(annotation, memberName, defaultIsNull);
+        if (value == null) return defaultIsNull ? null : Boolean.FALSE;
+        Object result = value.getValue();
+
+        if (result instanceof String) {
+            assert result.equals(ERROR_STRING) : result;
+            return Boolean.FALSE;
+        }
+
+        return (Boolean) value.getValue();
+    }
+
+    public static Object getValue(Declaration element, String annotationName, String memberName, boolean defaultIsNull) {
+        AnnotationValue value = assertAnnotationValue(element, annotationName, memberName, defaultIsNull);
+        return value != null ? value.getValue() : null;
+    }
+
+    public static List getAnnotationArrayValue(Declaration element, String annotationName,
+                                               String memberName, boolean defaultIsNull) {
+        AnnotationValue value = assertAnnotationValue(element, annotationName, memberName, defaultIsNull);
+        if (value == null) return null;
+        ArrayList ret = new ArrayList();
+        getValues(value, ret, true);
+        return ret;
+    }
+
+    public static List getAnnotationArray(AnnotationInstance annotation, String memberName,
+                                          boolean defaultIsNull) {
+        AnnotationValue value = getAnnotationValue(annotation, memberName, defaultIsNull);
+        return getAnnotationArray(value);
+    }
+
+    public static List getAnnotationArray(AnnotationValue value) {
+        if (value == null) return null;
+        ArrayList ret = new ArrayList();
+        getValues(value, ret, true);
+        return ret;
+    }
+
+    private static void getValues(AnnotationValue arrayValue, List translatedValues, boolean weedOutErrorType) {
+        List values = (List) arrayValue.getValue();
+        for (Iterator ii = values.iterator(); ii.hasNext();) {
+            Object i = ii.next();
+            Object value = i instanceof AnnotationValue ? ((AnnotationValue) i).getValue() : i;
+            if (! weedOutErrorType || ! isErrorString(value)) translatedValues.add(value);
+        }
+    }
+
+    public static String getQualifiedName(AnnotationInstance annotation) {
+        return getDeclaration(annotation.getAnnotationType()).getQualifiedName();
+    }
+
+    public static String getSimpleName(AnnotationInstance annotation) {
+        return getDeclaration(annotation.getAnnotationType()).getSimpleName();
+    }
+
+    public static AnnotationInstance getAnnotation(AnnotationInstance annotation, String memberName, boolean defaultIsNull) {
+        AnnotationValue value = getAnnotationValue(annotation, memberName, defaultIsNull);
+        return value != null ? (AnnotationInstance) value.getValue() : null;
+    }
+
+    public static MethodDeclaration getClassMethod(TypeDeclaration jclass, String methodName, String desiredAnnotation) {
+        return getClassMethod(jclass, methodName, desiredAnnotation, false);
+    }
+
+    private static MethodDeclaration getClassMethod(TypeDeclaration type, String methodName, String desiredAnnotation,
+                                                    boolean onlyPublicOrProtected) {
+        if (! (type instanceof ClassDeclaration)) return null;
+
+        ClassDeclaration jclass = (ClassDeclaration) type;
+        MethodDeclaration[] methods = jclass.getMethods();
+
+        for (int i = 0; i < methods.length; i++) {
+            MethodDeclaration method = methods[i];
+            if (! onlyPublicOrProtected || method.hasModifier(Modifier.PROTECTED)
+                    || method.hasModifier(Modifier.PUBLIC)) {
+                if (methodName.equals(method.getSimpleName())
+                        && (desiredAnnotation == null || getAnnotation(method, desiredAnnotation) != null)) {
+                    return method;
+                }
+            }
+        }
+
+        ClassType superclass = jclass.getSuperclass();
+
+        if (superclass != null) {
+            return getClassMethod(getDeclaration(superclass), methodName, desiredAnnotation, true);
+        }
+
+        return null;
+    }
+
+    public static FieldDeclaration getClassField(TypeDeclaration jclass, String fieldName, String desiredAnnotation) {
+        return getClassField(jclass, fieldName, desiredAnnotation, false);
+    }
+
+    private static FieldDeclaration getClassField(TypeDeclaration type, String fieldName, String desiredAnnotation,
+                                                  boolean onlyPublicOrProtected) {
+        if (! (type instanceof ClassDeclaration)) return null;
+
+        ClassDeclaration jclass = (ClassDeclaration) type;
+        FieldDeclaration[] fields = jclass.getFields();
+
+        for (int i = 0; i < fields.length; i++) {
+            FieldDeclaration field = fields[i];
+            if (! onlyPublicOrProtected || field.hasModifier(Modifier.PROTECTED)
+                    || field.hasModifier(Modifier.PUBLIC)) {
+                if (fieldName.equals(field.getSimpleName())
+                        && (desiredAnnotation == null || getAnnotation(field, desiredAnnotation) != null)) {
+                    return field;
+                }
+            }
+        }
+
+        ClassType superclass = jclass.getSuperclass();
+
+        if (superclass != null) {
+            return getClassField(getDeclaration(superclass), fieldName, desiredAnnotation, true);
+        }
+
+        return null;
+    }
+
+    public static MethodDeclaration[] getClassMethods(TypeDeclaration jclass, String desiredAnnotation) {
+        Collection results = new ArrayList();
+        getClassMethods(jclass, desiredAnnotation, false, results);
+        return (MethodDeclaration[]) results.toArray(new MethodDeclaration[ results.size() ]);
+    }
+
+    private static void getClassMethods(TypeDeclaration type, String desiredAnnotation, boolean onlyPublicOrPrivate,
+                                        Collection results) {
+        if (! (type instanceof ClassDeclaration)) return;
+
+        ClassDeclaration jclass = (ClassDeclaration) type;
+        MethodDeclaration[] methods = jclass.getMethods();
+
+        for (int i = 0; i < methods.length; i++) {
+            MethodDeclaration method = methods[i];
+
+            if (! onlyPublicOrPrivate || method.hasModifier(Modifier.PROTECTED)
+                    || method.hasModifier(Modifier.PUBLIC)) {
+                if (desiredAnnotation == null || getAnnotation(method, desiredAnnotation) != null) {
+                    boolean isDuplicate = false;
+
+                    //
+                    // Make sure we're not adding a duplicate method -- one that was already overridden.
+                    //
+                    if (onlyPublicOrPrivate) {
+                        ParameterDeclaration[] methodParams = method.getParameters();
+
+                        for (Iterator j = results.iterator(); j.hasNext();) {
+                            MethodDeclaration existingMethod = (MethodDeclaration) j.next();
+
+                            if (existingMethod.getSimpleName().equals(method.getSimpleName())) {
+                                ParameterDeclaration[] existingMethodParams = existingMethod.getParameters();
+
+                                if (existingMethodParams.length == methodParams.length) {
+                                    isDuplicate = true;
+
+                                    for (int k = 0; k < existingMethodParams.length; ++k) {
+                                        ParameterDeclaration existingMethodParam = existingMethodParams[k];
+                                        ParameterDeclaration methodParam = methodParams[k];
+
+                                        if (! existingMethodParam.getType().equals(methodParam.getType())) {
+                                            isDuplicate = false;
+                                            break;
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+
+                    if (! isDuplicate) results.add(method);
+                }
+            }
+        }
+
+        ClassType superclass = jclass.getSuperclass();
+
+        if (superclass != null && ! getDeclaration(superclass).getQualifiedName().startsWith("java.lang.")) {
+            getClassMethods(getDeclaration(superclass), desiredAnnotation, true, results);
+        }
+    }
+
+    public static Collection getClassFields(TypeDeclaration jclass) {
+        Collection results = new ArrayList();
+        getClassFields(jclass, false, results);
+        return results;
+    }
+
+    private static void getClassFields(TypeDeclaration type, boolean onlyPublicOrPrivate,
+                                       Collection results) {
+        if (! (type instanceof ClassDeclaration)) return;
+
+        ClassDeclaration jclass = (ClassDeclaration) type;
+        FieldDeclaration[] fields = jclass.getFields();
+
+        for (int i = 0; i < fields.length; i++) {
+            FieldDeclaration field = fields[i];
+            if (! onlyPublicOrPrivate || field.hasModifier(Modifier.PROTECTED) || field.hasModifier(Modifier.PUBLIC)) {
+                results.add(field);
+            }
+        }
+
+        ClassType superclass = jclass.getSuperclass();
+        if (superclass != null) getClassFields(getDeclaration(superclass), true, results);
+    }
+
+    public static Collection getClassNestedTypes(TypeDeclaration jclass) {
+        Collection results = new ArrayList();
+        getClassNestedTypes(jclass, false, results);
+        return results;
+    }
+
+    private static void getClassNestedTypes(TypeDeclaration type, boolean onlyPublicOrPrivate,
+                                            Collection results) {
+        if (! (type instanceof ClassDeclaration)) return;
+
+        ClassDeclaration jclass = (ClassDeclaration) type;
+        TypeDeclaration[] nestedTypes = jclass.getNestedTypes();
+
+        for (int i = 0; i < nestedTypes.length; i++) {
+            TypeDeclaration nestedType = nestedTypes[i];
+            if (! onlyPublicOrPrivate || nestedType.hasModifier(Modifier.PROTECTED)
+                    || nestedType.hasModifier(Modifier.PUBLIC)) {
+                results.add(nestedType);
+            }
+        }
+
+        ClassType superclass = jclass.getSuperclass();
+        if (superclass != null) getClassNestedTypes(getDeclaration(superclass), true, results);
+    }
+
+    /**
+     * Get a Class.forName-able string for the given type signature.
+     *
+     * @todo make this pluggable
+     */
+    public static String getFormClassName(TypeDeclaration jclass, AnnotationProcessorEnvironment env) {
+        if (isAssignableFrom(APACHE_XMLOBJECT_CLASS_NAME, jclass, env)) {
+            return XML_FORM_CLASS_NAME;
+        } else {
+            return getLoadableName(jclass);
+        }
+    }
+
+    public static String getFormClassName(DeclaredType jclass, AnnotationProcessorEnvironment env) {
+        return getFormClassName(getDeclaration(jclass), env);
+    }
+
+    public static boolean isAbsoluteURL(String path) {
+        try {
+            return new URI(path).getScheme() != null;
+        }
+        catch (URISyntaxException e) {
+            return false;
+        }
+    }
+
+    public static boolean isAssignableFrom(String className, TypeInstance type, AnnotationProcessorEnvironment env) {
+        if (! (type instanceof DeclaredType)) return false;
+        return isAssignableFrom(className, getDeclaration((DeclaredType) type), env);
+    }
+
+    public static boolean isAssignableFrom(TypeDeclaration base, TypeDeclaration typeDecl) {
+        if (base != null && typeDecl != null) {
+            if (typesAreEqual(typeDecl, base)) return true;
+
+            if (typeDecl instanceof ClassDeclaration) {
+                ClassType superclass = ((ClassDeclaration) typeDecl).getSuperclass();
+                if (superclass != null && isAssignableFrom(base, getDeclaration(superclass))) return true;
+            }
+
+            InterfaceType[] superInterfaces = typeDecl.getSuperinterfaces();
+            for (int i = 0; i < superInterfaces.length; i++) {
+                InterfaceType superInterface = superInterfaces[i];
+                if (isAssignableFrom(base, getDeclaration(superInterface))) return true;
+            }
+        }
+
+        return false;
+    }
+
+    public static boolean isAssignableFrom(TypeInstance base, TypeDeclaration cl) {
+        if (! (base instanceof DeclaredType)) return false;
+        return isAssignableFrom(getDeclaration((DeclaredType) base), cl);
+    }
+
+    public static boolean isAssignableFrom(TypeDeclaration base, TypeInstance cl) {
+        if (! (cl instanceof DeclaredType)) return false;
+        return isAssignableFrom(base, getDeclaration((DeclaredType) cl));
+    }
+
+    public static boolean isAssignableFrom(String className, TypeDeclaration cl, AnnotationProcessorEnvironment env) {
+        TypeDeclaration base = env.getTypeDeclaration(className);
+        return isAssignableFrom(base, cl);
+    }
+
+    public static boolean isOfClass(TypeInstance type, String className, AnnotationProcessorEnvironment env) {
+        if (! (type instanceof DeclaredType)) return false;
+        return typesAreEqual(getDeclaration((DeclaredType) type), env.getTypeDeclaration(className));
+    }
+
+    public static boolean typesAreEqual(TypeDeclaration t1, TypeDeclaration t2) {
+        assert t1 != null;
+        if (t2 == null) return false;
+        return t1.getQualifiedName().equals(t2.getQualifiedName());
+    }
+
+    public static TypeDeclaration getOuterClass(MemberDeclaration classMember) {
+        return classMember instanceof ClassDeclaration
+                ? (ClassDeclaration) classMember
+                : classMember.getDeclaringType();
+    }
+
+    public static TypeDeclaration getOutermostClass(MemberDeclaration classMember) {
+        TypeDeclaration containingClass;
+        while ((containingClass = classMember.getDeclaringType()) != null) {
+            classMember = containingClass;
+        }
+
+        assert classMember instanceof ClassDeclaration : classMember.getClass().getName();
+        return (ClassDeclaration) classMember;
+    }
+
+    public static boolean hasDefaultConstructor(TypeDeclaration jclass) {
+        if (! (jclass instanceof ClassDeclaration)) return false;
+
+        ConstructorDeclaration[] constructors = ((ClassDeclaration) jclass).getConstructors();
+
+        for (int i = 0; i < constructors.length; i++) {
+            ConstructorDeclaration ctor = constructors[i];
+            if (ctor.getParameters().length == 0) return true;
+        }
+
+        return false;
+    }
+
+    private static Declaration findElement(Collection elements, String elementName) {
+        for (Iterator ii = elements.iterator(); ii.hasNext();) {
+            Object element = ii.next();
+            Declaration decl = (Declaration) element;
+            if (decl.getSimpleName().equals(elementName)) return decl;
+        }
+
+        return null;
+    }
+
+    public static FieldDeclaration findField(TypeDeclaration jclass, String fieldName) {
+        return (FieldDeclaration) findElement(getClassFields(jclass), fieldName);
+    }
+
+    public static ClassDeclaration findInnerClass(TypeDeclaration jclass, String innerClassName) {
+        return (ClassDeclaration) findElement(getClassNestedTypes(jclass), innerClassName);
+    }
+
+    public static String getEnumFieldName(AnnotationValue enumMember) {
+        if (enumMember == null || enumMember.getValue() == null)
+            return "";
+        else
+            return enumMember.getValue().toString();
+    }
+
+    /**
+     * Get the qualified name of the given class, with '$' used to separate inner classes; the returned string can be
+     * used with Class.forName().
+     */
+    public static String getLoadableName(TypeDeclaration jclass) {
+        TypeDeclaration containingClass = jclass.getDeclaringType();
+
+        if (containingClass == null) {
+            return jclass.getQualifiedName();
+        } else {
+            return getLoadableName(containingClass) + '$' + jclass.getSimpleName();
+        }
+    }
+
+    public static String getLoadableName(DeclaredType jclass) {
+        return getLoadableName(getDeclaration(jclass));
+    }
+
+    public static File getSourceFile(TypeDeclaration decl, boolean mustBeNonNull) {
+        decl = getOutermostClass(decl);
+        SourcePosition position = decl.getPosition();
+        if (mustBeNonNull) assert position != null : "no source file for " + decl.toString();
+        return position != null ? position.file() : null;
+    }
+
+    public static class ExtendedAnnotationProcessorEnvironment
+            implements AnnotationProcessorEnvironment {
+
+        private AnnotationProcessorEnvironment _env;
+        private boolean _useEqualsToCompareAnnotations;
+        private HashMap _attributes;
+
+        public ExtendedAnnotationProcessorEnvironment(AnnotationProcessorEnvironment env,
+                                                      boolean useEqualsToCompareAnnotations) {
+            _env = env;
+            _useEqualsToCompareAnnotations = useEqualsToCompareAnnotations;
+        }
+
+        public boolean useEqualsToCompareAnnotations() {
+            return _useEqualsToCompareAnnotations;
+        }
+
+        public Map getOptions() {
+            return _env.getOptions();
+        }
+
+        public Messager getMessager() {
+            return _env.getMessager();
+        }
+
+        public Filer getFiler() {
+            return _env.getFiler();
+        }
+
+        public TypeDeclaration[] getSpecifiedTypeDeclarations() {
+            return _env.getSpecifiedTypeDeclarations();
+        }
+
+        public TypeDeclaration getTypeDeclaration(String s) {
+            return _env.getTypeDeclaration(s);
+        }
+
+        public Declaration[] getDeclarationsAnnotatedWith(AnnotationTypeDeclaration annotationTypeDeclaration) {
+            return _env.getDeclarationsAnnotatedWith(annotationTypeDeclaration);
+        }
+
+        public void setAttribute(String propertyName, Object value) {
+            if (_attributes == null) _attributes = new HashMap();
+            _attributes.put(propertyName, value);
+        }
+
+        public Object getAttribute(String propertyName) {
+            return _attributes != null ? _attributes.get(propertyName) : null;
+        }
+    }
+
+    public static boolean annotationsAreEqual(AnnotationInstance a1, AnnotationInstance a2, boolean allowExactDuplicates,
+                                              AnnotationProcessorEnvironment env) {
+        assert a1 != null;
+        if (a2 == null) return false;
+
+        //
+        // TODO: This entire method is a workaround for a bug in APT where an annotation may not equal itelf.
+        // If this behavior changes, we want to rely on equals(), not this deep comparison, which is more expensive
+        // and wrong if the two annotations 'look' exactly the same.
+        //
+        if (! allowExactDuplicates
+                && env instanceof ExtendedAnnotationProcessorEnvironment
+                && ((ExtendedAnnotationProcessorEnvironment) env).useEqualsToCompareAnnotations()) {
+            return a1.equals(a2);
+        }
+
+        Map vals1 = a1.getElementValues();
+        Map vals2 = a2.getElementValues();
+
+        if (vals1.size() != vals2.size()) return false;
+
+
+        Iterator ents1 = vals1.entrySet().iterator();
+        Iterator ents2 = vals2.entrySet().iterator();
+        while (ents1.hasNext()) {
+            Map.Entry entry1 = (Map.Entry) ents1.next();
+            Map.Entry entry2 = (Map.Entry) ents2.next();
+
+            if (! ((AnnotationTypeElementDeclaration) entry1.getKey()).getSimpleName().equals(((AnnotationTypeElementDeclaration) entry2.getKey()).getSimpleName())) return false;
+            Object val1 = ((AnnotationValue) entry1.getValue()).getValue();
+            Object val2 = ((AnnotationValue) entry2.getValue()).getValue();
+
+            if (val1 instanceof Collection) {
+                if (! (val2 instanceof Collection)) return false;
+                Collection list1 = (Collection) val1;
+                Collection list2 = (Collection) val2;
+                if (list1.size() != list2.size()) return false;
+                Iterator j1 = list1.iterator();
+                Iterator j2 = list2.iterator();
+
+                while (j1.hasNext()) {
+                    Object o1 = ((AnnotationValue) j1.next()).getValue();
+                    Object o2 = ((AnnotationValue) j2.next()).getValue();
+
+                    if (o1 instanceof AnnotationInstance) {
+                        if (! (o2 instanceof AnnotationInstance)) return false;
+                        if (! annotationsAreEqual((AnnotationInstance) o1, (AnnotationInstance) o2, allowExactDuplicates, env)) return false;
+                    } else {
+                        if (! o1.equals(o2)) return false;
+                    }
+                }
+            } else if (val1 instanceof AnnotationInstance) {
+                if (! (val2 instanceof AnnotationInstance)) return false;
+                if (! annotationsAreEqual((AnnotationInstance) val1, (AnnotationInstance) val2, allowExactDuplicates, env)) return false;
+            } else if (! val1.equals(val2)) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    public static class BeanPropertyDescriptor {
+
+        private String _propertyName;
+        private String _type;
+
+        public BeanPropertyDescriptor(String propertyName, String type) {
+            _propertyName = propertyName;
+            _type = type;
+        }
+
+        public String getPropertyName() {
+            return _propertyName;
+        }
+
+        public String getType() {
+            return _type;
+        }
+    }
+
+    public static class BeanPropertyDeclaration
+            extends BeanPropertyDescriptor {
+
+        private MethodDeclaration _getter;
+
+
+        public BeanPropertyDeclaration(String propertyName, String type, MethodDeclaration getter) {
+            super(propertyName, type);
+            _getter = getter;
+        }
+
+        public MethodDeclaration getGetter() {
+            return _getter;
+        }
+    }
+
+    public static BeanPropertyDeclaration getBeanProperty(MethodDeclaration method) {
+        if (method.hasModifier(Modifier.PUBLIC) && ! method.hasModifier(Modifier.STATIC)) {
+            String returnType = method.getReturnType().toString();
+
+            if (! returnType.equals("void") && method.getParameters().length == 0) {
+                String methodName = method.getSimpleName();
+                String propertyName = null;
+
+                if (methodName.startsWith(GETTER_PREFIX) && methodName.length() > GETTER_PREFIX.length()) {
+                    propertyName = methodName.substring(GETTER_PREFIX.length());
+                } else if (methodName.startsWith(BOOLEAN_GETTER_PREFIX) && returnType.equals("boolean")
+                        && methodName.length() > BOOLEAN_GETTER_PREFIX.length()) {
+                    propertyName = methodName.substring(BOOLEAN_GETTER_PREFIX.length());
+                }
+
+                if (propertyName != null) {
+                    //
+                    // If the first two letters are uppercase, we don't change the first character to lowercase.
+                    // This is so that something like getURI has a property name of 'URI' (see JavaBeans spec).
+                    //
+                    if (propertyName.length() == 1) {
+                        propertyName = propertyName.toLowerCase();
+                    } else if (! Character.isUpperCase(propertyName.charAt(1))) {
+                        propertyName = Character.toLowerCase(propertyName.charAt(0)) + propertyName.substring(1);
+                    }
+
+                    return new BeanPropertyDeclaration(propertyName, returnType, method);
+                }
+            }
+        }
+
+        return null;
+    }
+
+    public static Collection getBeanProperties(ClassDeclaration type, boolean getInheritedProperties) {
+        MethodDeclaration[] methods = getInheritedProperties ? getClassMethods(type, null) : type.getMethods();
+        ArrayList ret = new ArrayList();
+
+        for (int i = 0; i < methods.length; i++) {
+            MethodDeclaration method = methods[i];
+
+            if (method.hasModifier(Modifier.PUBLIC)) {
+                BeanPropertyDeclaration bpd = getBeanProperty(method);
+                if (bpd != null) ret.add(bpd);
+            }
+        }
+
+        return ret;
+    }
+
+    public static boolean isPageFlowClass(ClassDeclaration jclass, AnnotationProcessorEnvironment env) {
+        return getAnnotation(jclass, CONTROLLER_TAG_NAME) != null && isAssignableFrom(JPF_BASE_CLASS, jclass, env);
+    }
+
+    public static String removeFileExtension(String uri) {
+        int lastDot = uri.lastIndexOf('.');
+        return uri.substring(0, lastDot);
+    }
+
+    public static TypeDeclaration inferTypeFromPath(String webappRelativePath, AnnotationProcessorEnvironment env) {
+        assert webappRelativePath.startsWith("/") : webappRelativePath;
+        String className = removeFileExtension(webappRelativePath.substring(1));
+        return env.getTypeDeclaration(className.replace('/', '.'));
+    }
+
+    public static TypeDeclaration getDeclaration(DeclaredType type) {
+        return type != null ? type.getDeclaration() : ERROR_TYPE_DECLARATION;
+    }
+
+    private static class ErrorTypeInstance
+            implements TypeInstance {
+
+        public String toString() {
+            return ERROR_STRING;
+        }
+    }
+
+    private static class ErrorTypeDeclaration
+            implements TypeDeclaration {
+
+        private static final InterfaceType[] SUPERINTERFACES = new InterfaceType[0];
+        private static final FieldDeclaration[] FIELDS = new FieldDeclaration[0];
+        private static final MethodDeclaration[] METHODS = new MethodDeclaration[0];
+        private static final TypeDeclaration[] NESTED_TYPES = new TypeDeclaration[0];
+        private static final AnnotationInstance[] ANNOTATIONS = new AnnotationInstance[0];
+
+        public PackageDeclaration getPackage() {
+            throw new IllegalStateException("not implemented ");
+        }
+
+        public String getQualifiedName() {
+            return ERROR_STRING;
+        }
+
+        /*
+        public Collection getFormalTypeParameters()
+        {
+            return Collections.EMPTY_LIST;
+        }
+        */
+
+        public InterfaceType[] getSuperinterfaces() {
+            return SUPERINTERFACES;
+        }
+
+        public FieldDeclaration[] getFields() {
+            return FIELDS;
+        }
+
+        public MethodDeclaration[] getMethods() {
+            return METHODS;
+        }
+
+        public TypeDeclaration[] getNestedTypes() {
+            return NESTED_TYPES;
+        }
+
+        public TypeDeclaration getDeclaringType() {
+            return null;
+        }
+
+        public String getDocComment() {
+            throw new IllegalStateException("not implemented ");
+        }
+
+        public AnnotationInstance[] getAnnotationInstances() {
+            return ANNOTATIONS;
+        }
+
+        /*
+        public Annotation getAnnotation( Class s )
+        {
+            throw new IllegalStateException( "not implemented " );
+        }
+        */
+
+        public Set getModifiers() {
+            return Collections.EMPTY_SET;
+        }
+
+        public String getSimpleName() {
+            return getQualifiedName();
+        }
+
+        public SourcePosition getPosition() {
+            throw new IllegalStateException("not implemented ");
+        }
+
+        public boolean hasModifier(Modifier modifier) {
+            return false;
+        }
+
+        /*
+        public void accept( DeclarationVisitor declarationVisitor )
+        {
+            throw new IllegalStateException( "not implemented " );
+        }
+        */
+    }
+
+    /**
+     * This is the same logic that we have in the runtime, in PageFlowRequestProcessor.  Can't share the code, though.
+     */
+    public static boolean isAbsoluteURI(String uri) {
+        //
+        // This method needs to be fast, so it can't use java.net.URI.
+        //
+        if (uri.length() == 0 || uri.charAt(0) == '/') return false;
+
+        for (int i = 0, len = uri.length(); i < len; ++i) {
+            char c = uri.charAt(i);
+
+            if (c == ':') {
+                return true;
+            } else if (c == '/') {
+                return false;
+            }
+        }
+
+        return false;
+    }
+
+    public static TypeInstance getArrayBaseType(ArrayType arrayType) {
+        TypeInstance baseType = arrayType;
+
+        do {
+            baseType = ((ArrayType) baseType).getComponentType();
+        } while (baseType instanceof ArrayType);
+
+        return baseType;
+    }
+
+    public static final class Mutable {
+
+        private Object _val = null;
+
+        public Mutable() {
+        }
+
+        public Mutable(Object val) {
+            _val = val;
+        }
+
+        public void set(Object val) {
+            _val = val;
+        }
+
+        public Object get() {
+            return _val;
+        }
+    }
+
+    public static TypeInstance getGenericBoundsType(TypeInstance type) {
+        if (type instanceof TypeVariable) {
+            ReferenceType[] bounds = ((TypeVariable) type).getDeclaration().getBounds();
+            return bounds.length > 0 ? bounds[0] : type;
+        }
+
+        return type;
+    }
+
+    public static File getFileRelativeToSourceFile(TypeDeclaration outerClass, String relativePath,
+                                                   AnnotationProcessorEnvironment env)
+            throws FatalCompileTimeException {
+        assert relativePath.length() > 0;
+
+        //
+        // If it starts with '/', just find the webapp-relative file.
+        //
+        if (relativePath.charAt(0) == '/') return getWebappRelativeFile(relativePath, true, env);
+
+        //
+        // Look for the file relative to the source directory of the given class.
+        //
+        File sourceFile = getSourceFile(outerClass, false);
+        File desiredParentDir = sourceFile.getAbsoluteFile().getParentFile();
+        File retVal = new File(desiredParentDir, relativePath);
+
+        //
+        // If we still haven't found it, construct a webapp-relative path and look for the file relative to the webapp.
+        //
+        if (! retVal.exists()) {
+            PackageDeclaration jpfPackage = outerClass.getPackage();
+            return getWebappRelativeFile(getPathRelativeToPackage(relativePath, jpfPackage), true, env);
+        }
+
+        return retVal;
+    }
+
+    public static String getPathRelativeToPackage(String relativePath, PackageDeclaration packageDecl) {
+        if (packageDecl != null) {
+            String packageName = packageDecl.getQualifiedName();
+            if (packageName.length() > 0) return '/' + packageName.replace('.', '/') + '/' + relativePath;
+        }
+
+        return '/' + relativePath;
+    }
+
+    public static File getWebappRelativeFile(String webappRelativePath, boolean lookInSourceRoots,
+                                             AnnotationProcessorEnvironment env)
+            throws FatalCompileTimeException {
+        //
+        // Look for the file out in the web-addressable portion of the webapp.
+        //
+        assert webappRelativePath.startsWith("/") : webappRelativePath;
+        String[] webContentRoots = getWebContentRoots(env);
+
+        for (int i = 0; i < webContentRoots.length; i++) {
+            String webContentRoot = webContentRoots[i];
+            File retVal = new File(webContentRoot + webappRelativePath);
+            if (retVal.exists()) return retVal;
+        }
+
+        //
+        // If appropriate, look for the file under all the source roots.
+        //
+        if (lookInSourceRoots) {
+            String[] webSourceRoots = getWebSourceRoots(env);
+
+            for (int i = 0; i < webSourceRoots.length; i++) {
+                String webSourceRoot = webSourceRoots[i];
+                File webSourceRelativeFile = new File(webSourceRoot + webappRelativePath);
+                if (webSourceRelativeFile.exists()) return webSourceRelativeFile;
+            }
+        }
+
+        return null;
+    }
+
+    public static String[] getWebSourceRoots(AnnotationProcessorEnvironment env)
+            throws FatalCompileTimeException {
+        return (String[]) getOption("-sourcepath", true, env);
+    }
+
+    public static String[] getWebContentRoots(AnnotationProcessorEnvironment env)
+            throws FatalCompileTimeException {
+        return (String[]) getOption("-Aweb.content.root", true, env);
+    }
+
+    private static Object getOption(String optionName, boolean isList, AnnotationProcessorEnvironment env)
+            throws MissingOptionException {
+        Object cached = env.getAttribute(optionName);
+        if (cached != null) return cached;
+
+        Map options = env.getOptions();
+        String value = (String) options.get(optionName);
+
+        if (value == null) {
+            // TODO: there appears to be a bug in APT where both the key/value are contained in the key
+            String aptOption = optionName + '=';
+            for (Iterator i = options.keySet().iterator(); i.hasNext();) {
+                String key = (String) i.next();
+
+                if (key.startsWith(aptOption)) {
+                    value = key.substring(aptOption.length());
+                    break;
+                }
+            }
+        }
+
+        if (value == null) throw new MissingOptionException(optionName);
+
+        Object retVal = value;
+
+        if (isList) {
+            String[] values = ((String) retVal).trim().split(File.pathSeparator);
+            for (int i = 0; i < values.length; i++) {
+                values[i] = values[i].trim();
+            }
+            retVal = values;
+        }
+
+        env.setAttribute(optionName, retVal);
+        return retVal;
+    }
+}



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@struts.apache.org
For additional commands, e-mail: dev-help@struts.apache.org