Source Code Cross Referenced for ElementContext.java in  » Web-Framework » rife-1.6.1 » com » uwyn » rife » engine » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Web Framework » rife 1.6.1 » com.uwyn.rife.engine 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Copyright 2001-2007 Geert Bevin <gbevin[remove] at uwyn dot com>
0003:         * Distributed under the terms of either:
0004:         * - the common development and distribution license (CDDL), v1.0; or
0005:         * - the GNU Lesser General Public License, v2.1 or later
0006:         * $Id: ElementContext.java 3813 2007-06-25 18:22:03Z gbevin $
0007:         */
0008:        package com.uwyn.rife.engine;
0009:
0010:        import com.uwyn.rife.engine.exceptions.*;
0011:        import com.uwyn.rife.template.*;
0012:        import com.uwyn.rife.tools.*;
0013:        import java.util.*;
0014:
0015:        import com.uwyn.rife.authentication.credentialsmanagers.RoleUserAttributes;
0016:        import com.uwyn.rife.authentication.credentialsmanagers.RoleUserIdentity;
0017:        import com.uwyn.rife.authentication.elements.Identified;
0018:        import com.uwyn.rife.config.RifeConfig;
0019:        import com.uwyn.rife.continuations.CallState;
0020:        import com.uwyn.rife.continuations.ContinuationConfigRuntime;
0021:        import com.uwyn.rife.continuations.ContinuationContext;
0022:        import com.uwyn.rife.continuations.ContinuationManager;
0023:        import com.uwyn.rife.continuations.exceptions.AnswerException;
0024:        import com.uwyn.rife.continuations.exceptions.CallException;
0025:        import com.uwyn.rife.continuations.exceptions.PauseException;
0026:        import com.uwyn.rife.continuations.exceptions.StepBackException;
0027:        import com.uwyn.rife.engine.CharSequenceDeferred;
0028:        import com.uwyn.rife.site.Constrained;
0029:        import com.uwyn.rife.site.ConstrainedProperty;
0030:        import com.uwyn.rife.site.ConstrainedUtils;
0031:        import com.uwyn.rife.site.FormBuilder;
0032:        import com.uwyn.rife.template.exceptions.TemplateException;
0033:        import com.uwyn.rife.tools.exceptions.BeanUtilsException;
0034:        import com.uwyn.rife.tools.exceptions.LightweightError;
0035:        import com.uwyn.rife.tools.exceptions.SerializationUtilsErrorException;
0036:        import java.beans.PropertyDescriptor;
0037:        import java.io.IOException;
0038:        import java.io.Serializable;
0039:        import java.io.UnsupportedEncodingException;
0040:        import java.lang.reflect.InvocationTargetException;
0041:        import java.lang.reflect.Method;
0042:        import java.util.regex.Matcher;
0043:        import java.util.regex.Pattern;
0044:        import javax.servlet.RequestDispatcher;
0045:        import javax.servlet.http.Cookie;
0046:        import javax.servlet.http.HttpServletResponse;
0047:
0048:        public class ElementContext {
0049:            public static final String PREFIX_EXIT_QUERY = "EXIT:QUERY:";
0050:            public static final String PREFIX_EXIT_FORM = "EXIT:FORM:";
0051:            public static final String PREFIX_EXIT_PARAMS = "EXIT:PARAMS:";
0052:            public static final String PREFIX_EXIT_PARAMSJS = "EXIT:PARAMSJS:";
0053:            public static final String PREFIX_SUBMISSION_QUERY = "SUBMISSION:QUERY:";
0054:            public static final String PREFIX_SUBMISSION_FORM = "SUBMISSION:FORM:";
0055:            public static final String PREFIX_SUBMISSION_PARAMS = "SUBMISSION:PARAMS:";
0056:            public static final String PREFIX_SUBMISSION_PARAMSJS = "SUBMISSION:PARAMSJS:";
0057:
0058:            public static final String PREFIX_PARAM = "PARAM:";
0059:            public static final String PREFIX_INPUT = "INPUT:";
0060:            public static final String PREFIX_OUTPUT = "OUTPUT:";
0061:            public static final String PREFIX_INCOOKIE = "INCOOKIE:";
0062:            public static final String PREFIX_OUTCOOKIE = "OUTCOOKIE:";
0063:            public static final String PREFIX_ELEMENT = "ELEMENT:";
0064:            public static final String PREFIX_PROPERTY = "PROPERTY:";
0065:            public static final String PREFIX_OGNL_ROLEUSER = "OGNL:ROLEUSER:";
0066:            public static final String PREFIX_MVEL_ROLEUSER = "MVEL:ROLEUSER:";
0067:            public static final String PREFIX_GROOVY_ROLEUSER = "GROOVY:ROLEUSER:";
0068:            public static final String PREFIX_JANINO_ROLEUSER = "JANINO:ROLEUSER:";
0069:
0070:            public static final String ID_WEBAPP_ROOTURL = "WEBAPP:ROOTURL";
0071:            public static final String ID_SERVER_ROOTURL = "SERVER:ROOTURL";
0072:
0073:            public static final String TAG_PROPERTY = "^" + PREFIX_PROPERTY
0074:                    + "\\s*(.*?)\\s*$";
0075:            public static final String TAG_ELEMENT = "^(" + PREFIX_ELEMENT
0076:                    + "\\s*([\\-\\+]?)\\s*(.*?)\\s*)(?::([^:]*))?$";
0077:            public static final String TAG_OGNL_ROLEUSER = "(?s)^("
0078:                    + PREFIX_OGNL_ROLEUSER
0079:                    + ".*):\\s*\\[\\[\\s*+(.*?)\\s*+\\]\\]\\s*$";
0080:            public static final String TAG_MVEL_ROLEUSER = "(?s)^("
0081:                    + PREFIX_MVEL_ROLEUSER
0082:                    + ".*):\\s*\\[\\[\\s*+(.*?)\\s*+\\]\\]\\s*$";
0083:            public static final String TAG_JANINO_ROLEUSER = "(?s)^("
0084:                    + PREFIX_JANINO_ROLEUSER
0085:                    + ".*):\\s*\\[\\[\\s*+(.*?)\\s*+\\]\\]\\s*$";
0086:            public static final String TAG_GROOVY_ROLEUSER = "(?s)^("
0087:                    + PREFIX_GROOVY_ROLEUSER
0088:                    + ".*):\\s*\\[\\[\\s*+(.*?)\\s*+\\]\\]\\s*$";
0089:
0090:            private static ThreadLocal<ElementSupport> sActiveElementSupport = new ThreadLocal<ElementSupport>();
0091:
0092:            private ElementSupport mElement = null;
0093:            private ElementInfo mElementInfo = null;
0094:            private RequestState mRequestState = null;
0095:            private ElementExecutionState mElementState = null;
0096:            private Response mResponse = null;
0097:            private OutputValues mOutputs = null;
0098:            private OutcookieValues mOutcookies = null;
0099:            private ArrayList<OutputListener> mOutputListeners = null;
0100:            private ArrayList<OutcookieListener> mOutcookieListeners = null;
0101:            private String mContextId = null;
0102:            private String mSubmission = null;
0103:            private boolean mSteppedBack = false;
0104:
0105:            public static ElementSupport getActiveElementSupport() {
0106:                return sActiveElementSupport.get();
0107:            }
0108:
0109:            ElementContext(ElementSupport element, RequestState state,
0110:                    Response response) throws EngineException {
0111:                assert element != null;
0112:                assert state != null;
0113:                assert response != null;
0114:
0115:                mElement = element;
0116:                synchronized (mElement) {
0117:                    mElement.setElementContext(this );
0118:
0119:                    mElementInfo = mElement.getElementInfo();
0120:
0121:                    mRequestState = state;
0122:                    mElementState = mRequestState.getElementState();
0123:                    mResponse = response;
0124:                    mOutputs = new OutputValues(this );
0125:                    mOutcookies = new OutcookieValues(this );
0126:
0127:                    // register the EmbeddingListener of the current state so that the
0128:                    // output values are kept in sync with global vars and the outcookies
0129:                    // are kept in sync with the global cookies
0130:                    if (state.isEmbedded()) {
0131:                        RequestState.EmbeddingListener listener = state
0132:                                .getEmbeddingListener();
0133:                        addOutputListener(listener);
0134:                        addOutcookieListener(listener);
0135:                    }
0136:
0137:                    // register the PrecedenceListener of the current state so that the
0138:                    // output values are kept in sync with global vars and the outcookies
0139:                    // are kept in sync with the global cookies
0140:                    if (state.isPreceeding()) {
0141:                        RequestState.PrecedenceListener listener = state
0142:                                .getPrecedenceListener();
0143:                        addOutputListener(listener);
0144:                        addOutcookieListener(listener);
0145:                    }
0146:
0147:                    // if the child element has been reached, replace the request parameters with the
0148:                    // original child request parameters
0149:                    if (mElementState.isInheritanceTarget()
0150:                            && mElementState
0151:                                    .hasRequestParameterValue(ReservedParameters.CHILDREQUEST)) {
0152:                        ChildRequestEncoder.decode(element.getElementInfo(),
0153:                                mRequestState);
0154:                    }
0155:
0156:                    // automatically set an output value if the input value has been provided
0157:                    // and it's a global variable
0158:                    String[] output_values = null;
0159:                    for (String globalvar_name : mElementInfo
0160:                            .getGlobalVarNames()) {
0161:                        if (mElementState.hasInputValue(globalvar_name)) {
0162:                            output_values = mElementState
0163:                                    .getInputValues(globalvar_name);
0164:                            setAutomatedOutputValues(globalvar_name,
0165:                                    output_values);
0166:                        }
0167:                    }
0168:                }
0169:            }
0170:
0171:            private void handleChildTriggerVariablesPre()
0172:                    throws EngineException {
0173:                // verify if no value are present that will automatically launch a child trigger
0174:                if (mElementInfo.getChildTriggerNames().size() > 0) {
0175:                    // check each child trigger for a corresponding value
0176:                    // if it was found, launch the trigger
0177:                    for (String child_trigger_name : mElementInfo
0178:                            .getChildTriggerNames()) {
0179:                        // check if a provided input value is acceptable for this
0180:                        // element as input or global variable
0181:                        if (mElementState.hasInputValue(child_trigger_name)) {
0182:                            if (mElementInfo
0183:                                    .containsGlobalVar(child_trigger_name)
0184:                                    || mElementInfo
0185:                                            .containsInput(child_trigger_name)) {
0186:                                triggerChild(child_trigger_name,
0187:                                        getInputValues(child_trigger_name));
0188:                                continue;
0189:                            }
0190:                        }
0191:                        // check if a provided cookie is acceptable for this
0192:                        // element as incookie
0193:                        else if (mRequestState.getCookie(child_trigger_name) != null) {
0194:                            if (mElementInfo
0195:                                    .containsGlobalCookie(child_trigger_name)
0196:                                    || mElementInfo
0197:                                            .containsIncookie(child_trigger_name)) {
0198:                                triggerChild(
0199:                                        child_trigger_name,
0200:                                        new String[] { getCookie(
0201:                                                child_trigger_name).getValue() });
0202:                                continue;
0203:                            }
0204:                        }
0205:                        // check if a default input value is present that can trigger the child
0206:                        else if (mElementInfo
0207:                                .hasInputDefaultValues(child_trigger_name)) {
0208:                            triggerChild(child_trigger_name, mElementInfo
0209:                                    .getInputDefaultValues(child_trigger_name));
0210:                            continue;
0211:                        }
0212:                        // check if a default cookie value is present that can trigger the child
0213:                        else if (mElementInfo
0214:                                .hasIncookieDefaultValue(child_trigger_name)) {
0215:                            triggerChild(
0216:                                    child_trigger_name,
0217:                                    new String[] { mElementInfo
0218:                                            .getIncookieDefaultValue(child_trigger_name) });
0219:                            continue;
0220:                        }
0221:                        // check if a global var default is present for the trigger name
0222:                        else if (mElementInfo
0223:                                .containsGlobalVar(child_trigger_name)
0224:                                && mElementInfo
0225:                                        .hasGlobalVarDefaultValues(child_trigger_name)) {
0226:                            triggerChild(
0227:                                    child_trigger_name,
0228:                                    mElementInfo
0229:                                            .getGlobalVarDefaultValues(child_trigger_name));
0230:                            continue;
0231:                        }
0232:                        // check if a global cookie default is present for the trigger name
0233:                        else if (mElementInfo
0234:                                .containsGlobalCookie(child_trigger_name)
0235:                                && mElementInfo
0236:                                        .hasGlobalCookieDefaultValue(child_trigger_name)) {
0237:                            triggerChild(
0238:                                    child_trigger_name,
0239:                                    new String[] { mElementInfo
0240:                                            .getGlobalCookieDefaultValue(child_trigger_name) });
0241:                            continue;
0242:                        }
0243:                    }
0244:                }
0245:            }
0246:
0247:            private void handleChildTriggerVariablesPost()
0248:                    throws EngineException {
0249:                // verify if no value are present that will automatically launch a child trigger
0250:                if (mElementInfo.getChildTriggerNames().size() > 0) {
0251:                    // check each child trigger for a corresponding value
0252:                    // if it was found, launch the trigger
0253:                    for (String child_trigger_name : mElementInfo
0254:                            .getChildTriggerNames()) {
0255:                        // check if an output default value is present
0256:                        if (mElementInfo
0257:                                .hasOutputDefaultValues(child_trigger_name)) {
0258:                            String[] output_defaultvalues = mElementInfo
0259:                                    .getOutputDefaultValues(child_trigger_name);
0260:                            triggerChild(child_trigger_name,
0261:                                    output_defaultvalues);
0262:                            continue;
0263:                        }
0264:                    }
0265:                }
0266:            }
0267:
0268:            ElementContext processContext() throws EngineException {
0269:                long start = mElementInfo.startTrace();
0270:                boolean clear_request = false;
0271:
0272:                ElementContext result = null;
0273:
0274:                try {
0275:                    ElementSupport previous_active_element;
0276:
0277:                    synchronized (mElement) {
0278:                        // handle the inheritance structure
0279:                        if (mElementState.inInheritanceStructure()) {
0280:                            // try to see if the top of the trigger list matches the current element
0281:                            if (mElementState.isNextTrigger(mElementInfo)) {
0282:                                // if it does, and it's a child trigger, use the values to launch a child trigger
0283:                                if (TriggerContext.TRIGGER_CHILD == mElementState
0284:                                        .getNextTriggerType()
0285:                                        && mElementInfo
0286:                                                .containsChildTrigger(mElementState
0287:                                                        .getNextTriggerName())) {
0288:                                    triggerChild(mElementState
0289:                                            .getNextTriggerName(),
0290:                                            mElementState
0291:                                                    .getNextTriggerValues());
0292:                                } else if (TriggerContext.TRIGGER_EXIT == mElementState
0293:                                        .getNextTriggerType()
0294:                                        && mElementInfo
0295:                                                .containsExit(mElementState
0296:                                                        .getNextTriggerName())) {
0297:                                    exit(mElementState.getNextTriggerName());
0298:                                }
0299:                            }
0300:
0301:                            handleChildTriggerVariablesPre();
0302:                        }
0303:
0304:                        // handle precedence
0305:                        mRequestState.handlePrecedence(mResponse,
0306:                                getElementInfo());
0307:
0308:                        // set the response content type if this has been specified by the element
0309:                        if (mElementInfo.getContentType() != null
0310:                                && mElementInfo.getContentType().length() > 0) {
0311:                            mResponse.setContentType(mElementInfo
0312:                                    .getContentType());
0313:                        }
0314:
0315:                        // obtain the continuation context
0316:                        ContinuationContext continuation_context = mRequestState
0317:                                .getContinuationContext(mElementInfo);
0318:                        ContinuationContext
0319:                                .setActiveContext(continuation_context);
0320:                        ContinuationConfigRuntime
0321:                                .setActiveConfigRuntime(EngineContinuationConfigRuntimeSingleton.INSTANCE);
0322:
0323:                        // register the element as the active one in this thread and remember
0324:                        // which one that was previously active
0325:                        previous_active_element = sActiveElementSupport.get();
0326:
0327:                        sActiveElementSupport.set(mElement);
0328:                    }
0329:
0330:                    try {
0331:                        final ElementAware element_aware;
0332:                        Method submission_handler = null;
0333:
0334:                        synchronized (mElement) {
0335:                            // get the element aware interface
0336:                            element_aware = mElement.getElementAware();
0337:
0338:                            // check if there's are submissions
0339:                            if (mElementState
0340:                                    .hasRequestParameterValue(ReservedParameters.SUBMISSION)) {
0341:                                String[] submission_names = mElementState
0342:                                        .getRequestParameterValues(ReservedParameters.SUBMISSION);
0343:                                String[] submission_contexts = mElementState
0344:                                        .getRequestParameterValues(ReservedParameters.SUBMISSIONCONTEXT);
0345:                                String submission_context = null;
0346:                                String submission_context_id = null;
0347:                                String submission_target = null;
0348:                                HashSet<String> non_requestparameter_inputs = null;
0349:                                int counter = 0;
0350:                                for (String submission_name : submission_names) {
0351:                                    // get the submission context
0352:                                    if (null == submission_contexts
0353:                                            || counter >= submission_contexts.length) {
0354:                                        submission_context = getContextId();
0355:                                    } else {
0356:                                        try {
0357:                                            byte[] decoded = Base64
0358:                                                    .decode(submission_contexts[counter]
0359:                                                            .getBytes("UTF-8"));
0360:                                            if (decoded != null
0361:                                                    && decoded.length > 0) {
0362:                                                submission_context = new String(
0363:                                                        decoded);
0364:                                            } else {
0365:                                                submission_context = getContextId();
0366:                                            }
0367:                                        } catch (UnsupportedEncodingException e) {
0368:                                            // should never happen
0369:                                        }
0370:                                    }
0371:
0372:                                    // split up in the submission context id and the submission target
0373:                                    int seperator_index = submission_context
0374:                                            .indexOf("^");
0375:                                    if (-1 == seperator_index) {
0376:                                        submission_context_id = submission_context;
0377:                                        submission_target = submission_context;
0378:                                    } else {
0379:                                        submission_context_id = submission_context
0380:                                                .substring(0, seperator_index);
0381:                                        submission_target = submission_context
0382:                                                .substring(seperator_index + 1);
0383:                                    }
0384:
0385:                                    // check if the submission target corresponds to the context id
0386:                                    if (null == mSubmission
0387:                                            && getContextId().equals(
0388:                                                    submission_context_id)
0389:                                            && mElementInfo
0390:                                                    .hasSubmission(submission_name)) {
0391:                                        mSubmission = submission_name;
0392:                                    }
0393:                                    // if it doesn't, use the submission target element id to
0394:                                    // retrieve the submission declaration, and the parameters
0395:                                    // that have to be disabled as inputs for this element
0396:                                    else {
0397:                                        // get the submission target
0398:                                        if (0 == submission_target.length()) {
0399:                                            submission_target = getElementInfo()
0400:                                                    .getId();
0401:                                        }
0402:
0403:                                        // obtain the element info
0404:                                        ElementInfo submission_target_element = mElementInfo
0405:                                                .getSite().resolveId(
0406:                                                        submission_target);
0407:                                        if (submission_target_element != null) {
0408:                                            // get the submission declaration
0409:                                            Submission submission = submission_target_element
0410:                                                    .getSubmission(submission_name);
0411:                                            if (submission != null) {
0412:                                                // get the submission parameter names
0413:                                                Collection<String> names = submission
0414:                                                        .getParameterNames();
0415:                                                if (names != null
0416:                                                        && names.size() > 0) {
0417:                                                    if (null == non_requestparameter_inputs) {
0418:                                                        non_requestparameter_inputs = new HashSet<String>();
0419:                                                    }
0420:
0421:                                                    // add the submission parameters to the collection
0422:                                                    // of inputs that shouldn't retrieve their values
0423:                                                    // from the request parameters
0424:                                                    non_requestparameter_inputs
0425:                                                            .addAll(names);
0426:                                                }
0427:                                            }
0428:                                        }
0429:                                    }
0430:
0431:                                    counter++;
0432:                                }
0433:
0434:                                // register the non parameter inputs
0435:                                mElementState
0436:                                        .setNonRequestParameterInputs(non_requestparameter_inputs);
0437:                            }
0438:
0439:                            // check if there's a submission handler
0440:
0441:                            // check if a submission is present and a corresponding do*() method is
0442:                            // available and retrieve the method
0443:                            final String submission_name = getSubmission();
0444:                            if (submission_name != null) {
0445:                                String submission_handler_name = "do"
0446:                                        + StringUtils
0447:                                                .capitalize(submission_name);
0448:                                try {
0449:                                    submission_handler = element_aware
0450:                                            .getClass().getMethod(
0451:                                                    submission_handler_name,
0452:                                                    (Class[]) null);
0453:                                    submission_handler.setAccessible(true);
0454:                                } catch (NoSuchMethodException e) {
0455:                                    submission_handler = null;
0456:                                } catch (SecurityException e) {
0457:                                    throw new EngineException(e);
0458:                                }
0459:                            }
0460:
0461:                            // inject the properties request values into the element instance
0462:                            new ElementInjector(this )
0463:                                    .performInjection(submission_name);
0464:
0465:                            // update the target element in the response
0466:                            mResponse.setLastElement(mElement);
0467:
0468:                            // initialize the element in a fully setup context
0469:                            mElement.initialize();
0470:                        }
0471:
0472:                        try {
0473:                            try {
0474:                                synchronized (mElement) {
0475:                                    // call the processElement() method of the element itself if no handler could be found
0476:                                    if (null == submission_handler) {
0477:                                        element_aware.processElement();
0478:                                    }
0479:                                    // call the submission handler if it's available
0480:                                    else {
0481:                                        try {
0482:                                            submission_handler.invoke(
0483:                                                    element_aware,
0484:                                                    (Object[]) null);
0485:                                        } catch (InvocationTargetException e) {
0486:                                            if (e.getCause() instanceof  LightweightError) {
0487:                                                throw (LightweightError) e
0488:                                                        .getCause();
0489:                                            } else if (e.getCause() instanceof  EngineException) {
0490:                                                throw (EngineException) e
0491:                                                        .getCause();
0492:                                            } else {
0493:                                                throw new EngineException(e
0494:                                                        .getCause());
0495:                                            }
0496:                                        } catch (IllegalArgumentException e) {
0497:                                            throw new EngineException(e);
0498:                                        } catch (IllegalAccessException e) {
0499:                                            throw new EngineException(e);
0500:                                        }
0501:                                    }
0502:                                }
0503:                            } catch (CallException e) {
0504:                                ContinuationContext context = e.getContext();
0505:
0506:                                // register context
0507:                                ContinuationManager manager = mElementInfo
0508:                                        .getSite().getContinuationManager();
0509:                                manager.addContext(context);
0510:
0511:                                synchronized (mElement) {
0512:                                    String exit = (String) e.getTarget();
0513:                                    mElementInfo.validateExitName(exit);
0514:                                    if (null == mElementInfo.getFlowLink(exit)) {
0515:                                        throw new ExitNotAttachedException(
0516:                                                mElementInfo
0517:                                                        .getDeclarationName(),
0518:                                                exit);
0519:                                    }
0520:
0521:                                    // create a new call state
0522:                                    CallState call_state = new CallState(
0523:                                            context.getId(), mElementState
0524:                                                    .clone());
0525:                                    context.setCreatedCallState(call_state);
0526:
0527:                                    // setup the exit
0528:                                    result = setupExitContext(exit);
0529:                                }
0530:                            }
0531:                        } finally {
0532:                            synchronized (mElement) {
0533:                                String context_id = getContextId();
0534:
0535:                                ElementResultState result_state = null;
0536:
0537:                                // extract the preserved inputs of this element
0538:                                Set<Map.Entry<String, String[]>> output_value_entries = mOutputs
0539:                                        .aggregateValues().entrySet();
0540:                                Map<String, String[]> preserved_inputs = collectPreservedInputs(output_value_entries);
0541:
0542:                                // if a call continuation is active, also preserve the previous preserved inputs without overriding the new ones
0543:                                ContinuationContext active_context = ContinuationContext
0544:                                        .getActiveContext();
0545:                                if (active_context != null
0546:                                        && active_context.getActiveCallState() != null) {
0547:                                    ElementResultState previous_result_state = mRequestState
0548:                                            .getElementResultStatesRestored()
0549:                                            .get(context_id);
0550:                                    if (previous_result_state != null) {
0551:                                        Map<String, String[]> previous_preserved_inputs = previous_result_state
0552:                                                .getPreservedInputs();
0553:                                        if (previous_preserved_inputs != null) {
0554:                                            if (null == preserved_inputs) {
0555:                                                preserved_inputs = previous_preserved_inputs;
0556:                                            } else {
0557:                                                for (Map.Entry<String, String[]> entry : previous_preserved_inputs
0558:                                                        .entrySet()) {
0559:                                                    if (!preserved_inputs
0560:                                                            .containsKey(entry
0561:                                                                    .getKey())) {
0562:                                                        preserved_inputs
0563:                                                                .put(
0564:                                                                        entry
0565:                                                                                .getKey(),
0566:                                                                        entry
0567:                                                                                .getValue());
0568:                                                    }
0569:                                                }
0570:                                            }
0571:                                        }
0572:                                    }
0573:
0574:                                    // preserve the continuation ID of this element
0575:                                    if (null == result_state) {
0576:                                        result_state = mElementInfo
0577:                                                .getStateStore()
0578:                                                .createNewResultState(
0579:                                                        context_id);
0580:                                    }
0581:                                    result_state
0582:                                            .setContinuationId(active_context
0583:                                                    .getActiveCallState()
0584:                                                    .getContinuationId());
0585:                                }
0586:
0587:                                // add the preserved inputs to the result state
0588:                                if (preserved_inputs != null
0589:                                        && preserved_inputs.size() > 0) {
0590:                                    if (null == result_state) {
0591:                                        result_state = mElementInfo
0592:                                                .getStateStore()
0593:                                                .createNewResultState(
0594:                                                        context_id);
0595:                                    }
0596:
0597:                                    result_state
0598:                                            .setPreservedInputs(preserved_inputs);
0599:                                }
0600:
0601:                                // state the resulting element state
0602:                                if (result_state != null) {
0603:                                    mRequestState
0604:                                            .getElementResultStatesObtained()
0605:                                            .put(result_state);
0606:                                }
0607:
0608:                                // handle the setting of the getter outcookies
0609:                                mOutcookies.processGetters();
0610:
0611:                                // handle the firing of listener methods for getters outjection
0612:                                mOutputs.processGetters();
0613:                            }
0614:
0615:                            // handle the outcookie and output childtriggers from the getters outjection
0616:                            mOutcookies.processGetterChildTriggers();
0617:                            mOutputs.processGetterChildTriggers();
0618:                        }
0619:                    } catch (AnswerException e) {
0620:                        synchronized (mElement) {
0621:                            // only answer a call if a call state is available
0622:                            // otherwise the answer will function as a regular return
0623:                            if (e.getContext().getActiveCallState() != null) {
0624:                                throw e;
0625:                            }
0626:                        }
0627:                    } finally {
0628:                        synchronized (mElement) {
0629:                            // restore the previously active element
0630:                            sActiveElementSupport.set(previous_active_element);
0631:                        }
0632:                    }
0633:
0634:                    synchronized (mElement) {
0635:                        // handle the child trigger values that could have an effect after
0636:                        // the actual element logic
0637:                        handleChildTriggerVariablesPost();
0638:
0639:                        // handle the default outcookies
0640:                        if (mElementInfo.hasOutcookieDefaults()) {
0641:                            Cookie default_cookie = null;
0642:
0643:                            for (Map.Entry<String, String> default_outcookie_entry : mElementInfo
0644:                                    .getDefaultOutcookies().entrySet()) {
0645:                                if (!mOutcookies
0646:                                        .contains(default_outcookie_entry
0647:                                                .getKey())) {
0648:                                    default_cookie = new Cookie(
0649:                                            default_outcookie_entry.getKey(),
0650:                                            default_outcookie_entry.getValue());
0651:                                    default_cookie.setPath("");
0652:                                    setCookie(default_cookie);
0653:                                }
0654:                            }
0655:                        }
0656:
0657:                        // handle the default global cookies
0658:                        if (mElementInfo.hasGlobalCookieDefaults()) {
0659:                            Cookie default_cookie = null;
0660:
0661:                            for (Map.Entry<String, String> default_globalcookie_entry : mElementInfo
0662:                                    .getDefaultGlobalCookies().entrySet()) {
0663:                                if (!mOutcookies
0664:                                        .contains(default_globalcookie_entry
0665:                                                .getKey())) {
0666:                                    default_cookie = new Cookie(
0667:                                            default_globalcookie_entry.getKey(),
0668:                                            default_globalcookie_entry
0669:                                                    .getValue());
0670:                                    default_cookie.setPath("");
0671:                                    setCookie(default_cookie);
0672:                                }
0673:                            }
0674:                        }
0675:                    }
0676:                } catch (PauseException e) {
0677:                    ContinuationContext context = e.getContext();
0678:
0679:                    // register context
0680:                    ContinuationManager manager = mElementInfo.getSite()
0681:                            .getContinuationManager();
0682:                    manager.addContext(context);
0683:
0684:                    synchronized (mElement) {
0685:                        // preserve the continuation ID of this element
0686:                        String context_id = getContextId();
0687:                        ElementResultState result_state = mRequestState
0688:                                .getElementResultStatesObtained().get(
0689:                                        context_id);
0690:
0691:                        if (null == result_state) {
0692:                            result_state = mElementInfo.getStateStore()
0693:                                    .createNewResultState(context_id);
0694:                            mRequestState.getElementResultStatesObtained().put(
0695:                                    result_state);
0696:                        }
0697:                        result_state.setContinuationId(context.getId());
0698:
0699:                        clear_request = true;
0700:                        try {
0701:                            mResponse.flush();
0702:                        } catch (EngineException e2) {
0703:                            // if errors occurred during flushing it means that the client has
0704:                            // disconnected, disregard them
0705:                        }
0706:                        mResponse = null;
0707:                    }
0708:                } catch (ChildTriggeredException e) {
0709:                    synchronized (mElement) {
0710:                        result = setupChildtriggerContext(e
0711:                                .getChildTriggerName(), e
0712:                                .getChildTriggerValues());
0713:                    }
0714:                } catch (ExitTriggeredException e) {
0715:                    synchronized (mElement) {
0716:                        result = handleExitTrigger(e.getExitName());
0717:                    }
0718:                } catch (StepBackException e) {
0719:                    ContinuationContext context = e.getContext();
0720:
0721:                    // register context
0722:                    ContinuationManager manager = mElementInfo.getSite()
0723:                            .getContinuationManager();
0724:                    manager.addContext(context);
0725:
0726:                    synchronized (mElement) {
0727:                        // preserve the continuation ID of this element
0728:                        String context_id = getContextId();
0729:                        ElementResultState result_state = mRequestState
0730:                                .getElementResultStatesObtained().get(
0731:                                        context_id);
0732:                        if (null == result_state) {
0733:                            result_state = mElementInfo.getStateStore()
0734:                                    .createNewResultState(context_id);
0735:                            mRequestState.getElementResultStatesObtained().put(
0736:                                    result_state);
0737:                        }
0738:                        result_state.setContinuationId(context.getId());
0739:
0740:                        // try to obtain the id of the previous continuation
0741:                        String stepbackid = e.lookupStepBackId();
0742:
0743:                        // there is no previous continuation, so start from the beginning again
0744:                        if (null == stepbackid) {
0745:                            ContinuationContext.clearActiveContext();
0746:                            mRequestState.setContinuationId(null);
0747:                        } else {
0748:                            mRequestState.setContinuationId(stepbackid);
0749:                        }
0750:
0751:                        result = new ElementContext(mElement, mRequestState,
0752:                                mResponse);
0753:                        result.mSteppedBack = true;
0754:                    }
0755:                } catch (ForwardException e) {
0756:                    synchronized (mElement) {
0757:                        handleForward(e.getUrl());
0758:                    }
0759:                } catch (RedirectException e) {
0760:                    synchronized (mElement) {
0761:                        getResponse().sendRedirect(e.getUrl());
0762:                    }
0763:                } finally {
0764:                    synchronized (mElement) {
0765:                        try {
0766:                            // flush the output buffer
0767:                            if (mResponse != null) {
0768:                                mResponse.flush();
0769:                            }
0770:
0771:                            // trace element activity
0772:                            mElementInfo.outputTrace(start, mRequestState);
0773:                        } catch (EngineException e) {
0774:                            // if errors occurred during flushing it means that the client has
0775:                            // disconnected, disregard them
0776:                        } finally {
0777:                            // clear the request if this is needed, this typically happens
0778:                            // for continuations, to prevent the request to be cloned when
0779:                            // element instances are cloned
0780:                            if (clear_request) {
0781:                                mRequestState.clearRequest();
0782:                            }
0783:                        }
0784:                    }
0785:                }
0786:
0787:                return result;
0788:            }
0789:
0790:            private ElementContext setupChildtriggerContext(
0791:                    String childtrigger, String[] values)
0792:                    throws EngineException {
0793:                ElementContext element_context = null;
0794:                Map<String, String[]> child_inputs = null;
0795:
0796:                if (mElementState.inInheritanceStructure()) {
0797:                    // construct the child element
0798:                    ElementInfo child_element_info = mElementState
0799:                            .getInheritanceStack().pop();
0800:
0801:                    // verify if the trigger wasn't raised automatically, if this is the
0802:                    // case, the first trigger context has to be removed from the trigger
0803:                    // list since it has been used by this element
0804:                    if (mElementState.isNextChildTrigger(mElementInfo,
0805:                            childtrigger)) {
0806:                        // obtain the stored exit inputs
0807:                        child_inputs = mElementState.nextTrigger()
0808:                                .getParameters();
0809:                    }
0810:                    // since the current element deferred the logical flow to its child,
0811:                    // record the child trigger that caused this
0812:                    else {
0813:                        child_inputs = getChildInputValues(child_element_info);
0814:
0815:                        // don't store an child trigger which isn't dependent on watched values in the
0816:                        // trigger list, the whole element will be executed each time for those triggers
0817:                        if (childtrigger != null) {
0818:                            mElementState
0819:                                    .addTrigger(TriggerContext
0820:                                            .generateChildTrigger(mElementInfo,
0821:                                                    childtrigger, values,
0822:                                                    child_inputs));
0823:                        }
0824:                    }
0825:
0826:                    // construct the child element's context
0827:                    mElementState.setTriggerInputs(child_inputs);
0828:                    element_context = mRequestState.getElementContext(
0829:                            child_element_info, mResponse);
0830:                }
0831:
0832:                return element_context;
0833:            }
0834:
0835:            private ElementContext handleExitTrigger(String exit)
0836:                    throws EngineException {
0837:                // get the the flowlink to check first if it's a redirection
0838:                FlowLink flowlink = mElementInfo.getFlowLink(exit);
0839:                if (null == flowlink) {
0840:                    throw new ExitNotAttachedException(mElementInfo
0841:                            .getDeclarationName(), exit);
0842:                }
0843:
0844:                if (flowlink.isRedirect()) {
0845:                    getResponse().sendRedirect(
0846:                            _getExitQueryUrl(flowlink, null,
0847:                                    mOutputs.aggregateValues(), null)
0848:                                    .toString());
0849:                    return null;
0850:                } else {
0851:                    return setupExitContext(exit);
0852:                }
0853:            }
0854:
0855:            private ElementContext setupExitContext(String exit)
0856:                    throws EngineException {
0857:                // get the element info of the exit target
0858:                FlowLink flowlink = mElementInfo.getFlowLink(exit);
0859:                if (null == flowlink) {
0860:                    throw new ExitNotAttachedException(mElementInfo
0861:                            .getDeclarationName(), exit);
0862:                }
0863:                ElementInfo target = flowlink.getExitTarget(mRequestState);
0864:
0865:                // handle embedding cancellation
0866:                if (mRequestState.isEmbedded() && flowlink.cancelEmbedding()) {
0867:                    // this flag is set in the embedding context to indicate that the
0868:                    // embedding needs to be cancelled, it will be checked by the
0869:                    // processEmbeddedElement method of the embedding element
0870:                    mRequestState.getEmbeddingContext()
0871:                            .setCancelEmbedding(true);
0872:
0873:                    // clear all current output buffers
0874:                    RequestState request_state = mRequestState;
0875:                    while (request_state.isEmbedded()) {
0876:                        request_state.getEmbeddingContext().getElementContext()
0877:                                .getResponse().clearBuffer();
0878:                        request_state = request_state.getEmbeddingContext()
0879:                                .getElementContext().getRequestState();
0880:                    }
0881:                }
0882:
0883:                Map<String, String[]> exit_request_params = null;
0884:                Map<String, String[]> exit_inputs = null;
0885:                Stack<ElementInfo> inheritance_stack = null;
0886:
0887:                Set<Map.Entry<String, String[]>> output_entries = mOutputs
0888:                        .aggregateValues().entrySet();
0889:                if (mElementState.inInheritanceStructure()
0890:                        && !flowlink.cancelInheritance()) {
0891:                    // verify if the trigger wasn't raised automatically, if this is the
0892:                    // case, the first trigger context has to be removed from the trigger
0893:                    // list since it has been used by this element
0894:                    if (mElementState.isNextExitTrigger(mElementInfo, exit)) {
0895:                        exit_request_params = mElementState
0896:                                .getRequestParameters();
0897:                        // obtain the stored exit inputs
0898:                        exit_inputs = mElementState.nextTrigger()
0899:                                .getParameters();
0900:                    }
0901:                    // since the current element deferred the logical flow to an exit,
0902:                    // record this action in the trigger list
0903:                    else {
0904:                        exit_request_params = new HashMap<String, String[]>();
0905:                        exit_request_params.put(
0906:                                ReservedParameters.CHILDREQUEST,
0907:                                new String[] { getEncodedChildRequest() });
0908:
0909:                        exit_request_params
0910:                                .put(
0911:                                        ReservedParameters.TRIGGERLIST,
0912:                                        mElementState
0913:                                                .getRequestParameterValues(ReservedParameters.TRIGGERLIST));
0914:
0915:                        exit_inputs = getExitInputValues(flowlink,
0916:                                output_entries, target, flowlink.isSnapback());
0917:
0918:                        mElementState.addTrigger(TriggerContext
0919:                                .generateExitTrigger(mElementInfo, exit,
0920:                                        exit_inputs));
0921:                    }
0922:
0923:                    inheritance_stack = mElementState.getInheritanceStack();
0924:
0925:                    // check for successive inheritance stacks
0926:                    Stack<ElementInfo> dest_inheritance_stack = target
0927:                            .getInheritanceStack();
0928:                    if (dest_inheritance_stack != null) {
0929:                        inheritance_stack.addAll(dest_inheritance_stack);
0930:                        target = inheritance_stack.pop();
0931:                    }
0932:                } else {
0933:                    exit_request_params = new HashMap<String, String[]>();
0934:                    exit_inputs = getExitInputValues(flowlink, output_entries,
0935:                            target, flowlink.isSnapback());
0936:
0937:                    mRequestState.setTarget(target);
0938:
0939:                    // obtain the inheritance stack and if it exists the top parent
0940:                    // this isn't done if an inheritance structure is already present
0941:                    Stack<ElementInfo> dest_inheritance_stack = target
0942:                            .getInheritanceStack();
0943:                    if (dest_inheritance_stack != null) {
0944:                        inheritance_stack = new Stack<ElementInfo>();
0945:                        inheritance_stack.addAll(dest_inheritance_stack);
0946:                        target = inheritance_stack.pop();
0947:                    }
0948:                }
0949:
0950:                // the request method isn't get or post anymore since all parameters have
0951:                // been removed
0952:                mElementState.setMethod(RequestMethod.EXIT);
0953:
0954:                // construct the target element's context
0955:                mElementState.setRequestParameters(exit_request_params);
0956:                mElementState.setInheritanceStack(inheritance_stack);
0957:                mElementState.setTriggerInputs(exit_inputs);
0958:
0959:                // return the new element context
0960:                return mRequestState.getElementContext(target, mResponse);
0961:            }
0962:
0963:            private void handleForward(String url) {
0964:                boolean is_absolute_url = true;
0965:                if (-1 == url.indexOf(":/")) {
0966:                    is_absolute_url = false;
0967:
0968:                    StringBuilder absolute_url = new StringBuilder();
0969:                    absolute_url.append(mRequestState
0970:                            .getWebappRootUrl(RifeConfig.Engine
0971:                                    .getLocalForwardPort()));
0972:                    if (url.startsWith("/")) {
0973:                        absolute_url.append(url.substring(1));
0974:                    } else {
0975:                        absolute_url.append(url);
0976:                    }
0977:                    url = absolute_url.toString();
0978:                }
0979:
0980:                try {
0981:                    Map<String, String> request_header_map = new HashMap<String, String>();
0982:
0983:                    Request request = mRequestState.getRequest();
0984:                    Enumeration<String> request_header_names = request
0985:                            .getHeaderNames();
0986:
0987:                    // convert the headers to a map
0988:                    if (request_header_names.hasMoreElements()) {
0989:                        String header_name = null;
0990:                        String header_name_lowercase = null;
0991:                        String header_value = null;
0992:                        do {
0993:                            header_name = request_header_names.nextElement();
0994:                            if (null != header_name) {
0995:                                header_name_lowercase = header_name
0996:                                        .toLowerCase();
0997:                                header_value = request.getHeader(header_name);
0998:                                if (is_absolute_url
0999:                                        && ("host"
1000:                                                .equals(header_name_lowercase)
1001:                                                || "connection"
1002:                                                        .equals(header_name_lowercase)
1003:                                                || "keep-alive"
1004:                                                        .equals(header_name_lowercase)
1005:                                                || "content-type"
1006:                                                        .equals(header_name_lowercase) || "content-length"
1007:                                                .equals(header_name_lowercase))) {
1008:                                    continue;
1009:                                }
1010:                                request_header_map.put(header_name,
1011:                                        header_value);
1012:                            }
1013:                        } while (request_header_names.hasMoreElements());
1014:                    }
1015:
1016:                    // retrieve the page
1017:                    HttpUtils.Page page = new HttpUtils.Request(url).headers(
1018:                            request_header_map).retrieve();
1019:
1020:                    // incorporate the page data in the current request
1021:                    if ((page.getResponseCode() / 100) != 2) {
1022:                        // report errors
1023:                        mResponse.sendError(page.getResponseCode(), page
1024:                                .getResponseMessage());
1025:                    } else {
1026:                        // preserve the status code
1027:                        mResponse.setStatus(page.getResponseCode());
1028:                    }
1029:
1030:                    if (page.getContent() != null) {
1031:                        mResponse.print(page.getContent());
1032:                    }
1033:
1034:                    for (Map.Entry<String, List<String>> header : page
1035:                            .getHeaders().entrySet()) {
1036:                        if (header.getKey() != null) {
1037:                            String key = header.getKey().toLowerCase();
1038:
1039:                            // strip out several duplicate headers
1040:                            if (key.equals("accept-encoding")
1041:                                    || key.equals("content-encoding")
1042:                                    || key.equals("content-length")
1043:                                    || key.equals("date") || key.equals("host")
1044:                                    || key.equals("server")
1045:                                    || key.equals("transfer-encoding")) {
1046:                                continue;
1047:                            }
1048:
1049:                            // handle the content type differently
1050:                            if (key.equals("content-type")) {
1051:                                mResponse.setContentType(HttpUtils
1052:                                        .extractMimeTypeFromContentType(page
1053:                                                .getContentType()));
1054:                                continue;
1055:                            }
1056:
1057:                            for (String header_value : header.getValue()) {
1058:                                mResponse.addHeader(header.getKey(),
1059:                                        header_value);
1060:                            }
1061:                        }
1062:                    }
1063:                } catch (IOException e) {
1064:                    mResponse.sendError(HttpServletResponse.SC_NOT_FOUND);
1065:                }
1066:
1067:                RequestDispatcher dispatcher = mRequestState.getRequest()
1068:                        .getRequestDispatcher(url);
1069:                if (null == dispatcher) {
1070:                    mResponse.sendError(HttpServletResponse.SC_NOT_FOUND);
1071:                }
1072:            }
1073:
1074:            RequestState getRequestState() {
1075:                return mRequestState;
1076:            }
1077:
1078:            ElementInfo getElementInfo() {
1079:                return mElementInfo;
1080:            }
1081:
1082:            ElementSupport getElementSupport() {
1083:                return mElement;
1084:            }
1085:
1086:            ElementExecutionState getElementState() {
1087:                return mElementState;
1088:            }
1089:
1090:            Response getResponse() {
1091:                return mResponse;
1092:            }
1093:
1094:            void setResponse(Response response) {
1095:                mResponse = response;
1096:            }
1097:
1098:            Template getHtmlTemplate(String name, String encoding,
1099:                    TemplateTransformer transformer) throws TemplateException {
1100:                if (null == name)
1101:                    throw new IllegalArgumentException("name can't be null.");
1102:                if (0 == name.length())
1103:                    throw new IllegalArgumentException("name can't be empty.");
1104:
1105:                return TemplateFactory.ENGINEHTML.get(name, encoding,
1106:                        transformer);
1107:            }
1108:
1109:            Template getXhtmlTemplate(String name, String encoding,
1110:                    TemplateTransformer transformer) throws TemplateException {
1111:                if (null == name)
1112:                    throw new IllegalArgumentException("name can't be null.");
1113:                if (0 == name.length())
1114:                    throw new IllegalArgumentException("name can't be empty.");
1115:
1116:                return TemplateFactory.ENGINEXHTML.get(name, encoding,
1117:                        transformer);
1118:            }
1119:
1120:            Template getXmlTemplate(String name, String encoding,
1121:                    TemplateTransformer transformer) throws TemplateException {
1122:                if (null == name)
1123:                    throw new IllegalArgumentException("name can't be null.");
1124:                if (0 == name.length())
1125:                    throw new IllegalArgumentException("name can't be empty.");
1126:
1127:                return TemplateFactory.ENGINEXML.get(name, encoding,
1128:                        transformer);
1129:            }
1130:
1131:            Template getTxtTemplate(String name, String encoding,
1132:                    TemplateTransformer transformer) throws TemplateException {
1133:                if (null == name)
1134:                    throw new IllegalArgumentException("name can't be null.");
1135:                if (0 == name.length())
1136:                    throw new IllegalArgumentException("name can't be empty.");
1137:
1138:                return TemplateFactory.ENGINETXT.get(name, encoding,
1139:                        transformer);
1140:            }
1141:
1142:            void processEmbeddedElementsEarly(Template template,
1143:                    ElementSupport embeddingElement) {
1144:                // process the embedded elements
1145:                if (template.hasFilteredValues(TAG_ELEMENT)) {
1146:                    List<String[]> element_tags = template
1147:                            .getFilteredValues(TAG_ELEMENT);
1148:                    for (String[] captured_groups : element_tags) {
1149:                        // only embed the element if the value hasn't been set in the
1150:                        // template yet and is declared as 'early'
1151:                        if (!template.isValueSet(captured_groups[0])
1152:                                && captured_groups[2].equals("-")) {
1153:                            processEmbeddedElement(captured_groups[0],
1154:                                    template, embeddingElement,
1155:                                    captured_groups[3], captured_groups[4],
1156:                                    null);
1157:                        }
1158:                    }
1159:
1160:                    for (String[] captured_groups : element_tags) {
1161:                        // only embed the element if the value hasn't been set in the
1162:                        // template yet and has no specific priority
1163:                        if (!template.isValueSet(captured_groups[0])
1164:                                && 0 == captured_groups[2].length()) {
1165:                            processEmbeddedElement(captured_groups[0],
1166:                                    template, embeddingElement,
1167:                                    captured_groups[3], captured_groups[4],
1168:                                    null);
1169:                        }
1170:                    }
1171:                }
1172:            }
1173:
1174:            void processEmbeddedElementsLate(Template template,
1175:                    ElementSupport embeddingElement) {
1176:                // process the embedded elements
1177:                if (template.hasFilteredValues(TAG_ELEMENT)) {
1178:                    List<String[]> element_tags = template
1179:                            .getFilteredValues(TAG_ELEMENT);
1180:                    for (String[] captured_groups : element_tags) {
1181:                        // only embed the element if the value hasn't been set in the
1182:                        // template yet and is declared as late
1183:                        if (!template.isValueSet(captured_groups[0])
1184:                                && captured_groups[2].equals("+")) {
1185:                            processEmbeddedElement(captured_groups[0],
1186:                                    template, embeddingElement,
1187:                                    captured_groups[3], captured_groups[4],
1188:                                    null);
1189:                        }
1190:                    }
1191:                }
1192:            }
1193:
1194:            void print(Template template) throws TemplateException,
1195:                    EngineException {
1196:                List<String> set_values = processTemplate(template);
1197:
1198:                // set the content type
1199:                if (!mResponse.isContentTypeSet()) {
1200:                    String content_type = template.getDefaultContentType();
1201:                    if (null == content_type) {
1202:                        content_type = RifeConfig.Engine
1203:                                .getDefaultContentType();
1204:                    }
1205:
1206:                    mResponse.setContentType(content_type);
1207:                }
1208:
1209:                // print the element contents with the auto-generated values
1210:                mResponse.print(template);
1211:
1212:                // clean up the values that were set
1213:                template.removeValues(set_values);
1214:            }
1215:
1216:            List<String> processTemplate(Template template)
1217:                    throws TemplateException, EngineException {
1218:                List<String> set_values = new ArrayList<String>();
1219:
1220:                // pre-obtain the output entries, since they process the outjection logic
1221:                Map<String, String[]> output_value_map = mOutputs
1222:                        .aggregateValues();
1223:                Set<Map.Entry<String, String[]>> output_value_entries = output_value_map
1224:                        .entrySet();
1225:
1226:                // retrieve the template encoder
1227:                TemplateEncoder encoder = template.getEncoder();
1228:
1229:                // process the filtered roleuser tags
1230:                evaluateExpressionRoleUserTags(set_values, template, null);
1231:
1232:                // create values for the exit urls
1233:                Set<Map.Entry<String, FlowLink>> exit_entries = mElementInfo
1234:                        .getExitEntries();
1235:                if (exit_entries.size() > 0) {
1236:                    String exit_name = null;
1237:                    FlowLink exit_flowlink = null;
1238:                    String exit_query_value_id = null;
1239:                    String exit_form_value_id = null;
1240:                    String exit_params_value_id = null;
1241:                    String exit_paramsjs_value_id = null;
1242:
1243:                    for (Map.Entry<String, FlowLink> exit_entry : exit_entries) {
1244:                        if (exit_entry.getValue() != null) {
1245:                            exit_name = exit_entry.getKey();
1246:                            exit_flowlink = exit_entry.getValue();
1247:
1248:                            exit_query_value_id = PREFIX_EXIT_QUERY + exit_name;
1249:                            exit_form_value_id = PREFIX_EXIT_FORM + exit_name;
1250:                            exit_params_value_id = PREFIX_EXIT_PARAMS
1251:                                    + exit_name;
1252:                            exit_paramsjs_value_id = PREFIX_EXIT_PARAMS
1253:                                    + exit_name;
1254:
1255:                            if (template.hasValueId(exit_query_value_id)
1256:                                    && !template
1257:                                            .isValueSet(exit_query_value_id)) {
1258:                                template.setValue(exit_query_value_id,
1259:                                        _getExitQueryUrl(exit_flowlink, null,
1260:                                                output_value_map, null)
1261:                                                .encoder(encoder));
1262:                                set_values.add(exit_query_value_id);
1263:                            }
1264:
1265:                            if (template.hasValueId(exit_form_value_id)) {
1266:                                // only substitute the template value if it hasn't been specified yet
1267:                                // this allows for user overriding
1268:                                if (!template.isValueSet(exit_form_value_id)) {
1269:                                    template.setValue(exit_form_value_id,
1270:                                            _getExitFormUrl(exit_flowlink,
1271:                                                    null, output_value_map)
1272:                                                    .encoder(encoder));
1273:                                    set_values.add(exit_form_value_id);
1274:                                }
1275:
1276:                                // only substitute the form parameters template value if the url is present
1277:                                if (template.hasValueId(exit_params_value_id)) {
1278:                                    // only substitute the template value if it hasn't been specified yet
1279:                                    // this allows for user overriding
1280:                                    if (!template
1281:                                            .isValueSet(exit_params_value_id)) {
1282:                                        template
1283:                                                .setValue(
1284:                                                        exit_params_value_id,
1285:                                                        _getExitFormParameters(
1286:                                                                exit_flowlink,
1287:                                                                output_value_map,
1288:                                                                null));
1289:                                        set_values.add(exit_params_value_id);
1290:                                    }
1291:                                } else if (template
1292:                                        .hasValueId(exit_paramsjs_value_id)) {
1293:                                    // only substitute the template value if it hasn't been specified yet
1294:                                    // this allows for user overriding
1295:                                    if (!template
1296:                                            .isValueSet(exit_paramsjs_value_id)) {
1297:                                        template
1298:                                                .setValue(
1299:                                                        exit_paramsjs_value_id,
1300:                                                        _getExitFormParametersJavascript(
1301:                                                                exit_flowlink,
1302:                                                                output_value_map,
1303:                                                                null));
1304:                                        set_values.add(exit_paramsjs_value_id);
1305:                                    }
1306:                                } else {
1307:                                    throw new EngineException(
1308:                                            "The required template value '"
1309:                                                    + exit_params_value_id
1310:                                                    + "' is not present. Replacement of the template value '"
1311:                                                    + exit_form_value_id
1312:                                                    + "' alone is not sufficient.");
1313:                                }
1314:                            } else {
1315:                                if (template.hasValueId(exit_params_value_id)) {
1316:                                    throw new EngineException(
1317:                                            "The template value '"
1318:                                                    + exit_params_value_id
1319:                                                    + "' was specified, while the template value '"
1320:                                                    + exit_form_value_id
1321:                                                    + "' could not be found. This is not sufficient, both are needed.");
1322:                                } else if (template
1323:                                        .hasValueId(exit_paramsjs_value_id)) {
1324:                                    throw new EngineException(
1325:                                            "The template value '"
1326:                                                    + exit_paramsjs_value_id
1327:                                                    + "' was specified, while the template value '"
1328:                                                    + exit_form_value_id
1329:                                                    + "' could not be found. This is not sufficient, both are needed.");
1330:                                }
1331:                            }
1332:                        }
1333:                    }
1334:                }
1335:
1336:                // create values for submission urls
1337:                String submission_query_value_id = null;
1338:                String submission_form_value_id = null;
1339:                String submission_params_value_id = null;
1340:                String submission_paramsjs_value_id = null;
1341:
1342:                for (String submission_name : mElementInfo.getSubmissionNames()) {
1343:                    submission_query_value_id = PREFIX_SUBMISSION_QUERY
1344:                            + submission_name;
1345:                    submission_form_value_id = PREFIX_SUBMISSION_FORM
1346:                            + submission_name;
1347:                    submission_params_value_id = PREFIX_SUBMISSION_PARAMS
1348:                            + submission_name;
1349:                    submission_paramsjs_value_id = PREFIX_SUBMISSION_PARAMSJS
1350:                            + submission_name;
1351:
1352:                    if (template.hasValueId(submission_query_value_id)
1353:                            && !template.isValueSet(submission_query_value_id)) {
1354:                        template.setValue(submission_query_value_id,
1355:                                _getSubmissionQueryUrl(submission_name, null,
1356:                                        null, output_value_entries).encoder(
1357:                                        encoder));
1358:                        set_values.add(submission_query_value_id);
1359:                    }
1360:
1361:                    if (template.hasValueId(submission_form_value_id)) {
1362:                        // only substitute the template value if it hasn't been specified yet
1363:                        // this allows for user overriding
1364:                        if (!template.isValueSet(submission_form_value_id)) {
1365:                            template
1366:                                    .setValue(submission_form_value_id,
1367:                                            getSubmissionFormUrl(null).encoder(
1368:                                                    encoder));
1369:                            set_values.add(submission_form_value_id);
1370:                        }
1371:
1372:                        // only substitute the form parameters template value if the url is present
1373:                        if (template.hasValueId(submission_params_value_id)) {
1374:                            // only substitute the template value if it hasn't been specified yet
1375:                            // this allows for user overriding
1376:                            if (!template
1377:                                    .isValueSet(submission_params_value_id)) {
1378:                                template.setValue(submission_params_value_id,
1379:                                        _getSubmissionFormParameters(
1380:                                                submission_name, null,
1381:                                                output_value_entries));
1382:                                set_values.add(submission_params_value_id);
1383:                            }
1384:                        } else if (template
1385:                                .hasValueId(submission_paramsjs_value_id)) {
1386:                            // only substitute the template value if it hasn't been specified yet
1387:                            // this allows for user overriding
1388:                            if (!template
1389:                                    .isValueSet(submission_paramsjs_value_id)) {
1390:                                template.setValue(submission_paramsjs_value_id,
1391:                                        _getSubmissionFormParametersJavascript(
1392:                                                submission_name, null,
1393:                                                output_value_entries));
1394:                                set_values.add(submission_paramsjs_value_id);
1395:                            }
1396:                        } else {
1397:                            throw new EngineException(
1398:                                    "The template value '"
1399:                                            + submission_params_value_id
1400:                                            + "' nor '"
1401:                                            + submission_paramsjs_value_id
1402:                                            + "'are not present. Replacement of the template value '"
1403:                                            + submission_form_value_id
1404:                                            + "' alone is not sufficient.");
1405:                        }
1406:                    } else {
1407:                        if (template.hasValueId(submission_params_value_id)) {
1408:                            throw new EngineException(
1409:                                    "The template value '"
1410:                                            + submission_params_value_id
1411:                                            + "' was specified, while the template value '"
1412:                                            + submission_form_value_id
1413:                                            + "' could not be found. This is not sufficient, both are needed.");
1414:                        } else if (template
1415:                                .hasValueId(submission_paramsjs_value_id)) {
1416:                            throw new EngineException(
1417:                                    "The template value '"
1418:                                            + submission_paramsjs_value_id
1419:                                            + "' was specified, while the template value '"
1420:                                            + submission_form_value_id
1421:                                            + "' could not be found. This is not sufficient, both are needed.");
1422:                        }
1423:                    }
1424:                }
1425:
1426:                // create values for properties
1427:                if (template.hasFilteredValues(TAG_PROPERTY)) {
1428:                    String property_value_id = null;
1429:                    String property_value = null;
1430:
1431:                    for (String[] property_tag : template
1432:                            .getFilteredValues(TAG_PROPERTY)) {
1433:                        property_value_id = PREFIX_PROPERTY + property_tag[1];
1434:                        if (template.hasValueId(property_value_id)
1435:                                && !template.isValueSet(property_value_id)) {
1436:                            property_value = mElementInfo
1437:                                    .getPropertyString(property_tag[1]);
1438:                            if (property_value != null) {
1439:                                template.setValue(property_value_id, encoder
1440:                                        .encode(property_value));
1441:                                set_values.add(property_value_id);
1442:                            }
1443:                        }
1444:                    }
1445:                }
1446:
1447:                // create values for inputs
1448:                String input_value_id = null;
1449:                String[] input_values = null;
1450:
1451:                for (Map.Entry<String, String[]> input_entry : mElementState
1452:                        .getInputEntries()) {
1453:                    if (mElementInfo.containsInput(input_entry.getKey())
1454:                            && mElementState
1455:                                    .hasInputValue(input_entry.getKey())) {
1456:                        input_value_id = PREFIX_INPUT + input_entry.getKey();
1457:                        input_values = input_entry.getValue();
1458:                        if (template.hasValueId(input_value_id)
1459:                                && !template.isValueSet(input_value_id)) {
1460:                            template.setValue(input_value_id, encoder
1461:                                    .encode(input_values[0]));
1462:                            set_values.add(input_value_id);
1463:                        }
1464:
1465:                        set_values.addAll(selectInputParameter(template,
1466:                                input_entry.getKey(), input_values));
1467:                    }
1468:                }
1469:
1470:                // create values for outputs
1471:                String output_value_id = null;
1472:
1473:                for (Map.Entry<String, String[]> output_entry : output_value_entries) {
1474:                    output_value_id = PREFIX_OUTPUT + output_entry.getKey();
1475:                    if (template.hasValueId(output_value_id)
1476:                            && !template.isValueSet(output_value_id)
1477:                            && output_entry.getValue() != null) {
1478:                        template.setValue(output_value_id, encoder
1479:                                .encode(output_entry.getValue()[0]));
1480:                        set_values.add(output_value_id);
1481:                    }
1482:                }
1483:
1484:                // create values for global variables
1485:                for (String globalvar_name : mElementInfo.getGlobalVarNames()) {
1486:                    if (mElementState.hasInputValue(globalvar_name)) {
1487:                        input_value_id = PREFIX_INPUT + globalvar_name;
1488:                        if (template.hasValueId(input_value_id)
1489:                                && !template.isValueSet(input_value_id)) {
1490:                            template.setValue(input_value_id, encoder
1491:                                    .encode(mElementState
1492:                                            .getInput(globalvar_name)));
1493:                            set_values.add(input_value_id);
1494:                        }
1495:
1496:                        set_values.addAll(selectInputParameter(template,
1497:                                globalvar_name, mElementState
1498:                                        .getInputValues(globalvar_name)));
1499:                    }
1500:
1501:                    String[] global_output_value = output_value_map
1502:                            .get(globalvar_name);
1503:                    if (global_output_value != null) {
1504:                        output_value_id = PREFIX_OUTPUT + globalvar_name;
1505:                        if (template.hasValueId(output_value_id)
1506:                                && !template.isValueSet(output_value_id)) {
1507:                            template.setValue(output_value_id, encoder
1508:                                    .encode(global_output_value[0]));
1509:                            set_values.add(output_value_id);
1510:                        }
1511:                    }
1512:                }
1513:
1514:                // create values for in cookies
1515:                String incookie_value_id = null;
1516:                for (Map.Entry<String, String> incookie_entry : getIncookieEntries()) {
1517:                    if (mElementInfo.containsIncookie(incookie_entry.getKey())
1518:                            || mElementInfo.containsGlobalCookie(incookie_entry
1519:                                    .getKey())) {
1520:                        incookie_value_id = PREFIX_INCOOKIE
1521:                                + incookie_entry.getKey();
1522:                        if (template.hasValueId(incookie_value_id)
1523:                                && !template.isValueSet(incookie_value_id)) {
1524:                            template.setValue(incookie_value_id, encoder
1525:                                    .encode(incookie_entry.getValue()));
1526:                            set_values.add(incookie_value_id);
1527:                        }
1528:                    }
1529:                }
1530:
1531:                // create values for out cookies
1532:                String outcookie_value_id = null;
1533:                for (Map.Entry<String, String> outcookie_entry : mOutcookies
1534:                        .aggregateValues().entrySet()) {
1535:                    if (mElementInfo
1536:                            .containsOutcookiePossibility(outcookie_entry
1537:                                    .getKey())) {
1538:                        outcookie_value_id = PREFIX_OUTCOOKIE
1539:                                + outcookie_entry.getKey();
1540:                        if (template.hasValueId(outcookie_value_id)
1541:                                && !template.isValueSet(outcookie_value_id)) {
1542:                            template.setValue(outcookie_value_id, encoder
1543:                                    .encode(outcookie_entry.getValue()));
1544:                            set_values.add(outcookie_value_id);
1545:                        }
1546:                    }
1547:                }
1548:
1549:                // set the webapp root
1550:                if (template.hasValueId(ID_WEBAPP_ROOTURL)
1551:                        && !template.isValueSet(ID_WEBAPP_ROOTURL)) {
1552:                    template.setValue(ID_WEBAPP_ROOTURL, mRequestState
1553:                            .getWebappRootUrl(-1));
1554:                    set_values.add(ID_WEBAPP_ROOTURL);
1555:                }
1556:
1557:                // set the server root
1558:                if (template.hasValueId(ID_SERVER_ROOTURL)
1559:                        && !template.isValueSet(ID_SERVER_ROOTURL)) {
1560:                    template.setValue(ID_SERVER_ROOTURL, mRequestState
1561:                            .getServerRootUrl(-1));
1562:                    set_values.add(ID_SERVER_ROOTURL);
1563:                }
1564:
1565:                // create values for submission parameters and beans
1566:                String[] submission_param_values = null;
1567:                String submission_param_value_id = null;
1568:
1569:                for (Submission submission : mElementInfo.getSubmissions()) {
1570:                    // create the parameters
1571:                    for (String submission_param_name : submission
1572:                            .getParameterNames()) {
1573:                        if (mElementState
1574:                                .hasRequestParameterValue(submission_param_name)) {
1575:                            submission_param_values = mElementState
1576:                                    .getRequestParameterValues(submission_param_name);
1577:
1578:                            submission_param_value_id = PREFIX_PARAM
1579:                                    + submission_param_name;
1580:                            if (template.hasValueId(submission_param_value_id)
1581:                                    && !template
1582:                                            .isValueSet(submission_param_value_id)) {
1583:                                template
1584:                                        .setValue(
1585:                                                submission_param_value_id,
1586:                                                encoder
1587:                                                        .encode(submission_param_values[0]));
1588:                                set_values.add(submission_param_value_id);
1589:                            }
1590:
1591:                            set_values.addAll(selectSubmissionParameter(
1592:                                    template, submission_param_name,
1593:                                    submission_param_values));
1594:                        }
1595:                    }
1596:
1597:                    // create the bean forms
1598:                    BeanHandler bean_handler = template.getBeanHandler();
1599:                    if (bean_handler != null) {
1600:                        FormBuilder form_builder = bean_handler
1601:                                .getFormBuilder();
1602:                        if (form_builder != null) {
1603:                            for (BeanDeclaration bean : submission.getBeans()) {
1604:                                try {
1605:                                    Map<String, String[]> parameters = null;
1606:                                    if (hasSubmission()
1607:                                            && submission.getName().equals(
1608:                                                    getSubmission())) {
1609:                                        parameters = mElementState
1610:                                                .getRequestParameters();
1611:                                    }
1612:                                    form_builder.generateForm(template, bean
1613:                                            .getBeanClass(), parameters, bean
1614:                                            .getPrefix());
1615:                                } catch (Throwable e) {
1616:                                    throw new SubmissionBeanFormGenerationErrorException(
1617:                                            mElementInfo.getDeclarationName(),
1618:                                            submission.getName(), bean
1619:                                                    .getClassname(), e);
1620:                                }
1621:                            }
1622:                        }
1623:                    }
1624:                }
1625:
1626:                // process the late embedded elements
1627:                processEmbeddedElementsLate(template, mElement);
1628:
1629:                return set_values;
1630:            }
1631:
1632:            void triggerChild(String childTriggerName,
1633:                    String[] childTriggerValues) throws EngineException {
1634:                mElement.enableRequestAccess(false);
1635:                try {
1636:                    if (mElement.childTriggered(childTriggerName,
1637:                            childTriggerValues)) {
1638:                        throw new ChildTriggeredException(childTriggerName,
1639:                                childTriggerValues);
1640:                    }
1641:                } finally {
1642:                    mElement.enableRequestAccess(true);
1643:                }
1644:            }
1645:
1646:            boolean hasSubmission() {
1647:                return null != getSubmission();
1648:            }
1649:
1650:            boolean hasSubmission(String name) {
1651:                String submission = getSubmission();
1652:                return submission != null && submission.equals(name);
1653:
1654:            }
1655:
1656:            String getSubmission() {
1657:                if (null == mSubmission) {
1658:                    return null;
1659:                }
1660:
1661:                return mSubmission;
1662:            }
1663:
1664:            private void validateParameter(String parameterName)
1665:                    throws EngineException {
1666:                assert parameterName != null;
1667:                assert parameterName.length() > 0;
1668:
1669:                boolean found = false;
1670:                for (Submission submission : mElementInfo.getSubmissions()) {
1671:                    if (submission.containsParameter(parameterName)) {
1672:                        found = true;
1673:                        break;
1674:                    }
1675:                }
1676:
1677:                if (!found) {
1678:                    throw new ParameterUnknownException(mElementInfo
1679:                            .getDeclarationName(), parameterName);
1680:                }
1681:            }
1682:
1683:            private void validateFile(String fileName) throws EngineException {
1684:                assert fileName != null;
1685:                assert fileName.length() > 0;
1686:
1687:                boolean found = false;
1688:                for (Submission submission : mElementInfo.getSubmissions()) {
1689:                    if (submission.containsFile(fileName)) {
1690:                        found = true;
1691:                        break;
1692:                    }
1693:                }
1694:
1695:                if (!found) {
1696:                    throw new FileUnknownException(mElementInfo
1697:                            .getDeclarationName(), fileName);
1698:                }
1699:            }
1700:
1701:            boolean isInputEmpty(String name) throws EngineException {
1702:                String input = getInput(name);
1703:
1704:                return null == input || input.trim().equals("");
1705:            }
1706:
1707:            String getInput(String name) throws EngineException {
1708:                assert name != null;
1709:                assert name.length() > 0;
1710:
1711:                mElementInfo.validateInputName(name);
1712:
1713:                String input = mElementState.getInput(name);
1714:
1715:                if (null == input && mElementInfo.hasInputDefaults()) {
1716:                    String[] default_values = mElementInfo
1717:                            .getInputDefaultValues(name);
1718:                    if (default_values != null) {
1719:                        input = default_values[0];
1720:                    }
1721:                }
1722:
1723:                if (null == input && mElementInfo.hasGlobalVarDefaults()) {
1724:                    String[] default_values = mElementInfo
1725:                            .getGlobalVarDefaultValues(name);
1726:                    if (default_values != null) {
1727:                        input = default_values[0];
1728:                    }
1729:                }
1730:
1731:                return input;
1732:            }
1733:
1734:            String[] getInputValues(String name) throws EngineException {
1735:                assert name != null;
1736:                assert name.length() > 0;
1737:
1738:                mElementInfo.validateInputName(name);
1739:
1740:                String[] input_values = mElementState.getInputValues(name);
1741:
1742:                if (null == input_values && mElementInfo.hasInputDefaults()) {
1743:                    input_values = mElementInfo.getInputDefaultValues(name);
1744:                }
1745:
1746:                if (null == input_values && mElementInfo.hasGlobalVarDefaults()) {
1747:                    input_values = mElementInfo.getGlobalVarDefaultValues(name);
1748:                }
1749:
1750:                return input_values;
1751:            }
1752:
1753:            boolean hasInputValue(String name) throws EngineException {
1754:                assert name != null;
1755:                assert name.length() > 0;
1756:
1757:                mElementInfo.validateInputName(name);
1758:
1759:                return mElementState.hasInputValue(name)
1760:                        || mElementInfo.hasInputDefaultValues(name)
1761:                        || mElementInfo.hasGlobalVarDefaultValues(name);
1762:            }
1763:
1764:            Collection<String> selectInputParameter(Template template,
1765:                    String name, String[] values) {
1766:                return selectParameter(template, PREFIX_INPUT + name, values);
1767:            }
1768:
1769:            OutputValues getOutputs() {
1770:                return mOutputs;
1771:            }
1772:
1773:            void setOutput(String name, String value) throws EngineException {
1774:                assert name != null;
1775:                assert name.length() > 0;
1776:                assert value != null;
1777:
1778:                mElementInfo.validateOutputName(name);
1779:
1780:                // create a string array
1781:                String[] value_array = new String[] { value };
1782:
1783:                // store the value
1784:                setOutputValues(name, value_array);
1785:
1786:                if (mElementState.inInheritanceStructure()
1787:                        && mElementInfo.containsChildTrigger(name)) {
1788:                    triggerChild(name, value_array);
1789:                }
1790:            }
1791:
1792:            void setOutput(String name, String[] values) throws EngineException {
1793:                assert name != null;
1794:                assert name.length() > 0;
1795:                assert values != null;
1796:                assert values.length > 0;
1797:
1798:                mElementInfo.validateOutputName(name);
1799:
1800:                setOutputValues(name, values);
1801:
1802:                if (mElementState.inInheritanceStructure()
1803:                        && mElementInfo.containsChildTrigger(name)) {
1804:                    triggerChild(name, values);
1805:                }
1806:            }
1807:
1808:            void setOutput(String name, Object value,
1809:                    ConstrainedProperty constrainedProperty)
1810:                    throws EngineException {
1811:                assert name != null;
1812:                assert name.length() > 0;
1813:                assert value != null;
1814:
1815:                String[] value_array = getOutputObjectValues(name, value,
1816:                        constrainedProperty);
1817:
1818:                // store the value
1819:                setOutputValues(name, value_array);
1820:
1821:                if (mElementState.inInheritanceStructure()
1822:                        && mElementInfo.containsChildTrigger(name)) {
1823:                    triggerChild(name, value_array);
1824:                }
1825:            }
1826:
1827:            private String[] getOutputObjectValues(String name, Object value,
1828:                    ConstrainedProperty constrainedProperty)
1829:                    throws EngineException {
1830:                mElementInfo.validateOutputName(name);
1831:
1832:                // create a string array
1833:                String[] value_array = null;
1834:
1835:                // convert the value to a string representation
1836:                Class value_type = value.getClass();
1837:                if (value_type.isArray() || !(value instanceof  Serializable)
1838:                        || ClassUtils.isBasic(value_type)) {
1839:                    value_array = ArrayUtils.createStringArray(value,
1840:                            constrainedProperty);
1841:                } else {
1842:                    try {
1843:                        value_array = new String[] { SerializationUtils
1844:                                .serializeToString((Serializable) value) };
1845:                    } catch (SerializationUtilsErrorException e) {
1846:                        throw new UnserializableOutputValueException(
1847:                                mElementInfo.getDeclarationName(), name, value,
1848:                                e);
1849:                    }
1850:                }
1851:
1852:                return value_array;
1853:            }
1854:
1855:            void addOutputValue(String name, String value)
1856:                    throws EngineException {
1857:                assert name != null;
1858:                assert name.length() > 0;
1859:                assert value != null;
1860:
1861:                mElementInfo.validateOutputName(name);
1862:
1863:                String[] value_array = null;
1864:
1865:                String[] existing_values = mOutputs.get(name);
1866:                if (existing_values != null) {
1867:                    value_array = ArrayUtils.join(existing_values, value);
1868:                } else {
1869:                    value_array = new String[] { value };
1870:                }
1871:
1872:                setOutputValues(name, value_array);
1873:
1874:                if (mElementState.inInheritanceStructure()
1875:                        && mElementInfo.containsChildTrigger(name)) {
1876:                    triggerChild(name, value_array);
1877:                }
1878:            }
1879:
1880:            void addOutputValues(String name, String[] values)
1881:                    throws EngineException {
1882:                assert name != null;
1883:                assert name.length() > 0;
1884:                assert values != null;
1885:                assert values.length > 0;
1886:
1887:                mElementInfo.validateOutputName(name);
1888:
1889:                String[] value_array = null;
1890:
1891:                String[] existing_values = mOutputs.get(name);
1892:                if (existing_values != null) {
1893:                    value_array = ArrayUtils.join(existing_values, values);
1894:                } else {
1895:                    value_array = values;
1896:                }
1897:
1898:                setOutputValues(name, value_array);
1899:
1900:                if (mElementState.inInheritanceStructure()
1901:                        && mElementInfo.containsChildTrigger(name)) {
1902:                    triggerChild(name, value_array);
1903:                }
1904:            }
1905:
1906:            void addOutputValue(String name, Object value)
1907:                    throws EngineException {
1908:                assert name != null;
1909:                assert name.length() > 0;
1910:                assert value != null;
1911:
1912:                mElementInfo.validateOutputName(name);
1913:
1914:                // convert the value to a string representation
1915:                String value_text = null;
1916:                Class value_type = value.getClass();
1917:                if (!(value instanceof  Serializable)
1918:                        || ClassUtils.isBasic(value_type)) {
1919:                    value_text = String.valueOf(value);
1920:                } else if (value instanceof  Serializable) {
1921:                    try {
1922:                        value_text = SerializationUtils
1923:                                .serializeToString((Serializable) value);
1924:                    } catch (SerializationUtilsErrorException e) {
1925:                        throw new UnserializableOutputValueException(
1926:                                mElementInfo.getDeclarationName(), name, value,
1927:                                e);
1928:                    }
1929:                } else {
1930:                    value_text = String.valueOf(value);
1931:                }
1932:
1933:                addOutputValue(name, value_text);
1934:            }
1935:
1936:            void clearOutput(String name) throws EngineException {
1937:                assert name != null;
1938:                assert name.length() > 0;
1939:
1940:                mElementInfo.validateOutputName(name);
1941:
1942:                clearOutputValue(name);
1943:            }
1944:
1945:            void clearNamedOutputBean(String name) throws EngineException {
1946:                assert name != null;
1947:
1948:                mElementInfo.validateOutbeanName(name);
1949:
1950:                BeanDeclaration output_bean = mElementInfo
1951:                        .getNamedOutbeanInfo(name);
1952:                if (null == output_bean) {
1953:                    output_bean = mElementInfo.getNamedGlobalBeanInfo(name);
1954:                }
1955:
1956:                Class output_bean_class = null;
1957:                try {
1958:                    output_bean_class = Class.forName(output_bean
1959:                            .getClassname());
1960:                } catch (ClassNotFoundException e) {
1961:                    throw new NamedOutbeanClassnameErrorException(mElementInfo
1962:                            .getDeclarationName(), name, output_bean
1963:                            .getClassname());
1964:                }
1965:
1966:                clearOutputBean(output_bean_class, output_bean.getPrefix());
1967:            }
1968:
1969:            void clearOutputBean(Class beanClass, String prefix)
1970:                    throws EngineException {
1971:                if (null == beanClass)
1972:                    throw new IllegalArgumentException(
1973:                            "beanClass can't be null.");
1974:
1975:                try {
1976:                    // handle outputs
1977:                    Collection<String> output_names = mElementInfo
1978:                            .getOutputNames();
1979:                    String[] output_names_array = new String[output_names
1980:                            .size()];
1981:                    output_names.toArray(output_names_array);
1982:
1983:                    // handle globals
1984:                    Collection<String> globalvar_names = mElementInfo
1985:                            .getGlobalVarNames();
1986:                    String[] globalvar_names_array = new String[globalvar_names
1987:                            .size()];
1988:                    globalvar_names.toArray(globalvar_names_array);
1989:
1990:                    // merge the both arrays
1991:                    String[] merged_names_array = ArrayUtils.join(
1992:                            output_names_array, globalvar_names_array);
1993:
1994:                    // process all the possible output names
1995:                    Set<String> property_names = BeanUtils.getPropertyNames(
1996:                            beanClass, merged_names_array, null, prefix);
1997:                    for (String property_name : property_names) {
1998:                        clearOutput(property_name);
1999:                    }
2000:                } catch (BeanUtilsException e) {
2001:                    throw new BeanClassNamesErrorException(beanClass, e);
2002:                }
2003:            }
2004:
2005:            String[] getOutput(String name) throws EngineException {
2006:                mElementInfo.validateOutputName(name);
2007:
2008:                return mOutputs.aggregateValues().get(name);
2009:            }
2010:
2011:            private Set<Map.Entry<String, String>> getIncookieEntries() {
2012:                return getCookieValues().entrySet();
2013:            }
2014:
2015:            boolean hasCookie(String name) throws EngineException {
2016:                assert name != null;
2017:                assert name.length() > 0;
2018:
2019:                mElementInfo.validateIncookieName(name);
2020:
2021:                return mRequestState.hasCookie(name)
2022:                        || mElementInfo.hasIncookieDefaultValue(name)
2023:                        || mElementInfo.hasGlobalCookieDefaultValue(name);
2024:            }
2025:
2026:            Cookie getCookie(String name) throws EngineException {
2027:                assert name != null;
2028:                assert name.length() > 0;
2029:
2030:                mElementInfo.validateIncookieName(name);
2031:
2032:                Cookie cookie = mRequestState.getCookie(name);
2033:                if (null == cookie) {
2034:                    if (mElementInfo.hasIncookieDefaultValue(name)) {
2035:                        cookie = new Cookie(name, mElementInfo
2036:                                .getIncookieDefaultValue(name));
2037:                    }
2038:
2039:                    if (mElementInfo.hasGlobalCookieDefaultValue(name)) {
2040:                        cookie = new Cookie(name, mElementInfo
2041:                                .getGlobalCookieDefaultValue(name));
2042:                    }
2043:                }
2044:
2045:                return cookie;
2046:            }
2047:
2048:            String getCookieValue(String name) throws EngineException {
2049:                Cookie cookie = getCookie(name);
2050:                String value = null;
2051:                if (cookie != null) {
2052:                    value = cookie.getValue();
2053:                }
2054:
2055:                return value;
2056:            }
2057:
2058:            void setCookie(Cookie cookie) throws EngineException {
2059:                assert cookie != null;
2060:                assert cookie.getName() != null;
2061:
2062:                mElementInfo.validateOutcookieName(cookie.getName());
2063:
2064:                mOutcookies.put(cookie.getName(), cookie.getValue());
2065:                setCookieRaw(cookie);
2066:
2067:                if (mElementState.inInheritanceStructure()
2068:                        && mElementInfo.containsChildTrigger(cookie.getName())) {
2069:                    triggerChild(cookie.getName(), new String[] { cookie
2070:                            .getValue() });
2071:                }
2072:            }
2073:
2074:            void setCookieRaw(Cookie cookie) {
2075:                mResponse.addCookie(cookie);
2076:                mRequestState.setStateCookie(cookie);
2077:                fireOutcookieSet(cookie);
2078:            }
2079:
2080:            HashMap<String, String> getCookieValues() throws EngineException {
2081:                HashMap<String, String> result = new HashMap<String, String>();
2082:
2083:                for (Map.Entry<String, String> entry : mElementInfo
2084:                        .getDefaultIncookies().entrySet()) {
2085:                    result.put(entry.getKey(), entry.getValue());
2086:                }
2087:
2088:                for (Map.Entry<String, String> entry : mElementInfo
2089:                        .getDefaultGlobalCookies().entrySet()) {
2090:                    result.put(entry.getKey(), entry.getValue());
2091:                }
2092:
2093:                for (Map.Entry<String, Cookie> entry : mRequestState
2094:                        .getCookies().entrySet()) {
2095:                    result.put(entry.getKey(), entry.getValue().getValue());
2096:                }
2097:
2098:                return result;
2099:            }
2100:
2101:            boolean hasParameterValue(String name) throws EngineException {
2102:                assert name != null;
2103:                assert name.length() > 0;
2104:
2105:                validateParameter(name);
2106:
2107:                String submission = getSubmission();
2108:                if (null == submission) {
2109:                    return false;
2110:                }
2111:
2112:                return mElementState.hasRequestParameterValue(name)
2113:                        || mElementInfo.hasParameterDefaultValues(submission,
2114:                                name);
2115:            }
2116:
2117:            boolean isParameterEmpty(String name) throws EngineException {
2118:                assert name != null;
2119:                assert name.length() > 0;
2120:
2121:                String parameter = getParameter(name);
2122:                if (null == parameter || parameter.trim().equals("")) {
2123:                    return true;
2124:                }
2125:                return false;
2126:            }
2127:
2128:            String getParameter(String name) throws EngineException {
2129:                assert name != null;
2130:                assert name.length() > 0;
2131:
2132:                validateParameter(name);
2133:
2134:                String submission = getSubmission();
2135:                if (null == submission) {
2136:                    return null;
2137:                }
2138:
2139:                String parameter = mElementState.getRequestParameter(name);
2140:
2141:                if (null == parameter
2142:                        && mElementInfo.hasParameterDefaults(submission)) {
2143:                    String[] default_values = mElementInfo
2144:                            .getParameterDefaultValues(submission, name);
2145:                    if (default_values != null) {
2146:                        return default_values[0];
2147:                    }
2148:                }
2149:
2150:                return parameter;
2151:            }
2152:
2153:            ArrayList<String> getParameterNames(String regexp)
2154:                    throws EngineException {
2155:                Pattern pattern = null;
2156:                if (regexp != null) {
2157:                    pattern = Pattern.compile("^" + regexp + "$");
2158:                }
2159:
2160:                ArrayList<String> result = new ArrayList<String>();
2161:                String submission_name = getSubmission();
2162:                if (null == submission_name) {
2163:                    return result;
2164:                }
2165:
2166:                Submission submission = mElementInfo
2167:                        .getSubmission(submission_name);
2168:                if (null == submission) {
2169:                    return result;
2170:                }
2171:
2172:                Collection<String> parameter_names = null;
2173:
2174:                // add all default parameters that match
2175:                parameter_names = submission.getParameterDefaultNames();
2176:                for (String parameter_name : parameter_names) {
2177:                    if (null == pattern
2178:                            || pattern.matcher(parameter_name).matches()) {
2179:                        result.add(parameter_name);
2180:                    }
2181:                }
2182:
2183:                // go over the possible parameters and check if they have values in the request
2184:                parameter_names = submission.getParameterNames();
2185:                for (String parameter_name : parameter_names) {
2186:                    if (mElementState.hasRequestParameterValue(parameter_name)
2187:                            && !result.contains(parameter_name)
2188:                            && (null == pattern || pattern.matcher(
2189:                                    parameter_name).matches())) {
2190:                        result.add(parameter_name);
2191:                    }
2192:                }
2193:
2194:                // go over all the parameter regexps and find those that match with the parameters in the request
2195:                Matcher matcher = null;
2196:                for (Pattern parameter_regexp : submission
2197:                        .getParameterRegexps()) {
2198:                    for (String parameter_name : mElementState
2199:                            .getRequestParameterNames()) {
2200:                        matcher = parameter_regexp.matcher(parameter_name);
2201:                        if (matcher.matches()) {
2202:                            if (mElementState
2203:                                    .hasRequestParameterValue(parameter_name)
2204:                                    && !result.contains(parameter_name)
2205:                                    && (null == pattern || pattern.matcher(
2206:                                            parameter_name).matches())) {
2207:                                result.add(parameter_name);
2208:                            }
2209:                        }
2210:                    }
2211:
2212:                }
2213:
2214:                return result;
2215:            }
2216:
2217:            String[] getParameterValues(String name) throws EngineException {
2218:                assert name != null;
2219:                assert name.length() > 0;
2220:
2221:                validateParameter(name);
2222:
2223:                String submission = getSubmission();
2224:                if (null == submission) {
2225:                    return null;
2226:                }
2227:
2228:                String[] parameter_values = mElementState
2229:                        .getRequestParameterValues(name);
2230:                if (null == parameter_values
2231:                        && mElementInfo.hasParameterDefaults(submission)) {
2232:                    return mElementInfo.getParameterDefaultValues(submission,
2233:                            name);
2234:                }
2235:
2236:                return parameter_values;
2237:            }
2238:
2239:            ArrayList<String> getUploadedFileNames(String regexp)
2240:                    throws EngineException {
2241:                Pattern pattern = null;
2242:                if (regexp != null) {
2243:                    pattern = Pattern.compile("^" + regexp + "$");
2244:                }
2245:
2246:                ArrayList<String> result = new ArrayList<String>();
2247:                String submission_name = getSubmission();
2248:                if (null == submission_name) {
2249:                    return result;
2250:                }
2251:
2252:                Submission submission = mElementInfo
2253:                        .getSubmission(submission_name);
2254:                if (null == submission) {
2255:                    return result;
2256:                }
2257:
2258:                Collection<String> file_names = null;
2259:
2260:                // go over the possible files and check if they have values in the request
2261:                file_names = submission.getFileNames();
2262:                for (String file_name : file_names) {
2263:                    if (mRequestState.hasUploadedFile(file_name)
2264:                            && !result.contains(file_name)
2265:                            && (null == pattern || pattern.matcher(file_name)
2266:                                    .matches())) {
2267:                        result.add(file_name);
2268:                    }
2269:                }
2270:
2271:                // go over all the file regexps and find those that match with the files in the request
2272:                Matcher matcher = null;
2273:                for (Pattern file_regexp : submission.getFileRegexps()) {
2274:                    for (String file_name : mRequestState
2275:                            .getUploadedFileNames()) {
2276:                        matcher = file_regexp.matcher(file_name);
2277:                        if (matcher.matches()) {
2278:                            if (mRequestState.hasUploadedFile(file_name)
2279:                                    && !result.contains(file_name)
2280:                                    && (null == pattern || pattern.matcher(
2281:                                            file_name).matches())) {
2282:                                result.add(file_name);
2283:                            }
2284:                        }
2285:                    }
2286:
2287:                }
2288:
2289:                return result;
2290:            }
2291:
2292:            ArrayList<String> getUploadedFileNames() throws EngineException {
2293:                ArrayList<String> result = new ArrayList<String>();
2294:                String submission_name = getSubmission();
2295:                if (null == submission_name) {
2296:                    return result;
2297:                }
2298:
2299:                Submission submission = mElementInfo
2300:                        .getSubmission(submission_name);
2301:                if (null == submission) {
2302:                    return result;
2303:                }
2304:
2305:                Collection<String> file_names = submission.getFileNames();
2306:                for (String file_name : file_names) {
2307:                    if (mRequestState.hasUploadedFile(file_name)) {
2308:                        result.add(file_name);
2309:                    }
2310:                }
2311:
2312:                return result;
2313:            }
2314:
2315:            boolean hasUploadedFile(String name) throws EngineException {
2316:                assert name != null;
2317:                assert name.length() > 0;
2318:
2319:                validateFile(name);
2320:
2321:                String submission = getSubmission();
2322:                if (null == submission) {
2323:                    return false;
2324:                }
2325:
2326:                return mRequestState.hasUploadedFile(name);
2327:            }
2328:
2329:            boolean isFileEmpty(String name) throws EngineException {
2330:                assert name != null;
2331:                assert name.length() > 0;
2332:
2333:                UploadedFile file = getUploadedFile(name);
2334:                return null == file || null == file.getFile()
2335:                        || 0 == file.getFile().length();
2336:            }
2337:
2338:            UploadedFile getUploadedFile(String name) throws EngineException {
2339:                assert name != null;
2340:                assert name.length() > 0;
2341:
2342:                validateFile(name);
2343:
2344:                String submission = getSubmission();
2345:                if (null == submission) {
2346:                    return null;
2347:                }
2348:
2349:                return mRequestState.getUploadedFile(name);
2350:            }
2351:
2352:            UploadedFile[] getUploadedFiles(String name) throws EngineException {
2353:                assert name != null;
2354:                assert name.length() > 0;
2355:
2356:                validateFile(name);
2357:
2358:                String submission = getSubmission();
2359:                if (null == submission) {
2360:                    return null;
2361:                }
2362:
2363:                return mRequestState.getUploadedFiles(name);
2364:            }
2365:
2366:            void setOutputValues(String name, String[] values) {
2367:                assert name != null;
2368:                assert name.length() > 0;
2369:                assert values != null;
2370:
2371:                mOutputs.put(name, values);
2372:                fireOutputValueSet(name, values);
2373:            }
2374:
2375:            void setAutomatedOutputValues(String name, String[] values) {
2376:                mOutputs.putFallback(name, values);
2377:
2378:                fireAutomatedOutputValueSet(name, values);
2379:            }
2380:
2381:            void clearOutputValue(String name) {
2382:                assert name != null;
2383:                assert name.length() > 0;
2384:
2385:                // clearing the output value instead of removing it, this prevents
2386:                // later automated processing to fill it in again
2387:                mOutputs.put(name, null);
2388:                fireOutputValueCleared(name);
2389:            }
2390:
2391:            void clearAutomatedOutputValue(String name) {
2392:                // clearing the output value instead of removing it, this prevents
2393:                // later automated processing to fill it in again
2394:                mOutputs.putFallback(name, null);
2395:                fireAutomatedOutputValueCleared(name);
2396:            }
2397:
2398:            void addOutputListener(OutputListener listener) {
2399:                if (null == mOutputListeners) {
2400:                    mOutputListeners = new ArrayList<OutputListener>();
2401:                }
2402:
2403:                mOutputListeners.add(listener);
2404:            }
2405:
2406:            void removeOutputListener(OutputListener listener) {
2407:                mOutputListeners.remove(listener);
2408:            }
2409:
2410:            void fireOutputValueSet(String name, String[] values) {
2411:                if (null == mOutputListeners) {
2412:                    return;
2413:                }
2414:
2415:                for (OutputListener listener : mOutputListeners) {
2416:                    listener.outputValueSet(name, values);
2417:                }
2418:            }
2419:
2420:            void fireOutputValueCleared(String name) {
2421:                if (null == mOutputListeners) {
2422:                    return;
2423:                }
2424:
2425:                for (OutputListener listener : mOutputListeners) {
2426:                    listener.outputValueCleared(name);
2427:                }
2428:            }
2429:
2430:            void fireAutomatedOutputValueSet(String name, String[] values) {
2431:                if (null == mOutputListeners) {
2432:                    return;
2433:                }
2434:
2435:                for (OutputListener listener : mOutputListeners) {
2436:                    listener.automatedOutputValueSet(name, values);
2437:                }
2438:            }
2439:
2440:            void fireAutomatedOutputValueCleared(String name) {
2441:                if (null == mOutputListeners) {
2442:                    return;
2443:                }
2444:
2445:                for (OutputListener listener : mOutputListeners) {
2446:                    listener.automatedOutputValueCleared(name);
2447:                }
2448:            }
2449:
2450:            void addOutcookieListener(OutcookieListener listener) {
2451:                if (null == mOutcookieListeners) {
2452:                    mOutcookieListeners = new ArrayList<OutcookieListener>();
2453:                }
2454:
2455:                mOutcookieListeners.add(listener);
2456:            }
2457:
2458:            void removeOutcookieListener(OutcookieListener listener) {
2459:                mOutcookieListeners.remove(listener);
2460:            }
2461:
2462:            void fireOutcookieSet(Cookie cookie) {
2463:                if (null == mOutcookieListeners) {
2464:                    return;
2465:                }
2466:
2467:                for (OutcookieListener listener : mOutcookieListeners) {
2468:                    listener.outcookieSet(cookie);
2469:                }
2470:            }
2471:
2472:            void child() throws EngineException {
2473:                throw new ChildTriggeredException(null, null);
2474:            }
2475:
2476:            void defer() throws EngineException {
2477:                throw new DeferException();
2478:            }
2479:
2480:            void forward(String url) throws EngineException {
2481:                throw new ForwardException(url);
2482:            }
2483:
2484:            void redirect(String url) {
2485:                throw new RedirectException(url);
2486:            }
2487:
2488:            boolean duringStepBack() {
2489:                return mSteppedBack;
2490:            }
2491:
2492:            void exit(String name) throws EngineException {
2493:                assert name != null;
2494:                assert name.length() > 0;
2495:
2496:                mElementInfo.validateExitName(name);
2497:
2498:                throw new ExitTriggeredException(name);
2499:            }
2500:
2501:            /**
2502:             * Retrieves the inputs values that a child receives when the parent
2503:             * delegates the control flow to it. This is based on the current output
2504:             * values of the parent element, combined with the global variables
2505:             */
2506:            private Map<String, String[]> getChildInputValues(
2507:                    ElementInfo targetElement) {
2508:                Map<String, String[]> inputs = null;
2509:
2510:                inputs = mElementState.getTriggerInputs();
2511:
2512:                if (null == inputs) {
2513:                    inputs = mElementState.getRequestParameters();
2514:                }
2515:
2516:                if (mElementInfo.hasGlobalVars()
2517:                        && targetElement.hasGlobalVars()) {
2518:                    String[] input_values_array = null;
2519:
2520:                    for (Map.Entry<String, String[]> output_entry : mOutputs
2521:                            .aggregateValues().entrySet()) {
2522:                        // create automatic data link for global variables
2523:                        if (mElementInfo.containsGlobalVar(output_entry
2524:                                .getKey())
2525:                                && targetElement.containsGlobalVar(output_entry
2526:                                        .getKey())) {
2527:                            input_values_array = output_entry.getValue();
2528:                            inputs.put(output_entry.getKey(),
2529:                                    input_values_array);
2530:                        }
2531:                    }
2532:                }
2533:
2534:                return inputs;
2535:            }
2536:
2537:            /**
2538:             * Retrieves the inputs values that an exit receives when it is
2539:             * followed. This is based on the current output values of the
2540:             * active element.
2541:             */
2542:            private HashMap<String, String[]> getExitInputValues(
2543:                    FlowLink flowLink,
2544:                    Set<Map.Entry<String, String[]>> outputEntries,
2545:                    ElementInfo target, boolean snapback)
2546:                    throws EngineException {
2547:                HashMap<String, String[]> inputs = new HashMap<String, String[]>();
2548:
2549:                // preserve the embedding element's inputs and global vars
2550:                if (target.getId().equals(mElementInfo.getId())) {
2551:                    ElementContext context = this ;
2552:                    while (context != null
2553:                            && context.mRequestState.isEmbedded()) {
2554:                        context = context.mRequestState.getEmbeddingContext()
2555:                                .getElementContext();
2556:                        for (String input_name : context.mElementInfo
2557:                                .getInputNames()) {
2558:                            if (context.mElementState.hasInputValue(input_name)) {
2559:                                inputs.put(input_name, context.mElementState
2560:                                        .getInputValues(input_name));
2561:                            }
2562:                        }
2563:                        for (String globalvar_name : context.mElementInfo
2564:                                .getGlobalVarNames()) {
2565:                            if (context.mElementState
2566:                                    .hasInputValue(globalvar_name)) {
2567:                                inputs
2568:                                        .put(
2569:                                                globalvar_name,
2570:                                                context.mElementState
2571:                                                        .getInputValues(globalvar_name));
2572:                            }
2573:                        }
2574:                    }
2575:                }
2576:
2577:                if (mElementInfo.hasSnapbackDataLinks()
2578:                        || mElementInfo.hasDataLink(target)
2579:                        || (mElementInfo.hasGlobalVars() && target
2580:                                .hasGlobalVars())) {
2581:                    HashMap<String, String[]> dest_input_candidates = new HashMap<String, String[]>();
2582:
2583:                    // if the exit is reflective, preserve the input values that have
2584:                    // identically named output values
2585:                    if (target == mElementInfo) {
2586:                        Collection<String> input_names = mElementInfo
2587:                                .getInputNames();
2588:                        Collection<String> output_names = mElementInfo
2589:                                .getOutputNames();
2590:                        Iterator<String> input_names_it = input_names
2591:                                .iterator();
2592:                        String input_name = null;
2593:                        String[] input_values = null;
2594:                        while (input_names_it.hasNext()) {
2595:                            input_name = input_names_it.next();
2596:
2597:                            if (output_names.contains(input_name)) {
2598:                                input_values = getInputValues(input_name);
2599:                                if (input_values != null) {
2600:                                    dest_input_candidates.put(input_name,
2601:                                            input_values);
2602:                                }
2603:                            }
2604:                        }
2605:                    }
2606:
2607:                    // add the global default values
2608:                    GlobalVar globalvar_data = null;
2609:
2610:                    for (Map.Entry<String, GlobalVar> globalvar_entry : mElementInfo
2611:                            .getGlobalVarEntries()) {
2612:                        globalvar_data = globalvar_entry.getValue();
2613:                        if (globalvar_data != null
2614:                                && globalvar_data.getDefaultValues() != null) {
2615:                            dest_input_candidates.put(globalvar_entry.getKey(),
2616:                                    globalvar_data.getDefaultValues());
2617:                        }
2618:                    }
2619:
2620:                    // add the output values
2621:                    String[] output_values_array = null;
2622:
2623:                    for (Map.Entry<String, String[]> output_entry : outputEntries) {
2624:                        output_values_array = output_entry.getValue();
2625:                        dest_input_candidates.put(output_entry.getKey(),
2626:                                output_values_array);
2627:                    }
2628:
2629:                    // process the exit input value candidates
2630:                    Collection<String> dest_input_names = null;
2631:
2632:                    GlobalVar globalvar_source = null;
2633:                    GlobalVar globalvar_target = null;
2634:
2635:                    for (String candidate : dest_input_candidates.keySet()) {
2636:                        if (!mElementInfo.containsDepartureVar(candidate)) {
2637:                            // create automatic data link for global variables
2638:                            if (mElementInfo.containsGlobalVar(candidate)
2639:                                    && target.containsGlobalVar(candidate)) {
2640:                                globalvar_source = mElementInfo
2641:                                        .getGlobalVarInfo(candidate);
2642:                                globalvar_target = target
2643:                                        .getGlobalVarInfo(candidate);
2644:
2645:                                // only create the link if the global vars are in the
2646:                                // same group scope
2647:                                if (globalvar_source.getGroupId() == globalvar_target
2648:                                        .getGroupId()) {
2649:                                    inputs.put(candidate, dest_input_candidates
2650:                                            .get(candidate));
2651:                                }
2652:                            }
2653:
2654:                            // translate outputs to inputs through a possible data link
2655:                            dest_input_names = mElementInfo.getDataLinkInputs(
2656:                                    candidate, target, snapback, flowLink);
2657:                            if (dest_input_names != null) {
2658:                                for (String dest_input_name : dest_input_names) {
2659:                                    inputs.put(dest_input_name,
2660:                                            dest_input_candidates
2661:                                                    .get(candidate));
2662:                                }
2663:                            }
2664:                        }
2665:                    }
2666:                }
2667:
2668:                return inputs;
2669:            }
2670:
2671:            private void appendTargetAndPathinfo(StringBuilder url,
2672:                    String targetUrl, String pathinfo) {
2673:                url.append(targetUrl);
2674:
2675:                // append the optional pathinfo
2676:                if (pathinfo != null && pathinfo.length() > 0) {
2677:                    // ensure that the pathinfo is prefixed with a /
2678:                    if (url.charAt(url.length() - 1) != '/') {
2679:                        url.append("/");
2680:                    }
2681:                    url.append(StringUtils.stripFromFront(pathinfo, "/"));
2682:                }
2683:            }
2684:
2685:            private String getExitUrl(FlowLink flowlink, String pathInfo)
2686:                    throws EngineException {
2687:                assert flowlink != null;
2688:
2689:                String url = null;
2690:                String pathinfo = null;
2691:
2692:                // obtain the declared flowlink target element and determine what the
2693:                // actual target element is according to the inheritance status
2694:                ElementInfo flowlink_target = flowlink
2695:                        .getExitTarget(mRequestState);
2696:                ElementInfo context_target = null;
2697:                if (mElementState.inInheritanceStructure()
2698:                        && !flowlink.cancelInheritance()) {
2699:                    context_target = mRequestState.getTarget();
2700:                } else {
2701:                    context_target = flowlink_target;
2702:                }
2703:                url = context_target.getUrl();
2704:
2705:                // if the element defined no url and the flowlink target points to the element
2706:                // itself when it's embedded, go up the hierarchy of embedded elements
2707:                // to grab the first defined element url
2708:                if (null == url) {
2709:                    if (!mRequestState.isEmbedded()
2710:                            && !flowlink_target.getId().equals(
2711:                                    mElementInfo.getId())) {
2712:                        throw new ExitTargetUrlMissingException(mElementInfo
2713:                                .getDeclarationName(), flowlink.getExitName(),
2714:                                context_target.getDeclarationName());
2715:                    }
2716:
2717:                    ElementContext context = this ;
2718:                    while (null == url && context != null
2719:                            && context.mRequestState.isEmbedded()) {
2720:                        context = context.mRequestState.getEmbeddingContext()
2721:                                .getElementContext();
2722:                        if (context.getElementInfo().isPathInfoUsed()) {
2723:                            pathinfo = context.mRequestState.getElementState()
2724:                                    .getPathInfo();
2725:                        } else {
2726:                            pathinfo = null;
2727:                        }
2728:                        if (context.mElementState.inInheritanceStructure()) {
2729:                            url = context.mRequestState.getTarget().getUrl();
2730:                        } else {
2731:                            url = context.mElementInfo.getUrl();
2732:                        }
2733:                    }
2734:                }
2735:
2736:                // apply a forced pathinfo
2737:                if (pathInfo != null && pathInfo.length() > 0) {
2738:                    pathinfo = pathInfo;
2739:                }
2740:
2741:                // construct the correct servlet path and url that points to the
2742:                // target child element, or the current element if there are no children
2743:                StringBuilder url_buffer = new StringBuilder(mRequestState
2744:                        .getGateUrl());
2745:                appendTargetAndPathinfo(url_buffer, url, pathinfo);
2746:                return url_buffer.toString();
2747:            }
2748:
2749:            private Map<String, String[]> overrideOutputValues(
2750:                    Map<String, String[]> outputValueMap, String[] outputValues)
2751:                    throws EngineException {
2752:                if (null == outputValues || 0 == outputValues.length) {
2753:                    return outputValueMap;
2754:                }
2755:
2756:                Map<String, String[]> outputs = new HashMap<String, String[]>(
2757:                        outputValueMap);
2758:                // store the output overrides
2759:                for (int i = 0; i < outputValues.length; i += 2) {
2760:                    outputs.put(outputValues[i],
2761:                            new String[] { outputValues[i + 1] });
2762:                }
2763:
2764:                return outputs;
2765:            }
2766:
2767:            private Map<String, String[]> getExitInputValues(FlowLink flowLink,
2768:                    ElementInfo target, boolean snapback,
2769:                    Map<String, String[]> outputValueMap, String[] outputValues)
2770:                    throws EngineException {
2771:                // override current output values
2772:                Map<String, String[]> overridden_outputs = overrideOutputValues(
2773:                        outputValueMap, outputValues);
2774:
2775:                // construct the exit input parameters
2776:                return getExitInputValues(flowLink, overridden_outputs
2777:                        .entrySet(), target, snapback);
2778:            }
2779:
2780:            private FlowState _getExitParameters(FlowLink flowlink,
2781:                    ElementInfo contextTarget,
2782:                    Map<String, String[]> outputValueMap, String[] outputValues) {
2783:                FlowState state = new FlowState();
2784:
2785:                // construct the exit input parameters
2786:                Map<String, String[]> inputs = getExitInputValues(flowlink,
2787:                        flowlink.getTarget(), flowlink.isSnapback(),
2788:                        outputValueMap, outputValues);
2789:
2790:                // Create or preserve the request parameters that were initially send to the child element
2791:                // this permits completely seperate processing of any other parameters.
2792:                // Maintain a stack of successful parent elements.
2793:                if (mElementState.inInheritanceStructure()
2794:                        && !flowlink.cancelInheritance()) {
2795:                    state.putParameter(ReservedParameters.CHILDREQUEST,
2796:                            getEncodedChildRequest());
2797:
2798:                    // preserve the trigger list
2799:                    List<TriggerContext> new_trigger_context = mElementState
2800:                            .cloneTriggerList();
2801:                    new_trigger_context.add(TriggerContext.generateExitTrigger(
2802:                            mElementInfo, flowlink.getExitName(), inputs));
2803:
2804:                    state.putParameter(ReservedParameters.TRIGGERLIST,
2805:                            TriggerListEncoder.encode(new_trigger_context));
2806:                } else {
2807:                    // construct the exit input parameters
2808:                    state.setParameters(inputs);
2809:                }
2810:
2811:                if (!flowlink.cancelContinuations()) {
2812:                    // Preserve the continuation id if a continuation context is active
2813:                    // and the exit goes back to the same element
2814:                    if (mElementInfo == flowlink.getTarget()) {
2815:                        String continuation_id = ContinuationContext
2816:                                .getActiveContextId();
2817:                        if (continuation_id != null) {
2818:                            state.putParameter(ReservedParameters.CONTID,
2819:                                    continuation_id);
2820:                        }
2821:                    }
2822:                }
2823:
2824:                return state;
2825:            }
2826:
2827:            CharSequenceDeferred getExitFormUrl(String name, String pathinfo)
2828:                    throws EngineException {
2829:                assert name != null;
2830:                assert name.length() > 0;
2831:
2832:                mElementInfo.validateExitName(name);
2833:
2834:                FlowLink flowlink = null;
2835:                flowlink = mElementInfo.getFlowLink(name);
2836:                if (null == flowlink) {
2837:                    throw new ExitNotAttachedException(mElement
2838:                            .getElementInfo().getDeclarationName(), name);
2839:                }
2840:
2841:                return _getExitFormUrl(flowlink, pathinfo, mOutputs
2842:                        .aggregateValues());
2843:            }
2844:
2845:            private CharSequenceDeferred _getExitFormUrl(FlowLink flowlink,
2846:                    String pathinfo, Map<String, String[]> outputValueMap)
2847:                    throws EngineException {
2848:                assert flowlink != null;
2849:
2850:                ElementInfo flowlink_target = flowlink
2851:                        .getExitTarget(mRequestState);
2852:
2853:                StateStore state_store = flowlink_target.getStateStore();
2854:
2855:                // process the pathinfo mappings
2856:                if (null == pathinfo && flowlink_target.isPathInfoUsed()) {
2857:                    FlowState state = _getExitParameters(flowlink,
2858:                            flowlink_target, outputValueMap, null);
2859:                    pathinfo = handlePathInfoMapping(flowlink_target, state,
2860:                            pathinfo);
2861:                }
2862:
2863:                return new CharSequenceFormUrl(state_store, getExitUrl(
2864:                        flowlink, pathinfo));
2865:            }
2866:
2867:            CharSequenceDeferred getExitFormParameters(String name,
2868:                    String[] outputValues) throws EngineException {
2869:                assert name != null;
2870:                assert name.length() > 0;
2871:                assert outputValues == null || outputValues.length % 2 == 0;
2872:
2873:                mElementInfo.validateExitName(name);
2874:
2875:                FlowLink flowlink = null;
2876:                flowlink = mElementInfo.getFlowLink(name);
2877:                if (null == flowlink) {
2878:                    throw new ExitNotAttachedException(mElement
2879:                            .getElementInfo().getDeclarationName(), name);
2880:                }
2881:
2882:                return _getExitFormParameters(flowlink, mOutputs
2883:                        .aggregateValues(), outputValues);
2884:            }
2885:
2886:            CharSequenceDeferred getExitFormParametersJavascript(String name,
2887:                    String[] outputValues) throws EngineException {
2888:                assert name != null;
2889:                assert name.length() > 0;
2890:                assert outputValues == null || outputValues.length % 2 == 0;
2891:
2892:                mElementInfo.validateExitName(name);
2893:
2894:                FlowLink flowlink = null;
2895:                flowlink = mElementInfo.getFlowLink(name);
2896:                if (null == flowlink) {
2897:                    throw new ExitNotAttachedException(mElement
2898:                            .getElementInfo().getDeclarationName(), name);
2899:                }
2900:
2901:                return _getExitFormParametersJavascript(flowlink, mOutputs
2902:                        .aggregateValues(), outputValues);
2903:            }
2904:
2905:            private CharSequenceDeferred _getExitFormParameters(
2906:                    FlowLink flowlink, Map<String, String[]> outputValueMap,
2907:                    String[] outputValues) throws EngineException {
2908:                assert flowlink != null;
2909:
2910:                ElementInfo flowlink_target = flowlink
2911:                        .getExitTarget(mRequestState);
2912:                FlowState state = _getExitParameters(flowlink, flowlink_target,
2913:                        outputValueMap, outputValues);
2914:                return new CharSequenceFormState(flowlink_target
2915:                        .getStateStore(), state, FormStateType.PARAMS);
2916:            }
2917:
2918:            private CharSequenceDeferred _getExitFormParametersJavascript(
2919:                    FlowLink flowlink, Map<String, String[]> outputValueMap,
2920:                    String[] outputValues) throws EngineException {
2921:                assert flowlink != null;
2922:
2923:                ElementInfo flowlink_target = flowlink
2924:                        .getExitTarget(mRequestState);
2925:                FlowState state = _getExitParameters(flowlink, flowlink_target,
2926:                        outputValueMap, outputValues);
2927:                return new CharSequenceFormState(flowlink_target
2928:                        .getStateStore(), state, FormStateType.JAVASCRIPT);
2929:            }
2930:
2931:            CharSequenceDeferred getExitQueryUrl(String name, String pathinfo,
2932:                    String[] outputValues) throws EngineException {
2933:                assert name != null;
2934:                assert name.length() > 0;
2935:                assert outputValues == null || outputValues.length % 2 == 0;
2936:
2937:                mElementInfo.validateExitName(name);
2938:
2939:                FlowLink flowlink = null;
2940:                flowlink = mElementInfo.getFlowLink(name);
2941:                if (null == flowlink) {
2942:                    throw new ExitNotAttachedException(mElement
2943:                            .getElementInfo().getDeclarationName(), name);
2944:                }
2945:
2946:                return _getExitQueryUrl(flowlink, pathinfo, mOutputs
2947:                        .aggregateValues(), outputValues);
2948:            }
2949:
2950:            private CharSequenceDeferred _getExitQueryUrl(FlowLink flowlink,
2951:                    String pathinfo, Map<String, String[]> outputValueMap,
2952:                    String[] outputValues) throws EngineException {
2953:                assert flowlink != null;
2954:
2955:                ElementInfo flowlink_target = flowlink
2956:                        .getExitTarget(mRequestState);
2957:
2958:                // process the exit url query parameters
2959:                StateStore state_store = flowlink_target.getStateStore();
2960:                FlowState state = _getExitParameters(flowlink, flowlink_target,
2961:                        outputValueMap, outputValues);
2962:
2963:                // process the pathinfo mappings
2964:                if (null == pathinfo && flowlink_target.isPathInfoUsed()) {
2965:                    pathinfo = handlePathInfoMapping(flowlink_target, state,
2966:                            pathinfo);
2967:                }
2968:
2969:                return new CharSequenceQueryUrl(state_store, getExitUrl(
2970:                        flowlink, pathinfo), state, mElementInfo, "exit",
2971:                        flowlink.getExitName());
2972:            }
2973:
2974:            private String handlePathInfoMapping(ElementInfo flowlinkTarget,
2975:                    FlowState state, String pathinfo) {
2976:                Map<String, String[]> parameters = state.getParameters();
2977:
2978:                mapping: for (PathInfoMapping mapping : flowlinkTarget
2979:                        .getPathInfoMappings()) {
2980:                    if (parameters.keySet().containsAll(mapping.getInputs())) {
2981:                        Iterator<String> inputs_it = mapping.getInputs()
2982:                                .iterator();
2983:
2984:                        StringBuilder builder = new StringBuilder();
2985:                        String input_name;
2986:                        String[] input_value;
2987:                        for (PathInfoMappingSegment segment : mapping
2988:                                .getSegments()) {
2989:                            if (segment.isRegexp()) {
2990:                                if (!inputs_it.hasNext()) {
2991:                                    continue mapping;
2992:                                }
2993:
2994:                                input_name = inputs_it.next();
2995:
2996:                                // ensure that the input has only got one value
2997:                                input_value = parameters.get(input_name);
2998:                                if (null == input_value
2999:                                        || input_value.length != 1) {
3000:                                    continue mapping;
3001:                                }
3002:
3003:                                // ensure that the input value corresponds to the
3004:                                // regexp pattern for it
3005:                                Matcher matcher = segment.getPattern().matcher(
3006:                                        input_value[0]);
3007:                                if (!matcher.matches()) {
3008:                                    continue mapping;
3009:                                }
3010:
3011:                                // add the url-encoded input value to the pathinfo
3012:                                builder.append(StringUtils
3013:                                        .encodeUrl(input_value[0]));
3014:                            } else {
3015:                                builder.append(segment.getValue());
3016:                            }
3017:                        }
3018:
3019:                        // remove the input parameters that are handled by the pathinfo
3020:                        for (String input : mapping.getInputs()) {
3021:                            parameters.remove(input);
3022:                        }
3023:
3024:                        // build the new pathinfo
3025:                        return builder.toString();
3026:                    }
3027:                }
3028:
3029:                return null;
3030:            }
3031:
3032:            void setExitQuery(Template template, String name, String pathinfo,
3033:                    String[] outputValues) throws TemplateException,
3034:                    EngineException {
3035:                template.setValue(PREFIX_EXIT_QUERY + name, getExitQueryUrl(
3036:                        name, pathinfo, outputValues).encoder(
3037:                        EncoderHtml.getInstance()));
3038:            }
3039:
3040:            void setExitForm(Template template, String name, String pathinfo,
3041:                    String[] outputValues) throws TemplateException,
3042:                    EngineException {
3043:                template.setValue(PREFIX_EXIT_FORM + name, getExitFormUrl(name,
3044:                        pathinfo).encoder(EncoderHtml.getInstance()));
3045:                String exit_javascript = PREFIX_EXIT_PARAMSJS + name;
3046:                if (template.hasValueId(exit_javascript)) {
3047:                    template.setValue(exit_javascript, getExitFormParameters(
3048:                            name, outputValues));
3049:                } else {
3050:                    template.setValue(PREFIX_EXIT_PARAMS + name,
3051:                            getExitFormParameters(name, outputValues));
3052:                }
3053:            }
3054:
3055:            Collection<String> selectParameter(Template template, String name,
3056:                    String[] values) {
3057:                assert name != null;
3058:                assert name.length() > 0;
3059:
3060:                BeanHandler bean_handler = template.getBeanHandler();
3061:                if (null == bean_handler) {
3062:                    return Collections.EMPTY_LIST;
3063:                }
3064:                FormBuilder form_builder = bean_handler.getFormBuilder();
3065:                if (null == form_builder) {
3066:                    return Collections.EMPTY_LIST;
3067:                }
3068:
3069:                return form_builder.selectParameter(template, name, values);
3070:            }
3071:
3072:            void generateForm(Template template, Object beanInstance,
3073:                    String prefix) throws EngineException {
3074:                BeanHandler bean_handler = template.getBeanHandler();
3075:                if (null == bean_handler) {
3076:                    return;
3077:                }
3078:                FormBuilder form_builder = bean_handler.getFormBuilder();
3079:                if (null == form_builder) {
3080:                    return;
3081:                }
3082:                try {
3083:                    form_builder.removeForm(template, beanInstance.getClass(),
3084:                            prefix);
3085:                    form_builder.generateForm(template, beanInstance, null,
3086:                            prefix);
3087:                } catch (BeanUtilsException e) {
3088:                    throw new EngineException(e);
3089:                }
3090:            }
3091:
3092:            void generateEmptyForm(Template template, Class beanClass,
3093:                    String prefix) throws EngineException {
3094:                BeanHandler bean_handler = template.getBeanHandler();
3095:                if (null == bean_handler) {
3096:                    return;
3097:                }
3098:                FormBuilder form_builder = bean_handler.getFormBuilder();
3099:                if (null == form_builder) {
3100:                    return;
3101:                }
3102:                try {
3103:                    form_builder.removeForm(template, beanClass, prefix);
3104:                    form_builder
3105:                            .generateForm(template, beanClass, null, prefix);
3106:                } catch (BeanUtilsException e) {
3107:                    throw new EngineException(e);
3108:                }
3109:            }
3110:
3111:            void removeForm(Template template, Class beanClass, String prefix)
3112:                    throws EngineException {
3113:                BeanHandler bean_handler = template.getBeanHandler();
3114:                if (null == bean_handler) {
3115:                    return;
3116:                }
3117:                FormBuilder form_builder = bean_handler.getFormBuilder();
3118:                if (null == form_builder) {
3119:                    return;
3120:                }
3121:                try {
3122:                    form_builder.removeForm(template, beanClass, prefix);
3123:                } catch (BeanUtilsException e) {
3124:                    throw new EngineException(e);
3125:                }
3126:            }
3127:
3128:            private String getContextId() {
3129:                if (mContextId != null) {
3130:                    return mContextId;
3131:                }
3132:
3133:                synchronized (mElement) {
3134:                    mContextId = mRequestState.buildContextId();
3135:                }
3136:
3137:                return mContextId;
3138:            }
3139:
3140:            private FlowState getSubmissionParameters(String name,
3141:                    String[] parameterValues,
3142:                    Set<Map.Entry<String, String[]>> outputEntries) {
3143:                FlowState state = new FlowState();
3144:
3145:                state.putParameter(ReservedParameters.SUBMISSION, name);
3146:
3147:                // add the submission parameters
3148:                if (parameterValues != null) {
3149:                    String parameter_name = null;
3150:                    String parameter_value = null;
3151:                    for (int i = 0; i < parameterValues.length; i += 2) {
3152:                        parameter_name = parameterValues[i];
3153:                        parameter_value = parameterValues[i + 1];
3154:                        state.putParameter(parameter_name, parameter_value);
3155:                    }
3156:
3157:                    validateParameter(parameter_name);
3158:                }
3159:
3160:                // Create the submission context parameter
3161:                Submission submission = mElementInfo.getSubmission(name);
3162:                if (null == submission || Scope.LOCAL == submission.getScope()) {
3163:                    String submission_context = getContextId();
3164:                    String target = getElementInfo().getId();
3165:                    if (!submission_context.equals(target)) {
3166:                        StringBuilder submission_context_buffer = new StringBuilder(
3167:                                submission_context);
3168:                        submission_context_buffer.append("^");
3169:                        submission_context_buffer.append(target);
3170:                        submission_context = submission_context_buffer
3171:                                .toString();
3172:                    }
3173:                    try {
3174:                        state.putParameter(
3175:                                ReservedParameters.SUBMISSIONCONTEXT, Base64
3176:                                        .encodeToString(submission_context
3177:                                                .getBytes("UTF-8"), false));
3178:                    } catch (UnsupportedEncodingException e) {
3179:                        // should never happen
3180:                    }
3181:                }
3182:
3183:                // Preserve the continuation ID if a continuation context is active
3184:                if (null == submission || !submission.getCancelContinuations()) {
3185:                    String continuation_id = ContinuationContext
3186:                            .getActiveContextId();
3187:                    if (continuation_id != null) {
3188:                        state.putParameter(ReservedParameters.CONTID,
3189:                                continuation_id);
3190:                    }
3191:                }
3192:
3193:                // create or preserve the request parameters that were initially send to the child element
3194:                // this permits completely seperate processing of any other parameters
3195:                if (mElementState.inInheritanceStructure()) {
3196:                    // preserve the original child request
3197:                    state.putParameter(ReservedParameters.CHILDREQUEST,
3198:                            getEncodedChildRequest());
3199:
3200:                    // preserve the trigger list
3201:                    state.putParameter(ReservedParameters.TRIGGERLIST,
3202:                            mElementState.encodeTriggerList());
3203:                }
3204:
3205:                // preserve the embedding element's inputs and global vars
3206:                ElementContext context = this ;
3207:                while (context != null && context.mRequestState.isEmbedded()) {
3208:                    context = context.mRequestState.getEmbeddingContext()
3209:                            .getElementContext();
3210:                    for (String input_name : context.mElementInfo
3211:                            .getInputNames()) {
3212:                        if (context.mElementState.hasInputValue(input_name)) {
3213:                            state.putSubmissionGlobalInput(input_name,
3214:                                    context.mElementState.getInputValues(
3215:                                            input_name, false));
3216:                        }
3217:                    }
3218:                    for (String globalvar_name : context.mElementInfo
3219:                            .getGlobalVarNames()) {
3220:                        if (context.mElementState.hasInputValue(globalvar_name)) {
3221:                            state.putSubmissionGlobalInput(globalvar_name,
3222:                                    context.mElementState.getInputValues(
3223:                                            globalvar_name, false));
3224:                        }
3225:                    }
3226:                }
3227:
3228:                // preserve the global variables
3229:                for (String globalvar_name : mElementInfo.getGlobalVarNames()) {
3230:                    if (mElementState.hasInputValue(globalvar_name)) {
3231:                        state.putSubmissionGlobalInput(globalvar_name,
3232:                                mElementState.getInputValues(globalvar_name,
3233:                                        false));
3234:                    }
3235:                }
3236:
3237:                // activate reflective datalinks for global vars
3238:                if (outputEntries != null) {
3239:                    for (Map.Entry<String, String[]> output : outputEntries) {
3240:                        // global vars
3241:                        if (mElementInfo.containsGlobalVar(output.getKey())) {
3242:                            state.putSubmissionGlobalInput(output.getKey(),
3243:                                    output.getValue());
3244:                        }
3245:                    }
3246:                }
3247:
3248:                // add this element's inputs
3249:                Map<String, String[]> element_inputs = null;
3250:
3251:                // preserve the input values
3252:                for (String input_name : mElementInfo.getInputNames()) {
3253:                    if (mElementState.hasInputValue(input_name)) {
3254:                        if (null == element_inputs) {
3255:                            element_inputs = new LinkedHashMap<String, String[]>();
3256:                        }
3257:
3258:                        element_inputs.put(input_name, mElementState
3259:                                .getInputValues(input_name));
3260:                    }
3261:                }
3262:
3263:                // merge this element's inputs with its preserved inputs
3264:                Map<String, String[]> preserved_inputs = collectPreservedInputs(outputEntries);
3265:
3266:                String context_id = getContextId();
3267:                if (preserved_inputs != null && preserved_inputs.size() > 0) {
3268:                    if (null == element_inputs) {
3269:                        element_inputs = new LinkedHashMap<String, String[]>();
3270:                    }
3271:                    element_inputs.putAll(preserved_inputs);
3272:                }
3273:                state.setSubmissionElementInputs(element_inputs);
3274:
3275:                // remember this element's context identifier for when the context inputs are extracted
3276:                state.setSubmissionContextId(context_id);
3277:
3278:                return state;
3279:            }
3280:
3281:            private Map<String, String[]> collectPreservedInputs(
3282:                    Set<Map.Entry<String, String[]>> outputEntries) {
3283:                Map<String, String[]> element_inputs = null;
3284:
3285:                // activate reflective datalinks for which outputs point to the inputs
3286:                if (outputEntries != null) {
3287:                    for (Map.Entry<String, String[]> output : outputEntries) {
3288:                        // reflective datalinks
3289:                        Collection<String> datalink_inputs = mElementInfo
3290:                                .getDataLinkInputs(output.getKey(),
3291:                                        mElementInfo, false, null);
3292:                        if (datalink_inputs != null) {
3293:                            for (String input_name : datalink_inputs) {
3294:                                if (null == element_inputs) {
3295:                                    element_inputs = new LinkedHashMap<String, String[]>();
3296:                                }
3297:
3298:                                element_inputs.put(input_name, output
3299:                                        .getValue());
3300:                            }
3301:                        }
3302:                    }
3303:                }
3304:
3305:                return element_inputs;
3306:            }
3307:
3308:            private String getSubmissionUrl(String pathInfo) {
3309:                String url = null;
3310:                String pathinfo = null;
3311:                if (mElementInfo.isPathInfoUsed()) {
3312:                    pathinfo = mRequestState.getElementState().getPathInfo();
3313:                }
3314:                if (mElementState.inInheritanceStructure()) {
3315:                    url = mRequestState.getTarget().getUrl();
3316:                } else {
3317:                    url = mElementInfo.getUrl();
3318:                }
3319:
3320:                // if the element defined no url, go up the hierarchy of embedded elements
3321:                // to grab the first defined element url
3322:                if (null == url) {
3323:                    if (!mRequestState.isEmbedded()) {
3324:                        if (mElementState.inInheritanceStructure()) {
3325:                            throw new SubmissionInheritanceUrlMissingException(
3326:                                    mRequestState.getTarget()
3327:                                            .getDeclarationName(), mElementInfo
3328:                                            .getDeclarationName());
3329:                        } else {
3330:                            throw new SubmissionUrlMissingException(
3331:                                    mElementInfo.getDeclarationName());
3332:                        }
3333:                    }
3334:                    ElementContext context = this ;
3335:                    while (null == url && context != null
3336:                            && context.mRequestState.isEmbedded()) {
3337:                        context = context.mRequestState.getEmbeddingContext()
3338:                                .getElementContext();
3339:                        if (context.getElementInfo().isPathInfoUsed()) {
3340:                            pathinfo = context.mRequestState.getElementState()
3341:                                    .getPathInfo();
3342:                        } else {
3343:                            pathinfo = null;
3344:                        }
3345:                        if (context.mElementState.inInheritanceStructure()) {
3346:                            url = context.mRequestState.getTarget().getUrl();
3347:                        } else {
3348:                            url = context.mElementInfo.getUrl();
3349:                        }
3350:                    }
3351:                }
3352:
3353:                // apply a forced pathinfo
3354:                if (pathInfo != null && pathInfo.length() > 0) {
3355:                    pathinfo = pathInfo;
3356:                }
3357:
3358:                // construct the correct servlet path and url that points to the
3359:                // target child element, or the current element if there are no children
3360:                StringBuilder url_buffer = new StringBuilder(mRequestState
3361:                        .getGateUrl());
3362:                appendTargetAndPathinfo(url_buffer, url, pathinfo);
3363:                return url_buffer.toString();
3364:            }
3365:
3366:            private CharSequenceDeferred _getSubmissionQueryUrl(String name,
3367:                    String pathinfo, String[] parameterValues,
3368:                    Set<Map.Entry<String, String[]>> outputEntries)
3369:                    throws EngineException {
3370:                StateStore state_store = mElementInfo.getStateStore();
3371:                FlowState state = getSubmissionParameters(name,
3372:                        parameterValues, outputEntries);
3373:                return new CharSequenceQueryUrl(state_store,
3374:                        getSubmissionUrl(pathinfo), state, mElementInfo,
3375:                        "submission", name);
3376:            }
3377:
3378:            CharSequenceDeferred getSubmissionQueryUrl(String name,
3379:                    String pathinfo, String[] parameterValues)
3380:                    throws EngineException {
3381:                assert name != null;
3382:                assert name.length() > 0;
3383:                assert parameterValues == null
3384:                        || parameterValues.length % 2 == 0;
3385:
3386:                mElementInfo.validateSubmissionName(name);
3387:
3388:                return _getSubmissionQueryUrl(name, pathinfo, parameterValues,
3389:                        mOutputs.aggregateValues().entrySet());
3390:            }
3391:
3392:            CharSequenceDeferred getSubmissionFormUrl(String pathinfo)
3393:                    throws EngineException {
3394:                return new CharSequenceFormUrl(mElementInfo.getStateStore(),
3395:                        getSubmissionUrl(pathinfo));
3396:            }
3397:
3398:            CharSequenceDeferred getSubmissionFormParameters(String name,
3399:                    String[] parameterValues) throws EngineException {
3400:                assert name != null;
3401:                assert name.length() > 0;
3402:                assert parameterValues == null
3403:                        || parameterValues.length % 2 == 0;
3404:
3405:                mElementInfo.validateSubmissionName(name);
3406:
3407:                return _getSubmissionFormParameters(name, parameterValues,
3408:                        mOutputs.aggregateValues().entrySet());
3409:            }
3410:
3411:            CharSequenceDeferred getSubmissionFormParametersJavascript(
3412:                    String name, String[] parameterValues)
3413:                    throws EngineException {
3414:                assert name != null;
3415:                assert name.length() > 0;
3416:                assert parameterValues == null
3417:                        || parameterValues.length % 2 == 0;
3418:
3419:                mElementInfo.validateSubmissionName(name);
3420:
3421:                return _getSubmissionFormParametersJavascript(name,
3422:                        parameterValues, mOutputs.aggregateValues().entrySet());
3423:            }
3424:
3425:            private CharSequenceDeferred _getSubmissionFormParameters(
3426:                    String name, String[] parameterValues,
3427:                    Set<Map.Entry<String, String[]>> outputEntries)
3428:                    throws EngineException {
3429:                FlowState state = getSubmissionParameters(name,
3430:                        parameterValues, outputEntries);
3431:                return new CharSequenceFormState(mElementInfo.getStateStore(),
3432:                        state, FormStateType.PARAMS);
3433:            }
3434:
3435:            private CharSequenceDeferred _getSubmissionFormParametersJavascript(
3436:                    String name, String[] parameterValues,
3437:                    Set<Map.Entry<String, String[]>> outputEntries)
3438:                    throws EngineException {
3439:                FlowState state = getSubmissionParameters(name,
3440:                        parameterValues, outputEntries);
3441:                return new CharSequenceFormState(mElementInfo.getStateStore(),
3442:                        state, FormStateType.JAVASCRIPT);
3443:            }
3444:
3445:            void setSubmissionQuery(Template template, String name,
3446:                    String pathinfo, String[] parameterValues)
3447:                    throws TemplateException, EngineException {
3448:                template.setValue(PREFIX_SUBMISSION_QUERY + name,
3449:                        getSubmissionQueryUrl(name, pathinfo, parameterValues)
3450:                                .encoder(EncoderHtml.getInstance()));
3451:            }
3452:
3453:            void setSubmissionForm(Template template, String name,
3454:                    String pathinfo, String[] parameterValues)
3455:                    throws TemplateException, EngineException {
3456:                template.setValue(PREFIX_SUBMISSION_FORM + name,
3457:                        getSubmissionFormUrl(pathinfo).encoder(
3458:                                EncoderHtml.getInstance()));
3459:                String submission_javascript = PREFIX_SUBMISSION_PARAMSJS
3460:                        + name;
3461:                if (template.hasValueId(submission_javascript)) {
3462:                    template.setValue(submission_javascript,
3463:                            getSubmissionFormParametersJavascript(name,
3464:                                    parameterValues));
3465:                } else {
3466:                    template.setValue(PREFIX_SUBMISSION_PARAMS + name,
3467:                            getSubmissionFormParameters(name, parameterValues));
3468:                }
3469:            }
3470:
3471:            Collection<String> selectSubmissionParameter(Template template,
3472:                    String name, String[] values) {
3473:                return selectParameter(template, PREFIX_PARAM + name, values);
3474:            }
3475:
3476:            void setSubmissionBean(Template template, Object beanInstance)
3477:                    throws TemplateException, EngineException {
3478:                setSubmissionBean(template, beanInstance, true);
3479:            }
3480:
3481:            void setSubmissionBean(Template template, Object beanInstance,
3482:                    boolean encode) throws TemplateException, EngineException {
3483:                template.setBean(beanInstance, PREFIX_PARAM, encode);
3484:            }
3485:
3486:            void removeSubmissionBean(Template template, Object beanInstance)
3487:                    throws TemplateException, EngineException {
3488:                template.removeBean(beanInstance, PREFIX_PARAM);
3489:            }
3490:
3491:            private <BeanType> BeanType _getSubmissionBean(
3492:                    Submission submission, Class<BeanType> beanClass,
3493:                    String prefix) throws EngineException {
3494:                assert submission != null;
3495:                assert beanClass != null;
3496:
3497:                BeanType bean_instance = getBeanInstance(beanClass);
3498:
3499:                try {
3500:                    HashMap<String, PropertyDescriptor> bean_properties = BeanUtils
3501:                            .getUppercasedBeanProperties(beanClass);
3502:
3503:                    String[] parameter_values = null;
3504:
3505:                    for (String parameter_name : submission.getParameterNames()) {
3506:                        if (mElementState
3507:                                .hasRequestParameterValue(parameter_name)) {
3508:                            parameter_values = mElementState
3509:                                    .getRequestParameterValues(parameter_name);
3510:                            if (parameter_values != null
3511:                                    && parameter_values.length > 0) {
3512:                                BeanUtils.setUppercasedBeanProperty(
3513:                                        parameter_name, parameter_values,
3514:                                        prefix, bean_properties, bean_instance,
3515:                                        null);
3516:                            }
3517:                        }
3518:                    }
3519:
3520:                    for (Pattern parameter_regexp : submission
3521:                            .getParameterRegexps()) {
3522:                        for (String parameter_name : getParameterNames(parameter_regexp
3523:                                .pattern())) {
3524:                            if (mElementState
3525:                                    .hasRequestParameterValue(parameter_name)) {
3526:                                parameter_values = mElementState
3527:                                        .getRequestParameterValues(parameter_name);
3528:                                if (parameter_values != null
3529:                                        && parameter_values.length > 0) {
3530:                                    BeanUtils.setUppercasedBeanProperty(
3531:                                            parameter_name, parameter_values,
3532:                                            prefix, bean_properties,
3533:                                            bean_instance, null);
3534:                                }
3535:                            }
3536:                        }
3537:                    }
3538:
3539:                    for (String uploadedfile_name : getUploadedFileNames()) {
3540:                        UploadedFile file = getUploadedFile(uploadedfile_name);
3541:                        BeanUtils.setUppercasedBeanProperty(uploadedfile_name,
3542:                                file, prefix, bean_properties, bean_instance);
3543:                    }
3544:                } catch (BeanUtilsException e) {
3545:                    throw new EngineException(e);
3546:                }
3547:
3548:                return bean_instance;
3549:            }
3550:
3551:            <BeanType> BeanType getNamedSubmissionBean(String submissionName,
3552:                    String beanName) throws EngineException {
3553:                assert submissionName != null;
3554:                assert submissionName.length() > 0;
3555:                assert beanName != null;
3556:                assert beanName.length() > 0;
3557:
3558:                mElementInfo.validateSubmissionName(submissionName);
3559:
3560:                if (!hasSubmission(submissionName)) {
3561:                    return null;
3562:                }
3563:
3564:                BeanDeclaration bean = mElementInfo.getSubmission(
3565:                        submissionName).getNamedBean(beanName);
3566:                Class<BeanType> bean_class = null;
3567:
3568:                try {
3569:                    bean_class = (Class<BeanType>) Class.forName(bean
3570:                            .getClassname());
3571:                } catch (ClassNotFoundException e) {
3572:                    throw new NamedSubmissionBeanClassnameErrorException(
3573:                            mElementInfo.getDeclarationName(), submissionName,
3574:                            beanName, bean.getClassname(), e);
3575:                }
3576:
3577:                return _getSubmissionBean(mElementInfo
3578:                        .getSubmission(submissionName), bean_class, bean
3579:                        .getPrefix());
3580:            }
3581:
3582:            <BeanType> BeanType getSubmissionBean(String submissionName,
3583:                    Class<BeanType> beanClass, String prefix)
3584:                    throws EngineException {
3585:                assert submissionName != null;
3586:                assert submissionName.length() > 0;
3587:                assert beanClass != null;
3588:
3589:                mElementInfo.validateSubmissionName(submissionName);
3590:
3591:                if (!hasSubmission(submissionName)) {
3592:                    return null;
3593:                }
3594:
3595:                return _getSubmissionBean(mElementInfo
3596:                        .getSubmission(submissionName), beanClass, prefix);
3597:            }
3598:
3599:            private void _fillSubmissionBean(Submission submission,
3600:                    Object bean, String prefix) throws EngineException {
3601:                assert submission != null;
3602:
3603:                if (null == bean) {
3604:                    return;
3605:                }
3606:
3607:                try {
3608:                    HashMap<String, PropertyDescriptor> bean_properties = BeanUtils
3609:                            .getUppercasedBeanProperties(bean.getClass());
3610:                    String[] parameter_values = null;
3611:
3612:                    Object empty_bean = null;
3613:
3614:                    // handle regular parameters
3615:                    for (String parameter_name : submission.getParameterNames()) {
3616:                        parameter_values = mElementState
3617:                                .getRequestParameterValues(parameter_name);
3618:                        if (null == empty_bean
3619:                                && (null == parameter_values || 0 == parameter_values[0]
3620:                                        .length())) {
3621:                            try {
3622:                                empty_bean = bean.getClass().newInstance();
3623:                            } catch (InstantiationException e) {
3624:                                throw new EngineException(
3625:                                        "Unexpected error while invoking the default constructor of the bean with class '"
3626:                                                + bean.getClass().getName()
3627:                                                + "'.", e);
3628:                            } catch (IllegalAccessException e) {
3629:                                throw new EngineException(
3630:                                        "No permission to invoke the default constructor of the bean with class '"
3631:                                                + bean.getClass().getName()
3632:                                                + "'.", e);
3633:                            }
3634:                        }
3635:
3636:                        BeanUtils.setUppercasedBeanProperty(parameter_name,
3637:                                parameter_values, prefix, bean_properties,
3638:                                bean, empty_bean);
3639:                    }
3640:
3641:                    // handle regexp parameters
3642:                    for (Pattern parameter_regexp : submission
3643:                            .getParameterRegexps()) {
3644:                        for (String parameter_name : getParameterNames(parameter_regexp
3645:                                .pattern())) {
3646:                            parameter_values = mElementState
3647:                                    .getRequestParameterValues(parameter_name);
3648:                            if (null == empty_bean
3649:                                    && (null == parameter_values || 0 == parameter_values[0]
3650:                                            .length())) {
3651:                                try {
3652:                                    empty_bean = bean.getClass().newInstance();
3653:                                } catch (InstantiationException e) {
3654:                                    throw new EngineException(
3655:                                            "Unexpected error while invoking the default constructor of the bean with class '"
3656:                                                    + bean.getClass().getName()
3657:                                                    + "'.", e);
3658:                                } catch (IllegalAccessException e) {
3659:                                    throw new EngineException(
3660:                                            "No permission to invoke the default constructor of the bean with class '"
3661:                                                    + bean.getClass().getName()
3662:                                                    + "'.", e);
3663:                                }
3664:                            }
3665:
3666:                            BeanUtils.setUppercasedBeanProperty(parameter_name,
3667:                                    parameter_values, prefix, bean_properties,
3668:                                    bean, empty_bean);
3669:                        }
3670:                    }
3671:
3672:                    // automatically handle uploaded files
3673:                    for (String uploadedfile_name : getUploadedFileNames()) {
3674:                        UploadedFile file = getUploadedFile(uploadedfile_name);
3675:                        BeanUtils.setUppercasedBeanProperty(uploadedfile_name,
3676:                                file, prefix, bean_properties, bean);
3677:                    }
3678:                } catch (BeanUtilsException e) {
3679:                    throw new EngineException(e);
3680:                }
3681:            }
3682:
3683:            void fillSubmissionBean(String submissionName, Object bean,
3684:                    String prefix) throws EngineException {
3685:                assert submissionName != null;
3686:                assert submissionName.length() > 0;
3687:
3688:                if (null == bean) {
3689:                    return;
3690:                }
3691:
3692:                mElementInfo.validateSubmissionName(submissionName);
3693:
3694:                if (!hasSubmission(submissionName)) {
3695:                    return;
3696:                }
3697:
3698:                _fillSubmissionBean(mElementInfo.getSubmission(submissionName),
3699:                        bean, prefix);
3700:            }
3701:
3702:            <BeanType> BeanType getNamedInputBean(String name)
3703:                    throws EngineException {
3704:                assert name != null;
3705:
3706:                mElementInfo.validateInbeanName(name);
3707:
3708:                BeanDeclaration input_bean = mElementInfo
3709:                        .getNamedInbeanInfo(name);
3710:                if (null == input_bean) {
3711:                    input_bean = mElementInfo.getNamedGlobalBeanInfo(name);
3712:                }
3713:
3714:                Class<BeanType> input_bean_class = null;
3715:
3716:                try {
3717:                    input_bean_class = (Class<BeanType>) Class
3718:                            .forName(input_bean.getClassname());
3719:                } catch (ClassNotFoundException e) {
3720:                    throw new NamedInbeanClassnameErrorException(mElementInfo
3721:                            .getDeclarationName(), name, input_bean
3722:                            .getClassname());
3723:                }
3724:
3725:                return getInputBean(input_bean_class, input_bean.getPrefix());
3726:            }
3727:
3728:            <BeanType> BeanType getInputBean(Class<BeanType> beanClass,
3729:                    String prefix) throws EngineException {
3730:                assert beanClass != null;
3731:
3732:                BeanType bean_instance = getBeanInstance(beanClass);
3733:
3734:                try {
3735:                    HashMap<String, PropertyDescriptor> bean_properties = BeanUtils
3736:                            .getUppercasedBeanProperties(beanClass);
3737:
3738:                    // merge the input and global variable names
3739:                    Collection<String> input_names = mElementInfo
3740:                            .getInputNames();
3741:                    Collection<String> globalvar_names = mElementInfo
3742:                            .getGlobalVarNames();
3743:                    ArrayList<String> merged_names = new ArrayList<String>();
3744:                    merged_names.addAll(input_names);
3745:                    merged_names.addAll(globalvar_names);
3746:
3747:                    // process all the possible input names
3748:                    String[] values = null;
3749:
3750:                    for (String name : merged_names) {
3751:                        if (mElementState.hasInputValue(name)) {
3752:                            values = mElementState.getInputValues(name);
3753:                            if (values != null && values.length > 0) {
3754:                                BeanUtils.setUppercasedBeanProperty(name,
3755:                                        values, prefix, bean_properties,
3756:                                        bean_instance, null);
3757:                            }
3758:                        }
3759:                    }
3760:                } catch (BeanUtilsException e) {
3761:                    throw new EngineException(e);
3762:                }
3763:
3764:                return bean_instance;
3765:            }
3766:
3767:            void setNamedOutputBean(String name, Object bean)
3768:                    throws EngineException {
3769:                assert name != null;
3770:
3771:                mElementInfo.validateOutbeanName(name);
3772:
3773:                BeanDeclaration output_bean = mElementInfo
3774:                        .getNamedOutbeanInfo(name);
3775:                if (null == output_bean) {
3776:                    output_bean = mElementInfo.getNamedGlobalBeanInfo(name);
3777:                }
3778:
3779:                setOutputBean(bean, output_bean.getPrefix());
3780:            }
3781:
3782:            void setOutputBean(Object bean, String prefix)
3783:                    throws EngineException {
3784:                if (null == bean)
3785:                    throw new IllegalArgumentException("bean can't be null.");
3786:
3787:                Map<String, String[]> values = getOutputBeanValues(bean,
3788:                        prefix, null);
3789:
3790:                String name;
3791:                String[] value;
3792:                for (Map.Entry<String, String[]> entry : values.entrySet()) {
3793:                    name = entry.getKey();
3794:                    value = entry.getValue();
3795:
3796:                    setOutputValues(name, value);
3797:
3798:                    if (mElementState.inInheritanceStructure()
3799:                            && mElementInfo.containsChildTrigger(name)) {
3800:                        triggerChild(name, value);
3801:                    }
3802:                }
3803:            }
3804:
3805:            Map<String, String[]> getOutputBeanValues(Object bean,
3806:                    String prefix, Collection<String> included)
3807:                    throws BeanInstanceValuesErrorException {
3808:                if (null == bean)
3809:                    return Collections.EMPTY_MAP;
3810:
3811:                Map<String, String[]> values = new LinkedHashMap<String, String[]>();
3812:                try {
3813:                    Constrained constrained = ConstrainedUtils
3814:                            .makeConstrainedInstance(bean);
3815:                    ConstrainedProperty constrained_property = null;
3816:
3817:                    Set<String> merged_names = new LinkedHashSet<String>();
3818:
3819:                    // handle outputs
3820:                    Collection<String> output_names = mElementInfo
3821:                            .getOutputNames();
3822:                    if (null == included) {
3823:                        merged_names.addAll(output_names);
3824:                    } else {
3825:                        for (String name : output_names) {
3826:                            if (included.contains(name)) {
3827:                                merged_names.add(name);
3828:                            }
3829:                        }
3830:                    }
3831:
3832:                    // handle globals
3833:                    Collection<String> globalvar_names = mElementInfo
3834:                            .getGlobalVarNames();
3835:                    if (null == included) {
3836:                        merged_names.addAll(globalvar_names);
3837:                    } else {
3838:                        for (String name : globalvar_names) {
3839:                            if (included.contains(name)) {
3840:                                merged_names.add(name);
3841:                            }
3842:                        }
3843:                    }
3844:
3845:                    // create the merged array
3846:                    String[] merged_names_array = new String[merged_names
3847:                            .size()];
3848:                    merged_names.toArray(merged_names_array);
3849:
3850:                    // process all the possible output names
3851:                    Map<String, Object> property_values = BeanUtils
3852:                            .getPropertyValues(bean, merged_names_array, null,
3853:                                    prefix);
3854:                    Object property_value = null;
3855:
3856:                    for (String property_name : property_values.keySet()) {
3857:                        property_value = property_values.get(property_name);
3858:
3859:                        if (property_value != null) {
3860:                            // get the constrained property if that's appropriate
3861:                            if (constrained != null) {
3862:                                if (prefix != null) {
3863:                                    constrained_property = constrained
3864:                                            .getConstrainedProperty(property_name
3865:                                                    .substring(prefix.length()));
3866:                                } else {
3867:                                    constrained_property = constrained
3868:                                            .getConstrainedProperty(property_name);
3869:                                }
3870:                            }
3871:
3872:                            values.put(property_name, getOutputObjectValues(
3873:                                    property_name, property_value,
3874:                                    constrained_property));
3875:                        }
3876:                    }
3877:                } catch (BeanUtilsException e) {
3878:                    throw new BeanInstanceValuesErrorException(bean, e);
3879:                }
3880:                return values;
3881:            }
3882:
3883:            private <BeanType> BeanType getBeanInstance(
3884:                    Class<BeanType> beanClass) throws EngineException {
3885:                BeanType bean_instance;
3886:
3887:                try {
3888:                    bean_instance = beanClass.newInstance();
3889:                } catch (InstantiationException e) {
3890:                    throw new EngineException(
3891:                            "Can't instantiate a bean with class '"
3892:                                    + beanClass.getName() + "'.", e);
3893:                } catch (IllegalAccessException e) {
3894:                    throw new EngineException(
3895:                            "No permission to instantiate a bean with class '"
3896:                                    + beanClass.getName() + "'.", e);
3897:                }
3898:
3899:                return bean_instance;
3900:            }
3901:
3902:            void processEmbeddedElement(Template template,
3903:                    ElementSupport embeddingElement, String elementId,
3904:                    String differentiator, Object data)
3905:                    throws TemplateException, EngineException {
3906:                // process the embedded elements
3907:                if (template.hasFilteredValues(TAG_ELEMENT)) {
3908:                    List<String[]> element_tags = template
3909:                            .getFilteredValues(TAG_ELEMENT);
3910:                    for (String[] captured_groups : element_tags) {
3911:                        if (null == differentiator) {
3912:                            if (elementId.equals(captured_groups[3])) {
3913:                                processEmbeddedElement(captured_groups[0],
3914:                                        template, embeddingElement,
3915:                                        captured_groups[3], null, data);
3916:                                return;
3917:                            }
3918:                        } else {
3919:                            if (elementId.equals(captured_groups[3])) {
3920:                                String value_id = captured_groups[1] + ":";
3921:
3922:                                String differentiator_value_id = value_id
3923:                                        + differentiator;
3924:                                if (template
3925:                                        .hasValueId(differentiator_value_id)) {
3926:                                    processEmbeddedElement(
3927:                                            differentiator_value_id, template,
3928:                                            embeddingElement, elementId,
3929:                                            differentiator, data);
3930:                                    return;
3931:                                } else if (template.hasValueId(value_id)) {
3932:                                    processEmbeddedElement(value_id, template,
3933:                                            embeddingElement, elementId,
3934:                                            differentiator, data);
3935:                                    return;
3936:                                }
3937:                            }
3938:                        }
3939:                    }
3940:                }
3941:
3942:                throw new EmbeddedElementNotFoundException(elementId);
3943:            }
3944:
3945:            private void processEmbeddedElement(String valueId,
3946:                    Template template, ElementSupport embeddingElement,
3947:                    String elementId, String differentiator, Object data)
3948:                    throws TemplateException, EngineException {
3949:                if (!template.hasValueId(valueId)) {
3950:                    throw new EmbeddedElementNotFoundException(elementId);
3951:                }
3952:
3953:                ElementInfo embedded_element = null;
3954:                RequestState embedded_state = null;
3955:                Response embedded_response = null;
3956:
3957:                // try to obtain the embedded element and throw an exception if
3958:                // it couldn't be found
3959:                embedded_element = mElementInfo.getSite().resolveId(elementId,
3960:                        mElementInfo);
3961:                if (null == embedded_element) {
3962:                    throw new ElementIdNotFoundException(elementId);
3963:                }
3964:
3965:                // build the embedded element request parameter by merging
3966:                // the current element's request parameters with its input values
3967:                // also merge in the state global vars
3968:                Map<String, String[]> parameters = new HashMap<String, String[]>(
3969:                        mElementState.getRequestParameters());
3970:                for (Map.Entry<String, String[]> input_entry : mElementState
3971:                        .getInputEntries()) {
3972:                    if (!parameters.containsKey(input_entry.getKey())) {
3973:                        parameters.put(input_entry.getKey(), input_entry
3974:                                .getValue());
3975:                    }
3976:                }
3977:                if (mRequestState.getStateGlobalVars() != null) {
3978:                    for (Map.Entry<String, String[]> globalvar_entry : mRequestState
3979:                            .getStateGlobalVars().entrySet()) {
3980:                        parameters.put(globalvar_entry.getKey(),
3981:                                globalvar_entry.getValue());
3982:                    }
3983:                }
3984:
3985:                // build the request and response objects for the embedded element
3986:                // and service the request
3987:                EmbeddingContext embedding_context = new EmbeddingContext(this ,
3988:                        embeddingElement, template, template
3989:                                .getDefaultValue(valueId), differentiator, data);
3990:                embedded_response = mResponse.createEmbeddedResponse(valueId,
3991:                        differentiator);
3992:                embedded_state = RequestState.getEmbeddedInstance(
3993:                        embedded_response, embedding_context, parameters,
3994:                        embedded_element);
3995:
3996:                embedded_state.service();
3997:                embedded_response.close();
3998:
3999:                if (embedding_context.getCancelEmbedding()) {
4000:                    // handle embedding cancellation by throwing a dedicated exception
4001:                    // that will bubble up to the first embedding element and print
4002:                    // out the embedded content
4003:                    throw new CancelEmbeddingTriggeredException(
4004:                            embedded_response.getEmbeddedContent());
4005:                } else {
4006:                    // set the output of the element to the value in the template
4007:                    template.setValue(valueId, embedded_response
4008:                            .getEmbeddedContent());
4009:                }
4010:            }
4011:
4012:            void evaluateExpressionRoleUserTags(List<String> setValues,
4013:                    Template template, String id) {
4014:                if (template.hasFilteredBlocks(TAG_OGNL_ROLEUSER)
4015:                        || template.hasFilteredBlocks(TAG_MVEL_ROLEUSER)
4016:                        || template.hasFilteredBlocks(TAG_GROOVY_ROLEUSER)
4017:                        || template.hasFilteredBlocks(TAG_JANINO_ROLEUSER)) {
4018:                    RoleUserIdentity identity = (RoleUserIdentity) mRequestState
4019:                            .getRequestAttribute(Identified.IDENTITY_ATTRIBUTE_NAME);
4020:
4021:                    if (identity != null) {
4022:                        RoleUserAttributes attributes = identity
4023:                                .getAttributes();
4024:                        HashMap<String, Object> map = new HashMap<String, Object>();
4025:                        map.put("login", identity.getLogin());
4026:                        map.put("password", attributes.getPassword());
4027:                        map.put("userId", attributes.getUserId());
4028:                        map.put("roles", attributes.getRoles());
4029:
4030:                        if (template.hasFilteredBlocks(TAG_OGNL_ROLEUSER)) {
4031:                            String language_id = id;
4032:                            if (language_id != null) {
4033:                                language_id = PREFIX_OGNL_ROLEUSER
4034:                                        + language_id;
4035:                            }
4036:                            FilteredTagProcessorOgnl
4037:                                    .getInstance()
4038:                                    .processTags(
4039:                                            setValues,
4040:                                            template,
4041:                                            template
4042:                                                    .getFilteredBlocks(TAG_OGNL_ROLEUSER),
4043:                                            language_id,
4044:                                            RoleUserAttributes.class, "user",
4045:                                            attributes, map);
4046:                        }
4047:
4048:                        if (template.hasFilteredBlocks(TAG_MVEL_ROLEUSER)) {
4049:                            String language_id = id;
4050:                            if (language_id != null) {
4051:                                language_id = PREFIX_MVEL_ROLEUSER
4052:                                        + language_id;
4053:                            }
4054:                            FilteredTagProcessorMvel
4055:                                    .getInstance()
4056:                                    .processTags(
4057:                                            setValues,
4058:                                            template,
4059:                                            template
4060:                                                    .getFilteredBlocks(TAG_MVEL_ROLEUSER),
4061:                                            language_id,
4062:                                            RoleUserAttributes.class, "user",
4063:                                            attributes, map);
4064:                        }
4065:
4066:                        if (template.hasFilteredBlocks(TAG_GROOVY_ROLEUSER)) {
4067:                            String language_id = id;
4068:                            if (language_id != null) {
4069:                                language_id = PREFIX_GROOVY_ROLEUSER
4070:                                        + language_id;
4071:                            }
4072:                            FilteredTagProcessorGroovy
4073:                                    .getInstance()
4074:                                    .processTags(
4075:                                            setValues,
4076:                                            template,
4077:                                            template
4078:                                                    .getFilteredBlocks(TAG_GROOVY_ROLEUSER),
4079:                                            language_id,
4080:                                            RoleUserAttributes.class, "user",
4081:                                            attributes, map);
4082:                        }
4083:
4084:                        if (template.hasFilteredBlocks(TAG_JANINO_ROLEUSER)) {
4085:                            String language_id = id;
4086:                            if (language_id != null) {
4087:                                language_id = PREFIX_JANINO_ROLEUSER
4088:                                        + language_id;
4089:                            }
4090:                            FilteredTagProcessorJanino
4091:                                    .getInstance()
4092:                                    .processTags(
4093:                                            setValues,
4094:                                            template,
4095:                                            template
4096:                                                    .getFilteredBlocks(TAG_JANINO_ROLEUSER),
4097:                                            language_id,
4098:                                            RoleUserAttributes.class, "user",
4099:                                            attributes, map);
4100:                        }
4101:                    }
4102:                }
4103:            }
4104:
4105:            private String getEncodedChildRequest() {
4106:                String child_request = null;
4107:
4108:                if (mElementState
4109:                        .hasRequestParameterValue(ReservedParameters.CHILDREQUEST)) {
4110:                    child_request = mElementState
4111:                            .getRequestParameter(ReservedParameters.CHILDREQUEST);
4112:                } else {
4113:                    child_request = ChildRequestEncoder.encode(mElementState
4114:                            .getInheritanceStack().get(0), mRequestState);
4115:                }
4116:
4117:                return child_request;
4118:            }
4119:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.