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 [8/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/genmodel/GenXWorkActionModel.java
URL: http://svn.apache.org/viewcvs/struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/genmodel/GenXWorkActionModel.java?rev=280879&view=auto
==============================================================================
--- struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/genmodel/GenXWorkActionModel.java (added)
+++ struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/genmodel/GenXWorkActionModel.java Wed Sep 14 09:20:05 2005
@@ -0,0 +1,207 @@
+/*
+ * 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.genmodel;
+
+import org.apache.ti.compiler.internal.CompilerUtils;
+import org.apache.ti.compiler.internal.JpfLanguageConstants;
+import org.apache.ti.compiler.internal.model.XWorkActionModel;
+import org.apache.ti.compiler.internal.model.XWorkResultModel;
+import org.apache.ti.compiler.internal.typesystem.declaration.AnnotationInstance;
+import org.apache.ti.compiler.internal.typesystem.declaration.ClassDeclaration;
+import org.apache.ti.compiler.internal.typesystem.declaration.Declaration;
+import org.apache.ti.compiler.internal.typesystem.declaration.MethodDeclaration;
+import org.apache.ti.compiler.internal.typesystem.declaration.ParameterDeclaration;
+import org.apache.ti.compiler.internal.typesystem.declaration.TypeDeclaration;
+import org.apache.ti.compiler.internal.typesystem.type.DeclaredType;
+import org.apache.ti.compiler.internal.typesystem.type.TypeInstance;
+
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+
+
+public class GenXWorkActionModel
+        extends XWorkActionModel
+        implements JpfLanguageConstants {
+
+    public GenXWorkActionModel(Declaration sourceElement, GenXWorkModuleConfigModel parentApp, ClassDeclaration jclass) {
+        super(parentApp);
+
+        init(getActionName(sourceElement), getActionAnnotation(sourceElement), parentApp, jclass);
+
+        // Get the form class from the method argument.
+        setFormBeanType(getFormBean(sourceElement, parentApp));
+
+        setComment("Generated from action method " + sourceElement.getSimpleName());
+    }
+
+    protected GenXWorkActionModel(String actionName, AnnotationInstance ann, GenXWorkModuleConfigModel parentApp, ClassDeclaration jclass) {
+        super(parentApp);
+        init(actionName, ann, parentApp, jclass);
+    }
+
+    private void init(String actionName, AnnotationInstance annotation, GenXWorkModuleConfigModel parentApp, ClassDeclaration jclass) {
+        setName(actionName);
+
+        //
+        // loginRequired
+        //
+        Boolean loginRequired = CompilerUtils.getBoolean(annotation, LOGIN_REQUIRED_ATTR, true);
+        if (loginRequired == null) {
+            loginRequired = parentApp.getFlowControllerInfo().getMergedControllerAnnotation().isLoginRequired();
+        }
+        if (loginRequired != null) setLoginRequired(loginRequired.booleanValue());
+
+        //
+        // prevent-double-submit
+        //
+        Boolean preventDoubleSubmit = CompilerUtils.getBoolean(annotation, PREVENT_DOUBLE_SUBMIT_ATTR, false);
+        setPreventDoubleSubmit(preventDoubleSubmit.booleanValue());
+
+        //
+        // readOnly
+        //
+        Boolean readOnly = CompilerUtils.getBoolean(annotation, READONLY_ATTR, true);
+        if (readOnly == null) {
+            readOnly = Boolean.valueOf(parentApp.getFlowControllerInfo().getMergedControllerAnnotation().isReadOnly());
+        }
+        setReadonly(readOnly.booleanValue());
+
+        //
+        // rolesAllowed -- avoid setting this if loginRequired is explicitly false.
+        //
+        if (loginRequired == null || loginRequired.booleanValue()) setRolesAllowed(annotation, jclass, parentApp);
+
+        //
+        // type (delegating Action class, with the FlowController as parameter)
+        //
+        setType(FLOW_CONTROLLER_ACTION_CLASS);
+
+        //
+        // form bean member -- the page-flow-scoped form referenced by the action (a member variable)
+        //
+        setFormBeanMember(CompilerUtils.getString(annotation, USE_FORM_BEAN_ATTR, true));
+
+        //
+        // forwards
+        //
+        getForwards(annotation, jclass, parentApp);
+
+        //
+        // validationErrorForward -- the forward used when validation fails
+        //
+        AnnotationInstance validateErrFwd = CompilerUtils.getAnnotation(annotation, VALIDATION_ERROR_FORWARD_ATTR, true);
+        boolean doValidation = false;
+        if (validateErrFwd != null) {
+            XWorkResultModel fwd = new GenXWorkResultModel(parentApp, validateErrFwd, jclass, " (validationErrorForward)");
+            addForward(fwd);
+            setValidationErrorForward(fwd.getName());
+            doValidation = true;
+        }
+
+        //
+        // validate
+        //
+        Boolean explicitDoValidation = CompilerUtils.getBoolean(annotation, DO_VALIDATION_ATTR, true);
+        setValidate(explicitDoValidation != null ? explicitDoValidation.booleanValue() : doValidation);
+
+        //
+        // exception-catches
+        //
+        GenXWorkExceptionHandlerModel.addCatches(annotation, this, jclass, parentApp);
+    }
+
+    private void setRolesAllowed(AnnotationInstance annotation, ClassDeclaration jclass, GenXWorkModuleConfigModel parentApp) {
+        List rolesAllowed = CompilerUtils.getStringArray(annotation, ROLES_ALLOWED_ATTR, true);
+        List classLevelRA = parentApp.getFlowControllerInfo().getMergedControllerAnnotation().getRolesAllowed();
+        Iterator it = null;
+
+        if (rolesAllowed != null && classLevelRA != null) {
+            HashSet merged = new HashSet();
+            for (Iterator ii = rolesAllowed.iterator(); ii.hasNext();) {
+                String role = (String) ii.next();
+                merged.add(role);
+            }
+            for (Iterator ii = classLevelRA.iterator(); ii.hasNext();) {
+                String classLevelRole = (String) ii.next();
+                merged.add(classLevelRole);
+            }
+            it = merged.iterator();
+        } else if (rolesAllowed != null) {
+            it = rolesAllowed.iterator();
+        } else if (classLevelRA != null) {
+            it = classLevelRA.iterator();
+        }
+
+        if (it != null && it.hasNext()) {
+            StringBuffer rolesAllowedStr = new StringBuffer((String) it.next());
+
+            while (it.hasNext()) {
+                rolesAllowedStr.append(',').append(((String) it.next()).trim());
+            }
+
+            setRoles(rolesAllowedStr.toString());
+        }
+    }
+
+    protected static String getActionName(Declaration sourceElement) {
+        return sourceElement.getSimpleName();
+    }
+
+    /**
+     * @return the Struts name of the form bean.
+     */
+    protected String getFormBean(Declaration sourceElement, GenXWorkModuleConfigModel parentApp) {
+        assert sourceElement instanceof MethodDeclaration : sourceElement.getClass().getName();
+        ParameterDeclaration[] params = ((MethodDeclaration) sourceElement).getParameters();
+        String formBeanName = null;
+
+        if (params.length > 0) {
+            assert params.length == 1 : params.length;  // checker should catch this
+            TypeInstance paramType = CompilerUtils.getGenericBoundsType(params[0].getType());
+            formBeanName = addFormBean(paramType, parentApp);
+        }
+
+        return formBeanName;
+    }
+
+    protected String addFormBean(TypeInstance paramType, GenXWorkModuleConfigModel parentApp) {
+        paramType = CompilerUtils.getGenericBoundsType(paramType);
+        assert paramType instanceof DeclaredType : paramType.getClass().getName();  // checker should enforce this
+        TypeDeclaration decl = CompilerUtils.getDeclaration((DeclaredType) paramType);
+        return parentApp.addFormBean(decl, this);
+    }
+
+    protected AnnotationInstance getActionAnnotation(Declaration sourceElement) {
+        assert sourceElement instanceof MethodDeclaration : sourceElement.getClass().getName();
+        return CompilerUtils.getAnnotation(sourceElement, ACTION_TAG_NAME);
+    }
+
+    protected void getForwards(AnnotationInstance annotation, ClassDeclaration jclass, GenXWorkModuleConfigModel parentApp) {
+        GenXWorkResultModel.addForwards(annotation, this, jclass, parentApp, null);
+
+        // Infer a "success" forward if there wasn't one specified.
+        XWorkResultModel successFwd = getForward("success");
+        if (successFwd == null) {
+            String defaultFileExt = parentApp.getDefaultFileExtension();
+            successFwd = new XWorkResultModel("success", getName() + defaultFileExt, parentApp);
+            successFwd.setComment("(implicit)");
+            addForward(successFwd);
+        }
+    }
+}

Added: struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/genmodel/GenXWorkExceptionHandlerModel.java
URL: http://svn.apache.org/viewcvs/struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/genmodel/GenXWorkExceptionHandlerModel.java?rev=280879&view=auto
==============================================================================
--- struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/genmodel/GenXWorkExceptionHandlerModel.java (added)
+++ struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/genmodel/GenXWorkExceptionHandlerModel.java Wed Sep 14 09:20:05 2005
@@ -0,0 +1,127 @@
+/*
+ * 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.genmodel;
+
+import org.apache.ti.compiler.internal.CompilerUtils;
+import org.apache.ti.compiler.internal.JpfLanguageConstants;
+import org.apache.ti.compiler.internal.model.XWorkExceptionHandlerContainer;
+import org.apache.ti.compiler.internal.model.XWorkExceptionHandlerModel;
+import org.apache.ti.compiler.internal.model.XWorkResultModel;
+import org.apache.ti.compiler.internal.typesystem.declaration.AnnotationInstance;
+import org.apache.ti.compiler.internal.typesystem.declaration.ClassDeclaration;
+import org.apache.ti.compiler.internal.typesystem.declaration.MethodDeclaration;
+import org.apache.ti.compiler.internal.typesystem.declaration.TypeDeclaration;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+
+
+public class GenXWorkExceptionHandlerModel
+        extends XWorkExceptionHandlerModel
+        implements JpfLanguageConstants {
+
+    public GenXWorkExceptionHandlerModel(GenXWorkModuleConfigModel parentApp, AnnotationInstance annotation,
+                                         ClassDeclaration jclass, String parentAnnotationName) {
+        super(parentApp);
+
+        setType(CompilerUtils.getLoadableName(CompilerUtils.getDeclaredType(annotation, TYPE_ATTR, true)));
+        setMessage(CompilerUtils.getString(annotation, MESSAGE_ATTR, true));
+        setMessageKey(CompilerUtils.getString(annotation, MESSAGE_KEY_ATTR, true));
+        String path = CompilerUtils.getString(annotation, PATH_ATTR, true);
+        String methodName = CompilerUtils.getString(annotation, METHOD_ATTR, true);
+
+        // "Generated by" comment
+        // TODO I18N
+        StringBuffer comment = new StringBuffer("Generated from ");
+        comment.append('@').append(ANNOTATION_INTERFACE_PREFIX);
+        comment.append(parentAnnotationName);
+        comment.append("/@").append(ANNOTATION_INTERFACE_PREFIX);
+        comment.append(annotation.getAnnotationType().getAnnotationTypeDeclaration().getSimpleName());
+        comment.append(" (type=");
+        comment.append(getType());
+        comment.append(") ");
+
+        //
+        // Now get the forwards (@Jpf.Forward) from the handler method, and add them as global or local
+        // forwards, as appropriate.
+        //
+        if (methodName != null) {
+            setHandlerMethod(methodName);
+            MethodDeclaration method = CompilerUtils.getClassMethod(jclass, methodName, EXCEPTION_HANDLER_TAG_NAME);
+            AnnotationInstance exHandlerAnnotation = CompilerUtils.getAnnotation(method, EXCEPTION_HANDLER_TAG_NAME);
+            GenXWorkResultModel.addForwards(exHandlerAnnotation, this, jclass, parentApp, null);
+
+            // Infer a "success" forward if there wasn't one specified.
+            XWorkResultModel successFwd = getForward("success");
+            if (successFwd == null) {
+                String defaultFileExt = parentApp.getDefaultFileExtension();
+                successFwd = new XWorkResultModel("success", methodName + defaultFileExt, parentApp);
+                successFwd.setComment("(implicit)");
+                addForward(successFwd);
+            }
+
+            //
+            // Also, if the exception-handler was marked "read-only", note this on the  tag.
+            //
+            Boolean readOnly = CompilerUtils.getBoolean(exHandlerAnnotation, READONLY_ATTR, true);
+            if (readOnly == null) {
+                readOnly = Boolean.valueOf(parentApp.getFlowControllerInfo().getMergedControllerAnnotation().isReadOnly());
+            }
+            setReadonly(readOnly.booleanValue());
+
+            comment.append("and method " + methodName);
+        } else {
+            assert path != null;
+
+            //
+            // If this annotation came from a base class, and if inheritLocalPaths is true on the Controller
+            // annotation, then make the path relative to the base class module.
+            //
+            TypeDeclaration containingType = annotation.getContainingType();
+            if (! CompilerUtils.typesAreEqual(jclass, containingType)
+                    && parentApp.getFlowControllerInfo().getMergedControllerAnnotation().isInheritLocalPaths()) {
+                // TODO: when we no longer support Struts 1.1, we can simply use the 'module' property
+                // to make this forward relative to the base class module.
+                path = CompilerUtils.getPathRelativeToPackage(path, containingType.getPackage());
+                setInheritedPath(true);
+            }
+
+            setPath(path);
+        }
+
+        setComment(comment.toString());
+    }
+
+    static void addCatches(AnnotationInstance annotation, XWorkExceptionHandlerContainer container, ClassDeclaration jclass,
+                           GenXWorkModuleConfigModel strutsApp) {
+        List catches = CompilerUtils.getAnnotationArray(annotation, CATCHES_ATTR, true);
+        addCatches(catches, container, jclass, strutsApp,
+                annotation.getAnnotationType().getAnnotationTypeDeclaration().getSimpleName());
+    }
+
+    static void addCatches(Collection catches, XWorkExceptionHandlerContainer container, ClassDeclaration jclass,
+                           GenXWorkModuleConfigModel strutsApp, String parentAnnotationName) {
+        if (catches != null) {
+            for (Iterator ii = catches.iterator(); ii.hasNext();) {
+                AnnotationInstance i = (AnnotationInstance) ii.next();
+                container.addException(new GenXWorkExceptionHandlerModel(strutsApp, i, jclass, parentAnnotationName));
+            }
+        }
+    }
+}

Added: struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/genmodel/GenXWorkModuleConfigModel.java
URL: http://svn.apache.org/viewcvs/struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/genmodel/GenXWorkModuleConfigModel.java?rev=280879&view=auto
==============================================================================
--- struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/genmodel/GenXWorkModuleConfigModel.java (added)
+++ struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/genmodel/GenXWorkModuleConfigModel.java Wed Sep 14 09:20:05 2005
@@ -0,0 +1,455 @@
+/*
+ * 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.genmodel;
+
+import org.apache.ti.compiler.internal.CompilerUtils;
+import org.apache.ti.compiler.internal.Diagnostics;
+import org.apache.ti.compiler.internal.FatalCompileTimeException;
+import org.apache.ti.compiler.internal.FlowControllerInfo;
+import org.apache.ti.compiler.internal.JpfLanguageConstants;
+import org.apache.ti.compiler.internal.MergedControllerAnnotation;
+import org.apache.ti.compiler.internal.grammar.WebappPathOrActionType;
+import org.apache.ti.compiler.internal.model.XWorkActionModel;
+import org.apache.ti.compiler.internal.model.XWorkModuleConfigModel;
+import org.apache.ti.compiler.internal.model.XWorkResultModel;
+import org.apache.ti.compiler.internal.model.XmlModelWriterException;
+import org.apache.ti.compiler.internal.typesystem.declaration.AnnotationInstance;
+import org.apache.ti.compiler.internal.typesystem.declaration.ClassDeclaration;
+import org.apache.ti.compiler.internal.typesystem.declaration.MethodDeclaration;
+import org.apache.ti.compiler.internal.typesystem.declaration.Modifier;
+import org.apache.ti.compiler.internal.typesystem.declaration.ParameterDeclaration;
+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.DeclaredType;
+import org.apache.ti.compiler.internal.typesystem.type.TypeInstance;
+import org.apache.xmlbeans.XmlException;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.List;
+
+
+public class GenXWorkModuleConfigModel
+        extends XWorkModuleConfigModel
+        implements JpfLanguageConstants {
+
+    private static final boolean CASE_INSENSITIVE_FILES = new File("x").equals(new File("X"));
+
+    private ClassDeclaration _jclass;
+    private String _containingPackage;
+    private File _strutsConfigFile;
+    private File _sourceFile;
+    private AnnotationProcessorEnvironment _env;
+    private FlowControllerInfo _fcInfo;
+
+    protected void recalculateStrutsConfigFile()
+            throws XmlException, IOException, FatalCompileTimeException {
+        _strutsConfigFile = calculateStrutsConfigFile(); // caching this
+    }
+
+    FlowControllerInfo getFlowControllerInfo() {
+        return _fcInfo;
+    }
+
+    public GenXWorkModuleConfigModel(File sourceFile, ClassDeclaration jclass, AnnotationProcessorEnvironment env,
+                                     FlowControllerInfo fcInfo, boolean checkOnly, Diagnostics diagnostics)
+            throws XmlException, IOException, FatalCompileTimeException {
+        super(jclass.getQualifiedName());
+
+        _jclass = jclass;
+        _containingPackage = jclass.getPackage().getQualifiedName();
+        _sourceFile = sourceFile;
+        _env = env;
+        assert fcInfo != null;
+        _fcInfo = fcInfo;
+
+        recalculateStrutsConfigFile();
+
+        if (checkOnly) return;
+
+        if (_jclass != null) {
+            MergedControllerAnnotation mca = fcInfo.getMergedControllerAnnotation();
+            setNestedPageFlow(mca.isNested());
+            setLongLivedPageFlow(mca.isLongLived());
+            //addMessageBundles( mca.getMessageBundles() );
+            addSimpleActions(mca.getSimpleActions());
+            setMultipartHandler(mca.getMultipartHandler());
+            GenXWorkResultModel.addForwards(mca.getForwards(), this, _jclass, this, null);
+
+            // TODO: comment
+            addForward(new XWorkResultModel("_auto", "", this));
+
+            GenXWorkExceptionHandlerModel.addCatches(mca.getCatches(), this, _jclass, this, CONTROLLER_TAG_NAME);
+            addTilesDefinitionsConfigs(mca.getTilesDefinitionsConfigs());
+            setAdditionalValidatorConfigs(mca.getCustomValidatorConfigs());
+
+            addActionMethods();
+            inferBeginAction(_jclass, fcInfo);
+            addFormBeans(_jclass);
+        }
+
+        if (fcInfo != null) {
+            setSharedFlows(fcInfo.getSharedFlowTypeNames());
+            setReturnToActionDisabled(! fcInfo.isNavigateToActionEnabled());
+            setReturnToPageDisabled(! fcInfo.isNavigateToPageEnabled());
+        }
+    }
+
+    private void inferBeginAction(ClassDeclaration jclass, FlowControllerInfo fcInfo) {
+        boolean isAbstract = jclass.hasModifier(Modifier.ABSTRACT);
+
+        if (! isAbstract
+                && ! WebappPathOrActionType.actionExists(BEGIN_ACTION_NAME, jclass, null, getEnv(), fcInfo, true)) {
+            XWorkActionModel inferredBeginAction = new XWorkActionModel(BEGIN_ACTION_NAME, this);
+            inferredBeginAction.setSimpleAction(true);
+            inferredBeginAction.setDefaultForwardName("success");
+            XWorkResultModel fwd = new XWorkResultModel("success", BEGIN_ACTION_NAME + getDefaultFileExtension(), this);
+            inferredBeginAction.addForward(fwd);
+            inferredBeginAction.setComment("(implicit)");
+            addAction(inferredBeginAction);
+        }
+    }
+
+    private void addFormBeans(ClassDeclaration jclass) {
+        Collection innerTypes = CompilerUtils.getClassNestedTypes(jclass);
+
+        for (Iterator ii = innerTypes.iterator(); ii.hasNext();) {
+            TypeDeclaration innerType = (TypeDeclaration) ii.next();
+            if (innerType instanceof ClassDeclaration) {
+                ClassDeclaration innerClass = (ClassDeclaration) innerType;
+
+                if (innerType.hasModifier(Modifier.PUBLIC)
+                        && CompilerUtils.isAssignableFrom(PAGEFLOW_FORM_CLASS_NAME, innerClass, _env)) {
+                    addFormBean(innerClass, null);
+                }
+            }
+        }
+
+    }
+
+    /**
+     * @return the typename of the form bean class
+     */
+    String addFormBean(TypeDeclaration formType, XWorkActionModel usedByAction) {
+        String formClass = CompilerUtils.getFormClassName(formType, _env);
+
+        //
+        // Use the actual type of form to create the name.
+        // This avoids conflicts if there are multiple forms using the
+        // ANY_FORM_CLASS_NAME type.
+        //
+        String actualType = CompilerUtils.getLoadableName(formType);
+
+        //
+        // See if the app already has a form-bean of this type.  If so,
+        // we'll just use it; otherwise, we need to create it.
+        //
+        boolean usesPageFlowScopedFormBean = usedByAction != null ? usedByAction.getFormBeanMember() != null : false;
+        getMessageResourcesFromForm(formType, usedByAction);
+        return formClass;
+    }
+
+    /*
+    private void addMessageBundles( Collection messageBundles )
+    {
+        if ( messageBundles != null )
+        {
+            for ( Iterator ii = messageBundles.iterator(); ii.hasNext(); )  
+            {
+                AnnotationInstance ann = ( AnnotationInstance ) ii.next();
+                addMessageResources( new GenMessageBundleModel( this, ann ) );
+            }
+        }
+    }
+    */
+
+    private void addSimpleActions(Collection simpleActionAnnotations) {
+        if (simpleActionAnnotations != null) {
+            for (Iterator ii = simpleActionAnnotations.iterator(); ii.hasNext();) {
+                AnnotationInstance ann = (AnnotationInstance) ii.next();
+                addAction(new GenSimpleActionModel(ann, this, _jclass));
+            }
+        }
+    }
+
+    private void setMultipartHandler(String mpHandler) {
+        if (mpHandler != null) {
+            if (mpHandler.equals(MULTIPART_HANDLER_DISABLED_STR)) {
+                setMultipartHandlerClassName("none");
+            } else {
+                setMultipartHandlerClassName(COMMONS_MULTIPART_HANDLER_CLASSNAME);
+
+                if (mpHandler.equals(MULTIPART_HANDLER_DISK_STR)) {
+                    setMemFileSize("0K");
+                } else {
+                    assert mpHandler.equals(MULTIPART_HANDLER_MEMORY_STR) : mpHandler;
+                }
+            }
+        }
+    }
+
+    private void addTilesDefinitionsConfigs(List tilesDefinitionsConfigs) {
+        if (tilesDefinitionsConfigs == null || tilesDefinitionsConfigs.isEmpty()) {
+            return;
+        }
+
+        List paths = new ArrayList();
+
+        for (Iterator ii = tilesDefinitionsConfigs.iterator(); ii.hasNext();) {
+            String definitionsConfig = (String) ii.next();
+
+            if (definitionsConfig != null && definitionsConfig.length() > 0) {
+                paths.add(definitionsConfig);
+            }
+        }
+
+        setTilesDefinitionsConfigs(paths);
+    }
+
+    private void addActionMethods() {
+        MethodDeclaration[] actionMethods = CompilerUtils.getClassMethods(_jclass, ACTION_TAG_NAME);
+
+        for (int i = 0; i < actionMethods.length; i++) {
+            MethodDeclaration actionMethod = actionMethods[i];
+
+            if (! actionMethod.hasModifier(Modifier.ABSTRACT)) {
+                XWorkActionModel actionModel = new GenXWorkActionModel(actionMethod, this, _jclass);
+                addAction(actionModel);
+                ParameterDeclaration[] params = actionMethod.getParameters();
+
+                if (params.length > 0) {
+                    ParameterDeclaration param1 = params[0];
+                    TypeInstance paramType = param1.getType();
+
+                    if (paramType instanceof DeclaredType) {
+                        getMessageResourcesFromForm(CompilerUtils.getDeclaration((DeclaredType) paramType), actionModel);
+                    }
+                }
+            }
+        }
+    }
+
+    private void getMessageResourcesFromForm(TypeDeclaration formTypeDecl, XWorkActionModel actionModel) {
+        if (! (formTypeDecl instanceof ClassDeclaration)) return;
+
+        ClassDeclaration formClassDecl = (ClassDeclaration) formTypeDecl;
+
+        AnnotationInstance ann = CompilerUtils.getAnnotation(formClassDecl, FORM_BEAN_TAG_NAME, true);
+
+        if (ann != null) {
+            String defaultMessageResources = CompilerUtils.getString(ann, MESSAGE_BUNDLE_ATTR, true);
+
+            if (defaultMessageResources != null) {
+                String key = "formMessages:" + CompilerUtils.getLoadableName(formClassDecl);
+
+                /* TODO: re-add message bundle support
+                for ( Iterator ii = getMessageResourcesList().iterator(); ii.hasNext(); )  
+                {
+                    MessageResourcesModel i = ( MessageResourcesModel ) ii.next();
+                    if ( key.equals( i.getKey() ) && i.getParameter().equals( defaultMessageResources ) ) return;
+                }
+                
+                MessageResourcesModel mrm = new MessageResourcesModel( this );
+                mrm.setKey( key );
+                mrm.setParameter( defaultMessageResources );
+                mrm.setReturnNull( true );
+                addMessageResources( mrm );
+                if ( actionModel != null ) actionModel.setFormBeanMessageResourcesKey( key );
+                */
+            }
+        }
+    }
+
+    protected String getMergeFileName() {
+        return null;   // In Beehive, this was Struts merge.  Will we have XWork-merge?
+    }
+
+    public void writeToFile()
+            throws FileNotFoundException, IOException, XmlModelWriterException, FatalCompileTimeException {
+        PrintWriter writer = getEnv().getFiler().createTextFile(_strutsConfigFile);
+
+        try {
+            writeXml(writer, getMergeFile(getMergeFileName()));
+        }
+        finally {
+            writer.close();
+        }
+    }
+
+    public boolean isStale()
+            throws FatalCompileTimeException {
+        return isStale(getMergeFile(getMergeFileName()));
+    }
+
+    String getOutputFileURI(String filePrefix) {
+        return getOutputFilePath(filePrefix, _containingPackage);
+    }
+
+    String getConfigFilePath() {
+        return getOutputFilePath(PAGE_FLOW_CONFIG_FILE_BASENAME, _containingPackage);
+    }
+
+    protected String getContainingPackage() {
+        return _containingPackage;
+    }
+
+    private File calculateStrutsConfigFile() {
+        return new File(getConfigFilePath());
+    }
+
+    /**
+     * Tell whether the XWork output file is out of date, based on the
+     * file times of the source file and the (optional) xwork-merge file.
+     */
+    public boolean isStale(File mergeFile) {
+        //
+        // We can write to the file if it doesn't exist yet.
+        //
+        if (! _strutsConfigFile.exists()) {
+            return true;
+        }
+
+        long lastWrite = _strutsConfigFile.lastModified();
+
+        if (mergeFile != null && mergeFile.exists() && mergeFile.lastModified() > lastWrite) {
+            return true;
+        }
+
+        if (_sourceFile.lastModified() > lastWrite) {
+            return true;
+        }
+
+        return false;
+    }
+
+    /**
+     * In some cases, canWrite() does not guarantee that a FileNotFoundException will not
+     * be thrown when trying to write to a file.  This method actually tries to overwrite
+     * the file as a test to see whether it's possible.
+     */
+    public boolean canWrite() {
+        if (! _strutsConfigFile.canWrite()) {
+            return false;
+        }
+
+        try {
+            //
+            // This appears to be the only way to predict whether the file can actually be
+            // written to; it may be that canWrite() returns true, but the file permissions
+            // (NTFS only?) will cause an exception to be thrown.
+            //
+            new FileOutputStream(_strutsConfigFile, true).close();
+        }
+        catch (FileNotFoundException e) {
+            return false;
+        }
+        catch (IOException e) {
+            return false;
+        }
+
+        return true;
+    }
+
+    public File getStrutsConfigFile() {
+        return _strutsConfigFile;
+    }
+
+    public File getMergeFile(String mergeFileName)
+            throws FatalCompileTimeException {
+        if (mergeFileName != null) {
+            return CompilerUtils.getFileRelativeToSourceFile(_jclass, mergeFileName, getEnv());
+        }
+
+        return null;
+    }
+
+    protected String getHeaderComment(File mergeFile)
+            throws FatalCompileTimeException {
+        StringBuffer comment = new StringBuffer(" Generated from ");
+        comment.append(getWebappRelativePath(_sourceFile));
+        if (mergeFile != null) {
+            comment.append(" and ").append(getWebappRelativePath(mergeFile));
+        }
+        comment.append(" on ").append(new Date().toString()).append(' ');
+        return comment.toString();
+    }
+
+    private String getWebappRelativePath(File file)
+            throws FatalCompileTimeException {
+        String filePath = file.getAbsoluteFile().getPath();
+        String[] sourceRoots = CompilerUtils.getWebSourceRoots(_env);
+
+        //
+        // Look through the source roots.
+        //
+        for (int i = 0; i < sourceRoots.length; i++) {
+            String sourceRoot = sourceRoots[i].replace('/', File.separatorChar);
+
+            if (pathStartsWith(filePath, sourceRoot)) {
+                return filePath.substring(sourceRoot.length()).replace('\\', '/');
+            }
+        }
+
+        //
+        // Look in the web content root.
+        //
+        String[] webContentRoots = CompilerUtils.getWebContentRoots(getEnv());
+        for (int i = 0; i < webContentRoots.length; i++) {
+            String webContentRoot = webContentRoots[i].replace('/', File.separatorChar);
+
+            if (pathStartsWith(filePath, webContentRoot)) {
+                return filePath.substring(webContentRoot.length()).replace('\\', '/');
+            }
+        }
+
+        assert false : "could not calculate webapp-relative file from " + file;
+        return file.toString();
+    }
+
+    private static boolean pathStartsWith(String path, String prefix) {
+        if (CASE_INSENSITIVE_FILES) {
+            return path.toLowerCase().startsWith(prefix.toLowerCase());
+        } else {
+            return path.startsWith(prefix);
+        }
+    }
+
+    AnnotationProcessorEnvironment getEnv() {
+        return _env;
+    }
+
+    /**
+     * Get the file extension that is inferred from an action name if there is no explicit "success" forward.
+     *
+     * @todo make this configurable.
+     */
+    String getDefaultFileExtension() {
+        return '.' + JSP_FILE_EXTENSION;
+    }
+
+    protected String getValidationFilePrefix() {
+        return "pageflow-validation";
+    }
+}

Added: struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/genmodel/GenXWorkResultModel.java
URL: http://svn.apache.org/viewcvs/struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/genmodel/GenXWorkResultModel.java?rev=280879&view=auto
==============================================================================
--- struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/genmodel/GenXWorkResultModel.java (added)
+++ struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/genmodel/GenXWorkResultModel.java Wed Sep 14 09:20:05 2005
@@ -0,0 +1,160 @@
+/*
+ * 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.genmodel;
+
+import org.apache.ti.compiler.internal.CompilerUtils;
+import org.apache.ti.compiler.internal.JpfLanguageConstants;
+import org.apache.ti.compiler.internal.model.XWorkResultContainer;
+import org.apache.ti.compiler.internal.model.XWorkResultModel;
+import org.apache.ti.compiler.internal.typesystem.declaration.AnnotationInstance;
+import org.apache.ti.compiler.internal.typesystem.declaration.ClassDeclaration;
+import org.apache.ti.compiler.internal.typesystem.declaration.FieldDeclaration;
+import org.apache.ti.compiler.internal.typesystem.declaration.TypeDeclaration;
+import org.apache.ti.compiler.internal.typesystem.type.DeclaredType;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+
+public class GenXWorkResultModel
+        extends XWorkResultModel
+        implements JpfLanguageConstants {
+
+    public GenXWorkResultModel(GenXWorkModuleConfigModel parent, AnnotationInstance annotation, ClassDeclaration jclass,
+                               String commentSuffix) {
+        super(parent);
+
+        setName(CompilerUtils.getString(annotation, NAME_ATTR, true));
+        setRedirect(CompilerUtils.getBoolean(annotation, REDIRECT_ATTR, false).booleanValue());
+        if (CompilerUtils.getBoolean(annotation, EXTERNAL_REDIRECT_ATTR, false).booleanValue()) {
+            setExternalRedirect(true);
+        }
+
+        //
+        // outputFormBean/outputFormBeanType
+        //
+        DeclaredType outputFormType = CompilerUtils.getDeclaredType(annotation, OUTPUT_FORM_BEAN_TYPE_ATTR, true);
+        String outputFormMember = CompilerUtils.getString(annotation, OUTPUT_FORM_BEAN_ATTR, true);
+        if (outputFormMember != null) {
+            FieldDeclaration field = CompilerUtils.getClassField(jclass, outputFormMember, null);
+            assert outputFormType == null;  // checker should catch this
+            assert field != null;           // checker should catch this
+            assert field.getType() instanceof DeclaredType : field.getType().getClass().getName(); // checker enforces
+            outputFormType = (DeclaredType) field.getType();
+        }
+        setOutputFormBeanMember(outputFormMember);
+        setOutputFormBeanType(outputFormType != null ? CompilerUtils.getLoadableName(outputFormType) : null);
+
+        //
+        // path, tilesDefinition, navigateTo, returnAction (mutually exclusive)
+        //
+        String returnAction = CompilerUtils.getString(annotation, RETURN_ACTION_ATTR, true);
+        String navigateTo = CompilerUtils.getEnumFieldName(annotation, NAVIGATE_TO_ATTR, true);
+        String tilesDefinition = CompilerUtils.getString(annotation, TILES_DEFINITION_ATTR, true);
+        String path = CompilerUtils.getString(annotation, PATH_ATTR, true);
+        String action = CompilerUtils.getString(annotation, ACTION_ATTR, true);
+
+        if (action != null) {
+            assert path == null;  // checker should enforce this
+            path = action + ACTION_EXTENSION_DOT;
+        }
+
+        if (returnAction != null) {
+            assert navigateTo == null;
+            assert tilesDefinition == null;
+            assert path == null;
+            setReturnAction(returnAction);
+        } else if (navigateTo != null) {
+            assert tilesDefinition == null;
+            assert path == null;
+
+            if (navigateTo.equals(NAVIGATE_TO_CURRENT_PAGE_STR)) {
+                setReturnToPage(0);
+            } else if (navigateTo.equals(NAVIGATE_TO_PREVIOUS_PAGE_STR)) {
+                setReturnToPage(1);
+            } else if (navigateTo.equals(NAVIGATE_TO_PREVIOUS_ACTION_STR)) {
+                setReturnToAction();
+            } else {
+                assert false : "unknown value for navigateTo: \"" + navigateTo + '"';
+            }
+
+            boolean restore = CompilerUtils.getBoolean(annotation, RESTORE_QUERY_STRING_ATTR, false).booleanValue();
+            setRestoreQueryString(restore);
+        } else if (tilesDefinition != null) {
+            assert path == null;
+            setPath(tilesDefinition);    // set the tilesDefinition as the path -- the runtime expects it there
+        } else {
+            assert path != null;      // checker should enforce this
+
+            //
+            // Translate our relative-path convention (normal) to the Struts convention, which adds a '/'
+            // to any module-relative path.
+            //
+            if (! path.startsWith("/")) {
+                //
+                // If this annotation came from a base class, and if inheritLocalPaths is true on the Controller
+                // annotation, then make the path relative to the base class module.
+                //
+                TypeDeclaration containingType = annotation.getContainingType();
+                if (! CompilerUtils.typesAreEqual(jclass, containingType)
+                        && parent.getFlowControllerInfo().getMergedControllerAnnotation().isInheritLocalPaths()) {
+                    // TODO: when we no longer support Struts 1.1, we can simply use the 'module' property
+                    // to make this forward relative to the base class module.
+                    path = CompilerUtils.getPathRelativeToPackage(path, containingType.getPackage());
+                    setInheritedPath(true);
+                }
+            }
+
+            setPath(path);
+        }
+
+        addActionOutputs(annotation, jclass);
+
+        if (commentSuffix != null) {
+            setComment("forward \"" + getName() + '"' + commentSuffix);  // @TODO I18N the comment
+        }
+    }
+
+    static void addForwards(AnnotationInstance annotation, XWorkResultContainer container, ClassDeclaration jclass,
+                            GenXWorkModuleConfigModel strutsApp, String commentSuffix) {
+        List forwards = CompilerUtils.getAnnotationArray(annotation, FORWARDS_ATTR, true);
+        addForwards(forwards, container, jclass, strutsApp, commentSuffix);
+    }
+
+    static void addForwards(Collection forwards, XWorkResultContainer container,
+                            ClassDeclaration jclass, GenXWorkModuleConfigModel strutsApp, String commentSuffix) {
+        if (forwards != null) {
+            for (Iterator ii = forwards.iterator(); ii.hasNext();) {
+                AnnotationInstance ann = (AnnotationInstance) ii.next();
+                container.addForward(new GenXWorkResultModel(strutsApp, ann, jclass, commentSuffix));
+            }
+        }
+    }
+
+    protected void addActionOutputs(AnnotationInstance annotation, ClassDeclaration jclass) {
+        List actionOutputs =
+                CompilerUtils.getAnnotationArray(annotation, ACTION_OUTPUTS_ATTR, true);
+
+        if (actionOutputs != null) {
+            for (Iterator ii = actionOutputs.iterator(); ii.hasNext();) {
+                AnnotationInstance ann = (AnnotationInstance) ii.next();
+                addActionOutput(new GenActionOutputModel(ann, jclass));
+            }
+        }
+    }
+}

Added: struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/genmodel/ValidatorRuleFactory.java
URL: http://svn.apache.org/viewcvs/struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/genmodel/ValidatorRuleFactory.java?rev=280879&view=auto
==============================================================================
--- struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/genmodel/ValidatorRuleFactory.java (added)
+++ struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/genmodel/ValidatorRuleFactory.java Wed Sep 14 09:20:05 2005
@@ -0,0 +1,28 @@
+/*
+ * 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.genmodel;
+
+import org.apache.ti.compiler.internal.model.validation.ValidatorRule;
+import org.apache.ti.compiler.internal.typesystem.declaration.AnnotationInstance;
+
+
+public interface ValidatorRuleFactory {
+
+    public ValidatorRule getFieldRule(String entityName, String propertyName, AnnotationInstance ruleAnnotation);
+}
+

Added: struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/grammar/AbsolutePathType.java
URL: http://svn.apache.org/viewcvs/struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/grammar/AbsolutePathType.java?rev=280879&view=auto
==============================================================================
--- struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/grammar/AbsolutePathType.java (added)
+++ struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/grammar/AbsolutePathType.java Wed Sep 14 09:20:05 2005
@@ -0,0 +1,43 @@
+/**
+ * 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.grammar;
+
+import org.apache.ti.compiler.internal.AnnotationGrammar;
+import org.apache.ti.compiler.internal.AnnotationMemberType;
+import org.apache.ti.compiler.internal.CompilerUtils;
+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;
+
+public class AbsolutePathType extends AnnotationMemberType {
+
+    public AbsolutePathType(String requiredRuntimeVersion, AnnotationGrammar parentGrammar) {
+        super(requiredRuntimeVersion, parentGrammar);
+    }
+
+
+    public Object onCheck(AnnotationTypeElementDeclaration valueDecl, AnnotationValue member,
+                          AnnotationInstance[] parentAnnotations, MemberDeclaration classMember,
+                          int annotationArrayIndex) {
+        AnnotationInstance parentAnnotation = parentAnnotations[parentAnnotations.length - 1];
+        String path = CompilerUtils.getString(parentAnnotation, PATH_ATTR, false);
+        if (! path.startsWith("/")) addError(member, "error.absolute-path-required-for-external-redirect", null);
+        return null;
+    }
+}

Added: struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/grammar/ActionGrammar.java
URL: http://svn.apache.org/viewcvs/struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/grammar/ActionGrammar.java?rev=280879&view=auto
==============================================================================
--- struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/grammar/ActionGrammar.java (added)
+++ struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/grammar/ActionGrammar.java Wed Sep 14 09:20:05 2005
@@ -0,0 +1,264 @@
+/*
+ * 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.grammar;
+
+import org.apache.ti.compiler.internal.AnnotationMemberType;
+import org.apache.ti.compiler.internal.CompilerUtils;
+import org.apache.ti.compiler.internal.Diagnostics;
+import org.apache.ti.compiler.internal.FatalCompileTimeException;
+import org.apache.ti.compiler.internal.FlowControllerInfo;
+import org.apache.ti.compiler.internal.JpfLanguageConstants;
+import org.apache.ti.compiler.internal.RuntimeVersionChecker;
+import org.apache.ti.compiler.internal.typesystem.declaration.*;
+import org.apache.ti.compiler.internal.typesystem.env.AnnotationProcessorEnvironment;
+import org.apache.ti.compiler.internal.typesystem.type.DeclaredType;
+import org.apache.ti.compiler.internal.typesystem.type.TypeInstance;
+
+
+public class ActionGrammar
+        extends BaseFlowControllerGrammar
+        implements JpfLanguageConstants {
+
+    public ActionGrammar(AnnotationProcessorEnvironment env, Diagnostics diags,
+                         RuntimeVersionChecker rvc, FlowControllerInfo fcInfo) {
+        super(env, diags, null, rvc, fcInfo);
+
+        addMemberType(LOGIN_REQUIRED_ATTR, new AnnotationMemberType(null, this));
+        addMemberType(ROLES_ALLOWED_ATTR, new RolesAllowedType(this));
+        addMemberType(READONLY_ATTR, new AnnotationMemberType(VERSION_8_SP2_STRING, this));
+        addMemberType(USE_FORM_BEAN_ATTR, new UseFormBeanType());
+        addMemberType(PREVENT_DOUBLE_SUBMIT_ATTR, new AnnotationMemberType(null, this));
+        addMemberType(DO_VALIDATION_ATTR, new DoValidateType());
+
+        addMemberArrayGrammar(FORWARDS_ATTR, new ForwardGrammar(env, diags, null, rvc, fcInfo));
+        addMemberArrayGrammar(CATCHES_ATTR, new CatchGrammar(env, diags, null, rvc, ACTION_TAG_NAME, fcInfo));
+        addMemberArrayGrammar(VALIDATABLE_PROPERTIES_ATTR, new ValidatablePropertyGrammar(env, diags, rvc));
+        addMemberGrammar(VALIDATION_ERROR_FORWARD_ATTR, new ActionForwardGrammar());
+    }
+
+    public String[][] getMutuallyExclusiveAttrs() {
+        return null;
+    }
+
+    public String[][] getRequiredAttrs() {
+        return null;
+    }
+
+    protected boolean onBeginCheck(AnnotationInstance annotation, AnnotationInstance[] parentAnnotations,
+                                   MemberDeclaration classMember)
+            throws FatalCompileTimeException {
+        //
+        // First check the form bean type.
+        //
+        TypeInstance argType = getFormBeanType(annotation, classMember);
+        TypeDeclaration argTypeDecl = null;
+
+        if (! (argType instanceof DeclaredType)) {
+            if (argType != null) {
+                getDiagnostics().addError(annotation, "error.action-invalid-form-bean-type", argType.toString());
+                argType = null;
+            }
+        } else {
+            argTypeDecl = CompilerUtils.getDeclaration((DeclaredType) argType);
+            boolean isClass = argTypeDecl instanceof ClassDeclaration;
+
+            if (isClass && ! CompilerUtils.hasDefaultConstructor(argTypeDecl)) {
+                getDiagnostics().addError(annotation, "error.action-form-bean-no-default-constructor",
+                        argTypeDecl.getQualifiedName());
+            }
+
+            if (! argTypeDecl.hasModifier(Modifier.PUBLIC)) {
+                getDiagnostics().addError(annotation, "error.action-form-bean-not-public",
+                        argTypeDecl.getQualifiedName());
+            }
+
+            if (isClass && argTypeDecl.getDeclaringType() != null && ! argTypeDecl.hasModifier(Modifier.STATIC)) {
+                getDiagnostics().addError(annotation, "error.action-form-bean-not-static",
+                        argTypeDecl.getQualifiedName());
+            }
+
+            //
+            // Give a warning if there is no validationErrorForward annotation and doValidation isn't set to false.
+            //
+            if (CompilerUtils.getAnnotationValue(annotation, VALIDATION_ERROR_FORWARD_ATTR, true) == null
+                    && hasValidationAnnotations(argTypeDecl)) {
+                Boolean doValidation = CompilerUtils.getBoolean(annotation, DO_VALIDATION_ATTR, true);
+
+                if (doValidation == null || doValidation.booleanValue()) {
+                    getDiagnostics().addWarning(
+                            annotation, "warning.validatable-formbean-no-forward",
+                            ANNOTATION_INTERFACE_PREFIX + annotation.getAnnotationType().getDeclaration().getSimpleName(),
+                            VALIDATION_ERROR_FORWARD_ATTR, argTypeDecl.getQualifiedName());
+                }
+            }
+        }
+
+        //
+        // Add this action to the FlowControllerInfo.
+        //
+        getFlowControllerInfo().addAction(getActionName(annotation, classMember),
+                argTypeDecl != null ? argTypeDecl.getQualifiedName() : null);
+
+        //
+        // Check to make sure the 'useFormBean' attribute (reference to a member variable) matches the form declared as
+        // an argument to the action method.
+        //
+        TypeInstance useFormBeanType = getUseFormBeanType(annotation, classMember);
+
+        if (useFormBeanType != null && useFormBeanType instanceof DeclaredType) {
+            if (argType == null) {
+                String memberFormTypeName = CompilerUtils.getDeclaration((DeclaredType) useFormBeanType).getQualifiedName();
+                getDiagnostics().addError(annotation, "error.action-mismatched-form", USE_FORM_BEAN_ATTR,
+                        memberFormTypeName);
+            } else if (! CompilerUtils.isAssignableFrom(argTypeDecl, useFormBeanType)) {
+                String memberFormTypeName = CompilerUtils.getDeclaration((DeclaredType) useFormBeanType).getQualifiedName();
+                getDiagnostics().addError(annotation, "error.action-mismatched-form", USE_FORM_BEAN_ATTR,
+                        memberFormTypeName);
+            }
+        }
+
+        return true;
+    }
+
+    protected String getActionName(AnnotationInstance annotation, MemberDeclaration classMember) {
+        assert classMember instanceof MethodDeclaration : classMember.getClass().getName();
+        return classMember.getSimpleName();
+    }
+
+    private static boolean hasValidationAnnotations(TypeDeclaration type) {
+        // Could cache this if it's a performance problem.
+
+        MethodDeclaration[] methods = type.getMethods();
+
+        for (int i = 0; i < methods.length; i++) {
+            MethodDeclaration method = methods[i];
+            AnnotationInstance[] annotations = method.getAnnotationInstances();
+
+            for (int j = 0; j < annotations.length; j++) {
+                AnnotationInstance ann = annotations[j];
+                String annotationName = CompilerUtils.getDeclaration(ann.getAnnotationType()).getQualifiedName();
+                int pos = annotationName.indexOf(ANNOTATION_QUALIFIER);
+
+                if (pos != -1) {
+                    if (annotationName.substring(pos + ANNOTATION_QUALIFIER.length()).startsWith("Validat")) {
+                        return true;
+                    }
+                }
+            }
+        }
+
+        return false;
+    }
+
+    protected static TypeInstance getUseFormBeanType(AnnotationInstance annotation, MemberDeclaration classMember) {
+        String formBeanFieldName = CompilerUtils.getString(annotation, USE_FORM_BEAN_ATTR, true);
+
+        if (formBeanFieldName != null) {
+            FieldDeclaration formBeanField =
+                    CompilerUtils.findField(CompilerUtils.getOutermostClass(classMember), formBeanFieldName);
+
+            if (formBeanField != null) {
+                return CompilerUtils.getGenericBoundsType(formBeanField.getType());
+            }
+        }
+
+        return null;
+    }
+
+    protected TypeInstance getFormBeanType(AnnotationInstance annotation, MemberDeclaration classMember) {
+        assert classMember instanceof MethodDeclaration : classMember.getClass().getName();
+        MethodDeclaration method = (MethodDeclaration) classMember;
+        ParameterDeclaration[] parameters = method.getParameters();
+        int nParameters = parameters.length;
+
+        if (nParameters > 1) getDiagnostics().addError(method, "error.action-method-wrong-arg");
+        if (nParameters > 0) return CompilerUtils.getGenericBoundsType(parameters[0].getType());
+
+        return null;
+    }
+
+    private class DoValidateType
+            extends AnnotationMemberType {
+
+        public DoValidateType() {
+            super(null, ActionGrammar.this);
+        }
+
+
+        public Object onCheck(AnnotationTypeElementDeclaration valueDecl, AnnotationValue member,
+                              AnnotationInstance[] parentAnnotations, MemberDeclaration classMember,
+                              int annotationArrayIndex) {
+            //
+            // If this value is set to true, there must be a value for validationErrorForward.
+            //
+            if (((Boolean) member.getValue()).booleanValue()) {
+                AnnotationInstance parentAnnotation = parentAnnotations[parentAnnotations.length - 1];
+
+                if (CompilerUtils.getAnnotation(parentAnnotation, VALIDATION_ERROR_FORWARD_ATTR, true) == null) {
+                    addError(member, "error.validate-with-no-validation-error-forward", DO_VALIDATION_ATTR,
+                            VALIDATION_ERROR_FORWARD_ATTR);
+                }
+            }
+
+            return null;
+        }
+    }
+
+    private class ActionForwardGrammar
+            extends ForwardGrammar {
+
+        public ActionForwardGrammar() {
+            super(ActionGrammar.this.getEnv(), ActionGrammar.this.getDiagnostics(), null,
+                    ActionGrammar.this.getRuntimeVersionChecker(), ActionGrammar.this.getFlowControllerInfo());
+            ExternalPathOrActionType baseForwardType =
+                    new ExternalPathOrActionType(false, null, this, ActionGrammar.this.getFlowControllerInfo());
+            addMemberType(PATH_ATTR, new ForwardToExternalPathType(baseForwardType, null, ActionGrammar.this));
+        }
+    }
+
+    private class UseFormBeanType
+            extends WritableFieldType {
+
+        public UseFormBeanType() {
+            super(null, USE_FORM_BEAN_ATTR, null, ActionGrammar.this);
+        }
+
+
+        public Object onCheck(AnnotationTypeElementDeclaration valueDecl, AnnotationValue value,
+                              AnnotationInstance[] parentAnnotations, MemberDeclaration classMember,
+                              int annotationArrayIndex) {
+            FieldDeclaration memberField =
+                    (FieldDeclaration) super.onCheck(valueDecl, value, parentAnnotations, classMember,
+                            annotationArrayIndex);
+
+            if (memberField != null) {
+                //
+                // If this action is marked 'readOnly', print a warning about the 'useFormBean' attribute implicitly
+                // modifying member data.
+                //
+                AnnotationInstance parentAnnotation = parentAnnotations[parentAnnotations.length - 1];
+                if (CompilerUtils.getBoolean(parentAnnotation, READONLY_ATTR, false).booleanValue()) {
+                    addWarning(value, "warning.use-form-bean-on-readonly-action", READONLY_ATTR, USE_FORM_BEAN_ATTR,
+                            memberField.getSimpleName());
+                }
+            }
+
+            return memberField;
+        }
+    }
+}

Added: struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/grammar/ActionOutputGrammar.java
URL: http://svn.apache.org/viewcvs/struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/grammar/ActionOutputGrammar.java?rev=280879&view=auto
==============================================================================
--- struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/grammar/ActionOutputGrammar.java (added)
+++ struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/grammar/ActionOutputGrammar.java Wed Sep 14 09:20:05 2005
@@ -0,0 +1,40 @@
+/*
+ * 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.grammar;
+
+import org.apache.ti.compiler.internal.AnnotationGrammar;
+import org.apache.ti.compiler.internal.Diagnostics;
+import org.apache.ti.compiler.internal.RuntimeVersionChecker;
+import org.apache.ti.compiler.internal.typesystem.env.AnnotationProcessorEnvironment;
+
+public class ActionOutputGrammar
+        extends AnnotationGrammar {
+
+    private static final String[][] REQUIRED_ATTRS = {{NAME_ATTR}, {TYPE_ATTR}};
+
+    public ActionOutputGrammar(AnnotationProcessorEnvironment env, Diagnostics diags, RuntimeVersionChecker rvc) {
+        super(env, diags, null, rvc);
+
+        addMemberType(NAME_ATTR, new UniqueValueType(ACTION_OUTPUTS_ATTR, false, false, null, this));
+        addMemberType(TYPE_ATTR, new TypeNameType(null, true, null, this));
+    }
+
+    public String[][] getRequiredAttrs() {
+        return REQUIRED_ATTRS;
+    }
+}

Added: struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/grammar/BaseFlowControllerGrammar.java
URL: http://svn.apache.org/viewcvs/struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/grammar/BaseFlowControllerGrammar.java?rev=280879&view=auto
==============================================================================
--- struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/grammar/BaseFlowControllerGrammar.java (added)
+++ struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/grammar/BaseFlowControllerGrammar.java Wed Sep 14 09:20:05 2005
@@ -0,0 +1,41 @@
+/*
+ * 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.grammar;
+
+import org.apache.ti.compiler.internal.AnnotationGrammar;
+import org.apache.ti.compiler.internal.Diagnostics;
+import org.apache.ti.compiler.internal.FlowControllerInfo;
+import org.apache.ti.compiler.internal.RuntimeVersionChecker;
+import org.apache.ti.compiler.internal.typesystem.env.AnnotationProcessorEnvironment;
+
+public class BaseFlowControllerGrammar
+        extends AnnotationGrammar {
+
+    private FlowControllerInfo _flowControllerInfo;
+
+    public BaseFlowControllerGrammar(AnnotationProcessorEnvironment env, Diagnostics diags,
+                                     String requiredRuntimeVersion, RuntimeVersionChecker runtimeVersionChecker,
+                                     FlowControllerInfo flowControllerInfo) {
+        super(env, diags, requiredRuntimeVersion, runtimeVersionChecker);
+        _flowControllerInfo = flowControllerInfo;
+    }
+
+    FlowControllerInfo getFlowControllerInfo() {
+        return _flowControllerInfo;
+    }
+}

Added: struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/grammar/BaseValidationRuleGrammar.java
URL: http://svn.apache.org/viewcvs/struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/grammar/BaseValidationRuleGrammar.java?rev=280879&view=auto
==============================================================================
--- struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/grammar/BaseValidationRuleGrammar.java (added)
+++ struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/grammar/BaseValidationRuleGrammar.java Wed Sep 14 09:20:05 2005
@@ -0,0 +1,120 @@
+/*
+* 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.grammar;
+
+import org.apache.ti.compiler.internal.AnnotationGrammar;
+import org.apache.ti.compiler.internal.CompilerUtils;
+import org.apache.ti.compiler.internal.Diagnostics;
+import org.apache.ti.compiler.internal.FatalCompileTimeException;
+import org.apache.ti.compiler.internal.RuntimeVersionChecker;
+import org.apache.ti.compiler.internal.typesystem.declaration.AnnotationInstance;
+import org.apache.ti.compiler.internal.typesystem.declaration.MemberDeclaration;
+import org.apache.ti.compiler.internal.typesystem.env.AnnotationProcessorEnvironment;
+
+import java.util.Iterator;
+import java.util.List;
+
+
+public class BaseValidationRuleGrammar
+        extends AnnotationGrammar {
+
+    private static final String[][] MUTUALLY_EXCLUSIVE_ATTRS =
+            {
+                    {MESSAGE_KEY_ATTR, MESSAGE_ATTR}
+            };
+
+    private static final String[][] ATTR_DEPENDENCIES =
+            {
+                    {BUNDLE_NAME_ATTR, MESSAGE_KEY_ATTR}
+            };
+
+    private String[][] _requiredAttrs = null;
+
+    public BaseValidationRuleGrammar(AnnotationProcessorEnvironment env, Diagnostics diags,
+                                     RuntimeVersionChecker rvc) {
+        super(env, diags, VERSION_9_0_STRING, rvc);
+
+        addMemberType(MESSAGE_KEY_ATTR, new MessageKeyType(null, this));
+        addMemberArrayGrammar(MESSAGE_ARGS_ATTR, new ValidationMessageArgsGrammar(env, diags, rvc));
+        addMemberType(BUNDLE_NAME_ATTR, new BundleNameType(null, this));
+    }
+
+    public BaseValidationRuleGrammar(AnnotationProcessorEnvironment env, Diagnostics diags,
+                                     RuntimeVersionChecker rvc, String[][] requiredAttrs) {
+        this(env, diags, rvc);
+
+        _requiredAttrs = requiredAttrs;
+    }
+
+    public String[][] getRequiredAttrs() {
+        return _requiredAttrs;
+    }
+
+    public String[][] getMutuallyExclusiveAttrs() {
+        return MUTUALLY_EXCLUSIVE_ATTRS;
+    }
+
+    public String[][] getAttrDependencies() {
+        return ATTR_DEPENDENCIES;
+    }
+
+
+    protected boolean onBeginCheck(AnnotationInstance annotation, AnnotationInstance[] parentAnnotations,
+                                   MemberDeclaration classMember)
+            throws FatalCompileTimeException {
+        //
+        // Check to make sure that either the parent ValidatableProperty annotation has a displayName property,
+        // or this rule specifies a first argument to the default message, or this rule specifies its own message.
+        // If none of these are true, output a warning.
+        //
+        assert parentAnnotations.length > 0;
+        AnnotationInstance immediateParent = parentAnnotations[parentAnnotations.length - 1];
+
+        if (CompilerUtils.getString(immediateParent, DISPLAY_NAME_ATTR, true) == null
+                && CompilerUtils.getString(immediateParent, DISPLAY_NAME_KEY_ATTR, true) == null
+                && CompilerUtils.getString(annotation, MESSAGE_KEY_ATTR, true) == null
+                && CompilerUtils.getString(annotation, MESSAGE_ATTR, true) == null) {
+            boolean useDefaultDisplayName = true;
+            List messageArgs =
+                    CompilerUtils.getAnnotationArray(annotation, MESSAGE_ARGS_ATTR, true);
+
+            if (messageArgs != null) {
+                boolean firstArg = true;
+
+                for (Iterator ii = messageArgs.iterator(); ii.hasNext();) {
+                    AnnotationInstance messageArg = (AnnotationInstance) ii.next();
+                    Integer position = CompilerUtils.getInteger(messageArg, POSITION_ATTR, true);
+
+                    if ((position == null && firstArg) || (position != null && position.intValue() == 0)) {
+                        useDefaultDisplayName = false;
+                        break;
+                    }
+
+                    firstArg = false;
+                }
+            }
+
+            if (useDefaultDisplayName) {
+                addWarning(annotation, "warning.using-default-display-name",
+                        CompilerUtils.getDeclaration(immediateParent.getAnnotationType()).getSimpleName());
+            }
+        }
+
+        return super.onBeginCheck(annotation, parentAnnotations, classMember);
+    }
+}

Added: struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/grammar/BundleNameType.java
URL: http://svn.apache.org/viewcvs/struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/grammar/BundleNameType.java?rev=280879&view=auto
==============================================================================
--- struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/grammar/BundleNameType.java (added)
+++ struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/grammar/BundleNameType.java Wed Sep 14 09:20:05 2005
@@ -0,0 +1,99 @@
+/*
+* 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.grammar;
+
+import org.apache.ti.compiler.internal.AnnotationGrammar;
+import org.apache.ti.compiler.internal.AnnotationMemberType;
+import org.apache.ti.compiler.internal.CompilerUtils;
+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.ClassDeclaration;
+import org.apache.ti.compiler.internal.typesystem.declaration.MemberDeclaration;
+import org.apache.ti.compiler.internal.typesystem.declaration.TypeDeclaration;
+
+
+public class BundleNameType
+        extends AnnotationMemberType {
+
+    public BundleNameType(String requiredRuntimeVersion, AnnotationGrammar parentGrammar) {
+        super(requiredRuntimeVersion, parentGrammar);
+    }
+
+
+    public Object onCheck(AnnotationTypeElementDeclaration valueDecl, AnnotationValue value,
+                          AnnotationInstance[] parentAnnotations, MemberDeclaration classMember,
+                          int annotationArrayIndex) {
+        //
+        // Check that the bundle attribute isn't used with commons-validator v1.0
+        //
+        String bundle = (String) value.getValue();
+
+        if (bundle != null && !bundlesSupported(parentAnnotations, classMember)) {
+            AnnotationInstance annotation = parentAnnotations[parentAnnotations.length - 1];
+            addError(value, "error.validation-bundle-support", BUNDLE_NAME_ATTR, annotation);
+        }
+
+        return null;
+    }
+
+    protected static boolean bundlesSupported(AnnotationInstance[] parentAnnotations, MemberDeclaration classMember) {
+        //
+        // Find the validator version attribute from the controller.
+        // Look at the annotation parent root for @Jpf.Controller,
+        // @Jpf.Action or @Jpf.ValidatableProperty. If the root is
+        // the Controller then just get the required attribute.
+        // Otherwise, get the controller class declaration then the
+        // attribute.
+        //
+        AnnotationInstance ann = parentAnnotations[0];
+        String validatorVersion = null;
+
+        if (CompilerUtils.isJpfAnnotation(ann, CONTROLLER_TAG_NAME)) {
+            validatorVersion = CompilerUtils.getEnumFieldName(ann, VALIDATOR_VERSION_ATTR, true);
+        } else {
+            TypeDeclaration outerType = null;
+
+            if (CompilerUtils.isJpfAnnotation(ann, ACTION_TAG_NAME)) {
+                outerType = CompilerUtils.getOuterClass(classMember);
+            } else if (CompilerUtils.isJpfAnnotation(ann, VALIDATABLE_PROPERTY_TAG_NAME)) {
+                outerType = CompilerUtils.getOutermostClass(classMember);
+            } else {
+                // Should not hit this condition
+                assert false;
+            }
+
+            if (outerType instanceof ClassDeclaration) {
+                ann = CompilerUtils.getAnnotation(outerType, CONTROLLER_TAG_NAME);
+
+                if (ann != null) {
+                    validatorVersion = CompilerUtils.getEnumFieldName(ann, VALIDATOR_VERSION_ATTR, true);
+                }
+            }
+        }
+
+        //
+        // Default is commons-validator v1.0 unless otherwise declared with the @Jpf.Controller
+        // validator version attribute.
+        if (validatorVersion == null || validatorVersion.equals(VALIDATOR_VERSION_ONE_ZERO_STR)) {
+            return false;
+        }
+
+        return true;
+    }
+}

Added: struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/grammar/CatchGrammar.java
URL: http://svn.apache.org/viewcvs/struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/grammar/CatchGrammar.java?rev=280879&view=auto
==============================================================================
--- struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/grammar/CatchGrammar.java (added)
+++ struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/grammar/CatchGrammar.java Wed Sep 14 09:20:05 2005
@@ -0,0 +1,189 @@
+/*
+ * 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.grammar;
+
+import org.apache.ti.compiler.internal.AnnotationMemberType;
+import org.apache.ti.compiler.internal.CompilerUtils;
+import org.apache.ti.compiler.internal.Diagnostics;
+import org.apache.ti.compiler.internal.FlowControllerInfo;
+import org.apache.ti.compiler.internal.JpfLanguageConstants;
+import org.apache.ti.compiler.internal.RuntimeVersionChecker;
+import org.apache.ti.compiler.internal.typesystem.declaration.AnnotationInstance;
+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.MethodDeclaration;
+import org.apache.ti.compiler.internal.typesystem.declaration.ParameterDeclaration;
+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.DeclaredType;
+import org.apache.ti.compiler.internal.typesystem.type.TypeInstance;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Map;
+
+
+public class CatchGrammar
+        extends BaseFlowControllerGrammar
+        implements JpfLanguageConstants {
+
+    private static String[][] MUTUALLY_EXCLUSIVE_ATTRS = {{PATH_ATTR, METHOD_ATTR}};
+    private static String[][] REQUIRED_ATTRS = {{TYPE_ATTR}, {PATH_ATTR, METHOD_ATTR}};
+
+    private String _annotationRootName;
+
+
+    public CatchGrammar(AnnotationProcessorEnvironment env, Diagnostics diags, String requiredRuntimeVersion,
+                        RuntimeVersionChecker runtimeVersionChecker, String annotationRootName,
+                        FlowControllerInfo fcInfo) {
+        super(env, diags, requiredRuntimeVersion, runtimeVersionChecker, fcInfo);
+
+        _annotationRootName = annotationRootName;   // the parent of the list of @Jpf.Catch annotations.
+        addMemberType(METHOD_ATTR, new CatchTagMethodType());
+        AnnotationMemberType typeAttrType =
+                new UniqueValueType(CATCHES_ATTR, false, false, null, this,
+                        new TypeNameType(THROWABLE_CLASS_NAME, false, null, this));
+        addMemberType(TYPE_ATTR, typeAttrType);
+        addMemberType(PATH_ATTR, new ForwardToExternalPathType(new WebappPathOrActionType(false, null, this, fcInfo), null, this));
+        addMemberType(MESSAGE_ATTR, new AnnotationMemberType(null, this));
+        addMemberType(MESSAGE_KEY_ATTR, new AnnotationMemberType(null, this));
+    }
+
+    public String[][] getMutuallyExclusiveAttrs() {
+        return MUTUALLY_EXCLUSIVE_ATTRS;
+    }
+
+    public String[][] getRequiredAttrs() {
+        return REQUIRED_ATTRS;
+    }
+
+    /**
+     * @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) {
+        MethodDeclaration handlerMethod = (MethodDeclaration) checkResults.get(METHOD_ATTR);
+        DeclaredType exceptionType = (DeclaredType) checkResults.get(TYPE_ATTR);
+
+        //
+        // If either of these are null, then there was another already-reported error (e.g., type was unresolved).
+        //
+        if (handlerMethod == null || exceptionType == null) {
+            return null;
+        }
+
+        //
+        // Make sure the given handler method can catch the right kind of exception.
+        //
+        ParameterDeclaration[] parameters = handlerMethod.getParameters();
+
+        //
+        // If the method's arguments are wrong in any way, don't worry about it -- the exception-handler checker will
+        // report an error.
+        //
+        if (parameters.length > 0) {
+            TypeInstance handledExceptionType = parameters[0].getType();
+
+            if (! CompilerUtils.isAssignableFrom(handledExceptionType, CompilerUtils.getDeclaration(exceptionType))) {
+                addError(annotation, "error.incompatible-exception-handler", handlerMethod.getSimpleName(),
+                        CompilerUtils.getDeclaration(exceptionType).getQualifiedName());
+            }
+        }
+
+        return null;
+    }
+
+    private class CatchTagMethodType
+            extends MemberMethodType {
+
+        public CatchTagMethodType() {
+            super(EXCEPTION_HANDLER_TAG_NAME, "error.unresolved-exception-handler", null, CatchGrammar.this);
+        }
+
+        /**
+         * Derived classes can plug in here to do additional checks.
+         */
+        protected void checkMethod(MethodDeclaration methodBeingChecked, AnnotationValue value,
+                                   AnnotationInstance[] parentAnnotations, MemberDeclaration classMember) {
+            //
+            // Make sure the current entity (class or action method) doesn't have two @Jpf.Catch annotations
+            // that refer to methods with duplicate @Jpf.Forwards.
+            //
+            Collection catches =
+                    CompilerUtils.getAnnotationArrayValue(classMember, _annotationRootName, CATCHES_ATTR, true);
+            TypeDeclaration outerType = CompilerUtils.getOuterClass(classMember);
+
+            if (catches == null) {
+                return;
+            }
+
+            for (Iterator ii = catches.iterator(); ii.hasNext();) {
+                AnnotationInstance catchAnnotation = (AnnotationInstance) ii.next();
+                //
+                // Find the method referred to in this annotation.  If we can't find it, do nothing -- this
+                // will get caught elsewhere in the checking.
+                //
+                String methodName = CompilerUtils.getString(catchAnnotation, METHOD_ATTR, false);
+
+                if (methodName.length() > 0 && ! methodName.equals(methodBeingChecked.getSimpleName())) {
+                    MethodDeclaration otherMethod = findMethod(methodName, outerType);
+
+                    if (otherMethod != null) {
+                        //
+                        // Look through this other method's forwards.  None may have the same name (and different path)
+                        // as the current one.
+                        //
+                        Collection otherForwards =
+                                CompilerUtils.getAnnotationArrayValue(otherMethod, EXCEPTION_HANDLER_TAG_NAME,
+                                        FORWARDS_ATTR, false);
+
+                        for (Iterator i2 = otherForwards.iterator(); i2.hasNext();) {
+                            AnnotationInstance otherForward = (AnnotationInstance) i2.next();
+                            String otherForwardName = CompilerUtils.getString(otherForward, NAME_ATTR, true);
+                            String otherForwardPath = CompilerUtils.getString(otherForward, PATH_ATTR, true);
+                            String otherFwdNavigateTo =
+                                    CompilerUtils.getEnumFieldName(otherForward, NAVIGATE_TO_ATTR, true);
+
+                            Collection forwards =
+                                    CompilerUtils.getAnnotationArrayValue(methodBeingChecked,
+                                            EXCEPTION_HANDLER_TAG_NAME,
+                                            FORWARDS_ATTR, false);
+
+                            for (Iterator i3 = forwards.iterator(); i3.hasNext();) {
+                                AnnotationInstance forward = (AnnotationInstance) i3.next();
+                                String forwardName = CompilerUtils.getString(forward, NAME_ATTR, true);
+                                String forwardPath = CompilerUtils.getString(forward, PATH_ATTR, true);
+                                String fwdNavigateTo = CompilerUtils.getEnumFieldName(forward, NAVIGATE_TO_ATTR, true);
+
+                                if (forwardName != null && forwardName.equals(otherForwardName)) {
+                                    if ((forwardPath == null || ! forwardPath.equals(otherForwardPath))
+                                            && (fwdNavigateTo == null || ! fwdNavigateTo.equals(otherFwdNavigateTo))) {
+                                        addError(value, "error.duplicate-exception-handler-forwards",
+                                                new Object[]{methodBeingChecked.getSimpleName(), methodName, forwardName});
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
+

Added: struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/grammar/CommandHandlerGrammar.java
URL: http://svn.apache.org/viewcvs/struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/grammar/CommandHandlerGrammar.java?rev=280879&view=auto
==============================================================================
--- struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/grammar/CommandHandlerGrammar.java (added)
+++ struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/grammar/CommandHandlerGrammar.java Wed Sep 14 09:20:05 2005
@@ -0,0 +1,35 @@
+/*
+ * 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.grammar;
+
+import org.apache.ti.compiler.internal.Diagnostics;
+import org.apache.ti.compiler.internal.FlowControllerInfo;
+import org.apache.ti.compiler.internal.RuntimeVersionChecker;
+import org.apache.ti.compiler.internal.typesystem.declaration.ClassDeclaration;
+import org.apache.ti.compiler.internal.typesystem.env.AnnotationProcessorEnvironment;
+
+
+public class CommandHandlerGrammar
+        extends BaseFlowControllerGrammar {
+
+    public CommandHandlerGrammar(AnnotationProcessorEnvironment env, Diagnostics diags, RuntimeVersionChecker rvc,
+                                 ClassDeclaration jpfClass, FlowControllerInfo fcInfo) {
+        super(env, diags, null, rvc, fcInfo);
+        addMemberArrayGrammar(RAISE_ACTIONS_ATTR, new RaiseActionGrammar(env, diags, null, rvc, jpfClass, fcInfo));
+    }
+}



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