| /* |
| * 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.acting; |
| |
| import java.util.HashMap; |
| import java.util.Map; |
| |
| import org.apache.avalon.framework.activity.Disposable; |
| import org.apache.avalon.framework.configuration.Configuration; |
| import org.apache.avalon.framework.configuration.ConfigurationException; |
| import org.apache.avalon.framework.parameters.Parameters; |
| import org.apache.avalon.framework.thread.ThreadSafe; |
| |
| import org.apache.avalon.excalibur.component.ComponentHandler; |
| |
| import org.apache.cocoon.components.sax.XMLByteStreamCompiler; |
| import org.apache.cocoon.components.sax.XMLByteStreamFragment; |
| import org.apache.cocoon.environment.ObjectModelHelper; |
| import org.apache.cocoon.environment.Redirector; |
| import org.apache.cocoon.environment.Request; |
| import org.apache.cocoon.environment.SourceResolver; |
| import org.apache.cocoon.generation.ServerPagesGenerator; |
| import org.apache.cocoon.xml.AbstractXMLConsumer; |
| |
| /** |
| * Allows actions to be written in XSP. This allows to use XSP to produce |
| * XML fragments that are later reused in generators.<br/> |
| * |
| * This action works in concert with the "action" logicheet, that offers |
| * actions-related services such as redirect or result map access, and the |
| * "capture" logicsheet that allows to capture parts of XSP-generated XML |
| * either as an <code>XMLizable</code> containing serialized SAX events, |
| * or as a DOM <code>Node</code>.<br/> |
| * |
| * As for generators, the XSP file name is set using the "src" attribute.<br/> |
| * |
| * This action accepts a single parameter, "output-attribute", which names |
| * the request attribute where the XSP-generated document will be stored |
| * (as an <code>XMLizable</code>). If this parameter is omitted, the |
| * XSP result is discarded (often the case when inner fragments are captured |
| * with the "capture" logicsheet").<br/> |
| * |
| * When "output-attribute" is set, the action status defaults to "success", |
| * meaning child sitemap statements are executed. This allows to use an |
| * existing XSP without modification with this action.<br/> |
| * |
| * When "output-attribute" isn't set, the action status defaults to "failure". |
| * The XSP must then use the "action" logicsheet to set its status.<br/> |
| * |
| * Example : |
| * <pre> |
| * <action type="serverpages" src="myAction.xsp"> |
| * <map:param name="output-attribute" value="xsp-action-result"/> |
| * ... |
| * </action> |
| * </pre> |
| * |
| * @author <a href="mailto:sylvain@apache.org">Sylvain Wallez</a> |
| * @version CVS $Id$ |
| */ |
| public class ServerPagesAction |
| extends ConfigurableComposerAction |
| implements Disposable, ThreadSafe { |
| |
| public static final String REDIRECTOR_OBJECT = "xsp-action:redirector"; |
| public static final String ACTION_RESULT_OBJECT = "xsp-action:result"; |
| public static final String ACTION_SUCCESS_OBJECT = "xsp-action:success"; |
| |
| ComponentHandler generatorHandler; |
| |
| public void configure(Configuration conf) |
| throws ConfigurationException { |
| try { |
| this.generatorHandler = ComponentHandler.getComponentHandler( |
| ServerPagesGenerator.class, |
| conf, |
| this.manager, |
| null, // Context |
| null, // RoleManager |
| null, // LogkitLoggerManager |
| null, // InstrumentManager |
| "N/A" // instrumentableName |
| ); |
| |
| this.generatorHandler.enableLogging(getLogger()); |
| this.generatorHandler.initialize(); |
| |
| } catch(Exception e) { |
| throw new ConfigurationException("Cannot set up component handler", e); |
| } |
| } |
| |
| /* (non-Javadoc) |
| * @see org.apache.avalon.framework.activity.Disposable#dispose() |
| */ |
| public void dispose() { |
| if (this.generatorHandler != null) { |
| this.generatorHandler.dispose(); |
| this.generatorHandler = null; |
| } |
| } |
| |
| public Map act(Redirector redirector, SourceResolver resolver, Map objectModel, |
| String source, Parameters parameters) |
| throws Exception { |
| |
| if (this.getLogger().isDebugEnabled()) { |
| getLogger().debug("serverpage source: " + source); |
| } |
| |
| String outputKey = parameters.getParameter("output-attribute", null); |
| Map resultMap = new HashMap(); |
| Object success = null; |
| |
| // Get a ServerPagesGenerator |
| ServerPagesGenerator generator = (ServerPagesGenerator)this.generatorHandler.get(); |
| |
| // Generator output, if output-attribute was given |
| XMLByteStreamCompiler compiler = null; |
| |
| try { |
| generator.enableLogging(getLogger()); |
| generator.compose(this.manager); |
| generator.setup(resolver, objectModel, source, parameters); |
| |
| // Setup generator output |
| if (outputKey == null) { |
| // discard output to a "black hole" |
| generator.setConsumer(new AbstractXMLConsumer() { } ); // Make the abstract class instanciable |
| } else { |
| // store output in a byte stream |
| compiler = new XMLByteStreamCompiler(); |
| generator.setConsumer(compiler); |
| } |
| |
| // Augment the object model for the "action" logicsheet |
| objectModel.put(REDIRECTOR_OBJECT, redirector); |
| objectModel.put(ACTION_RESULT_OBJECT, resultMap); |
| |
| // Let the XSP do it's stuff |
| generator.generate(); |
| success = objectModel.get(ACTION_SUCCESS_OBJECT); |
| |
| } finally { |
| // Release generator |
| generatorHandler.put(generator); |
| |
| // Clean up object model |
| objectModel.remove(REDIRECTOR_OBJECT); |
| objectModel.remove(ACTION_RESULT_OBJECT); |
| objectModel.remove(ACTION_SUCCESS_OBJECT); |
| } |
| |
| if (outputKey != null) { |
| // Success defaults to true when the whole output is captured |
| if (success == null) { |
| success = Boolean.TRUE; |
| } |
| |
| if (success == Boolean.TRUE) { |
| // Store the XSP output in the request |
| Request req = ObjectModelHelper.getRequest(objectModel); |
| req.setAttribute(outputKey, new XMLByteStreamFragment(compiler.getSAXFragment())); |
| } |
| } |
| |
| return (success == Boolean.TRUE) ? resultMap : null; |
| } |
| } |