001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.cocoon.webapps.portal.components;
018:
019: import java.util.ArrayList;
020: import java.util.HashMap;
021: import java.util.Map;
022:
023: import javax.xml.transform.sax.SAXResult;
024: import javax.xml.transform.sax.TransformerHandler;
025:
026: import org.apache.avalon.framework.component.Component;
027: import org.apache.avalon.framework.component.ComponentManager;
028: import org.apache.avalon.framework.logger.Logger;
029: import org.apache.cocoon.components.sax.XMLSerializer;
030: import org.apache.cocoon.components.source.SourceUtil;
031: import org.apache.cocoon.environment.ObjectModelHelper;
032: import org.apache.cocoon.environment.Request;
033: import org.apache.cocoon.webapps.portal.PortalConstants;
034: import org.apache.cocoon.webapps.portal.context.SessionContextImpl;
035: import org.apache.cocoon.xml.ContentHandlerWrapper;
036: import org.apache.cocoon.xml.IncludeXMLConsumer;
037: import org.apache.cocoon.xml.XMLConsumer;
038: import org.apache.cocoon.xml.dom.DOMUtil;
039:
040: import org.apache.excalibur.source.Source;
041: import org.apache.excalibur.source.SourceParameters;
042: import org.apache.excalibur.source.SourceResolver;
043: import org.apache.excalibur.xml.xpath.XPathProcessor;
044: import org.apache.excalibur.xml.xslt.XSLTProcessor;
045:
046: import org.w3c.dom.Element;
047: import org.w3c.dom.NodeList;
048:
049: /**
050: * This is the thread for loading one coplet in the background.
051: *
052: * @author <a href="mailto:cziegeler@s-und-n.de">Carsten Ziegeler</a>
053: * @version CVS $Id: CopletThread.java 433543 2006-08-22 06:22:54Z crossley $
054: */
055: public final class CopletThread implements Runnable {
056:
057: private Logger logger;
058: private String copletID;
059: private Map objectModel;
060: private Object[] loadedCoplet;
061: private ComponentManager manager;
062: private SourceResolver resolver;
063: private XPathProcessor processor;
064:
065: /**
066: * Initialise all instance variables.
067: * The main information is the loadedCoplet array:
068: * 0 : contains the result of the coplet loading, <code>null</code>or
069: * the compiled sax events
070: * 1 : The coplet configuration element from the coplet profile
071: * 2 : The resource parameters
072: * 3 : The coplet element
073: * 4 : Current time
074: * 5 : The timeout
075: * 6 : The thread (this)
076: * 7 : The status profile
077: */
078: public void init(String copletID, Map objectModel, Logger logger,
079: Object[] loadedCoplet, ComponentManager manager,
080: SourceResolver resolver, XPathProcessor processor) {
081: this .copletID = copletID;
082: this .objectModel = objectModel;
083: this .logger = logger;
084: this .loadedCoplet = loadedCoplet;
085: this .manager = manager;
086: this .resolver = resolver;
087: this .processor = processor;
088: }
089:
090: /**
091: * Process one coplet
092: */
093: public void run() {
094: XMLSerializer compiler = null;
095: Element copletConf = (Element) this .loadedCoplet[1];
096: SourceParameters p = (SourceParameters) loadedCoplet[2];
097:
098: try {
099: // Determine the resource to load
100: // If the coplet is customizable and has no customization info
101: // the customization resource is loaded, otherwise the resource
102: String resource = null;
103: boolean showCustomizePage = p.getParameterAsBoolean(
104: PortalConstants.PARAMETER_CUSTOMIZE, false);
105: if (showCustomizePage) {
106: final String value = DOMUtil.getValueOf(copletConf,
107: "customization/@uri", (String) null,
108: this .processor);
109: if (value == null) {
110: this .logger
111: .error("The coplet '"
112: + this .copletID
113: + "' is customizable but has no customization info.");
114: }
115: resource = value;
116: }
117: if (resource == null) {
118: resource = DOMUtil.getValueOf(copletConf,
119: "resource/@uri", this .processor);
120: }
121: boolean handlesSizable = DOMUtil.getValueAsBooleanOf(
122: copletConf, "configuration/handlesSizable", false,
123: this .processor);
124:
125: if (!handlesSizable
126: && !p.getParameter("size", "max").equals("max")) {
127: // do nothing here
128: loadedCoplet[0] = new byte[0];
129: } else {
130:
131: compiler = (XMLSerializer) this .manager
132: .lookup(XMLSerializer.ROLE);
133: compiler.startDocument();
134:
135: XMLConsumer nextConsumer = compiler;
136: NodeList transformations = DOMUtil.selectNodeList(
137: copletConf, "transformation/stylesheet",
138: this .processor);
139: XSLTProcessor xslt = null;
140: ArrayList transformers = null;
141: ArrayList sources = null;
142: Request request = ObjectModelHelper
143: .getRequest(this .objectModel);
144: XMLConsumer stylesheet = null;
145:
146: try {
147: if (transformations != null
148: && transformations.getLength() > 0) {
149: transformers = new ArrayList();
150: sources = new ArrayList();
151:
152: nextConsumer = new IncludeXMLConsumer(
153: nextConsumer);
154: for (int k = transformations.getLength() - 1; k >= 0; k--) {
155: xslt = (XSLTProcessor) this .manager
156: .lookup(XSLTProcessor.ROLE);
157: transformers.add(xslt);
158: Source source = this .resolver
159: .resolveURI(DOMUtil
160: .getValueOfNode(transformations
161: .item(k)));
162: sources.add(source);
163: TransformerHandler handler = xslt
164: .getTransformerHandler(source);
165:
166: final SAXResult result = new SAXResult(
167: nextConsumer);
168: result.setLexicalHandler(nextConsumer);
169: handler.setResult(result);
170: nextConsumer = new ContentHandlerWrapper(
171: handler, handler);
172: stylesheet = nextConsumer;
173: }
174: stylesheet.startDocument();
175: }
176: boolean includeFragment = true;
177: boolean handlesParameters = DOMUtil
178: .getValueAsBooleanOf(copletConf,
179: "configuration/handlesParameters",
180: true, this .processor);
181: String size = p.getParameter("size", "max");
182: includeFragment = size.equals("max");
183: if (!includeFragment) {
184: if (this .logger.isWarnEnabled()) {
185: this .logger.warn("Minimized coplet '"
186: + copletID
187: + "' not handled correctly.");
188: }
189: }
190: if (includeFragment) {
191: if (this .logger.isDebugEnabled()) {
192: this .logger.debug("portal: Loading coplet "
193: + copletID);
194: }
195: // add the parameters to the request attributes
196: Map info = new HashMap(3);
197: SessionContextImpl.copletInfo.set(info);
198: info.put(PortalConstants.COPLETINFO_PARAMETERS,
199: p);
200: info.put(PortalConstants.COPLETINFO_PORTALURI,
201: request.getRequestURI());
202: info
203: .put(
204: PortalConstants.COPLETINFO_STATUSPROFILE,
205: loadedCoplet[7]);
206: XMLConsumer xc = new IncludeXMLConsumer(
207: nextConsumer);
208: Source source = null;
209: try {
210: source = SourceUtil.getSource(resource,
211: null,
212: (handlesParameters ? p : null),
213: resolver);
214: SourceUtil.toSAX(source, xc);
215: } finally {
216: resolver.release(source);
217: }
218:
219: if (this .logger.isDebugEnabled()) {
220: this .logger.debug("portal: Loaded coplet "
221: + copletID);
222: }
223: }
224: if (stylesheet != null) {
225: stylesheet.endDocument();
226: }
227: } finally {
228: SessionContextImpl.copletInfo.set(null);
229: if (transformers != null) {
230: for (int i = 0; i < transformers.size(); i++) {
231: this .manager
232: .release((Component) transformers
233: .get(i));
234: this .resolver.release((Source) sources
235: .get(i));
236: }
237: }
238: }
239: nextConsumer = null;
240: compiler.endDocument();
241: loadedCoplet[0] = compiler.getSAXFragment();
242: }
243: } catch (Exception local) {
244: // this exception is ignored and an error message is included
245: // later on when the coplet is processed
246: this .logger.error("Exception during processing of coplet: "
247: + copletID, local);
248: } catch (Throwable local) {
249: // this exception is ignored and an error message is included
250: // later on when the coplet is processed
251: this .logger.error("Exception during processing of coplet: "
252: + copletID, local);
253: } finally {
254: if (compiler != null) {
255: this .manager.release(compiler);
256: }
257: }
258: loadedCoplet[6] = null;
259: copletID = null;
260: copletConf = null;
261: this .logger = null;
262: objectModel = null;
263: p = null;
264: loadedCoplet = null;
265: manager = null;
266: resolver = null;
267: } // END run
268: } // END CLASS
|