| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.apache.cocoon.woody.transformation; |
| |
| import java.io.IOException; |
| import java.io.StringReader; |
| import java.util.Locale; |
| import java.util.Map; |
| |
| import org.apache.avalon.framework.parameters.Parameters; |
| import org.apache.cocoon.components.flow.FlowHelper; |
| import org.apache.cocoon.components.flow.WebContinuation; |
| import org.apache.cocoon.environment.ObjectModelHelper; |
| import org.apache.cocoon.environment.Request; |
| import org.apache.cocoon.environment.Session; |
| import org.apache.cocoon.i18n.I18nUtils; |
| import org.apache.cocoon.woody.formmodel.Form; |
| import org.apache.cocoon.xml.AttributesImpl; |
| import org.apache.commons.jxpath.JXPathContext; |
| import org.apache.commons.jxpath.JXPathException; |
| import org.apache.commons.jxpath.Variables; |
| import org.xml.sax.Attributes; |
| import org.xml.sax.SAXException; |
| |
| /** |
| * WoodyPipeLineConfig |
| * |
| * @version CVS $Id$ |
| */ |
| public class WoodyPipelineConfig { |
| |
| /** |
| * Default key under which the woody form is stored in the JXPath context. |
| */ |
| public static final String WOODY_FORM = "woody-form"; |
| |
| /** |
| * Name of the request attribute under which the Woody form is stored (optional). */ |
| private final String attributeName; |
| |
| /** |
| * Pointer to the current request object. */ |
| private final Request request; |
| |
| /** |
| * Initialized jxpathcontext to evaluate passed expressions with. */ |
| private final JXPathContext jxpathContext; |
| |
| /** |
| * Containts locale specified as a parameter to the transformer, if any. */ |
| private final Locale localeParameter; |
| |
| /** |
| * The locale currently used by the transformer. */ |
| private Locale locale; |
| |
| /** |
| * Value for the action attribute of the form. |
| */ |
| private String formAction; |
| |
| /** |
| * Value for the method attribute of the form. |
| */ |
| private String formMethod; |
| |
| private WoodyPipelineConfig(JXPathContext jxpc, Request req, Locale localeParam, |
| String attName, String actionExpression, String method) { |
| this.attributeName = attName; |
| this.request = req; |
| this.jxpathContext =jxpc; |
| this.localeParameter = localeParam; |
| this.formAction = translateText(actionExpression); |
| this.formMethod = method; |
| } |
| |
| /** |
| * Creates and initializes a WoodyPipelineConfig object based on the passed |
| * arguments of the setup() of the specific Pipeline-component. |
| * |
| * @param objectModel the objectmodel as passed in the setup() |
| * @param parameters the parameters as passed in the setup() |
| * @return an instance of WoodyPipelineConfig initialized according to the |
| * settings in the sitemap. |
| */ |
| public static WoodyPipelineConfig createConfig(Map objectModel, Parameters parameters) { |
| // create and set the jxpathContext... |
| Object flowContext = FlowHelper.getContextObject(objectModel); |
| WebContinuation wk = FlowHelper.getWebContinuation(objectModel); |
| JXPathContext jxpc = JXPathContext.newContext(flowContext); |
| Variables vars = jxpc.getVariables(); |
| vars.declareVariable("continuation", wk); |
| Request request = ObjectModelHelper.getRequest(objectModel); |
| vars.declareVariable("request", request); |
| Session session = request.getSession(false); |
| vars.declareVariable("session", session); |
| vars.declareVariable("parameters", parameters); |
| |
| Locale localeParameter = null; |
| String localeStr = parameters.getParameter("locale", null); |
| if (localeStr != null) { |
| localeParameter = I18nUtils.parseLocale(localeStr); |
| } |
| |
| String attributeName = parameters.getParameter("attribute-name", null); |
| String actionExpression = parameters.getParameter("form-action", null); |
| String formMethod = parameters.getParameter("form-method", "POST"); |
| //TODO (20031223 mpo)think about adding form-encoding for the Generator. |
| // Note generator will also need some text to go on the submit-button? |
| // Alternative to adding more here is to apply xinclude ? |
| |
| return new WoodyPipelineConfig(jxpc, request, localeParameter, |
| attributeName, actionExpression, formMethod); |
| } |
| |
| /** |
| * Overloads {@link #findForm(String)} by setting the jxpath-expression to null |
| */ |
| public Form findForm() throws SAXException { |
| return this.findForm(null); |
| } |
| |
| /** |
| * Finds the form from the current request-context based on the settings of |
| * this configuration object. The fall-back search-procedure is as follows: |
| * <ol><li>Use the provided jxpathExpression (if not null)</li> |
| * <li>Use the setting of the 'attribute-name' parameter on the request</li> |
| * <li>Obtain the form from it's default location in the flow context</li> |
| * </ol> |
| * |
| * @param jxpathExpression that should be pointing to the form |
| * @return the found form if found |
| * @throws SAXException in any of the following cases: |
| * <ul><li>The provided jxpathExpression (if not null) not point to a |
| * {@link Form} instance.</li> |
| * <li>The request is not holding a {@link Form} instance under the key |
| * specified by 'attribute-name' (if specified)</li> |
| * <li>Both jxpathExpression and 'attribute-name' were not specified AND |
| * also the default location was not holding a valid {@link Form} instance.</li> |
| * </ol> |
| */ |
| public Form findForm(String jxpathExpression) throws SAXException { |
| Object form = null; |
| if (jxpathExpression != null) { |
| form = this.jxpathContext.getValue(jxpathExpression); |
| if (form == null) { |
| throw new SAXException("No form found at location \"" + jxpathExpression + "\"."); |
| } else if (!(form instanceof Form)) { |
| throw new SAXException("Object returned by expression \"" + jxpathExpression + "\" is not a Woody Form."); |
| } |
| } else if (this.attributeName != null) { // then see if an attribute-name was specified |
| form = this.request.getAttribute(this.attributeName); |
| if (form == null) { |
| throw new SAXException("No form found in request attribute with name \"" + this.attributeName + "\""); |
| } else if (!(form instanceof Form)) { |
| throw new SAXException("Object found in request (attribute = '" + this.attributeName + "') is not a Woody Form."); |
| } |
| } else { // and then see if we got a form from the flow |
| jxpathExpression = "/" + WoodyPipelineConfig.WOODY_FORM; |
| try { |
| form = this.jxpathContext.getValue(jxpathExpression); |
| } catch (JXPathException e) { /* do nothing */ } |
| if (form == null) { |
| throw new SAXException("No Woody form found."); |
| } |
| } |
| return (Form)form; |
| } |
| |
| /** |
| * Replaces JXPath expressions embedded inside #{ and } by their value. |
| * This will parse the passed String looking for #{} occurences and then |
| * uses the {@link #evaluateExpression(String)} to evaluate the found expression. |
| * |
| * @return the original String with it's #{}-parts replaced by the evaulated results. |
| */ |
| public String translateText(String original) { |
| if (original==null) { |
| return null; |
| } |
| |
| StringBuffer expression; |
| StringBuffer translated = new StringBuffer(); |
| StringReader in = new StringReader(original); |
| int chr; |
| try { |
| while ((chr = in.read()) != -1) { |
| char c = (char) chr; |
| if (c == '#') { |
| chr = in.read(); |
| if (chr != -1) { |
| c = (char) chr; |
| if (c == '{') { |
| expression = new StringBuffer(); |
| boolean more = true; |
| while ( more ) { |
| more = false; |
| if ((chr = in.read()) != -1) { |
| c = (char)chr; |
| if (c != '}') { |
| expression.append(c); |
| more = true; |
| } else { |
| translated.append(evaluateExpression(expression.toString()).toString()); |
| } |
| } else { |
| translated.append('#').append('{').append(expression); |
| } |
| } |
| } |
| } else { |
| translated.append((char) chr); |
| } |
| } else { |
| translated.append(c); |
| } |
| } |
| } catch (IOException ignored) { |
| ignored.printStackTrace(); |
| } |
| return translated.toString(); |
| } |
| |
| /** |
| * Evaluates the passed xpath expression using the internal jxpath context |
| * holding the declared variables: |
| * <ol><li>continuation: as made available by flowscript</li> |
| * <li>request: as present in the cocoon processing environment</li> |
| * <li>session: as present in the cocoon processing environment</li> |
| * <li>parameters: as present in the cocoon sitemap node of the pipeline component</li></ol> |
| * |
| * @param expression |
| * @return the object-value resulting the expression evaluation. |
| */ |
| public Object evaluateExpression(String expression) { |
| return this.jxpathContext.getValue(expression); |
| } |
| |
| public Locale getLocale() { |
| return locale; |
| } |
| |
| public void setLocale(Locale locale) { |
| this.locale = locale; |
| } |
| |
| public Locale getLocaleParameter() { |
| return localeParameter; |
| } |
| |
| /** |
| * The value for the wi:form-generated/@action. |
| * Note: wi:form-template copies this from its wt:form-template counterpart. |
| * |
| * @return the {@link #translateText(String)} result of the 'form-action' sitemap |
| * parameter to the pipeline component, or null if that parameter was not set. |
| */ |
| public String getFormAction() { |
| return formAction; |
| } |
| |
| /** |
| * The value for the wi:form-generated/@method. |
| * Note: wi:form-template copies this from its wt:form-template counterpart. |
| * |
| * @return the value of the 'form-method' sitemap parameter to the pipeline |
| * component. Defaults to 'POST' if it was not set. |
| */ |
| public String getFormMethod() { |
| return formMethod; |
| } |
| |
| /** |
| * The grouped attributes to set on the wi:form-generated element. |
| * Note: wi:form-template copies this from its wt:form-template counterpart. |
| * |
| * @see #getFormAction() |
| * @see #getFormMethod() |
| */ |
| public Attributes getFormAttributes() { |
| AttributesImpl formAtts = new AttributesImpl(); |
| if (getFormAction() != null) { |
| formAtts.addCDATAAttribute("action", getFormAction()); |
| } |
| formAtts.addCDATAAttribute("method", getFormMethod()); |
| return formAtts; |
| } |
| } |