Source Code Cross Referenced for ModelBuilder.java in  » 6.0-JDK-Modules » j2me » com » sun » perseus » builder » 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 » 6.0 JDK Modules » j2me » com.sun.perseus.builder 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         *
0003:         *
0004:         * Portions Copyright  2000-2007 Sun Microsystems, Inc. All Rights
0005:         * Reserved.  Use is subject to license terms.
0006:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
0007:         * 
0008:         * This program is free software; you can redistribute it and/or
0009:         * modify it under the terms of the GNU General Public License version
0010:         * 2 only, as published by the Free Software Foundation.
0011:         * 
0012:         * This program is distributed in the hope that it will be useful, but
0013:         * WITHOUT ANY WARRANTY; without even the implied warranty of
0014:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0015:         * General Public License version 2 for more details (a copy is
0016:         * included at /legal/license.txt).
0017:         * 
0018:         * You should have received a copy of the GNU General Public License
0019:         * version 2 along with this work; if not, write to the Free Software
0020:         * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
0021:         * 02110-1301 USA
0022:         * 
0023:         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
0024:         * Clara, CA 95054 or visit www.sun.com if you need additional
0025:         * information or have any questions.
0026:         */
0027:
0028:        /*****************************************************************************
0029:         * Copyright (C) The Apache Software Foundation. All rights reserved.        *
0030:         * ------------------------------------------------------------------------- *
0031:         * This software is published under the terms of the Apache Software License *
0032:         * version 1.1, a copy of which has been included with this distribution in  *
0033:         * the LICENSE file.                                                         *
0034:         *****************************************************************************/package com.sun.perseus.builder;
0035:
0036:        import com.sun.perseus.platform.ThreadSupport;
0037:
0038:        import com.sun.perseus.model.CompositeNode;
0039:        import com.sun.perseus.model.DocumentNode;
0040:        import com.sun.perseus.model.ElementNode;
0041:        import com.sun.perseus.model.Font;
0042:        import com.sun.perseus.model.FontFace;
0043:        import com.sun.perseus.model.ModelNode;
0044:        import com.sun.perseus.model.UpdateAdapter;
0045:        import com.sun.perseus.model.UpdateListener;
0046:        import com.sun.perseus.model.Use;
0047:
0048:        import com.sun.perseus.util.SimpleTokenizer;
0049:
0050:        import com.sun.perseus.util.SVGConstants;
0051:
0052:        import com.sun.perseus.platform.GZIPSupport;
0053:
0054:        import org.xml.sax.helpers.DefaultHandler;
0055:        import org.xml.sax.Attributes;
0056:        import org.xml.sax.Locator;
0057:        import org.xml.sax.InputSource;
0058:        import org.xml.sax.SAXException;
0059:        import org.xml.sax.SAXParseException;
0060:
0061:        import org.w3c.dom.DOMException;
0062:
0063:        import java.util.Vector;
0064:
0065:        import java.io.ByteArrayInputStream;
0066:        import java.io.InputStream;
0067:        import java.io.InputStreamReader;
0068:        import java.io.IOException;
0069:        import java.io.Reader;
0070:
0071:        import javax.xml.parsers.SAXParserFactory;
0072:        import javax.xml.parsers.SAXParser;
0073:        import javax.xml.parsers.ParserConfigurationException;
0074:
0075:        /**
0076:         * NOTE: need to change currentElement management so that there is only a
0077:         * need to do a getParent() and cast to (ElementNode).
0078:         *
0079:         * <code>ModelBuilder</code> is a SAX2 <code>ContentHandler</code> that
0080:         * builds a <b>Model</b> (i.e. a tree of <code>ModelNode</code>s from 
0081:         * the SAX2 events. <br />
0082:         *
0083:         * This class also offers a static method to synchronously builds a
0084:         * <b>Model</b> given a URI: {@link ModelBuilder#loadDocument loadDocument}.
0085:         *
0086:         * @version $Id: ModelBuilder.java,v 1.10 2006/07/13 00:55:57 st125089 Exp $
0087:         */
0088:        public class ModelBuilder extends DefaultHandler {
0089:            /**
0090:             * The default DTD subset used when resolving the DTD entities.
0091:             */
0092:            public static final String DTD_SUBSET = "<!ATTLIST svg\n"
0093:                    + "     xmlns CDATA #FIXED \"http://www.w3.org/2000/svg\"\n"
0094:                    + "     xmlns:xlink CDATA #FIXED \"http://www.w3.org/1999/xlink\"\n"
0095:                    + ">";
0096:
0097:            /**
0098:             * The message used in the SAXException when the 
0099:             * loading thread is interrupted
0100:             */
0101:            public static final String LOAD_INTERRUPTED = "Load Interrupted : ";
0102:
0103:            /**
0104:             * The accepted DTD public IDs.
0105:             */
0106:            protected static String dtdids = "-//W3C//DTD SVG 1.1 Tiny//EN";
0107:
0108:            /**
0109:             * Object keeping track of the current node, i.e., the 
0110:             * last node that was built from an element. 
0111:             */
0112:            protected ElementNode currentElement;
0113:
0114:            /**
0115:             * Root of the model tree
0116:             */
0117:            protected DocumentNode modelRoot;
0118:
0119:            /**
0120:             * Keeps track of opened streams (entities) so that
0121:             * they can be closed when parsing completes.
0122:             * @see #resolveEntity
0123:             */
0124:            protected Vector entityStreams = new Vector();
0125:
0126:            /**
0127:             * Keeps pending namespaceURI to prefix mapping. This is used because
0128:             * the prefix mapping is declared in the startPrefixMapping method
0129:             * _before_ startElement is called. Therefore, the startElement method
0130:             * will use this pendingPrefixMapping vector to declare prefix mappings
0131:             * on the newly created element.
0132:             */
0133:            protected Vector pendingPrefixMapping = null;
0134:
0135:            /**
0136:             * Used to allows quick check on pendingPrefixMapping.
0137:             */
0138:            protected Vector pendingPrefixMappingCache = new Vector();
0139:
0140:            /**
0141:             * The <code>modelFactory</code> is used to build 
0142:             * <code>ModelNode</code> instances corresponding
0143:             * to individual nodes in the parsed XML documents.
0144:             * This <code>ModelBuilder</code> aggregates the nodes
0145:             * manufactured by the <code>modelFactory</code>
0146:             *
0147:             * @param modelFactoryIn the factory that contains element
0148:             *        prototypes for the supported element types
0149:             * @param modelRootIn the DocumentNode that should be populated 
0150:             *        with the result of the build process.
0151:             */
0152:            ModelBuilder(Vector modelFactoryIn, final DocumentNode modelRootIn) {
0153:                if (modelFactoryIn == null) {
0154:                    modelFactoryIn = SVGTinyModelFactory
0155:                            .getPrototypes(modelRootIn);
0156:                }
0157:
0158:                this .modelRoot = modelRootIn;
0159:
0160:                int n = modelFactoryIn.size();
0161:                for (int i = 0; i < n; i++) {
0162:                    modelRoot.addPrototype((ElementNode) modelFactoryIn
0163:                            .elementAt(i));
0164:                }
0165:            }
0166:
0167:            /**
0168:             * @return the root of the tree built by this builder.
0169:             * null is returned if no tree was built yet
0170:             */
0171:            final DocumentNode getModelRoot() {
0172:                return modelRoot;
0173:            }
0174:
0175:            /**
0176:             * Utility method. Invokes the <code>Runnable</code> on the
0177:             * <code>modelRoot.invokeAndWait</code>.
0178:             *
0179:             * @param runnable the <code>Runnable</code> to run
0180:             * @throws SAXException if the input <code>Runnable</code> is 
0181:             *         interrupted while pending execution or while running.
0182:             */
0183:            protected void invokeAndWait(final Runnable runnable)
0184:                    throws SAXException {
0185:                try {
0186:                    if (!ThreadSupport.isInterrupted(Thread.currentThread())) {
0187:                        modelRoot.invokeAndWait(runnable);
0188:                    } else {
0189:                        throw new InterruptedException();
0190:                    }
0191:                } catch (InterruptedException ie) {
0192:                    throw new SAXException(LOAD_INTERRUPTED
0193:                            + Thread.currentThread());
0194:                }
0195:            }
0196:
0197:            ////////////////////////////////////////////////////////////////////
0198:            // Default implementation of the EntityResolver interface.
0199:            ////////////////////////////////////////////////////////////////////
0200:            /**
0201:             * Resolve an external entity.
0202:             *
0203:             * @param publicId The public identifer, or null if none is
0204:             *                 available.
0205:             * @param systemId The system identifier provided in the XML 
0206:             *                 document.
0207:             * @return The new input source, or null to require the
0208:             *         default behaviour.
0209:             * @exception org.xml.sax.SAXException Any SAX exception, possibly
0210:             *            wrapping another exception.
0211:             * @see org.xml.sax.EntityResolver#resolveEntity
0212:             */
0213:            public final InputSource resolveEntity(final String publicId,
0214:                    final String systemId) throws SAXException {
0215:                if (publicId == null || dtdids.indexOf(publicId) != -1) {
0216:                    // If there is no declared publicId or if the publicId is
0217:                    // one of the supported ones (the test is very lose but quick)
0218:                    // we assume the input source is an SVG Tiny view and we just
0219:                    // process a small DTD subset that includes the default 
0220:                    // namespace and xlink namespace declarations. Attribute defaulting
0221:                    // is handled by the code, so are default attributes, so there is
0222:                    // no need to process the DTDs.
0223:                    InputSource is = new InputSource();
0224:                    Reader reader = new InputStreamReader(
0225:                            new ByteArrayInputStream(DTD_SUBSET.getBytes()));
0226:                    is.setCharacterStream(reader);
0227:
0228:                    // Keep track of opened streams as some SAX 
0229:                    // implementations do not close that stream.
0230:                    entityStreams.addElement(reader);
0231:
0232:                    return is;
0233:                }
0234:
0235:                // Let the SAX parser find the entity.
0236:                return null;
0237:            }
0238:
0239:            ////////////////////////////////////////////////////////////////////
0240:            // Default implementation of DTDHandler interface.
0241:            ////////////////////////////////////////////////////////////////////
0242:
0243:            /**
0244:             * Receive notification of a notation declaration.
0245:             *
0246:             * <p>By default, do nothing.  Application writers may override this
0247:             * method in a subclass if they wish to keep track of the notations
0248:             * declared in a document.</p>
0249:             *
0250:             * @param name The notation name.
0251:             * @param publicId The notation public identifier, or null if not
0252:             *                 available.
0253:             * @param systemId The notation system identifier.
0254:             * @exception org.xml.sax.SAXException Any SAX exception, possibly
0255:             *            wrapping another exception.
0256:             * @see org.xml.sax.DTDHandler#notationDecl
0257:             */
0258:            /*
0259:            public void notationDecl(String name, String publicId, String systemId)
0260:                    throws SAXException {
0261:                // no op
0262:            } 
0263:             */
0264:
0265:            /**
0266:             * Receive notification of an unparsed entity declaration.
0267:             *
0268:             * <p>By default, do nothing.  Application writers may override this
0269:             * method in a subclass to keep track of the unparsed entities
0270:             * declared in a document.</p>
0271:             *
0272:             * @param name The entity name.
0273:             * @param publicId The entity public identifier, or null if not
0274:             *                 available.
0275:             * @param systemId The entity system identifier.
0276:             * @param notationName The name of the associated notation.
0277:             * @exception org.xml.sax.SAXException Any SAX exception, possibly
0278:             *            wrapping another exception.
0279:             * @see org.xml.sax.DTDHandler#unparsedEntityDecl
0280:             */
0281:            /*
0282:            public void unparsedEntityDecl(String name, String publicId,
0283:                    String systemId, String notationName) throws SAXException {
0284:                // no op
0285:            }
0286:             */
0287:
0288:            ////////////////////////////////////////////////////////////////////
0289:            // Default implementation of ContentHandler interface.
0290:            ////////////////////////////////////////////////////////////////////
0291:
0292:            /**
0293:             * Receive a Locator object for document events.
0294:             *
0295:             * <p>By default, do nothing.  Application writers may override this
0296:             * method in a subclass if they wish to store the locator for use
0297:             * with other document events.</p>
0298:             *
0299:             * @param locator A locator for all SAX document events.
0300:             * @see org.xml.sax.ContentHandler#setDocumentLocator
0301:             * @see org.xml.sax.Locator
0302:             */
0303:            public final void setDocumentLocator(final Locator locator) {
0304:                // ctx.setLocator(locator);
0305:            }
0306:
0307:            /**
0308:             * <b>SAX</b>: Implements {@link
0309:             * org.xml.sax.ContentHandler#startDocument() ContentHander.startDocument}.
0310:             */
0311:            public final void startDocument() {
0312:            }
0313:
0314:            /**
0315:             * Receive notification of the end of the document.
0316:             *
0317:             * <p>By default, do nothing.  Application writers may override this
0318:             * method in a subclass to take specific actions at the end
0319:             * of a document (such as finalising a tree or closing an output
0320:             * file).</p>
0321:             *
0322:             * @exception org.xml.sax.SAXException Any SAX exception, possibly
0323:             *            wrapping another exception.
0324:             * @see org.xml.sax.ContentHandler#endDocument
0325:             */
0326:            public final void endDocument() throws SAXException {
0327:                // Validate the document.
0328:                try {
0329:                    modelRoot.validate();
0330:                } catch (DOMException de) {
0331:                    de.printStackTrace();
0332:                    throw new SAXException(de.getMessage());
0333:                }
0334:
0335:                invokeAndWait(new Runnable() {
0336:                    public void run() {
0337:                        UpdateListener um = modelRoot.getUpdateListener();
0338:                        modelRoot.setLoaded(true);
0339:                        um.loadComplete(modelRoot);
0340:                    }
0341:                });
0342:            }
0343:
0344:            /**
0345:             * Receive notification of the start of a Namespace mapping.
0346:             *
0347:             * <p>By default, do nothing.  Application writers may override this
0348:             * method in a subclass to take specific actions at the start of
0349:             * each Namespace prefix scope (such as storing the prefix mapping).</p>
0350:             *
0351:             * @param prefix The Namespace prefix being declared.
0352:             * @param uri The Namespace URI mapped to the prefix.
0353:             * @exception org.xml.sax.SAXException Any SAX exception, possibly
0354:             *            wrapping another exception.
0355:             * @see org.xml.sax.ContentHandler#startPrefixMapping
0356:             */
0357:            public void startPrefixMapping(String prefix, String uri)
0358:                    throws SAXException {
0359:                pendingPrefixMappingCache
0360:                        .addElement(new String[] { prefix, uri });
0361:                pendingPrefixMapping = pendingPrefixMappingCache;
0362:            }
0363:
0364:            /**
0365:             * Receive notification of the end of a Namespace mapping.
0366:             *
0367:             * <p>By default, do nothing.  Application writers may override this
0368:             * method in a subclass to take specific actions at the end of
0369:             * each prefix mapping.</p>
0370:             *
0371:             * @param prefix The Namespace prefix being declared.
0372:             * @exception org.xml.sax.SAXException Any SAX exception, possibly
0373:             *            wrapping another exception.
0374:             * @see org.xml.sax.ContentHandler#endPrefixMapping
0375:             */
0376:            /*
0377:            public void endPrefixMapping(String prefix) throws SAXException {
0378:                // no op
0379:            }
0380:             */
0381:
0382:            /**
0383:             * Receive notification of the start of an element.
0384:             *
0385:             * @param uri The element's namespace uri
0386:             * @param localName The element's local name, i.e., within the given 
0387:             *        namespace
0388:             * @param qName The element's qualified name, i.e., including the namespace 
0389:             *        prefix
0390:             * @param attributes The specified or defaulted attributes.
0391:             * @exception org.xml.sax.SAXException Any SAX exception, possibly
0392:             *            wrapping another exception.
0393:             * @see org.xml.sax.ContentHandler#startElement
0394:             */
0395:            public final void startElement(final String uri,
0396:                    final String localName, final String qName,
0397:                    final Attributes attributes) throws SAXException {
0398:                // ====================================================================
0399:                // First, build a new element from its XML descriptor.
0400:                // ====================================================================
0401:                ElementNode modelNode = null;
0402:                try {
0403:                    modelNode = (ElementNode) modelRoot.createElementNS(uri,
0404:                            localName);
0405:
0406:                    // Handle prefix mappings
0407:                    if (pendingPrefixMapping != null) {
0408:                        int n = pendingPrefixMapping.size();
0409:                        for (int i = 0; i < n; i++) {
0410:                            String[] mapping = (String[]) pendingPrefixMapping
0411:                                    .elementAt(i);
0412:                            modelRoot.addNamespacePrefix(mapping[0],
0413:                                    mapping[1], modelNode);
0414:                        }
0415:                        pendingPrefixMapping.removeAllElements();
0416:                        pendingPrefixMapping = null;
0417:                    }
0418:
0419:                    // Make sure we mark the node as _not_ loaded.
0420:                    // This is important because we use the loaded bit to 
0421:                    // control certain behaviors, such as the progressive rendering
0422:                    // behavior.
0423:                    modelNode.setLoaded(false);
0424:
0425:                    // ================================================
0426:                    // Check that required traits have been specified.
0427:                    // ================================================
0428:                    String[] requiredTraits = modelNode.getRequiredTraits();
0429:                    if (requiredTraits != null) {
0430:                        for (int i = 0; i < requiredTraits.length; i++) {
0431:                            if (attributes.getValue(requiredTraits[i]) == null) {
0432:                                throw new SAXException(Messages.formatMessage(
0433:                                        Messages.ERROR_MISSING_ATTRIBUTE,
0434:                                        new Object[] { requiredTraits[i],
0435:                                                modelNode.getNamespaceURI(),
0436:                                                modelNode.getLocalName() }));
0437:                            }
0438:                        }
0439:                    }
0440:
0441:                    String[][] requiredTraitsNS = modelNode
0442:                            .getRequiredTraitsNS();
0443:                    if (requiredTraitsNS != null) {
0444:                        for (int i = 0; i < requiredTraitsNS.length; i++) {
0445:                            if (attributes.getValue(requiredTraitsNS[i][0],
0446:                                    requiredTraitsNS[i][1]) == null) {
0447:                                throw new SAXException(Messages.formatMessage(
0448:                                        Messages.ERROR_MISSING_ATTRIBUTE_NS,
0449:                                        new Object[] { requiredTraitsNS[i][1],
0450:                                                requiredTraitsNS[i][0],
0451:                                                modelNode.getNamespaceURI(),
0452:                                                modelNode.getLocalName() }));
0453:                            }
0454:                        }
0455:                    }
0456:
0457:                    // ================================================
0458:                    // End of required traits check
0459:                    // ================================================
0460:
0461:                    // ================================================
0462:                    // Apply all specified traits.
0463:                    // ================================================
0464:                    int n = attributes.getLength();
0465:                    for (int i = 0; i < n; i++) {
0466:                        modelNode.setAttributeNS(attributes.getURI(i),
0467:                                attributes.getLocalName(i), attributes
0468:                                        .getValue(i));
0469:                    }
0470:
0471:                    // ================================================
0472:                    // Apply default traits if they were not specified.
0473:                    // ================================================
0474:                    String[][] defaultTraits = modelNode.getDefaultTraits();
0475:                    if (defaultTraits != null) {
0476:                        for (int i = 0; i < defaultTraits.length; i++) {
0477:                            if (attributes.getValue(defaultTraits[i][0]) == null) {
0478:                                modelNode.setAttribute(defaultTraits[i][0],
0479:                                        defaultTraits[i][1]);
0480:                            }
0481:                        }
0482:                    }
0483:
0484:                    // ================================================
0485:                    // IMPL NOTE
0486:                    //
0487:                    // If the style attribute is specified, apply the 
0488:                    // traits it specified. The reason for handling the
0489:                    // style attribute at the parser level is that it 
0490:                    // is not a regular trait. It is an in-line 
0491:                    // stylesheet. We only support it in order to 
0492:                    // support imports from Adobe Illustrator which
0493:                    // uses the style attribute on gradients, even
0494:                    // when the option to export without the style 
0495:                    // attribute is selected.
0496:                    // ================================================
0497:                    String styleAttribute = attributes
0498:                            .getValue(SVGConstants.SVG_STYLE_ATTRIBUTE);
0499:                    if (styleAttribute != null) {
0500:                        parseStyleAttribute(styleAttribute, modelNode);
0501:                    }
0502:
0503:                    // ================================================
0504:                    // Apply trait aliases
0505:                    // ================================================
0506:                    String[][] traitAliases = modelNode.getTraitAliases();
0507:                    if (traitAliases != null) {
0508:                        for (int i = 0; i < traitAliases.length; i++) {
0509:                            if (attributes.getValue(traitAliases[i][0]) == null) {
0510:                                // The trait with alias was not specified.
0511:                                // Check if its alias was specified.
0512:                                String v = attributes
0513:                                        .getValue(traitAliases[i][1]);
0514:                                if (v != null) {
0515:                                    modelNode.setAttribute(traitAliases[i][0],
0516:                                            v);
0517:                                }
0518:                            }
0519:                        }
0520:                    }
0521:                } catch (DOMException e) {
0522:                    e.printStackTrace();
0523:                    throw new SAXException(e.getMessage());
0524:                }
0525:
0526:                // ====================================================================
0527:                // Append new element to the tree
0528:                // ====================================================================
0529:                if (currentElement != null) {
0530:                    addToParent(modelNode, currentElement);
0531:                } else {
0532:                    addToParent(modelNode, modelRoot);
0533:                }
0534:                currentElement = modelNode;
0535:
0536:                // ====================================================================
0537:                // Notify application that load has begun on a new element
0538:                // ====================================================================
0539:                final ModelNode startedNode = modelNode;
0540:                final UpdateListener ul = modelRoot.getUpdateListener();
0541:                invokeAndWait(new Runnable() {
0542:                    public void run() {
0543:                        ul.loadBegun(startedNode);
0544:
0545:                    }
0546:                });
0547:
0548:                // ====================================================================
0549:                // Check if there were any delayed exception. A delayed exception 
0550:                // allows progressive rendering of bad path to happen before the
0551:                // exception which captured the bad path data is actually thrown (below)
0552:                // ====================================================================
0553:                try {
0554:                    modelRoot.checkDelayedException();
0555:                } catch (DOMException e) {
0556:                    throw new SAXException(e.getMessage());
0557:                }
0558:            }
0559:
0560:            /**
0561:             * Utility method to parse a trait value.
0562:             *
0563:             * @param styleValue the value of the style attribute to parse.
0564:             * @param elt the ElementNode on which trait values should be set.
0565:             */
0566:            private void parseStyleAttribute(final String styleValue,
0567:                    final ElementNode elt) {
0568:                SimpleTokenizer st = new SimpleTokenizer(styleValue,
0569:                        SVGConstants.COMMA_STR);
0570:                while (st.hasMoreTokens()) {
0571:                    String traitSpec = st.nextToken();
0572:                    int ci = traitSpec.indexOf(':');
0573:                    String traitName = null;
0574:                    String traitValue = null;
0575:                    if (ci != -1) {
0576:                        traitName = traitSpec.substring(0, ci);
0577:                        traitValue = traitSpec.substring(ci + 1);
0578:                    } else {
0579:                        traitName = "";
0580:                        traitValue = "";
0581:                    }
0582:                    elt.setAttribute(traitName, traitValue);
0583:                }
0584:            }
0585:
0586:            /**
0587:             * Adds the input node to the given parent. If there is no
0588:             * associated <code>RunnableQueue</code>, the child is simply
0589:             * added to the parent in the calling thread. If there is
0590:             * a <code>RunnableQueue</code>, the child is added to the parent 
0591:             * the <code>RunnableQueue</code> thread, by invoking a 
0592:             * <code>Runnable</code> on the queue.
0593:             *
0594:             * @param child node to add to the parent
0595:             * @param parent node to which the child is added.
0596:             *
0597:             * @throws SAXException if the child cannot be added to the parent
0598:             *         because the thread was interrupted or if the thread 
0599:             *         was interrupted to begin with.
0600:             */
0601:            void addToParent(final ElementNode child, final CompositeNode parent)
0602:                    throws SAXException {
0603:
0604:                invokeAndWait(new Runnable() {
0605:                    public void run() {
0606:                        parent.add(child);
0607:                    }
0608:                });
0609:
0610:                // This may happen, for example, if the loading thread
0611:                // is interrupted by an update listener.
0612:                if (ThreadSupport.isInterrupted(Thread.currentThread())) {
0613:                    throw new SAXException(LOAD_INTERRUPTED
0614:                            + Thread.currentThread());
0615:                }
0616:            }
0617:
0618:            /**
0619:             * Debug: trace element to console
0620:             *
0621:             * @param uri the element's namespace uri
0622:             * @param localName the element's local name
0623:             * @param qName the element's qualified name
0624:             * @param attributes the element's attributes
0625:             */
0626:            /*
0627:            public final void traceAttributes(final String uri, 
0628:                                              final String localName,
0629:                                              final String qName, 
0630:                                              final Attributes attributes) {
0631:                System.out.println(">>>>> startElement <" + localName 
0632:                                   + "> \n\turi = " + uri + "\n\tqName = " + qName);
0633:
0634:                int n = attributes.getLength();
0635:                for (int i = 0; i < n; i++) {
0636:                    System.out.println("=============>");
0637:                    System.out.println(" uri[" + i + "] = " + attributes.getURI(i));
0638:                    System.out.println(" name[" + i + "] = local(" 
0639:                                       + attributes.getLocalName(i) + ") qname(" 
0640:                                       + attributes.getQName(i) + ")");
0641:                    System.out.println(" value[" + i + "] = ivalue(" 
0642:                                       + attributes.getValue(i) 
0643:                                       + ") qvalue(" 
0644:                                       + attributes.getValue(attributes.getQName(i)) 
0645:                                       + ") urivalue(" 
0646:                                       + attributes.getValue(attributes.getLocalName(i),
0647:                                                             attributes.getURI(i)) 
0648:                                       + ")");
0649:                    System.out.println(attributes.getQName(i) + " = " 
0650:                                       + attributes.getValue(i));
0651:                    System.out.println("<=============");
0652:                }
0653:            }
0654:             */
0655:
0656:            /**
0657:             * Updates the <tt>currentElement</tt>.
0658:             *
0659:             * @param uri The element's namespace uri.
0660:             * @param localName The element's local name
0661:             * @param qName The element's qualified name
0662:             * @exception org.xml.sax.SAXException Any SAX exception, possibly
0663:             *            wrapping another exception.
0664:             * @see org.xml.sax.ContentHandler#endElement
0665:             */
0666:            public final void endElement(final String uri,
0667:                    final String localName, final String qName)
0668:                    throws SAXException {
0669:                //
0670:                // See beginElement: currentElement _cannot_ be null
0671:                // 
0672:
0673:                // Update the Font data base if a new FontFace was loaded
0674:                if (currentElement instanceof  Font) {
0675:                    invokeAndWait(new Runnable() {
0676:                        public void run() {
0677:                            ModelNode fc = currentElement.getFirstChildNode();
0678:                            if (fc != null && fc instanceof  FontFace) {
0679:                                modelRoot.addFontFace((FontFace) fc);
0680:                            }
0681:                        }
0682:                    });
0683:                }
0684:
0685:                invokeAndWait(new Runnable() {
0686:                    public void run() {
0687:                        UpdateListener um = modelRoot.getUpdateListener();
0688:                        currentElement.setLoaded(true);
0689:                        um.loadComplete(currentElement);
0690:                    }
0691:                });
0692:
0693:                // Move up the next content node
0694:                ModelNode parent = currentElement.getParent();
0695:                if (parent instanceof  ElementNode) {
0696:                    currentElement = (ElementNode) parent;
0697:                } else {
0698:                    currentElement = null;
0699:                }
0700:            }
0701:
0702:            /**
0703:             * Receive notification of character data inside an element.
0704:             *
0705:             * <p>By default, do nothing.  Application writers may override this
0706:             * method to take specific actions for each chunk of character data
0707:             * (such as adding the data to a node or buffer, or printing it to
0708:             * a file).</p>
0709:             *
0710:             * @param ch The characters.
0711:             * @param start The start position in the character array.
0712:             * @param length The number of characters to use from the
0713:             *               character array.
0714:             * @exception org.xml.sax.SAXException Any SAX exception, possibly
0715:             *            wrapping another exception.
0716:             * @see org.xml.sax.ContentHandler#characters
0717:             */
0718:            public final void characters(final char[] ch, final int start,
0719:                    final int length) throws SAXException {
0720:                if (currentElement != null) {
0721:                    final String text = new String(ch, start, length);
0722:                    final UpdateListener ul = modelRoot.getUpdateListener();
0723:                    invokeAndWait(new Runnable() {
0724:                        public void run() {
0725:                            currentElement.appendTextChild(text);
0726:                            ul.textInserted(currentElement);
0727:                        }
0728:                    });
0729:                } else {
0730:                    System.err
0731:                            .println(">>>>>>>>>>>>>> currentElement is null!!!!!!!");
0732:                }
0733:            }
0734:
0735:            /**
0736:             * Receive notification of ignorable whitespace in element content.
0737:             *
0738:             * <p>By default, do nothing.  Application writers may override this
0739:             * method to take specific actions for each chunk of ignorable
0740:             * whitespace (such as adding data to a node or buffer, or printing
0741:             * it to a file).</p>
0742:             *
0743:             * @param ch The whitespace characters.
0744:             * @param start The start position in the character array.
0745:             * @param length The number of characters to use from the
0746:             *               character array.
0747:             * @exception org.xml.sax.SAXException Any SAX exception, possibly
0748:             *            wrapping another exception.
0749:             * @see org.xml.sax.ContentHandler#ignorableWhitespace
0750:             */
0751:            /*
0752:            public void ignorableWhitespace(char ch[], int start, int length)
0753:                    throws SAXException {
0754:                // no op
0755:            } 
0756:             */
0757:
0758:            /**
0759:             * Receive notification of a processing instruction.
0760:             *
0761:             * <p>By default, do nothing.  Application writers may override this
0762:             * method in a subclass to take specific actions for each
0763:             * processing instruction, such as setting status variables or
0764:             * invoking other methods.</p>
0765:             *
0766:             * @param target The processing instruction target.
0767:             * @param data The processing instruction data, or null if
0768:             *             none is supplied.
0769:             * @exception org.xml.sax.SAXException Any SAX exception, possibly
0770:             *            wrapping another exception.
0771:             * @see org.xml.sax.ContentHandler#processingInstruction
0772:             */
0773:            /*
0774:            public void processingInstruction(String target, String data)
0775:                    throws SAXException {
0776:                // no op
0777:            }
0778:             */
0779:
0780:            /**
0781:             * Receive notification of a skipped entity.
0782:             *
0783:             * <p>By default, do nothing.  Application writers may override this
0784:             * method in a subclass to take specific actions for each
0785:             * processing instruction, such as setting status variables or
0786:             * invoking other methods.</p>
0787:             *
0788:             * @param name The name of the skipped entity.
0789:             * @exception org.xml.sax.SAXException Any SAX exception, possibly
0790:             *            wrapping another exception.
0791:             * @see org.xml.sax.ContentHandler#processingInstruction
0792:             */
0793:            /*
0794:            public void skippedEntity(String name) throws SAXException {
0795:                // no op
0796:            }
0797:             */
0798:
0799:            ////////////////////////////////////////////////////////////////////
0800:            // Default implementation of the ErrorHandler interface.
0801:            ////////////////////////////////////////////////////////////////////
0802:            /**
0803:             * Report a fatal XML parsing error.
0804:             *
0805:             * <p>The default implementation throws a SAXParseException.
0806:             * Application writers may override this method in a subclass if
0807:             * they need to take specific actions for each fatal error (such as
0808:             * collecting all of the errors into a single report): in any case,
0809:             * the application must stop all regular processing when this
0810:             * method is invoked, since the document is no longer reliable, and
0811:             * the parser may no longer report parsing events.</p>
0812:             *
0813:             * @param e The error information encoded as an exception.
0814:             * @exception org.xml.sax.SAXException Any SAX exception, possibly
0815:             *            wrapping another exception.
0816:             * @see org.xml.sax.ErrorHandler#fatalError
0817:             * @see org.xml.sax.SAXParseException
0818:             */
0819:            public final void fatalError(final SAXParseException e)
0820:                    throws SAXException {
0821:                throw e;
0822:            }
0823:
0824:            // =========================================================================
0825:            // Utility method
0826:            // =========================================================================
0827:
0828:            /**
0829:             * Loads an SVG Tiny document from a given URI
0830:             *
0831:             * @param svgURI the URI of the SVG document to load.
0832:             * @return the <code>DocumentNode</code> built from the requested svgURI.
0833:             * @throws IOException if the file cannot be loaded.
0834:             */
0835:            public static DocumentNode loadDocument(final String svgURI)
0836:                    throws IOException {
0837:
0838:                InputStream is = GZIPSupport.openHandleGZIP(svgURI);
0839:                DocumentNode doc = new DocumentNode();
0840:                doc.setLoaded(false);
0841:                doc.setDocumentURI(svgURI);
0842:
0843:                UpdateAdapter updateAdapter = new UpdateAdapter();
0844:                doc.setUpdateListener(updateAdapter);
0845:
0846:                loadDocument(is, doc);
0847:
0848:                if (!updateAdapter.loadSuccess()) {
0849:                    Exception cause = updateAdapter.getLoadingFailedException();
0850:                    if (cause == null) {
0851:                        throw new IOException();
0852:                    } else {
0853:                        throw new IOException(cause.getMessage());
0854:                    }
0855:                }
0856:
0857:                return doc;
0858:            }
0859:
0860:            /**
0861:             * Load an SVG Tiny document at the given input stream.
0862:             *
0863:             * This method uses JAXP to define the SAX parser to use.
0864:             *
0865:             * Any error is reported to the input <code>DocumentNode</code>'s 
0866:             * <code>UpdateListener</code>'s <code>loadFailed</code> method.
0867:             *
0868:             * @param is the <code>InputStream</code> from which the SVG content is
0869:             *        read. This might be GZIPed compressed stream. If the input stream
0870:             *        is null, an input stream is opened from the root's document URI.
0871:             * @param root the documentNode to populate with the document's content
0872:             *
0873:             *
0874:             * @throws IllegalArgumentException if the root's URI is null, 
0875:             *         if root is null or if the root's <code>UpdateListener</code> is 
0876:             *         null
0877:             */
0878:            public static void loadDocument(final InputStream is,
0879:                    final DocumentNode root) {
0880:                loadDocument(is, root, null);
0881:            }
0882:
0883:            /**
0884:             * Load an SVG Tiny document at the given input stream.
0885:             *
0886:             * This method uses JAXP to define the SAX parser to use.
0887:             *
0888:             * Any error is reported to the input <code>DocumentNode</code>'s 
0889:             * <code>UpdateListener</code>'s <code>loadFailed</code> method.
0890:             *
0891:             * @param is the <code>InputStream</code> from which the SVG content is
0892:             *        read. This might be GZIPed compressed stream. If the input stream
0893:             *        is null, an input stream is opened from the root's document URI.
0894:             * @param root the documentNode to populate with the document's content
0895:             * @param modelFactory the <code>ModelFactory</code> used to turn XML 
0896:             *        elements into <code>ModelNode</code> instances.
0897:             *
0898:             * @throws IllegalArgumentException if the root's URI is null, 
0899:             *         if root is null or if the root's <code>UpdateListener</code> is 
0900:             *         null
0901:             */
0902:            public static void loadDocument(InputStream is,
0903:                    final DocumentNode root, Vector modelFactory) {
0904:
0905:                if (root == null) {
0906:                    throw new IllegalArgumentException();
0907:                }
0908:
0909:                root.setLoaded(false);
0910:
0911:                String svgURI = root.getURIBase();
0912:
0913:                if (is == null && svgURI == null) {
0914:                    throw new IllegalArgumentException();
0915:                }
0916:
0917:                final UpdateListener updateListener = root.getUpdateListener();
0918:                if (updateListener == null) {
0919:                    throw new IllegalArgumentException();
0920:                }
0921:
0922:                // Before parsing the file, we add a default mapping for the
0923:                // SVG and XLink namespaces.
0924:                root.addNamespacePrefix(SVGConstants.XLINK_PREFIX,
0925:                        SVGConstants.XLINK_NAMESPACE_URI, root);
0926:                root.addNamespacePrefix("", SVGConstants.SVG_NAMESPACE_URI,
0927:                        root);
0928:
0929:                ModelBuilder modelBuilder = null;
0930:                InputStream gzipIS = null;
0931:
0932:                try {
0933:                    // Get a SAX parser through the JAXP API. The 
0934:                    // parser does not do validation and is namespace aware
0935:                    SAXParserFactory factory = SAXParserFactory.newInstance();
0936:                    // System.err.println(">>>>>>>>>>>>>>>> SAXParserFactory class: " 
0937:                    //         + factory.getClass().getName());
0938:                    factory.setNamespaceAware(true);
0939:                    factory.setValidating(false);
0940:
0941:                    SAXParser parser = null;
0942:                    parser = factory.newSAXParser();
0943:                    final SAXParser saxParser = parser;
0944:
0945:                    // Check the input stream. If the input stream is not null, we
0946:                    // load that stream. Otherwise, we build an input stream from
0947:                    // the root's URI.
0948:                    if (is == null) {
0949:                        is = GZIPSupport.openHandleGZIP(svgURI);
0950:                    }
0951:
0952:                    // The following wraps the input stream, if necessary, to handle
0953:                    // GZIP compression.
0954:                    gzipIS = GZIPSupport.handleGZIP(is);
0955:                    final InputStream fgzipIS = gzipIS;
0956:
0957:                    root.invokeAndWait(new Runnable() {
0958:                        public void run() {
0959:                            // Parse the document now. Our modelBuilder 
0960:                            // handles the parser's SAX events.
0961:                            updateListener.loadStarting(root, fgzipIS);
0962:                        }
0963:                    });
0964:
0965:                    modelBuilder = new ModelBuilder(modelFactory, root);
0966:
0967:                    saxParser.parse(gzipIS, modelBuilder);
0968:                } catch (ParserConfigurationException pce) {
0969:                    loadingFailed(updateListener, root, pce);
0970:                } catch (SAXParseException spe) {
0971:                    loadingFailed(updateListener, root, spe);
0972:                } catch (SAXException se) {
0973:                    loadingFailed(updateListener, root, se);
0974:                } catch (IOException ioe) {
0975:                    loadingFailed(updateListener, root, ioe);
0976:                } catch (Exception e) {
0977:                    loadingFailed(updateListener, root, e);
0978:                } finally {
0979:                    try {
0980:                        if (gzipIS != null) {
0981:                            gzipIS.close();
0982:                        }
0983:                    } catch (IOException ioe) {
0984:                        // Don't do anything if we got an exception
0985:                        // while trying to close the stream.
0986:                    }
0987:
0988:                    if (modelBuilder != null) {
0989:                        int n = modelBuilder.entityStreams.size();
0990:                        for (int i = 0; i < n; i++) {
0991:                            Reader r = (Reader) modelBuilder.entityStreams
0992:                                    .elementAt(i);
0993:                            try {
0994:                                r.close();
0995:                            } catch (IOException ioe) {
0996:                                // Do nothing: this means the stream was 
0997:                                // closed by the SAX parser.
0998:                            }
0999:                        }
1000:                    }
1001:                }
1002:            }
1003:
1004:            /**
1005:             * Utility method to report an exception to the UpdateListener
1006:             * in the proper thread.
1007:             *
1008:             * @param updateListener the <code>UpdateListener</code> to which 
1009:             *        the error should be reported.
1010:             * @param root the <code>DocumentNode</code> which was being loaded.
1011:             * @param e the <code>Exception</code> which caused the failure.
1012:             */
1013:            protected static void loadingFailed(
1014:                    final UpdateListener updateListener,
1015:                    final DocumentNode root, final Exception e) {
1016:                System.err
1017:                        .println(">>>>>>>>>>>>>>>>>>> +++++ Loading failed ...");
1018:                e.printStackTrace();
1019:                try {
1020:                    root.invokeAndWait(new Runnable() {
1021:                        public void run() {
1022:                            updateListener.loadingFailed(root, e);
1023:                        }
1024:                    });
1025:                } catch (InterruptedException ie) {
1026:                    // The current thread was interrupted. Loading Failed will
1027:                    // not be reported...
1028:                    return;
1029:                }
1030:            }
1031:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.