Source Code Cross Referenced for AbstractSAXTransformer.java in  » Content-Management-System » apache-lenya-2.0 » org » apache » cocoon » transformation » 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 » Content Management System » apache lenya 2.0 » org.apache.cocoon.transformation 
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.transformation;
0018:
0019:        import org.apache.avalon.framework.activity.Disposable;
0020:        import org.apache.avalon.framework.configuration.Configurable;
0021:        import org.apache.avalon.framework.configuration.Configuration;
0022:        import org.apache.avalon.framework.configuration.ConfigurationException;
0023:        import org.apache.avalon.framework.parameters.Parameters;
0024:        import org.apache.avalon.framework.service.ServiceException;
0025:        import org.apache.avalon.framework.service.ServiceManager;
0026:        import org.apache.avalon.framework.service.Serviceable;
0027:
0028:        import org.apache.cocoon.ProcessingException;
0029:        import org.apache.cocoon.environment.Context;
0030:        import org.apache.cocoon.environment.ObjectModelHelper;
0031:        import org.apache.cocoon.environment.Request;
0032:        import org.apache.cocoon.environment.Response;
0033:        import org.apache.cocoon.environment.SourceResolver;
0034:        import org.apache.cocoon.transformation.helpers.ParametersRecorder;
0035:        import org.apache.cocoon.transformation.helpers.TextRecorder;
0036:        import org.apache.cocoon.util.ClassUtils;
0037:        import org.apache.cocoon.util.TraxErrorHandler;
0038:        import org.apache.cocoon.xml.AttributesImpl;
0039:        import org.apache.cocoon.xml.ImmutableAttributesImpl;
0040:        import org.apache.cocoon.xml.IncludeXMLConsumer;
0041:        import org.apache.cocoon.xml.SaxBuffer;
0042:        import org.apache.cocoon.xml.XMLConsumer;
0043:        import org.apache.cocoon.xml.XMLUtils;
0044:        import org.apache.cocoon.xml.dom.DOMBuilder;
0045:
0046:        import org.apache.excalibur.source.SourceParameters;
0047:        import org.apache.excalibur.xml.sax.XMLizable;
0048:        import org.w3c.dom.Document;
0049:        import org.w3c.dom.DocumentFragment;
0050:        import org.w3c.dom.Node;
0051:        import org.xml.sax.Attributes;
0052:        import org.xml.sax.ContentHandler;
0053:        import org.xml.sax.Locator;
0054:        import org.xml.sax.SAXException;
0055:        import org.xml.sax.ext.LexicalHandler;
0056:
0057:        import javax.xml.transform.TransformerFactory;
0058:        import javax.xml.transform.sax.SAXTransformerFactory;
0059:        import java.io.IOException;
0060:        import java.util.ArrayList;
0061:        import java.util.Iterator;
0062:        import java.util.List;
0063:        import java.util.Map;
0064:        import java.util.Properties;
0065:        import java.util.Stack;
0066:
0067:        /**
0068:         * This class is the basis for all transformers. It provides various useful
0069:         * methods and hooks for implementing own custom transformers.
0070:         *
0071:         * <p>The basic behaviour of each transformer consists of the following four
0072:         * parts:</p>
0073:         * <ul>
0074:         * <li>Listen for specific events with a given namespace</li>
0075:         * <li>Collect information via these events</li>
0076:         * <li>Process the information</li>
0077:         * <li>Create new events from the processed information</li>
0078:         * </ul>
0079:         *
0080:         * <p>For all these four purposes the AbstractSAXTransformer offers some
0081:         * powerful methods and hooks:</p>
0082:         *
0083:         * <h3>Namespace handling</h3>
0084:         * By setting the instance variable namespaceURI to the namespace the
0085:         * events are filtered and only events with this namespace are send to
0086:         * the two hooks: <code>startTransformingElement</code> and
0087:         * <code>endTransformingElement</code>. It is possible to override the default
0088:         * namespace for the transformer by specifying the parameter "namespaceURI"
0089:         * in the pipeline. This avoids possible namespace collisions.
0090:         *
0091:         * <h3>Recording of information</h3>
0092:         * There are several methods for recording information, e.g. startRecording(),
0093:         * startTextRecording() etc. These methods collect information from the xml
0094:         * stream for further processing.
0095:         *
0096:         * <h3>Creating new events</h3>
0097:         * New events can be easily created with the <code>sendEvents()</code>
0098:         * method, the <code>sendStartElementEvent()</code> methods, the
0099:         * <code>sendEndElementEvent()</code> method or the
0100:         * <code>sendTextEvent()</code> method.
0101:         *
0102:         * <h3>Initialization</h3>
0103:         * Before the document is processed the <code>setupTransforming</code> hook
0104:         * is invoked.
0105:         *
0106:         * @author <a href="mailto:cziegeler@s-und-n.de">Carsten Ziegeler</a>
0107:         * @version $Id: AbstractSAXTransformer.java 433543 2006-08-22 06:22:54Z crossley $
0108:         */
0109:        public abstract class AbstractSAXTransformer extends
0110:                AbstractTransformer implements  Serviceable, Configurable,
0111:                Disposable {
0112:
0113:            /**
0114:             * Empty immutable attributes (for performance). Use them
0115:             * whenever creating an element with no attributes.
0116:             */
0117:            protected static final Attributes EMPTY_ATTRIBUTES = XMLUtils.EMPTY_ATTRIBUTES;
0118:
0119:            /**
0120:             * The trax <code>TransformerFactory</code> used by this transformer.
0121:             */
0122:            private SAXTransformerFactory tfactory;
0123:
0124:            /**
0125:             * Controlls SAX event handling.
0126:             * If set to true all whitespace events are ignored.
0127:             */
0128:            protected boolean ignoreWhitespaces;
0129:
0130:            /**
0131:             * Controlls SAX event handling.
0132:             * If set to true all characters events containing only whitespaces
0133:             * are ignored.
0134:             */
0135:            protected boolean ignoreEmptyCharacters;
0136:
0137:            /**
0138:             * Controlls SAX event handling.
0139:             * If this is incremented all events are not forwarded to the next
0140:             * pipeline component, but the hooks are still called.
0141:             */
0142:            protected int ignoreEventsCount;
0143:
0144:            /**
0145:             * Controlls SAX event handling.
0146:             * If this is greater than zero, the hooks are not called. Attention,
0147:             * make sure, that you decrement this counter properly as your hooks are
0148:             * not called anymore!
0149:             */
0150:            protected int ignoreHooksCount;
0151:
0152:            /**
0153:             * The namespace used by the transformer for the SAX events filtering.
0154:             * This either equals to the {@link #defaultNamespaceURI} or to the value
0155:             * set by the <code>namespaceURI</code> sitemap parameter for the pipeline.
0156:             * Must never be null.
0157:             */
0158:            protected String namespaceURI;
0159:
0160:            /**
0161:             * This is the default namespace used by the transformer.
0162:             * Implementations should set its value in the constructor.
0163:             * Must never be null.
0164:             */
0165:            protected String defaultNamespaceURI;
0166:
0167:            /**
0168:             * A stack for collecting information.
0169:             * The stack is important for collection information especially when
0170:             * the tags can be nested.
0171:             */
0172:            protected final Stack stack = new Stack();
0173:
0174:            /**
0175:             * The stack of current used recorders
0176:             */
0177:            protected final Stack recorderStack = new Stack();
0178:
0179:            /**
0180:             * The current Request object
0181:             */
0182:            protected Request request;
0183:
0184:            /**
0185:             * The current Response object
0186:             */
0187:            protected Response response;
0188:
0189:            /**
0190:             * The current Context object
0191:             */
0192:            protected Context context;
0193:
0194:            /**
0195:             * The current objectModel of the environment
0196:             */
0197:            protected Map objectModel;
0198:
0199:            /**
0200:             * The parameters specified in the sitemap
0201:             */
0202:            protected Parameters parameters;
0203:
0204:            /**
0205:             * The source attribute specified in the sitemap
0206:             */
0207:            protected String source;
0208:
0209:            /**
0210:             * The Avalon ServiceManager for getting Components
0211:             */
0212:            protected ServiceManager manager;
0213:
0214:            /**
0215:             * The SourceResolver for this request
0216:             */
0217:            protected SourceResolver resolver;
0218:
0219:            /**
0220:             * Are we already initialized for the current request?
0221:             */
0222:            private boolean isInitialized;
0223:
0224:            /**
0225:             * Empty attributes (for performance). This can be used
0226:             * do create own attributes, but make sure to clean them
0227:             * afterwords.
0228:             * @deprecated Use {@link AbstractSAXTransformer#EMPTY_ATTRIBUTES}.
0229:             */
0230:            protected Attributes emptyAttributes = EMPTY_ATTRIBUTES;
0231:
0232:            /**
0233:             * The namespaces and their prefixes
0234:             */
0235:            private final List namespaces = new ArrayList(5);
0236:
0237:            /**
0238:             * The current prefix for our namespace
0239:             */
0240:            private String ourPrefix;
0241:
0242:            //
0243:            // Lifecycle
0244:            //
0245:
0246:            /* (non-Javadoc)
0247:             * @see org.apache.avalon.framework.service.Serviceable#service(ServiceManager)
0248:             */
0249:            public void service(ServiceManager manager) throws ServiceException {
0250:                this .manager = manager;
0251:            }
0252:
0253:            /* (non-Javadoc)
0254:             * @see Configurable#configure(Configuration)
0255:             */
0256:            public void configure(Configuration configuration)
0257:                    throws ConfigurationException {
0258:                String tFactoryClass = configuration.getChild(
0259:                        "transformer-factory").getValue(null);
0260:                if (tFactoryClass != null) {
0261:                    try {
0262:                        this .tfactory = (SAXTransformerFactory) ClassUtils
0263:                                .newInstance(tFactoryClass);
0264:                        if (getLogger().isDebugEnabled()) {
0265:                            getLogger().debug(
0266:                                    "Using transformer factory "
0267:                                            + tFactoryClass);
0268:                        }
0269:                    } catch (Exception e) {
0270:                        throw new ConfigurationException(
0271:                                "Cannot load transformer factory "
0272:                                        + tFactoryClass, e);
0273:                    }
0274:                } else {
0275:                    // Standard TrAX behaviour
0276:                    this .tfactory = (SAXTransformerFactory) TransformerFactory
0277:                            .newInstance();
0278:                }
0279:                tfactory.setErrorListener(new TraxErrorHandler(getLogger()));
0280:            }
0281:
0282:            /* (non-Javadoc)
0283:             * @see org.apache.cocoon.sitemap.SitemapModelComponent#setup(SourceResolver, Map, String, Parameters)
0284:             */
0285:            public void setup(SourceResolver resolver, Map objectModel,
0286:                    String src, Parameters params) throws ProcessingException,
0287:                    SAXException, IOException {
0288:
0289:                if (getLogger().isDebugEnabled()) {
0290:                    getLogger().debug(
0291:                            "Setup resolver=" + resolver + ", objectModel="
0292:                                    + objectModel + ", src=" + src
0293:                                    + ", parameters=" + params);
0294:                }
0295:
0296:                // defaultNamespaceURI should never be null
0297:                if (this .defaultNamespaceURI == null) {
0298:                    this .defaultNamespaceURI = "";
0299:                }
0300:                this .objectModel = objectModel;
0301:
0302:                this .request = ObjectModelHelper.getRequest(objectModel);
0303:                this .response = ObjectModelHelper.getResponse(objectModel);
0304:                this .context = ObjectModelHelper.getContext(objectModel);
0305:                this .resolver = resolver;
0306:                this .parameters = params;
0307:                this .source = src;
0308:                this .isInitialized = false;
0309:
0310:                // get the current namespace
0311:                this .namespaceURI = params.getParameter("namespaceURI",
0312:                        this .defaultNamespaceURI);
0313:
0314:                this .ignoreHooksCount = 0;
0315:                this .ignoreEventsCount = 0;
0316:                this .ignoreWhitespaces = true;
0317:                this .ignoreEmptyCharacters = false;
0318:            }
0319:
0320:            /* (non-Javadoc)
0321:             * @see org.apache.avalon.excalibur.pool.Recyclable#recycle()
0322:             */
0323:            public void recycle() {
0324:                this .namespaceURI = null;
0325:                this .objectModel = null;
0326:                this .request = null;
0327:                this .response = null;
0328:                this .context = null;
0329:                this .resolver = null;
0330:                this .stack.clear();
0331:                this .recorderStack.clear();
0332:                this .parameters = null;
0333:                this .source = null;
0334:                this .namespaces.clear();
0335:                this .ourPrefix = null;
0336:
0337:                super .recycle();
0338:            }
0339:
0340:            public void dispose() {
0341:                this .manager = null;
0342:            }
0343:
0344:            //
0345:            // SAX ContentHandler methods
0346:            //
0347:
0348:            /**
0349:             * Process the SAX event.
0350:             * @see ContentHandler#setDocumentLocator
0351:             */
0352:            public void setDocumentLocator(Locator locator) {
0353:                if (this .ignoreEventsCount == 0) {
0354:                    super .setDocumentLocator(locator);
0355:                }
0356:            }
0357:
0358:            /**
0359:             * Process the SAX event. A new document is processed. The hook method
0360:             * {@link #setupTransforming} is invoked.
0361:             * @see ContentHandler#startDocument
0362:             */
0363:            public void startDocument() throws SAXException {
0364:                if (!this .isInitialized) {
0365:                    try {
0366:                        setupTransforming();
0367:                    } catch (ProcessingException e) {
0368:                        throw new SAXException("ProcessingException: " + e, e);
0369:                    } catch (IOException e) {
0370:                        throw new SAXException("IOException: " + e, e);
0371:                    }
0372:                    this .isInitialized = true;
0373:                }
0374:
0375:                if (this .ignoreEventsCount == 0) {
0376:                    super .startDocument();
0377:                }
0378:            }
0379:
0380:            /**
0381:             * Process the SAX event. The processing of the document is finished.
0382:             * @see org.xml.sax.ContentHandler#endDocument
0383:             */
0384:            public void endDocument() throws SAXException {
0385:                if (this .ignoreEventsCount == 0) {
0386:                    super .endDocument();
0387:                }
0388:            }
0389:
0390:            /**
0391:             * Process the SAX event.
0392:             * @see org.xml.sax.ContentHandler#startPrefixMapping
0393:             */
0394:            public void startPrefixMapping(String prefix, String uri)
0395:                    throws SAXException {
0396:                if (prefix != null) {
0397:                    this .namespaces.add(new String[] { prefix, uri });
0398:                }
0399:                if (namespaceURI.equals(uri)) {
0400:                    this .ourPrefix = prefix;
0401:                }
0402:                if (this .ignoreEventsCount == 0) {
0403:                    super .startPrefixMapping(prefix, uri);
0404:                }
0405:            }
0406:
0407:            /**
0408:             * Process the SAX event.
0409:             * @see org.xml.sax.ContentHandler#endPrefixMapping
0410:             */
0411:            public void endPrefixMapping(String prefix) throws SAXException {
0412:
0413:                if (prefix != null) {
0414:                    // Find and remove the namespace prefix
0415:                    boolean found = false;
0416:                    for (int i = this .namespaces.size() - 1; i >= 0; i--) {
0417:                        final String[] prefixAndUri = (String[]) this .namespaces
0418:                                .get(i);
0419:                        if (prefixAndUri[0].equals(prefix)) {
0420:                            this .namespaces.remove(i);
0421:                            found = true;
0422:                            break;
0423:                        }
0424:                    }
0425:                    if (!found) {
0426:                        throw new SAXException("Namespace for prefix '"
0427:                                + prefix + "' not found.");
0428:                    }
0429:
0430:                    if (prefix.equals(this .ourPrefix)) {
0431:                        // Reset our current prefix
0432:                        this .ourPrefix = null;
0433:
0434:                        // Now search if we have a different prefix for our namespace
0435:                        for (int i = this .namespaces.size() - 1; i >= 0; i--) {
0436:                            final String[] prefixAndUri = (String[]) this .namespaces
0437:                                    .get(i);
0438:                            if (namespaceURI.equals(prefixAndUri[1])) {
0439:                                this .ourPrefix = prefixAndUri[0];
0440:                                break;
0441:                            }
0442:                        }
0443:                    }
0444:                }
0445:
0446:                if (this .ignoreEventsCount == 0) {
0447:                    super .endPrefixMapping(prefix);
0448:                }
0449:            }
0450:
0451:            /**
0452:             * Process the SAX event. The namespace of the event is checked.
0453:             * If it is the defined namespace for this transformer,
0454:             * the {@link #startTransformingElement} hook is called.
0455:             * @see org.xml.sax.ContentHandler#startElement
0456:             */
0457:            public void startElement(String uri, String name, String raw,
0458:                    Attributes attr) throws SAXException {
0459:                if (namespaceURI.equals(uri) && ignoreHooksCount == 0) {
0460:                    // this is our namespace:
0461:                    try {
0462:                        startTransformingElement(uri, name, raw, attr);
0463:                    } catch (ProcessingException e) {
0464:                        throw new SAXException("ProcessingException: " + e, e);
0465:                    } catch (IOException e) {
0466:                        throw new SAXException(
0467:                                "IOException occured during processing: " + e,
0468:                                e);
0469:                    }
0470:                } else {
0471:                    if (ignoreEventsCount == 0) {
0472:                        super .startElement(uri, name, raw, attr);
0473:                    }
0474:                }
0475:            }
0476:
0477:            /**
0478:             * Process the SAX event. The namespace of the event is checked.
0479:             * If it is the defined namespace for this transformer,
0480:             * the {@link #endTransformingElement} hook is called.
0481:             * @see org.xml.sax.ContentHandler#endElement
0482:             */
0483:            public void endElement(String uri, String name, String raw)
0484:                    throws SAXException {
0485:                if (namespaceURI.equals(uri) && this .ignoreHooksCount == 0) {
0486:                    // this is our namespace:
0487:                    try {
0488:                        endTransformingElement(uri, name, raw);
0489:                    } catch (ProcessingException e) {
0490:                        throw new SAXException("ProcessingException: " + e, e);
0491:                    } catch (IOException e) {
0492:                        throw new SAXException(
0493:                                "IOException occured during processing: " + e,
0494:                                e);
0495:                    }
0496:                } else {
0497:                    if (ignoreEventsCount == 0) {
0498:                        super .endElement(uri, name, raw);
0499:                    }
0500:                }
0501:            }
0502:
0503:            /**
0504:             * Process the SAX event.
0505:             * @see org.xml.sax.ContentHandler#characters
0506:             */
0507:            public void characters(char[] p0, int p1, int p2)
0508:                    throws SAXException {
0509:                if (this .ignoreEventsCount == 0) {
0510:                    if (this .ignoreEmptyCharacters) {
0511:                        String value = new String(p0, p1, p2);
0512:                        if (value.trim().length() > 0) {
0513:                            super .characters(p0, p1, p2);
0514:                        }
0515:                    } else {
0516:                        super .characters(p0, p1, p2);
0517:                    }
0518:                }
0519:            }
0520:
0521:            /**
0522:             * Process the SAX event.
0523:             * @see org.xml.sax.ContentHandler#ignorableWhitespace
0524:             */
0525:            public void ignorableWhitespace(char[] p0, int p1, int p2)
0526:                    throws SAXException {
0527:                if (ignoreWhitespaces == false && ignoreEventsCount == 0) {
0528:                    super .ignorableWhitespace(p0, p1, p2);
0529:                }
0530:            }
0531:
0532:            /**
0533:             * Process the SAX event.
0534:             * @see ContentHandler#processingInstruction
0535:             */
0536:            public void processingInstruction(String target, String data)
0537:                    throws SAXException {
0538:                if (this .ignoreEventsCount == 0) {
0539:                    super .processingInstruction(target, data);
0540:                }
0541:            }
0542:
0543:            /**
0544:             * Process the SAX event.
0545:             * @see ContentHandler#skippedEntity
0546:             */
0547:            public void skippedEntity(String name) throws SAXException {
0548:                if (this .ignoreEventsCount == 0) {
0549:                    super .skippedEntity(name);
0550:                }
0551:            }
0552:
0553:            //
0554:            // SAX LexicalHandler methods
0555:            //
0556:
0557:            /**
0558:             * @see LexicalHandler#startDTD
0559:             */
0560:            public void startDTD(String name, String public_id, String system_id)
0561:                    throws SAXException {
0562:                if (this .ignoreEventsCount == 0) {
0563:                    super .startDTD(name, public_id, system_id);
0564:                }
0565:            }
0566:
0567:            /**
0568:             * @see LexicalHandler#endDTD
0569:             */
0570:            public void endDTD() throws SAXException {
0571:                if (this .ignoreEventsCount == 0) {
0572:                    super .endDTD();
0573:                }
0574:            }
0575:
0576:            /**
0577:             * @see LexicalHandler#startEntity
0578:             */
0579:            public void startEntity(String name) throws SAXException {
0580:                if (this .ignoreEventsCount == 0) {
0581:                    super .startEntity(name);
0582:                }
0583:            }
0584:
0585:            /**
0586:             * @see LexicalHandler#endEntity
0587:             */
0588:            public void endEntity(String name) throws SAXException {
0589:                if (this .ignoreEventsCount == 0) {
0590:                    super .endEntity(name);
0591:                }
0592:            }
0593:
0594:            /**
0595:             * @see LexicalHandler#startCDATA
0596:             */
0597:            public void startCDATA() throws SAXException {
0598:                if (this .ignoreEventsCount == 0) {
0599:                    super .startCDATA();
0600:                }
0601:            }
0602:
0603:            /**
0604:             * @see LexicalHandler#endCDATA
0605:             */
0606:            public void endCDATA() throws SAXException {
0607:                if (this .ignoreEventsCount == 0) {
0608:                    super .endCDATA();
0609:                }
0610:            }
0611:
0612:            /**
0613:             * @see LexicalHandler#comment
0614:             */
0615:            public void comment(char ary[], int start, int length)
0616:                    throws SAXException {
0617:                if (this .ignoreEventsCount == 0) {
0618:                    super .comment(ary, start, length);
0619:                }
0620:            }
0621:
0622:            /*
0623:             * Recording of events.
0624:             * With this method all events are not forwarded to the next component in the pipeline.
0625:             * They are recorded to create a document fragment.
0626:             */
0627:
0628:            private LexicalHandler originalLexicalHandler;
0629:            private ContentHandler originalContentHandler;
0630:
0631:            /**
0632:             * Add a new recorder to the recording chain.
0633:             * Do not invoke this method directly.
0634:             */
0635:            protected void addRecorder(XMLConsumer recorder) {
0636:                if (this .recorderStack.empty()) {
0637:                    // redirect if first (top) recorder
0638:                    this .originalLexicalHandler = this .lexicalHandler;
0639:                    this .originalContentHandler = this .contentHandler;
0640:                }
0641:                setContentHandler(recorder);
0642:                setLexicalHandler(recorder);
0643:                this .recorderStack.push(recorder);
0644:            }
0645:
0646:            /**
0647:             * Remove a recorder from the recording chain.
0648:             * Do not invoke this method directly.
0649:             */
0650:            protected Object removeRecorder() {
0651:                Object recorder = this .recorderStack.pop();
0652:                if (this .recorderStack.empty() == true) {
0653:                    // undo redirect if no recorder any more
0654:                    setContentHandler(originalContentHandler);
0655:                    setLexicalHandler(originalLexicalHandler);
0656:                    this .originalLexicalHandler = null;
0657:                    this .originalContentHandler = null;
0658:                } else {
0659:                    XMLConsumer next = (XMLConsumer) recorderStack.peek();
0660:                    setContentHandler(next);
0661:                    setLexicalHandler(next);
0662:                }
0663:
0664:                return recorder;
0665:            }
0666:
0667:            /**
0668:             * Start recording of SAX events.
0669:             * All incoming events are recorded and not forwarded. The resulting
0670:             * XMLizable can be obtained by the matching {@link #endSAXRecording} call.
0671:             * @since 2.1.5
0672:             */
0673:            public void startSAXRecording() throws SAXException {
0674:                addRecorder(new SaxBuffer());
0675:                sendStartPrefixMapping();
0676:            }
0677:
0678:            /**
0679:             * Stop recording of SAX events.
0680:             * This method returns the resulting XMLizable.
0681:             * @since 2.1.5
0682:             */
0683:            public XMLizable endSAXRecording() throws SAXException {
0684:                sendEndPrefixMapping();
0685:                return (XMLizable) removeRecorder();
0686:            }
0687:
0688:            /**
0689:             * Start recording of a text.
0690:             * No events forwarded, and all characters events
0691:             * are collected into a string.
0692:             */
0693:            public void startTextRecording() throws SAXException {
0694:                if (getLogger().isDebugEnabled()) {
0695:                    getLogger().debug("Start text recording");
0696:                }
0697:                addRecorder(new TextRecorder());
0698:                sendStartPrefixMapping();
0699:            }
0700:
0701:            /**
0702:             * Stop recording of text and return the recorded information.
0703:             * @return The String, trimmed.
0704:             */
0705:            public String endTextRecording() throws SAXException {
0706:                sendEndPrefixMapping();
0707:
0708:                TextRecorder recorder = (TextRecorder) removeRecorder();
0709:                String text = recorder.getText();
0710:                if (getLogger().isDebugEnabled()) {
0711:                    getLogger().debug("End text recording. Text=" + text);
0712:                }
0713:                return text;
0714:            }
0715:
0716:            /**
0717:             * Start recording of serialized xml
0718:             * All events are converted to an xml string which can be retrieved by
0719:             * endSerializedXMLRecording.
0720:             * @param format The format for the serialized output. If <CODE>null</CODE>
0721:             *               is specified, the default format is used.
0722:             */
0723:            public void startSerializedXMLRecording(Properties format)
0724:                    throws SAXException {
0725:                if (getLogger().isDebugEnabled()) {
0726:                    getLogger().debug(
0727:                            "Start serialized XML recording. Format=" + format);
0728:                }
0729:                this .stack.push(format == null ? XMLUtils
0730:                        .createPropertiesForXML(false) : format);
0731:                startSAXRecording();
0732:            }
0733:
0734:            /**
0735:             * Return the serialized xml string.
0736:             * @return A string containing the recorded xml information, formatted by
0737:             * the properties passed to the corresponding startSerializedXMLRecording().
0738:             */
0739:            public String endSerializedXMLRecording() throws SAXException,
0740:                    ProcessingException {
0741:                XMLizable xml = endSAXRecording();
0742:                String text = XMLUtils.serialize(xml, (Properties) this .stack
0743:                        .pop());
0744:                if (getLogger().isDebugEnabled()) {
0745:                    getLogger().debug(
0746:                            "End serialized XML recording. XML=" + text);
0747:                }
0748:                return text;
0749:            }
0750:
0751:            /**
0752:             * Start recording of parameters.
0753:             * All events are not forwarded and the incoming xml is converted to
0754:             * parameters. Each toplevel node is a parameter and its text subnodes
0755:             * form the value.
0756:             * The Parameters can eiter be retrieved by endParametersRecording().
0757:             */
0758:            public void startParametersRecording() throws SAXException {
0759:                if (getLogger().isDebugEnabled()) {
0760:                    getLogger().debug("Start parameters recording");
0761:                }
0762:                addRecorder(new ParametersRecorder());
0763:                sendStartPrefixMapping();
0764:            }
0765:
0766:            /**
0767:             * End recording of parameters
0768:             * If source is null a new parameters object is created, otherwise
0769:             * the parameters are added to this object.
0770:             * @param source An optional parameters object.
0771:             * @return The object containing all parameters.
0772:             */
0773:            public SourceParameters endParametersRecording(Parameters source)
0774:                    throws SAXException {
0775:                sendEndPrefixMapping();
0776:
0777:                ParametersRecorder recorder = (ParametersRecorder) this 
0778:                        .removeRecorder();
0779:                SourceParameters parameters = recorder.getParameters(source);
0780:                if (getLogger().isDebugEnabled()) {
0781:                    getLogger().debug(
0782:                            "End parameters recording. Parameters="
0783:                                    + parameters);
0784:                }
0785:                return parameters;
0786:            }
0787:
0788:            /**
0789:             * End recording of parameters
0790:             * If source is null a new parameters object is created, otherwise
0791:             * the parameters are added to this object.
0792:             * @param source An optional parameters object.
0793:             * @return The object containing all parameters.
0794:             */
0795:            public SourceParameters endParametersRecording(
0796:                    SourceParameters source) throws SAXException {
0797:                sendEndPrefixMapping();
0798:
0799:                ParametersRecorder recorder = (ParametersRecorder) removeRecorder();
0800:                SourceParameters parameters = recorder.getParameters(source);
0801:                if (getLogger().isDebugEnabled()) {
0802:                    getLogger().debug(
0803:                            "End parameters recording. Parameters="
0804:                                    + parameters);
0805:                }
0806:                return parameters;
0807:            }
0808:
0809:            /**
0810:             * Start DOM DocumentFragment recording.
0811:             * All incoming events are recorded and not forwarded. The resulting
0812:             * DocumentFragment can be obtained by the matching {@link #endRecording} call.
0813:             */
0814:            public void startRecording() throws SAXException {
0815:                if (getLogger().isDebugEnabled()) {
0816:                    getLogger().debug("Start recording");
0817:                }
0818:                DOMBuilder builder = new DOMBuilder(this .tfactory);
0819:                addRecorder(builder);
0820:                builder.startDocument();
0821:                builder.startElement("", "cocoon", "cocoon", EMPTY_ATTRIBUTES);
0822:                sendStartPrefixMapping();
0823:            }
0824:
0825:            /**
0826:             * Stop DOM DocumentFragment recording.
0827:             * This method returns the resulting DocumentFragment, normalized.
0828:             */
0829:            public DocumentFragment endRecording() throws SAXException {
0830:                sendEndPrefixMapping();
0831:
0832:                DOMBuilder builder = (DOMBuilder) removeRecorder();
0833:                builder.endElement("", "cocoon", "cocoon");
0834:                builder.endDocument();
0835:
0836:                // Create Document Fragment
0837:                final Document doc = builder.getDocument();
0838:                final DocumentFragment fragment = doc.createDocumentFragment();
0839:                final Node root = doc.getDocumentElement();
0840:
0841:                // Remove empty text nodes and collapse neighbouring text nodes
0842:                root.normalize();
0843:
0844:                // Move all nodes into the fragment
0845:                boolean space = true;
0846:                while (root.hasChildNodes()) {
0847:                    Node child = root.getFirstChild();
0848:                    root.removeChild(child);
0849:
0850:                    // Leave out leading whitespace nodes
0851:                    // FIXME: Why leading spaces are trimmed at all? Why not trailing spaces?
0852:                    if (space && child.getNodeType() == Node.TEXT_NODE
0853:                            && child.getNodeValue().trim().length() == 0) {
0854:                        continue;
0855:                    }
0856:                    space = false;
0857:
0858:                    fragment.appendChild(child);
0859:                }
0860:
0861:                if (getLogger().isDebugEnabled()) {
0862:                    Object serializedXML = null;
0863:                    try {
0864:                        serializedXML = fragment == null ? "null" : XMLUtils
0865:                                .serializeNode(fragment, XMLUtils
0866:                                        .createPropertiesForXML(false));
0867:                    } catch (ProcessingException ignore) {
0868:                        serializedXML = fragment;
0869:                    }
0870:                    getLogger().debug(
0871:                            "End recording. Fragment=" + serializedXML);
0872:                }
0873:
0874:                return fragment;
0875:            }
0876:
0877:            //
0878:            // Hooks
0879:            //
0880:
0881:            /**
0882:             * Setup the transformation of an xml document.
0883:             * This method is called just before the transformation (sending of sax events)
0884:             * starts. It should be used to initialize setup parameter depending on the
0885:             * object modell.
0886:             */
0887:            public void setupTransforming() throws IOException,
0888:                    ProcessingException, SAXException {
0889:                if (getLogger().isDebugEnabled()) {
0890:                    getLogger().debug("setupTransforming");
0891:                }
0892:                this .stack.clear();
0893:                this .recorderStack.clear();
0894:                this .ignoreWhitespaces = true;
0895:                this .ignoreEmptyCharacters = false;
0896:            }
0897:
0898:            /**
0899:             * Start processing elements of our namespace.
0900:             * This hook is invoked for each sax event with our namespace.
0901:             * @param uri The namespace of the element.
0902:             * @param name The local name of the element.
0903:             * @param raw The qualified name of the element.
0904:             * @param attr The attributes of the element.
0905:             */
0906:            public void startTransformingElement(String uri, String name,
0907:                    String raw, Attributes attr) throws ProcessingException,
0908:                    IOException, SAXException {
0909:                if (this .ignoreEventsCount == 0) {
0910:                    super .startElement(uri, name, raw, attr);
0911:                }
0912:            }
0913:
0914:            /**
0915:             * Start processing elements of our namespace.
0916:             * This hook is invoked for each sax event with our namespace.
0917:             * @param uri The namespace of the element.
0918:             * @param name The local name of the element.
0919:             * @param raw The qualified name of the element.
0920:             */
0921:            public void endTransformingElement(String uri, String name,
0922:                    String raw) throws ProcessingException, IOException,
0923:                    SAXException {
0924:                if (this .ignoreEventsCount == 0) {
0925:                    super .endElement(uri, name, raw);
0926:                }
0927:            }
0928:
0929:            /**
0930:             * Send SAX events to the next pipeline component.
0931:             * The characters event for the given text is send to the next
0932:             * component in the current pipeline.
0933:             * @param text The string containing the information.
0934:             */
0935:            public void sendTextEvent(String text) throws SAXException {
0936:                characters(text.toCharArray(), 0, text.length());
0937:            }
0938:
0939:            /**
0940:             * Send SAX events to the next pipeline component.
0941:             * The startElement event for the given element is send
0942:             * to the next component in the current pipeline.
0943:             * The element has no namespace and no attributes
0944:             * @param localname The name of the event.
0945:             */
0946:            public void sendStartElementEvent(String localname)
0947:                    throws SAXException {
0948:                startElement("", localname, localname, EMPTY_ATTRIBUTES);
0949:            }
0950:
0951:            /**
0952:             * Send SAX events to the next pipeline component.
0953:             * The startElement event for the given element is send
0954:             * to the next component in the current pipeline.
0955:             * The element has the namespace of the transformer,
0956:             * but not attributes
0957:             * @param localname The name of the event.
0958:             */
0959:            public void sendStartElementEventNS(String localname)
0960:                    throws SAXException {
0961:                startElement(this .namespaceURI, localname, this .ourPrefix + ':'
0962:                        + localname, EMPTY_ATTRIBUTES);
0963:            }
0964:
0965:            /**
0966:             * Send SAX events to the next pipeline component.
0967:             * The startElement event for the given element is send
0968:             * to the next component in the current pipeline.
0969:             * The element has no namespace.
0970:             * @param localname The name of the event.
0971:             * @param attr The Attributes of the element
0972:             */
0973:            public void sendStartElementEvent(String localname, Attributes attr)
0974:                    throws SAXException {
0975:                startElement("", localname, localname, attr);
0976:            }
0977:
0978:            /**
0979:             * Send SAX events to the next pipeline component.
0980:             * The startElement event for the given element is send
0981:             * to the next component in the current pipeline.
0982:             * The element has the namespace of the transformer.
0983:             * @param localname The name of the event.
0984:             * @param attr The Attributes of the element
0985:             */
0986:            public void sendStartElementEventNS(String localname,
0987:                    Attributes attr) throws SAXException {
0988:                startElement(this .namespaceURI, localname, this .ourPrefix + ':'
0989:                        + localname, attr);
0990:            }
0991:
0992:            /**
0993:             * Send SAX events to the next pipeline component.
0994:             * The endElement event for the given element is send
0995:             * to the next component in the current pipeline.
0996:             * The element has no namespace.
0997:             * @param localname The name of the event.
0998:             */
0999:            public void sendEndElementEvent(String localname)
1000:                    throws SAXException {
1001:                endElement("", localname, localname);
1002:            }
1003:
1004:            /**
1005:             * Send SAX events to the next pipeline component.
1006:             * The endElement event for the given element is send
1007:             * to the next component in the current pipeline.
1008:             * The element has the namespace of the transformer.
1009:             * @param localname The name of the event.
1010:             */
1011:            public void sendEndElementEventNS(String localname)
1012:                    throws SAXException {
1013:                endElement(this .namespaceURI, localname, this .ourPrefix + ':'
1014:                        + localname);
1015:            }
1016:
1017:            /**
1018:             * Send SAX events to the next pipeline component.
1019:             * The node is parsed and the events are send to
1020:             * the next component in the pipeline.
1021:             * @param node The tree to be included.
1022:             */
1023:            public void sendEvents(Node node) throws SAXException {
1024:                IncludeXMLConsumer.includeNode(node, this , this );
1025:            }
1026:
1027:            /**
1028:             * Send SAX events for the <code>SourceParameters</code>.
1029:             * For each parametername/value pair an element is
1030:             * created with the name of the parameter and the content
1031:             * of this element is the value.
1032:             */
1033:            public void sendParametersEvents(SourceParameters pars)
1034:                    throws SAXException {
1035:
1036:                if (pars != null) {
1037:                    Iterator names = pars.getParameterNames();
1038:                    while (names.hasNext()) {
1039:                        final String currentName = (String) names.next();
1040:                        Iterator values = pars.getParameterValues(currentName);
1041:                        while (values.hasNext()) {
1042:                            final String currentValue = (String) values.next();
1043:                            sendStartElementEvent(currentName);
1044:                            sendTextEvent(currentValue);
1045:                            sendEndElementEvent(currentName);
1046:                        }
1047:                    }
1048:                }
1049:            }
1050:
1051:            /**
1052:             * Send all start prefix mapping events to the current content handler
1053:             */
1054:            protected void sendStartPrefixMapping() throws SAXException {
1055:                final int l = this .namespaces.size();
1056:                for (int i = 0; i < l; i++) {
1057:                    String[] prefixAndUri = (String[]) this .namespaces.get(i);
1058:                    super .contentHandler.startPrefixMapping(prefixAndUri[0],
1059:                            prefixAndUri[1]);
1060:                }
1061:            }
1062:
1063:            /**
1064:             * Send all end prefix mapping events to the current content handler
1065:             */
1066:            protected void sendEndPrefixMapping() throws SAXException {
1067:                final int l = this .namespaces.size();
1068:                for (int i = 0; i < l; i++) {
1069:                    String[] prefixAndUri = (String[]) this .namespaces.get(i);
1070:                    super .contentHandler.endPrefixMapping(prefixAndUri[0]);
1071:                }
1072:            }
1073:
1074:            /**
1075:             * Find prefix mapping for the given namespace URI.
1076:             * @return Prefix mapping or null if no prefix defined
1077:             */
1078:            protected String findPrefixMapping(String uri) {
1079:                final int l = this .namespaces.size();
1080:                for (int i = 0; i < l; i++) {
1081:                    String[] prefixAndUri = (String[]) this .namespaces.get(i);
1082:                    if (prefixAndUri[1].equals(uri)) {
1083:                        return prefixAndUri[0];
1084:                    }
1085:                }
1086:
1087:                return null;
1088:            }
1089:
1090:            /**
1091:             * Helper method to get a modifiable attribute set.
1092:             */
1093:            protected AttributesImpl getMutableAttributes(Attributes a) {
1094:                if (a instanceof  AttributesImpl
1095:                        && !(a instanceof  ImmutableAttributesImpl)) {
1096:                    return (AttributesImpl) a;
1097:                }
1098:                return new AttributesImpl(a);
1099:            }
1100:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.