You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@cocoon.apache.org by vg...@apache.org on 2004/09/22 22:54:32 UTC
svn commit: rev 47074 - in cocoon/trunk/src: blocks/scratchpad/java/org/apache/cocoon/components/pipeline/impl java/org/apache/cocoon/components/pipeline java/org/apache/cocoon/components/pipeline/impl
Author: vgritsenko
Date: Wed Sep 22 13:54:31 2004
New Revision: 47074
Modified:
cocoon/trunk/src/blocks/scratchpad/java/org/apache/cocoon/components/pipeline/impl/ExpiresCachingProcessingPipeline.java
cocoon/trunk/src/java/org/apache/cocoon/components/pipeline/AbstractProcessingPipeline.java
cocoon/trunk/src/java/org/apache/cocoon/components/pipeline/impl/AbstractCachingProcessingPipeline.java
Log:
Unify pipeline exception handling. Add case for Tomcat5.
Modified: cocoon/trunk/src/blocks/scratchpad/java/org/apache/cocoon/components/pipeline/impl/ExpiresCachingProcessingPipeline.java
==============================================================================
--- cocoon/trunk/src/blocks/scratchpad/java/org/apache/cocoon/components/pipeline/impl/ExpiresCachingProcessingPipeline.java (original)
+++ cocoon/trunk/src/blocks/scratchpad/java/org/apache/cocoon/components/pipeline/impl/ExpiresCachingProcessingPipeline.java Wed Sep 22 13:54:31 2004
@@ -1,12 +1,12 @@
/*
* Copyright 1999-2004 The Apache Software Foundation.
- *
+ *
* Licensed 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.
@@ -15,15 +15,10 @@
*/
package org.apache.cocoon.components.pipeline.impl;
-import java.io.ByteArrayOutputStream;
-import java.io.OutputStream;
-import java.net.SocketException;
-import java.util.Map;
-
import org.apache.avalon.framework.parameters.ParameterException;
import org.apache.avalon.framework.parameters.Parameters;
import org.apache.avalon.framework.service.ServiceException;
-import org.apache.cocoon.ConnectionResetException;
+
import org.apache.cocoon.ProcessingException;
import org.apache.cocoon.caching.CachedResponse;
import org.apache.cocoon.caching.CachingOutputStream;
@@ -35,49 +30,54 @@
import org.apache.cocoon.environment.ObjectModelHelper;
import org.apache.cocoon.environment.Response;
import org.apache.cocoon.xml.XMLConsumer;
+
import org.apache.excalibur.source.SourceValidity;
import org.apache.excalibur.source.impl.validity.ExpiresValidity;
+import java.io.ByteArrayOutputStream;
+import java.io.OutputStream;
+import java.util.Map;
+
/**
* This pipeline implementation caches the complete content for a defined
- * period of time (expires).
- *
+ * period of time (expires).
+ *
* <map:pipe name="expires" src="org.apache.cocoon.components.pipeline.impl.ExpiresCachingProcessingPipeline">
* <parameter name="cache-expires" value="180"/> <!-- Expires in secondes -->
* </map:pipe>
- *
+ *
* @since 2.1
* @author <a href="mailto:cziegeler@apache.org">Carsten Ziegeler</a>
- * @version CVS $Id: ExpiresCachingProcessingPipeline.java,v 1.6 2004/07/16 12:36:45 sylvain Exp $
+ * @version CVS $Id$
*/
public class ExpiresCachingProcessingPipeline
extends BaseCachingProcessingPipeline {
/** This key can be used to put a key in the object model */
public static final String CACHE_KEY_KEY = ExpiresCachingProcessingPipeline.class.getName() + "/CacheKey";
-
+
/** This key can be used to put an expires information in the object model */
public static final String CACHE_EXPIRES_KEY = ExpiresCachingProcessingPipeline.class.getName() + "/Expires";
-
+
/** The source validity */
protected SourceValidity cacheValidity;
/** The key used for caching */
protected IdentifierCacheKey cacheKey;
-
+
/** The expires information */
protected long cacheExpires;
-
+
/** Default value for expiration */
protected long defaultCacheExpires = 3600; // 1 hour
-
+
/** The cached response */
protected CachedResponse cachedResponse;
-
+
public void parameterize(Parameters params)
throws ParameterException {
super.parameterize(params);
-
+
this.defaultCacheExpires = params.getParameterAsLong("cache-expires", this.defaultCacheExpires);
}
@@ -87,7 +87,7 @@
protected boolean processXMLPipeline(Environment environment)
throws ProcessingException {
try {
- if ( this.cachedResponse != null ) {
+ if (this.cachedResponse != null) {
byte[] content = cachedResponse.getResponse();
if ( this.serializer == this.lastConsumer ) {
@@ -108,19 +108,19 @@
if ( this.cacheExpires == 0 ) {
return super.processXMLPipeline( environment );
}
-
+
byte[] cachedData;
if ( this.serializer == this.lastConsumer ) {
-
+
if (this.serializer.shouldSetContentLength()) {
OutputStream os = environment.getOutputStream(this.outputBufferSize);
-
+
// set the output stream
ByteArrayOutputStream baos = new ByteArrayOutputStream();
this.serializer.setOutputStream(baos);
-
+
this.generator.generate();
-
+
cachedData = baos.toByteArray();
environment.setContentLength(cachedData.length);
os.write(cachedData);
@@ -129,38 +129,29 @@
// set the output stream
this.serializer.setOutputStream( os );
this.generator.generate();
-
+
cachedData = os.getContent();
}
-
+
} else {
this.generator.generate();
cachedData = (byte[])this.xmlSerializer.getSAXFragment();
}
+
//
// Now that we have processed the pipeline,
// we do the actual caching
//
- if ( this.cacheValidity != null ) {
+ if (this.cacheValidity != null) {
cachedResponse = new CachedResponse(this.cacheValidity,
cachedData);
- this.cache.store(this.cacheKey,
- cachedResponse);
+ this.cache.store(this.cacheKey, cachedResponse);
}
}
- } catch ( SocketException se ) {
- if (se.getMessage().indexOf("reset") > 0
- || se.getMessage().indexOf("aborted") > 0
- || se.getMessage().indexOf("connection abort") > 0) {
- throw new ConnectionResetException("Connection reset by peer", se);
- } else {
- throw new ProcessingException("Failed to execute pipeline.", se);
- }
- } catch ( ProcessingException pe ) {
- throw pe;
- } catch ( Exception e ) {
- throw new ProcessingException("Error executing pipeline.", e);
+ } catch (Exception e) {
+ handleException(e);
}
+
return true;
}
@@ -178,9 +169,9 @@
final XMLConsumer old = this.lastConsumer;
this.xmlSerializer = (XMLSerializer)this.manager.lookup( XMLSerializer.ROLE );
this.lastConsumer = new XMLTeePipe(this.lastConsumer, this.xmlSerializer);
-
+
super.connectPipeline( environment );
-
+
this.lastConsumer = old;
} catch ( ServiceException e ) {
throw new ProcessingException("Could not connect pipeline.", e);
@@ -205,7 +196,7 @@
}
/**
- * Prepare the pipeline
+ * Prepare the pipeline
*/
protected void preparePipeline(Environment environment)
throws ProcessingException {
@@ -228,37 +219,37 @@
this.cacheExpires = this.parameters.getParameterAsLong("cache-expires", this.defaultCacheExpires);
} else {
this.cacheExpires = Long.valueOf(expiresValue).longValue();
- objectModel.remove(CACHE_EXPIRES_KEY);
+ objectModel.remove(CACHE_EXPIRES_KEY);
}
-
+
// prepare the pipeline
super.preparePipeline( environment );
// and now prepare the caching information
- this.cacheKey = new IdentifierCacheKey(key,
+ this.cacheKey = new IdentifierCacheKey(key,
this.serializer == this.lastConsumer);
if ( this.cacheExpires > 0) {
- this.cacheValidity = new ExpiresValidity(this.cacheExpires*1000);
+ this.cacheValidity = new ExpiresValidity(this.cacheExpires*1000);
}
final boolean purge = this.parameters.getParameterAsBoolean("purge-cache", false);
-
+
this.cachedResponse = this.cache.get(this.cacheKey);
if ( this.cachedResponse != null ) {
final SourceValidity sv = cachedResponse.getValidityObjects()[0];
- if ( purge
+ if ( purge
|| (this.cacheExpires != -1 && sv.isValid() != SourceValidity.VALID) ) {
this.cache.remove( this.cacheKey );
this.cachedResponse = null;
}
}
- if ( this.cacheExpires > 0
+ if ( this.cacheExpires > 0
&& (this.reader != null || this.lastConsumer == this.serializer )) {
Response res = ObjectModelHelper.getResponse(environment.getObjectModel());
res.setDateHeader("Expires", System.currentTimeMillis() + (this.cacheExpires*1000));
res.setHeader("Cache-Control", "max-age=" + this.cacheExpires + ", public");
}
}
-
+
/**
* Return valid validity objects for the event pipeline
* If the "event pipeline" (= the complete pipeline without the
@@ -273,12 +264,12 @@
* @see org.apache.cocoon.components.pipeline.ProcessingPipeline#getKeyForEventPipeline()
*/
public String getKeyForEventPipeline() {
- if ( this.cacheKey != null && this.cacheValidity != null) {
+ if (this.cacheKey != null && this.cacheValidity != null) {
return this.cacheKey.toString();
}
return null;
}
-
+
/**
* Recyclable Interface
*/
@@ -295,30 +286,29 @@
protected boolean processReader(Environment environment)
throws ProcessingException {
try {
- if ( this.cachedResponse != null ) {
-
+ if (this.cachedResponse != null) {
final byte[] content = cachedResponse.getResponse();
environment.setContentLength(content.length);
-
+
final OutputStream os = environment.getOutputStream(0);
os.write(content);
-
+
} else {
// generate new response
if ( this.cacheExpires == 0 ) {
return super.processReader( environment );
}
-
+
byte[] cachedData;
-
+
if (this.reader.shouldSetContentLength()) {
final OutputStream os = environment.getOutputStream(this.outputBufferSize);
// set the output stream
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
this.reader.setOutputStream(baos);
-
+
this.reader.generate();
cachedData = baos.toByteArray();
@@ -329,7 +319,7 @@
// set the output stream
this.reader.setOutputStream( os );
this.reader.generate();
-
+
cachedData = os.getContent();
}
@@ -337,27 +327,16 @@
// Now that we have processed the pipeline,
// we do the actual caching
//
- if ( this.cacheValidity != null ) {
+ if (this.cacheValidity != null) {
cachedResponse = new CachedResponse(this.cacheValidity,
cachedData);
- this.cache.store(this.cacheKey,
- cachedResponse);
+ this.cache.store(this.cacheKey, cachedResponse);
}
}
- } catch ( SocketException se ) {
- if (se.getMessage().indexOf("reset") > 0
- || se.getMessage().indexOf("aborted") > 0
- || se.getMessage().indexOf("connection abort") > 0) {
- throw new ConnectionResetException("Connection reset by peer", se);
- } else {
- throw new ProcessingException("Failed to execute pipeline.", se);
- }
- } catch ( ProcessingException pe ) {
- throw pe;
- } catch ( Exception e ) {
- throw new ProcessingException("Error executing pipeline.", e);
+ } catch (Exception e) {
+ handleException(e);
}
+
return true;
}
-
}
Modified: cocoon/trunk/src/java/org/apache/cocoon/components/pipeline/AbstractProcessingPipeline.java
==============================================================================
--- cocoon/trunk/src/java/org/apache/cocoon/components/pipeline/AbstractProcessingPipeline.java (original)
+++ cocoon/trunk/src/java/org/apache/cocoon/components/pipeline/AbstractProcessingPipeline.java Wed Sep 22 13:54:31 2004
@@ -1,12 +1,12 @@
/*
* Copyright 1999-2004 The Apache Software Foundation.
- *
+ *
* Licensed 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.
@@ -15,14 +15,6 @@
*/
package org.apache.cocoon.components.pipeline;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.net.SocketException;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.NoSuchElementException;
-import java.util.StringTokenizer;
-
import org.apache.avalon.excalibur.pool.Recyclable;
import org.apache.avalon.framework.component.Component;
import org.apache.avalon.framework.logger.AbstractLogEnabled;
@@ -33,6 +25,7 @@
import org.apache.avalon.framework.service.ServiceManager;
import org.apache.avalon.framework.service.ServiceSelector;
import org.apache.avalon.framework.service.Serviceable;
+
import org.apache.cocoon.ConnectionResetException;
import org.apache.cocoon.ProcessingException;
import org.apache.cocoon.Processor;
@@ -48,17 +41,26 @@
import org.apache.cocoon.transformation.Transformer;
import org.apache.cocoon.xml.XMLConsumer;
import org.apache.cocoon.xml.XMLProducer;
+
import org.apache.excalibur.source.SourceValidity;
import org.xml.sax.SAXException;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.net.SocketException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+import java.util.StringTokenizer;
+
/**
* This is the base for all implementations of a <code>ProcessingPipeline</code>.
* It is advisable to inherit from this base class instead of doing a complete
* own implementation!
- *
+ *
* @since 2.1
* @author <a href="mailto:cziegeler@apache.org">Carsten Ziegeler</a>
- * @version CVS $Id: AbstractProcessingPipeline.java,v 1.27 2004/07/17 10:51:14 joerg Exp $
+ * @version CVS $Id$
*/
public abstract class AbstractProcessingPipeline
extends AbstractLogEnabled
@@ -115,13 +117,13 @@
/** Configured Output Buffer Size */
protected int configuredOutputBufferSize;
-
+
/** Output Buffer Size */
protected int outputBufferSize;
/** The current Processor */
protected Processor processor;
-
+
/**
* Composable Interface
*/
@@ -141,7 +143,7 @@
/**
* Parameterizable Interface - Configuration
*/
- public void parameterize(Parameters params)
+ public void parameterize(Parameters params)
throws ParameterException {
this.configuration = params;
final String expiresValue = params.getParameter("expires", null);
@@ -374,7 +376,7 @@
this.serializerParam
);
}
-
+
if (this.lastConsumer == null) {
// internal processing: text/xml
environment.setContentType("text/xml");
@@ -452,9 +454,9 @@
this.preparePipeline(environment);
}
if ( this.reader != null ) {
- this.preparePipeline(environment);
+ this.preparePipeline(environment);
}
-
+
// See if we need to set an "Expires:" header
if (this.expires != 0) {
Response res = ObjectModelHelper.getResponse(environment.getObjectModel());
@@ -480,7 +482,7 @@
}
/**
- * Prepare the pipeline
+ * Prepare the pipeline
*/
protected void preparePipeline(Environment environment)
throws ProcessingException {
@@ -496,7 +498,7 @@
this.setupPipeline(environment);
}
}
-
+
/**
* Prepare an internal processing
* @param environment The current environment.
@@ -507,7 +509,7 @@
this.lastConsumer = null;
this.preparePipeline(environment);
}
-
+
/**
* Process the SAX event pipeline
*/
@@ -523,7 +525,7 @@
// set the output stream
ByteArrayOutputStream os = new ByteArrayOutputStream();
this.serializer.setOutputStream(os);
-
+
// execute the pipeline:
this.generator.generate();
environment.setContentLength(os.size());
@@ -557,14 +559,14 @@
// Ask the Reader for a MIME type:
// A *.doc reader could peek into the file
// and return either text/plain or application/vnd.msword or
- // the reader can use MIME type declared in WEB-INF/web.xml or
+ // the reader can use MIME type declared in WEB-INF/web.xml or
// by the server.
if ( this.readerMimeType != null ) {
environment.setContentType(this.readerMimeType);
} else {
final String mimeType = this.reader.getMimeType();
if (mimeType != null) {
- environment.setContentType(mimeType);
+ environment.setContentType(mimeType);
}
}
// set the expires parameter on the pipeline if the reader is configured with one
@@ -575,7 +577,7 @@
} catch (SAXException e){
throw new ProcessingException("Failed to execute reader pipeline.", e);
} catch (ParameterException e) {
- throw new ProcessingException("Expires parameter needs to be of type long.",e);
+ throw new ProcessingException("Expires parameter needs to be of type long.",e);
} catch (IOException e){
throw new ProcessingException("Failed to execute reader pipeline.", e);
}
@@ -610,19 +612,10 @@
this.reader.setOutputStream(environment.getOutputStream(this.outputBufferSize));
this.reader.generate();
}
- } catch ( SocketException se ) {
- if (se.getMessage().indexOf("reset") > 0
- || se.getMessage().indexOf("aborted") > 0
- || se.getMessage().indexOf("connection abort") > 0) {
- throw new ConnectionResetException("Connection reset by peer", se);
- } else {
- throw new ProcessingException("Failed to execute reader pipeline.", se);
- }
- } catch ( ProcessingException e ) {
- throw e;
- } catch ( Exception e ) {
- throw new ProcessingException("Error executing reader pipeline.",e);
+ } catch (Exception e) {
+ handleException(e);
}
+
return true;
}
@@ -774,7 +767,7 @@
public String getKeyForEventPipeline() {
return null;
}
-
+
protected String getLocation(Parameters param) {
String value = null;
if ( param instanceof SitemapParameters ) {
@@ -784,5 +777,29 @@
value = "[unknown location]";
}
return value;
+ }
+
+ /**
+ * Handles exception which can happen during pipeline processing.
+ * @throws ConnectionResetException if connection reset detected
+ * @throws ProcessingException in all other cases
+ */
+ protected void handleException(Exception e) throws ProcessingException {
+ if (e instanceof SocketException) {
+ if (e.getMessage().indexOf("reset") > 0
+ || e.getMessage().indexOf("aborted") > 0
+ || e.getMessage().indexOf("connection abort") > 0) {
+ throw new ConnectionResetException("Connection reset by peer", e);
+ }
+ } else if (e instanceof IOException) {
+ // Tomcat5 wraps SocketException into ClientAbortException which extends IOException.
+ if (e.getClass().getName().endsWith("ClientAbortException")) {
+ throw new ConnectionResetException("Connection reset by peer", e);
+ }
+ } else if (e instanceof ProcessingException) {
+ throw (ProcessingException) e;
+ }
+
+ throw new ProcessingException("Error executing pipeline.", e);
}
}
Modified: cocoon/trunk/src/java/org/apache/cocoon/components/pipeline/impl/AbstractCachingProcessingPipeline.java
==============================================================================
--- cocoon/trunk/src/java/org/apache/cocoon/components/pipeline/impl/AbstractCachingProcessingPipeline.java (original)
+++ cocoon/trunk/src/java/org/apache/cocoon/components/pipeline/impl/AbstractCachingProcessingPipeline.java Wed Sep 22 13:54:31 2004
@@ -15,16 +15,9 @@
*/
package org.apache.cocoon.components.pipeline.impl;
-import java.io.ByteArrayOutputStream;
-import java.io.OutputStream;
-import java.io.Serializable;
-import java.net.SocketException;
-import java.util.ArrayList;
-import java.util.Date;
-
import org.apache.avalon.framework.parameters.ParameterException;
import org.apache.avalon.framework.parameters.Parameters;
-import org.apache.cocoon.ConnectionResetException;
+
import org.apache.cocoon.ProcessingException;
import org.apache.cocoon.caching.CacheableProcessingComponent;
import org.apache.cocoon.caching.CachedResponse;
@@ -34,10 +27,17 @@
import org.apache.cocoon.environment.Environment;
import org.apache.cocoon.transformation.Transformer;
import org.apache.cocoon.util.HashUtil;
+
import org.apache.excalibur.source.SourceValidity;
import org.apache.excalibur.source.impl.validity.AggregatedValidity;
import org.apache.excalibur.source.impl.validity.DeferredValidity;
+import java.io.ByteArrayOutputStream;
+import java.io.OutputStream;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Date;
+
/**
* This is the base class for all caching pipeline implementations
* that check the different pipeline components.
@@ -164,6 +164,7 @@
throws ProcessingException {
if (this.toCacheKey == null && this.cachedResponse == null) {
return super.processXMLPipeline(environment);
+
} else if (this.cachedResponse != null
&& this.completeResponseIsCached) {
@@ -179,29 +180,16 @@
environment.setContentLength(this.cachedResponse.length);
outputStream.write(this.cachedResponse);
}
- } catch (SocketException se) {
- if (se.getMessage().indexOf("reset") > 0
- || se.getMessage().indexOf("aborted") > 0
- || se.getMessage().indexOf("connection abort") > 0) {
- throw new ConnectionResetException(
- "Connection reset by peer", se);
- } else {
- throw new ProcessingException(
- "Failed to execute pipeline.", se);
- }
} catch (Exception e) {
- if (e instanceof ProcessingException)
- throw (ProcessingException)e;
- throw new ProcessingException("Error executing pipeline.", e);
+ handleException(e);
}
} else {
-
- if (this.getLogger().isDebugEnabled() && this.toCacheKey != null) {
- this.getLogger().debug(
- "processXMLPipeline: caching content for further" +
- " requests of '" + environment.getURI() +
- "' using key " + this.toCacheKey);
+ if (getLogger().isDebugEnabled() && this.toCacheKey != null) {
+ getLogger().debug("processXMLPipeline: caching content for further" +
+ " requests of '" + environment.getURI() +
+ "' using key " + this.toCacheKey);
}
+
try {
OutputStream os = null;
@@ -255,23 +243,15 @@
// Now that we have processed the pipeline,
// we do the actual caching
//
- this.cacheResults(environment,os);
-
- } catch (SocketException se) {
- if (se.getMessage().indexOf("reset") > 0
- || se.getMessage().indexOf("aborted") > 0
- || se.getMessage().indexOf("connection abort") > 0) {
- throw new ConnectionResetException("Connection reset by peer", se);
- }
+ cacheResults(environment,os);
- throw new ProcessingException("Failed to execute pipeline.", se);
- } catch (ProcessingException e) {
- throw e;
} catch (Exception e) {
- throw new ProcessingException("Failed to execute pipeline.", e);
+ handleException(e);
}
+
return true;
}
+
return true;
}
@@ -749,7 +729,6 @@
}
}
-
if (this.reader.shouldSetContentLength()) {
ByteArrayOutputStream os = new ByteArrayOutputStream();
this.reader.setOutputStream(os);
@@ -776,18 +755,8 @@
);
}
}
- } catch ( SocketException se ) {
- if (se.getMessage().indexOf("reset") > 0
- || se.getMessage().indexOf("aborted") > 0
- || se.getMessage().indexOf("connection abort") > 0) {
- throw new ConnectionResetException("Connection reset by peer", se);
- } else {
- throw new ProcessingException("Failed to execute pipeline.", se);
- }
- } catch ( ProcessingException e ) {
- throw e;
- } catch ( Exception e ) {
- throw new ProcessingException("Failed to execute pipeline.", e);
+ } catch (Exception e) {
+ handleException(e);
}
return true;
@@ -810,7 +779,7 @@
} else {
int vals = 0;
-
+
if ( null != this.toCacheKey
&& !this.cacheCompleteResponse
&& this.firstNotCacheableTransformerIndex == super.transformers.size()) {