Source Code Cross Referenced for AbstractProcessingPipeline.java in  » Web-Framework » cocoon » org » apache » cocoon » components » pipeline » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Web Framework » cocoon » org.apache.cocoon.components.pipeline 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Licensed to the Apache Software Foundation (ASF) under one or more
0003:         * contributor license agreements.  See the NOTICE file distributed with
0004:         * this work for additional information regarding copyright ownership.
0005:         * The ASF licenses this file to You under the Apache License, Version 2.0
0006:         * (the "License"); you may not use this file except in compliance with
0007:         * the License.  You may obtain a copy of the License at
0008:         *
0009:         *      http://www.apache.org/licenses/LICENSE-2.0
0010:         *
0011:         * Unless required by applicable law or agreed to in writing, software
0012:         * distributed under the License is distributed on an "AS IS" BASIS,
0013:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014:         * See the License for the specific language governing permissions and
0015:         * limitations under the License.
0016:         */
0017:        package org.apache.cocoon.components.pipeline;
0018:
0019:        import java.io.ByteArrayOutputStream;
0020:        import java.io.IOException;
0021:        import java.net.SocketException;
0022:        import java.util.ArrayList;
0023:        import java.util.Iterator;
0024:        import java.util.NoSuchElementException;
0025:        import java.util.StringTokenizer;
0026:
0027:        import org.apache.avalon.excalibur.pool.Recyclable;
0028:        import org.apache.avalon.framework.component.Component;
0029:        import org.apache.avalon.framework.component.ComponentException;
0030:        import org.apache.avalon.framework.component.ComponentManager;
0031:        import org.apache.avalon.framework.component.ComponentSelector;
0032:        import org.apache.avalon.framework.logger.AbstractLogEnabled;
0033:        import org.apache.avalon.framework.parameters.ParameterException;
0034:        import org.apache.avalon.framework.parameters.Parameterizable;
0035:        import org.apache.avalon.framework.parameters.Parameters;
0036:        import org.apache.cocoon.ConnectionResetException;
0037:        import org.apache.cocoon.ProcessingException;
0038:        import org.apache.cocoon.components.CocoonComponentManager;
0039:        import org.apache.cocoon.environment.Environment;
0040:        import org.apache.cocoon.environment.ObjectModelHelper;
0041:        import org.apache.cocoon.environment.Response;
0042:        import org.apache.cocoon.generation.Generator;
0043:        import org.apache.cocoon.reading.Reader;
0044:        import org.apache.cocoon.serialization.Serializer;
0045:        import org.apache.cocoon.sitemap.SitemapErrorHandler;
0046:        import org.apache.cocoon.sitemap.SitemapModelComponent;
0047:        import org.apache.cocoon.transformation.Transformer;
0048:        import org.apache.cocoon.util.location.Locatable;
0049:        import org.apache.cocoon.util.location.Location;
0050:        import org.apache.cocoon.xml.SaxBuffer;
0051:        import org.apache.cocoon.xml.XMLConsumer;
0052:        import org.apache.cocoon.xml.XMLProducer;
0053:        import org.apache.excalibur.source.SourceValidity;
0054:        import org.xml.sax.SAXException;
0055:
0056:        /**
0057:         * This is the base for all implementations of a <code>ProcessingPipeline</code>.
0058:         *
0059:         * @since 2.1
0060:         * @author <a href="mailto:cziegeler@apache.org">Carsten Ziegeler</a>
0061:         * @version CVS $Id: AbstractProcessingPipeline.java 451148 2006-09-29 07:50:00Z anathaniel $
0062:         */
0063:        public abstract class AbstractProcessingPipeline extends
0064:                AbstractLogEnabled implements  ProcessingPipeline,
0065:                Parameterizable, Recyclable {
0066:
0067:            // Generator stuff
0068:            protected Generator generator;
0069:            protected Parameters generatorParam;
0070:            protected String generatorSource;
0071:            protected ComponentSelector generatorSelector;
0072:
0073:            // Transformer stuff
0074:            protected ArrayList transformers = new ArrayList();
0075:            protected ArrayList transformerParams = new ArrayList();
0076:            protected ArrayList transformerSources = new ArrayList();
0077:            protected ArrayList transformerSelectors = new ArrayList();
0078:
0079:            // Serializer stuff
0080:            protected Serializer serializer;
0081:            protected Parameters serializerParam;
0082:            protected String serializerSource;
0083:            protected String serializerMimeType;
0084:            protected String sitemapSerializerMimeType;
0085:            protected OutputComponentSelector serializerSelector;
0086:
0087:            // Reader stuff
0088:            protected Reader reader;
0089:            protected Parameters readerParam;
0090:            protected String readerSource;
0091:            protected String readerMimeType;
0092:            protected String sitemapReaderMimeType;
0093:            protected OutputComponentSelector readerSelector;
0094:
0095:            // Error handler stuff
0096:            private SitemapErrorHandler errorHandler;
0097:            private ProcessingPipeline errorPipeline;
0098:
0099:            /** True when pipeline has been prepared. */
0100:            private boolean prepared;
0101:
0102:            /**
0103:             * This is the last component in the pipeline, either the serializer
0104:             * or a custom XML consumer in case of internal processing.
0105:             */
0106:            protected XMLConsumer lastConsumer;
0107:
0108:            /** The component manager set with compose() */
0109:            protected ComponentManager manager;
0110:
0111:            /** The component manager set with compose() and recompose() */
0112:            protected ComponentManager newManager;
0113:
0114:            /** The configuration */
0115:            protected Parameters configuration;
0116:
0117:            /** Configured Expires value */
0118:            protected long configuredExpires;
0119:
0120:            /** Configured Output Buffer Size */
0121:            protected int configuredOutputBufferSize;
0122:
0123:            /** The parameters */
0124:            protected Parameters parameters;
0125:
0126:            /** Expires value */
0127:            protected long expires;
0128:
0129:            /** Output Buffer Size */
0130:            protected int outputBufferSize;
0131:
0132:            /**
0133:             * Composable Interface
0134:             */
0135:            public void compose(ComponentManager manager)
0136:                    throws ComponentException {
0137:                this .manager = manager;
0138:                this .newManager = manager;
0139:            }
0140:
0141:            /**
0142:             * Recomposable Interface
0143:             */
0144:            public void recompose(ComponentManager manager)
0145:                    throws ComponentException {
0146:                this .newManager = manager;
0147:            }
0148:
0149:            /**
0150:             * Parameterizable Interface - Configuration
0151:             */
0152:            public void parameterize(Parameters params)
0153:                    throws ParameterException {
0154:                this .configuration = params;
0155:                final String expiresValue = params
0156:                        .getParameter("expires", null);
0157:                if (expiresValue != null) {
0158:                    this .configuredExpires = parseExpires(expiresValue);
0159:                }
0160:                this .configuredOutputBufferSize = params.getParameterAsInteger(
0161:                        "outputBufferSize", -1);
0162:            }
0163:
0164:            /**
0165:             * Setup this component
0166:             */
0167:            public void setup(Parameters params) {
0168:                this .parameters = params;
0169:                final String expiresValue = params
0170:                        .getParameter("expires", null);
0171:                if (expiresValue != null) {
0172:                    this .expires = parseExpires(expiresValue);
0173:                } else {
0174:                    this .expires = this .configuredExpires;
0175:                }
0176:                this .outputBufferSize = params.getParameterAsInteger(
0177:                        "outputBufferSize", this .configuredOutputBufferSize);
0178:            }
0179:
0180:            /**
0181:             * Release this component.
0182:             * If you get an instance not by a component manager but for example
0183:             * by a processor, you have to release this component by calling
0184:             * this method and NOT by using a component manager!
0185:             */
0186:            public void release() {
0187:                try {
0188:                    CocoonComponentManager.removeFromAutomaticRelease(this );
0189:                } catch (ProcessingException e) {
0190:                    // ignore this
0191:                    getLogger()
0192:                            .error(
0193:                                    "Unable to release self from automatic release.",
0194:                                    e);
0195:                }
0196:            }
0197:
0198:            /**
0199:             * Informs pipeline we have come across a branch point.
0200:             * Default behaviour is do nothing.
0201:             */
0202:            public void informBranchPoint() {
0203:                // this can be overwritten in subclasses
0204:            }
0205:
0206:            /**
0207:             * Get the generator - used for content aggregation
0208:             */
0209:            public Generator getGenerator() {
0210:                return this .generator;
0211:            }
0212:
0213:            /**
0214:             * Set the generator that will be used as the initial step in the pipeline.
0215:             * The generator role is given : the actual <code>Generator</code> is fetched
0216:             * from the latest <code>ComponentManager</code> given by <code>compose()</code>
0217:             * or <code>recompose()</code>.
0218:             *
0219:             * @param role the generator role in the component manager.
0220:             * @param source the source where to produce XML from, or <code>null</code> if no
0221:             *        source is given.
0222:             * @param param the parameters for the generator.
0223:             * @throws ProcessingException if the generator couldn't be obtained.
0224:             */
0225:            public void setGenerator(String role, String source,
0226:                    Parameters param, Parameters hintParam)
0227:                    throws ProcessingException {
0228:                if (this .generator != null) {
0229:                    throw new ProcessingException(
0230:                            "Generator already set. Cannot set generator '"
0231:                                    + role + "'", getLocation(param));
0232:                }
0233:                if (this .reader != null) {
0234:                    throw new ProcessingException(
0235:                            "Reader already set. Cannot set generator '" + role
0236:                                    + "'", getLocation(param));
0237:                }
0238:                try {
0239:                    this .generatorSelector = (ComponentSelector) this .newManager
0240:                            .lookup(Generator.ROLE + "Selector");
0241:                } catch (ComponentException ce) {
0242:                    throw ProcessingException.throwLocated(
0243:                            "Lookup of generator selector failed", ce,
0244:                            getLocation(param));
0245:                }
0246:                try {
0247:                    this .generator = (Generator) this .generatorSelector
0248:                            .select(role);
0249:                } catch (ComponentException ce) {
0250:                    throw ProcessingException.throwLocated(
0251:                            "Lookup of generator '" + role + "' failed", ce,
0252:                            getLocation(param));
0253:                }
0254:                this .generatorSource = source;
0255:                this .generatorParam = param;
0256:            }
0257:
0258:            /**
0259:             * Add a transformer at the end of the pipeline.
0260:             * The transformer role is given : the actual <code>Transformer</code> is fetched
0261:             * from the latest <code>ComponentManager</code> given by <code>compose()</code>
0262:             * or <code>recompose()</code>.
0263:             *
0264:             * @param role the transformer role in the component manager.
0265:             * @param source the source used to setup the transformer (e.g. XSL file), or
0266:             *        <code>null</code> if no source is given.
0267:             * @param param the parameters for the transfomer.
0268:             * @throws ProcessingException if the generator couldn't be obtained.
0269:             */
0270:            public void addTransformer(String role, String source,
0271:                    Parameters param, Parameters hintParam)
0272:                    throws ProcessingException {
0273:                if (this .reader != null) {
0274:                    // Should normally never happen as setting a reader starts pipeline processing
0275:                    throw new ProcessingException(
0276:                            "Reader already set. Cannot add transformer '"
0277:                                    + role + "'", getLocation(param));
0278:                }
0279:                if (this .generator == null) {
0280:                    throw new ProcessingException(
0281:                            "Must set a generator before adding transformer '"
0282:                                    + role + "'", getLocation(param));
0283:                }
0284:                ComponentSelector selector = null;
0285:                try {
0286:                    selector = (ComponentSelector) this .newManager
0287:                            .lookup(Transformer.ROLE + "Selector");
0288:                } catch (ComponentException ce) {
0289:                    throw ProcessingException.throwLocated(
0290:                            "Lookup of transformer selector failed", ce,
0291:                            getLocation(param));
0292:                }
0293:                try {
0294:                    this .transformers.add(selector.select(role));
0295:                    this .transformerSelectors.add(selector);
0296:                } catch (ComponentException ce) {
0297:                    throw ProcessingException.throwLocated(
0298:                            "Lookup of transformer '" + role + "' failed", ce,
0299:                            getLocation(param));
0300:                }
0301:                this .transformerSources.add(source);
0302:                this .transformerParams.add(param);
0303:            }
0304:
0305:            /**
0306:             * Set the serializer for this pipeline
0307:             * @param mimeType Can be null
0308:             */
0309:            public void setSerializer(String role, String source,
0310:                    Parameters param, Parameters hintParam, String mimeType)
0311:                    throws ProcessingException {
0312:                if (this .serializer != null) {
0313:                    // Should normally not happen as adding a serializer starts pipeline processing
0314:                    throw new ProcessingException(
0315:                            "Serializer already set. Cannot set serializer '"
0316:                                    + role + "'", getLocation(param));
0317:                }
0318:                if (this .reader != null) {
0319:                    // Should normally never happen as setting a reader starts pipeline processing
0320:                    throw new ProcessingException(
0321:                            "Reader already set. Cannot set serializer '"
0322:                                    + role + "'", getLocation(param));
0323:                }
0324:                if (this .generator == null) {
0325:                    throw new ProcessingException(
0326:                            "Must set a generator before setting serializer '"
0327:                                    + role + "'", getLocation(param));
0328:                }
0329:
0330:                try {
0331:                    this .serializerSelector = (OutputComponentSelector) this .newManager
0332:                            .lookup(Serializer.ROLE + "Selector");
0333:                } catch (ComponentException ce) {
0334:                    throw ProcessingException.throwLocated(
0335:                            "Lookup of serializer selector failed", ce,
0336:                            getLocation(param));
0337:                }
0338:                try {
0339:                    this .serializer = (Serializer) serializerSelector
0340:                            .select(role);
0341:                } catch (ComponentException ce) {
0342:                    throw ProcessingException.throwLocated(
0343:                            "Lookup of serializer '" + role + "' failed", ce,
0344:                            getLocation(param));
0345:                }
0346:                this .serializerSource = source;
0347:                this .serializerParam = param;
0348:                this .serializerMimeType = mimeType;
0349:                this .sitemapSerializerMimeType = serializerSelector
0350:                        .getMimeTypeForHint(role);
0351:                this .lastConsumer = this .serializer;
0352:            }
0353:
0354:            /**
0355:             * Set the reader for this pipeline
0356:             * @param mimeType Can be null
0357:             */
0358:            public void setReader(String role, String source, Parameters param,
0359:                    String mimeType) throws ProcessingException {
0360:                if (this .reader != null) {
0361:                    // Should normally never happen as setting a reader starts pipeline processing
0362:                    throw new ProcessingException(
0363:                            "Reader already set. Cannot set reader '" + role
0364:                                    + "'", getLocation(param));
0365:                }
0366:                if (this .generator != null) {
0367:                    // Should normally never happen as setting a reader starts pipeline processing
0368:                    throw new ProcessingException(
0369:                            "Generator already set. Cannot use reader '" + role
0370:                                    + "'", getLocation(param));
0371:                }
0372:
0373:                try {
0374:                    this .readerSelector = (OutputComponentSelector) this .newManager
0375:                            .lookup(Reader.ROLE + "Selector");
0376:                } catch (ComponentException ce) {
0377:                    throw ProcessingException.throwLocated(
0378:                            "Lookup of reader selector failed", ce,
0379:                            getLocation(param));
0380:                }
0381:                try {
0382:                    this .reader = (Reader) readerSelector.select(role);
0383:                } catch (ComponentException ce) {
0384:                    throw ProcessingException.throwLocated("Lookup of reader '"
0385:                            + role + "' failed", ce, getLocation(param));
0386:                }
0387:                this .readerSource = source;
0388:                this .readerParam = param;
0389:                this .readerMimeType = mimeType;
0390:                this .sitemapReaderMimeType = readerSelector
0391:                        .getMimeTypeForHint(role);
0392:            }
0393:
0394:            /**
0395:             * Sets error handler for this pipeline.
0396:             * Used for handling errors in the internal pipelines.
0397:             * @param errorHandler error handler
0398:             */
0399:            public void setErrorHandler(SitemapErrorHandler errorHandler) {
0400:                this .errorHandler = errorHandler;
0401:            }
0402:
0403:            /**
0404:             * Sanity check
0405:             * @return true if the pipeline is 'sane', false otherwise.
0406:             */
0407:            protected boolean checkPipeline() {
0408:                if (this .generator == null && this .reader == null) {
0409:                    return false;
0410:                }
0411:
0412:                if (this .generator != null && this .serializer == null) {
0413:                    return false;
0414:                }
0415:
0416:                return true;
0417:            }
0418:
0419:            /**
0420:             * Setup pipeline components.
0421:             */
0422:            protected void setupPipeline(Environment environment)
0423:                    throws ProcessingException {
0424:                try {
0425:                    // setup the generator
0426:                    this .generator.setup(environment, environment
0427:                            .getObjectModel(), generatorSource, generatorParam);
0428:
0429:                    Iterator transformerItt = this .transformers.iterator();
0430:                    Iterator transformerSourceItt = this .transformerSources
0431:                            .iterator();
0432:                    Iterator transformerParamItt = this .transformerParams
0433:                            .iterator();
0434:
0435:                    while (transformerItt.hasNext()) {
0436:                        Transformer trans = (Transformer) transformerItt.next();
0437:                        trans.setup(environment, environment.getObjectModel(),
0438:                                (String) transformerSourceItt.next(),
0439:                                (Parameters) transformerParamItt.next());
0440:                    }
0441:
0442:                    if (this .serializer instanceof  SitemapModelComponent) {
0443:                        ((SitemapModelComponent) this .serializer).setup(
0444:                                environment, environment.getObjectModel(),
0445:                                this .serializerSource, this .serializerParam);
0446:                    }
0447:                } catch (Exception e) {
0448:                    handleException(e);
0449:                }
0450:            }
0451:
0452:            /**
0453:             * Connect the next component
0454:             */
0455:            protected void connect(Environment environment,
0456:                    XMLProducer producer, XMLConsumer consumer)
0457:                    throws ProcessingException {
0458:                // Connect next component.
0459:                producer.setConsumer(consumer);
0460:            }
0461:
0462:            /**
0463:             * Connect the XML pipeline.
0464:             */
0465:            protected void connectPipeline(Environment environment)
0466:                    throws ProcessingException {
0467:                XMLProducer prev = this .generator;
0468:
0469:                Iterator itt = this .transformers.iterator();
0470:                while (itt.hasNext()) {
0471:                    Transformer next = (Transformer) itt.next();
0472:                    connect(environment, prev, next);
0473:                    prev = next;
0474:                }
0475:
0476:                // insert the serializer
0477:                connect(environment, prev, this .lastConsumer);
0478:            }
0479:
0480:            /**
0481:             * Process the given <code>Environment</code>, producing the output.
0482:             */
0483:            public boolean process(Environment environment)
0484:                    throws ProcessingException {
0485:                if (!this .prepared) {
0486:                    preparePipeline(environment);
0487:                }
0488:
0489:                // See if we need to set an "Expires:" header
0490:                if (this .expires != 0) {
0491:                    Response res = ObjectModelHelper.getResponse(environment
0492:                            .getObjectModel());
0493:                    res.setDateHeader("Expires", System.currentTimeMillis()
0494:                            + expires);
0495:                    res.setHeader("Cache-Control", "max-age=" + expires / 1000
0496:                            + ", public");
0497:                    if (getLogger().isDebugEnabled()) {
0498:                        getLogger()
0499:                                .debug(
0500:                                        "Setting a new Expires object for this resource");
0501:                    }
0502:                    environment.getObjectModel().put(
0503:                            ObjectModelHelper.EXPIRES_OBJECT,
0504:                            new Long(expires + System.currentTimeMillis()));
0505:                }
0506:
0507:                if (this .reader != null) {
0508:                    if (checkIfModified(environment, this .reader
0509:                            .getLastModified())) {
0510:                        return true;
0511:                    }
0512:
0513:                    return processReader(environment);
0514:                } else {
0515:                    // If this is an internal request, lastConsumer was reset!
0516:                    if (this .lastConsumer == null) {
0517:                        this .lastConsumer = this .serializer;
0518:                    }
0519:
0520:                    connectPipeline(environment);
0521:                    return processXMLPipeline(environment);
0522:                }
0523:            }
0524:
0525:            /**
0526:             * Prepare the pipeline
0527:             */
0528:            protected void preparePipeline(Environment environment)
0529:                    throws ProcessingException {
0530:                if (!checkPipeline()) {
0531:                    throw new ProcessingException(
0532:                            "Attempted to process incomplete pipeline.");
0533:                }
0534:
0535:                if (this .prepared) {
0536:                    throw new ProcessingException(
0537:                            "Duplicate preparePipeline call caught.");
0538:                }
0539:
0540:                if (this .reader != null) {
0541:                    setupReader(environment);
0542:                } else {
0543:                    setupPipeline(environment);
0544:                }
0545:                this .prepared = true;
0546:            }
0547:
0548:            /**
0549:             * Prepare an internal processing.
0550:             * @param environment The current environment.
0551:             * @throws ProcessingException
0552:             */
0553:            public void prepareInternal(Environment environment)
0554:                    throws ProcessingException {
0555:                this .lastConsumer = null;
0556:                try {
0557:                    preparePipeline(environment);
0558:                } catch (ProcessingException e) {
0559:                    prepareInternalErrorHandler(environment, e);
0560:                }
0561:            }
0562:
0563:            /**
0564:             * If prepareInternal fails, prepare internal error handler.
0565:             */
0566:            protected void prepareInternalErrorHandler(Environment environment,
0567:                    ProcessingException ex) throws ProcessingException {
0568:                if (this .errorHandler != null) {
0569:                    try {
0570:                        this .errorPipeline = this .errorHandler
0571:                                .prepareErrorPipeline(ex);
0572:                        if (this .errorPipeline != null) {
0573:                            this .errorPipeline.prepareInternal(environment);
0574:                            return;
0575:                        }
0576:                    } catch (ProcessingException e) {
0577:                        // Log the original exception
0578:                        getLogger()
0579:                                .error(
0580:                                        "Failed to process error handler for exception",
0581:                                        ex);
0582:                        throw e;
0583:                    } catch (Exception e) {
0584:                        getLogger()
0585:                                .error(
0586:                                        "Failed to process error handler for exception",
0587:                                        ex);
0588:                        throw new ProcessingException(
0589:                                "Failed to handle exception <"
0590:                                        + ex.getMessage() + ">", e);
0591:                    }
0592:                } else {
0593:                    // propagate exception if we have no error handler
0594:                    throw ex;
0595:                }
0596:            }
0597:
0598:            /**
0599:             * @return true if error happened during internal pipeline prepare call.
0600:             */
0601:            protected boolean isInternalError() {
0602:                return this .errorPipeline != null;
0603:            }
0604:
0605:            /**
0606:             * Process the SAX event pipeline
0607:             */
0608:            protected boolean processXMLPipeline(Environment environment)
0609:                    throws ProcessingException {
0610:
0611:                setMimeTypeForSerializer(environment);
0612:                try {
0613:                    if (this .lastConsumer == null) {
0614:                        // internal processing
0615:                        this .generator.generate();
0616:                    } else {
0617:                        if (this .serializer.shouldSetContentLength()) {
0618:                            // set the output stream
0619:                            ByteArrayOutputStream os = new ByteArrayOutputStream();
0620:                            this .serializer.setOutputStream(os);
0621:
0622:                            // execute the pipeline:
0623:                            this .generator.generate();
0624:                            environment.setContentLength(os.size());
0625:                            os.writeTo(environment.getOutputStream(0));
0626:                        } else {
0627:                            // set the output stream
0628:                            this .serializer.setOutputStream(environment
0629:                                    .getOutputStream(this .outputBufferSize));
0630:                            // execute the pipeline:
0631:                            this .generator.generate();
0632:                        }
0633:                    }
0634:                } catch (Exception e) {
0635:                    handleException(e);
0636:                }
0637:
0638:                return true;
0639:            }
0640:
0641:            /**
0642:             * Setup the reader
0643:             */
0644:            protected void setupReader(Environment environment)
0645:                    throws ProcessingException {
0646:                try {
0647:                    this .reader.setup(environment,
0648:                            environment.getObjectModel(), readerSource,
0649:                            readerParam);
0650:                    // set the expires parameter on the pipeline if the reader is configured with one
0651:                    if (readerParam.isParameter("expires")) {
0652:                        // should this checking be done somewhere else??
0653:                        this .expires = readerParam
0654:                                .getParameterAsLong("expires");
0655:                    }
0656:                } catch (Exception e) {
0657:                    handleException(e);
0658:                }
0659:            }
0660:
0661:            /**
0662:             * Set the mime-type for a reader
0663:             * @param environment The current environment
0664:             */
0665:            protected void setMimeTypeForReader(Environment environment)
0666:                    throws ProcessingException {
0667:                // Set the mime-type
0668:                // the behaviour has changed from 2.1.6 to 2.1.7 according to bugs #10277 and #25121:
0669:                // MIME type declared in the sitemap (instance or declaration, in this order)
0670:                // Ask the Reader for a MIME type:
0671:                //     A *.doc reader could peek into the file
0672:                //     and return either text/plain or application/vnd.msword or
0673:                //     the reader can use MIME type declared in WEB-INF/web.xml or
0674:                //     by the server.
0675:                if (this .readerMimeType != null) {
0676:                    // there was a mime-type defined on map:read in the sitemap
0677:                    environment.setContentType(this .readerMimeType);
0678:                } else if (this .sitemapReaderMimeType != null) {
0679:                    // there was a mime-type defined on map:reader in the sitemap
0680:                    environment.setContentType(this .sitemapReaderMimeType);
0681:                } else {
0682:                    // ask to the component itself
0683:                    final String mimeType = this .reader.getMimeType();
0684:                    if (mimeType != null) {
0685:                        environment.setContentType(mimeType);
0686:                    }
0687:                    // If no mimeType available, leave to to upstream proxy
0688:                    // or browser to deduce content-type from URL extension.
0689:                }
0690:            }
0691:
0692:            /**
0693:             * Set the mime-type for a serializer
0694:             * @param environment The current environment
0695:             */
0696:            protected void setMimeTypeForSerializer(Environment environment)
0697:                    throws ProcessingException {
0698:                if (this .lastConsumer == null) {
0699:                    // internal processing: text/xml
0700:                    environment.setContentType("text/xml");
0701:                } else {
0702:                    // Set the mime-type
0703:                    // the behaviour has changed from 2.1.6 to 2.1.7 according to bugs #10277 and #25121:
0704:                    if (serializerMimeType != null) {
0705:                        // there was a mime-type defined on map:serialize in the sitemap
0706:                        environment.setContentType(serializerMimeType);
0707:                    } else if (sitemapSerializerMimeType != null) {
0708:                        // there was a mime-type defined on map:serializer in the sitemap
0709:                        environment.setContentType(sitemapSerializerMimeType);
0710:                    } else {
0711:                        // ask to the component itself
0712:                        String mimeType = this .serializer.getMimeType();
0713:                        if (mimeType != null) {
0714:                            environment.setContentType(mimeType);
0715:                        } else {
0716:                            // No mimeType available
0717:                            final String message = "Unable to determine MIME type for "
0718:                                    + environment.getURIPrefix()
0719:                                    + "/"
0720:                                    + environment.getURI();
0721:                            throw new ProcessingException(message);
0722:                        }
0723:                    }
0724:                }
0725:            }
0726:
0727:            protected boolean checkIfModified(Environment environment,
0728:                    long lastModified) throws ProcessingException {
0729:                // has the read resource been modified?
0730:                if (!environment.isResponseModified(lastModified)) {
0731:                    // environment supports this, so we are finished
0732:                    environment.setResponseIsNotModified();
0733:                    return true;
0734:                }
0735:                return false;
0736:            }
0737:
0738:            /**
0739:             * Process the pipeline using a reader.
0740:             * @throws ProcessingException if
0741:             */
0742:            protected boolean processReader(Environment environment)
0743:                    throws ProcessingException {
0744:                try {
0745:                    this .setMimeTypeForReader(environment);
0746:                    if (this .reader.shouldSetContentLength()) {
0747:                        ByteArrayOutputStream os = new ByteArrayOutputStream();
0748:                        this .reader.setOutputStream(os);
0749:                        this .reader.generate();
0750:                        environment.setContentLength(os.size());
0751:                        os.writeTo(environment.getOutputStream(0));
0752:                    } else {
0753:                        this .reader.setOutputStream(environment
0754:                                .getOutputStream(this .outputBufferSize));
0755:                        this .reader.generate();
0756:                    }
0757:                } catch (Exception e) {
0758:                    handleException(e);
0759:                }
0760:
0761:                return true;
0762:            }
0763:
0764:            public void recycle() {
0765:                this .prepared = false;
0766:
0767:                // Release reader.
0768:                if (this .readerSelector != null) {
0769:                    this .readerSelector.release(this .reader);
0770:                    this .newManager.release(this .readerSelector);
0771:                    this .readerSelector = null;
0772:                    this .reader = null;
0773:                    this .readerParam = null;
0774:                }
0775:
0776:                // Release generator.
0777:                if (this .generatorSelector != null) {
0778:                    this .generatorSelector.release(this .generator);
0779:                    this .newManager.release(this .generatorSelector);
0780:                    this .generatorSelector = null;
0781:                    this .generator = null;
0782:                    this .generatorParam = null;
0783:                }
0784:
0785:                // Release transformers
0786:                int size = this .transformerSelectors.size();
0787:                for (int i = 0; i < size; i++) {
0788:                    final ComponentSelector selector = (ComponentSelector) this .transformerSelectors
0789:                            .get(i);
0790:                    selector.release((Component) this .transformers.get(i));
0791:                    this .newManager.release(selector);
0792:                }
0793:                this .transformerSelectors.clear();
0794:                this .transformers.clear();
0795:                this .transformerParams.clear();
0796:                this .transformerSources.clear();
0797:
0798:                // Release serializer
0799:                if (this .serializerSelector != null) {
0800:                    this .serializerSelector.release(this .serializer);
0801:                    this .newManager.release(this .serializerSelector);
0802:                    this .serializerSelector = null;
0803:                    this .serializerParam = null;
0804:                }
0805:                this .serializer = null;
0806:                this .parameters = null;
0807:                this .lastConsumer = null;
0808:
0809:                // Release error handler
0810:                this .errorHandler = null;
0811:                if (this .errorPipeline != null) {
0812:                    this .errorPipeline.release();
0813:                    this .errorPipeline = null;
0814:                }
0815:            }
0816:
0817:            /**
0818:             * Process the given <code>Environment</code>, but do not use the
0819:             * serializer. Instead all SAX events are streamed to the XMLConsumer.
0820:             */
0821:            public boolean process(Environment environment, XMLConsumer consumer)
0822:                    throws ProcessingException {
0823:                if (this .reader != null) {
0824:                    throw new ProcessingException(
0825:                            "Streaming of an internal pipeline is not possible with a reader.");
0826:                }
0827:
0828:                // Exception happened during setup and was handled
0829:                if (this .errorPipeline != null) {
0830:                    return this .errorPipeline.process(environment, consumer);
0831:                }
0832:
0833:                // Have to buffer events if error handler is specified.
0834:                SaxBuffer buffer = null;
0835:                this .lastConsumer = this .errorHandler == null ? consumer
0836:                        : (buffer = new SaxBuffer());
0837:                try {
0838:                    connectPipeline(environment);
0839:                    return processXMLPipeline(environment);
0840:                } catch (ProcessingException e) {
0841:                    buffer = null;
0842:                    return processErrorHandler(environment, e, consumer);
0843:                } finally {
0844:                    if (buffer != null) {
0845:                        try {
0846:                            buffer.toSAX(consumer);
0847:                        } catch (SAXException e) {
0848:                            throw new ProcessingException(
0849:                                    "Failed to execute pipeline.", e);
0850:                        }
0851:                    }
0852:                }
0853:            }
0854:
0855:            protected boolean processErrorHandler(Environment environment,
0856:                    ProcessingException e, XMLConsumer consumer)
0857:                    throws ProcessingException {
0858:                if (this .errorHandler != null) {
0859:                    try {
0860:                        this .errorPipeline = this .errorHandler
0861:                                .prepareErrorPipeline(e);
0862:                        if (this .errorPipeline != null) {
0863:                            this .errorPipeline.prepareInternal(environment);
0864:                            return this .errorPipeline.process(environment,
0865:                                    consumer);
0866:                        }
0867:                    } catch (Exception ignored) {
0868:                        getLogger()
0869:                                .debug("Exception in error handler", ignored);
0870:                    }
0871:                }
0872:
0873:                throw e;
0874:            }
0875:
0876:            /**
0877:             * Return valid validity objects for the event pipeline
0878:             * If the "event pipeline" (= the complete pipeline without the
0879:             * serializer) is cacheable and valid, return all validity objects.
0880:             * Otherwise return <code>null</code>
0881:             */
0882:            public SourceValidity getValidityForEventPipeline() {
0883:                return null;
0884:            }
0885:
0886:            /**
0887:             * Return the key for the event pipeline
0888:             * If the "event pipeline" (= the complete pipeline without the
0889:             * serializer) is cacheable and valid, return a key.
0890:             * Otherwise return <code>null</code>
0891:             */
0892:            public String getKeyForEventPipeline() {
0893:                return null;
0894:            }
0895:
0896:            /**
0897:             * Parse the expires parameter
0898:             */
0899:            private long parseExpires(String expire) {
0900:                StringTokenizer tokens = new StringTokenizer(expire);
0901:
0902:                // get <base>
0903:                String current = tokens.nextToken();
0904:                if (current.equals("modification")) {
0905:                    getLogger()
0906:                            .warn(
0907:                                    "the \"modification\" keyword is not yet"
0908:                                            + " implemented. Assuming \"now\" as the base attribute");
0909:                    current = "now";
0910:                }
0911:
0912:                if (!current.equals("now") && !current.equals("access")) {
0913:                    getLogger()
0914:                            .error(
0915:                                    "bad <base> attribute, Expires header will not be set");
0916:                    return -1;
0917:                }
0918:
0919:                long number = 0;
0920:                long modifier = 0;
0921:                long expires = 0;
0922:
0923:                while (tokens.hasMoreTokens()) {
0924:                    current = tokens.nextToken();
0925:
0926:                    // get rid of the optional <plus> keyword
0927:                    if (current.equals("plus")) {
0928:                        current = tokens.nextToken();
0929:                    }
0930:
0931:                    // We're expecting a sequence of <number> and <modification> here
0932:                    // get <number> first
0933:                    try {
0934:                        number = Long.parseLong(current);
0935:                    } catch (NumberFormatException nfe) {
0936:                        getLogger().error(
0937:                                "state violation: a number was expected here");
0938:                        return -1;
0939:                    }
0940:
0941:                    // now get <modifier>
0942:                    try {
0943:                        current = tokens.nextToken();
0944:                    } catch (NoSuchElementException nsee) {
0945:                        getLogger()
0946:                                .error(
0947:                                        "State violation: expecting a modifier"
0948:                                                + " but no one found: Expires header will not be set");
0949:                    }
0950:                    if (current.equals("years")) {
0951:                        modifier = 365L * 24L * 60L * 60L * 1000L;
0952:                    } else if (current.equals("months")) {
0953:                        modifier = 30L * 24L * 60L * 60L * 1000L;
0954:                    } else if (current.equals("weeks")) {
0955:                        modifier = 7L * 24L * 60L * 60L * 1000L;
0956:                    } else if (current.equals("days")) {
0957:                        modifier = 24L * 60L * 60L * 1000L;
0958:                    } else if (current.equals("hours")) {
0959:                        modifier = 60L * 60L * 1000L;
0960:                    } else if (current.equals("minutes")) {
0961:                        modifier = 60L * 1000L;
0962:                    } else if (current.equals("seconds")) {
0963:                        modifier = 1000L;
0964:                    } else {
0965:                        getLogger().error(
0966:                                "Bad modifier (" + current
0967:                                        + "): ignoring expires configuration");
0968:                        return -1;
0969:                    }
0970:                    expires += number * modifier;
0971:                }
0972:
0973:                return expires;
0974:            }
0975:
0976:            protected Location getLocation(Parameters param) {
0977:                Location location = null;
0978:                if (param instanceof  Locatable) {
0979:                    location = ((Locatable) param).getLocation();
0980:                }
0981:                if (location == null) {
0982:                    location = Location.UNKNOWN;
0983:                }
0984:                return location;
0985:            }
0986:
0987:            /**
0988:             * Handles exception which can happen during pipeline processing.
0989:             * If this not a connection reset, then all locations for pipeline components are
0990:             * added to the exception.
0991:             * 
0992:             * @throws ConnectionResetException if connection reset detected
0993:             * @throws ProcessingException in all other cases
0994:             */
0995:            protected void handleException(Exception e)
0996:                    throws ProcessingException {
0997:                // Check if the client aborted the connection
0998:                if (e instanceof  SocketException) {
0999:                    if (e.getMessage().indexOf("reset") > -1
1000:                            || e.getMessage().indexOf("aborted") > -1
1001:                            || e.getMessage().indexOf("Broken pipe") > -1
1002:                            || e.getMessage().indexOf("connection abort") > -1) {
1003:                        throw new ConnectionResetException(
1004:                                "Connection reset by peer", e);
1005:                    }
1006:                } else if (e instanceof  IOException) {
1007:                    // Tomcat5 wraps SocketException into ClientAbortException which extends IOException.
1008:                    if (e.getClass().getName().endsWith("ClientAbortException")) {
1009:                        throw new ConnectionResetException(
1010:                                "Connection reset by peer", e);
1011:                    }
1012:                } else if (e instanceof  ConnectionResetException) {
1013:                    // Exception comes up from a deeper pipeline
1014:                    throw (ConnectionResetException) e;
1015:                }
1016:
1017:                // Not a connection reset: add all location information        
1018:                if (this .reader == null) {
1019:                    // Add all locations in reverse order
1020:                    ArrayList locations = new ArrayList(this .transformers
1021:                            .size() + 2);
1022:                    locations.add(getLocation(this .serializerParam));
1023:                    for (int i = this .transformerParams.size() - 1; i >= 0; i--) {
1024:                        locations
1025:                                .add(getLocation((Parameters) this .transformerParams
1026:                                        .get(i)));
1027:                    }
1028:                    locations.add(getLocation(this .generatorParam));
1029:
1030:                    throw ProcessingException.throwLocated(
1031:                            "Failed to process pipeline", e, locations);
1032:
1033:                } else {
1034:                    // Add reader location
1035:                    throw ProcessingException.throwLocated(
1036:                            "Failed to process reader", e,
1037:                            getLocation(this.readerParam));
1038:                }
1039:            }
1040:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.