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.components.profiler;
018:
019: import java.io.IOException;
020: import java.util.Iterator;
021:
022: import org.apache.avalon.framework.component.ComponentException;
023: import org.apache.avalon.framework.component.ComponentManager;
024: import org.apache.avalon.framework.parameters.Parameters;
025: import org.apache.cocoon.ProcessingException;
026: import org.apache.cocoon.components.pipeline.impl.CachingProcessingPipeline;
027: import org.apache.cocoon.environment.Environment;
028: import org.apache.cocoon.sitemap.SitemapModelComponent;
029: import org.apache.cocoon.transformation.Transformer;
030: import org.apache.cocoon.xml.XMLConsumer;
031: import org.apache.cocoon.xml.XMLProducer;
032: import org.xml.sax.SAXException;
033:
034: /**
035: * @author <a href="mailto:vgritsenko@apache.org">Vadim Gritsenko</a>
036: * @author <a href="mailto:stephan@apache.org">Stephan Michels</a>
037: * @author <a href="mailto:bruno@outerthought.org">Bruno Dumon</a>
038: * @version $Id: ProfilingCachingProcessingPipeline.java 433543 2006-08-22 06:22:54Z crossley $
039: */
040: public class ProfilingCachingProcessingPipeline extends
041: CachingProcessingPipeline {
042:
043: private Profiler profiler;
044:
045: private ProfilerData data;
046:
047: private int index;
048:
049: /**
050: * Composable
051: *
052: * @param manager
053: */
054: public void compose(ComponentManager manager)
055: throws ComponentException {
056: super .compose(manager);
057: this .profiler = (Profiler) manager.lookup(Profiler.ROLE);
058: }
059:
060: /**
061: * Disposable
062: */
063: public void dispose() {
064: if (this .profiler != null) {
065: this .manager.release(this .profiler);
066: this .profiler = null;
067: }
068: super .dispose();
069: }
070:
071: /**
072: * Recyclable
073: */
074: public void recycle() {
075: this .data = null;
076: this .index = 0;
077: super .recycle();
078: }
079:
080: /**
081: * Set the generator that will be used as the initial step in the pipeline.
082: * The generator role is given : the actual <code>Generator</code> is fetched
083: * from the latest <code>ComponentManager</code> given by <code>compose()</code>
084: * or <code>recompose()</code>.
085: *
086: * @param role the generator role in the component manager.
087: * @param source the source where to produce XML from, or <code>null</code> if no
088: * source is given.
089: * @param param the parameters for the generator.
090: * @param hintParam
091: * @throws ProcessingException if the generator couldn't be obtained.
092: */
093: public void setGenerator(String role, String source,
094: Parameters param, Parameters hintParam)
095: throws ProcessingException {
096:
097: super .setGenerator(role, source, param, hintParam);
098:
099: if (this .data == null) {
100: this .data = new ProfilerData();
101: }
102: this .data.addComponent(super .generator, role, source);
103: }
104:
105: /**
106: * Add a transformer at the end of the pipeline.
107: * The transformer role is given : the actual <code>Transformer</code> is fetched
108: * from the latest <code>ComponentManager</code> given by <code>compose()</code>
109: * or <code>recompose()</code>.
110: *
111: * @param role the transformer role in the component manager.
112: * @param source the source used to setup the transformer (e.g. XSL file), or
113: * <code>null</code> if no source is given.
114: * @param param the parameters for the transfomer.
115: * @param hintParam
116: * @throws ProcessingException if the generator couldn't be obtained.
117: */
118: public void addTransformer(String role, String source,
119: Parameters param, Parameters hintParam)
120: throws ProcessingException {
121:
122: super .addTransformer(role, source, param, hintParam);
123:
124: if (this .data == null) {
125: this .data = new ProfilerData();
126: }
127: this .data.addComponent(super .transformers
128: .get(super .transformers.size() - 1), role, source);
129: }
130:
131: /**
132: * Set the serializer for this pipeline
133: *
134: * @param role
135: * @param source
136: * @param param
137: * @param hintParam
138: * @param mimeType
139: */
140: public void setSerializer(String role, String source,
141: Parameters param, Parameters hintParam, String mimeType)
142: throws ProcessingException {
143:
144: super .setSerializer(role, source, param, hintParam, mimeType);
145:
146: if (this .data == null) {
147: this .data = new ProfilerData();
148: }
149: this .data.addComponent(super .serializer, role, source);
150: }
151:
152: /**
153: * Set the reader for this pipeline
154: *
155: * @param role
156: * @param source
157: * @param param
158: * @param mimeType
159: */
160: public void setReader(String role, String source, Parameters param,
161: String mimeType) throws ProcessingException {
162:
163: super .setReader(role, source, param, mimeType);
164:
165: if (this .data == null) {
166: this .data = new ProfilerData();
167: }
168: this .data.addComponent(super .reader, role, source);
169: }
170:
171: /**
172: * Timed version of {@link org.apache.cocoon.components.pipeline.AbstractProcessingPipeline#setupPipeline}
173: * and {@link org.apache.cocoon.components.pipeline.impl.AbstractCachingProcessingPipeline#setupPipeline}.
174: */
175: protected void setupPipeline(Environment environment)
176: throws ProcessingException {
177: try {
178: // Setup the generator
179: long time = System.currentTimeMillis();
180: this .generator.setup(environment, environment
181: .getObjectModel(), generatorSource, generatorParam);
182: this .data
183: .setSetupTime(0, System.currentTimeMillis() - time);
184:
185: Iterator transformerItt = this .transformers.iterator();
186: Iterator transformerSourceItt = this .transformerSources
187: .iterator();
188: Iterator transformerParamItt = this .transformerParams
189: .iterator();
190:
191: // Setup transformers
192: int index = 1;
193: while (transformerItt.hasNext()) {
194: Transformer trans = (Transformer) transformerItt.next();
195:
196: time = System.currentTimeMillis();
197: trans.setup(environment, environment.getObjectModel(),
198: (String) transformerSourceItt.next(),
199: (Parameters) transformerParamItt.next());
200: this .data.setSetupTime(index++, System
201: .currentTimeMillis()
202: - time);
203: }
204:
205: // Setup serializer
206: time = System.currentTimeMillis();
207: if (this .serializer instanceof SitemapModelComponent) {
208: ((SitemapModelComponent) this .serializer).setup(
209: environment, environment.getObjectModel(),
210: serializerSource, serializerParam);
211: }
212: this .data.setSetupTime(index++, System.currentTimeMillis()
213: - time);
214:
215: setMimeTypeForSerializer(environment);
216: } catch (SAXException e) {
217: throw new ProcessingException("Could not setup pipeline.",
218: e);
219: } catch (IOException e) {
220: throw new ProcessingException("Could not setup pipeline.",
221: e);
222: }
223:
224: // Generate the key to fill the cache
225: generateCachingKey(environment);
226:
227: // Test the cache for a valid response
228: if (this .toCacheKey != null) {
229: validatePipeline(environment);
230: }
231:
232: setupValidities();
233: }
234:
235: /**
236: * Process the given <code>Environment</code>, producing the output.
237: *
238: * @param environment
239: *
240: * @return true on success
241: */
242: public boolean process(Environment environment)
243: throws ProcessingException {
244: this .index = 0;
245: if (this .data != null) {
246: // Capture environment info
247: this .data.setEnvironmentInfo(new EnvironmentInfo(
248: environment));
249:
250: // Execute pipeline
251: long time = System.currentTimeMillis();
252: boolean result = super .process(environment);
253: this .data.setTotalTime(System.currentTimeMillis() - time);
254:
255: // Report
256: profiler.addResult(environment.getURI(), this .data);
257: return result;
258: } else {
259: getLogger().warn(
260: "Profiler data has no components to measure");
261: return super .process(environment);
262: }
263: }
264:
265: /**
266: * Process the SAX event pipeline
267: * FIXME: VG: Why override processXMLPipeline, not process(env, consumer)?
268: */
269: protected boolean processXMLPipeline(Environment environment)
270: throws ProcessingException {
271: this .index = 0;
272: if (this .data != null) {
273: // Capture environment info
274: this .data.setEnvironmentInfo(new EnvironmentInfo(
275: environment));
276:
277: // Execute pipeline
278: long time = System.currentTimeMillis();
279: boolean result = super .processXMLPipeline(environment);
280: this .data.setTotalTime(System.currentTimeMillis() - time);
281:
282: // Report
283: profiler.addResult(environment.getURI(), this .data);
284: return result;
285: } else {
286: getLogger().warn(
287: "Profiler data has no components to measure");
288: return super .processXMLPipeline(environment);
289: }
290: }
291:
292: /**
293: * Process the pipeline using a reader.
294: */
295: protected boolean processReader(Environment environment)
296: throws ProcessingException {
297: this .index = 0;
298: if (this .data != null) {
299: // Capture environment info
300: this .data.setEnvironmentInfo(new EnvironmentInfo(
301: environment));
302:
303: // Execute pipeline
304: long time = System.currentTimeMillis();
305: boolean result = super .processReader(environment);
306: this .data.setTotalTime(System.currentTimeMillis() - time);
307:
308: // Report
309: profiler.addResult(environment.getURI(), this .data);
310: return result;
311: } else {
312: getLogger().warn(
313: "Profiler data has no components to measure");
314: return super .processReader(environment);
315: }
316: }
317:
318: /**
319: * Connect the next component
320: *
321: * @param environment
322: * @param producer
323: * @param consumer
324: */
325: protected void connect(Environment environment,
326: XMLProducer producer, XMLConsumer consumer)
327: throws ProcessingException {
328: ProfilingXMLPipe connector = new ProfilingXMLPipe();
329: connector.setup(this.index, this.data);
330: this.index++;
331: super.connect(environment, producer, connector);
332: super.connect(environment, connector, consumer);
333: }
334: }
|