Source Code Cross Referenced for MarkupUnit.java in  » IDE-Netbeans » visualweb.api.designer » org » netbeans » modules » visualweb » insync » markup » 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 » IDE Netbeans » visualweb.api.designer » org.netbeans.modules.visualweb.insync.markup 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
0003:         *
0004:         * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
0005:         *
0006:         * The contents of this file are subject to the terms of either the GNU
0007:         * General Public License Version 2 only ("GPL") or the Common
0008:         * Development and Distribution License("CDDL") (collectively, the
0009:         * "License"). You may not use this file except in compliance with the
0010:         * License. You can obtain a copy of the License at
0011:         * http://www.netbeans.org/cddl-gplv2.html
0012:         * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
0013:         * specific language governing permissions and limitations under the
0014:         * License.  When distributing the software, include this License Header
0015:         * Notice in each file and include the License file at
0016:         * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
0017:         * particular file as subject to the "Classpath" exception as provided
0018:         * by Sun in the GPL Version 2 section of the License file that
0019:         * accompanied this code. If applicable, add the following below the
0020:         * License Header, with the fields enclosed by brackets [] replaced by
0021:         * your own identifying information:
0022:         * "Portions Copyrighted [year] [name of copyright owner]"
0023:         *
0024:         * Contributor(s):
0025:         *
0026:         * The Original Software is NetBeans. The Initial Developer of the Original
0027:         * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
0028:         * Microsystems, Inc. All Rights Reserved.
0029:         *
0030:         * If you wish your version of this file to be governed by only the CDDL
0031:         * or only the GPL Version 2, indicate your decision by adding
0032:         * "[Contributor] elects to include this software in this distribution
0033:         * under the [CDDL or GPL Version 2] license." If you do not indicate a
0034:         * single choice of license, a recipient has the option to distribute
0035:         * your version of this file under either the CDDL, the GPL Version 2 or
0036:         * to extend the choice of license to its licensees as provided above.
0037:         * However, if you add GPL Version 2 code and therefore, elected the GPL
0038:         * Version 2 license, then the option applies only if the new code is
0039:         * made subject to such option by the copyright holder.
0040:         */
0041:        package org.netbeans.modules.visualweb.insync.markup;
0042:
0043:        import org.netbeans.api.queries.FileEncodingQuery;
0044:        import org.netbeans.modules.visualweb.api.designer.cssengine.CssProvider;
0045:        import com.sun.rave.designtime.markup.MarkupDesignBean;
0046:        import org.netbeans.modules.visualweb.insync.InSyncServiceProvider;
0047:        import org.netbeans.modules.visualweb.insync.Util;
0048:        import java.io.ByteArrayInputStream;
0049:        import java.io.CharArrayReader;
0050:        import java.io.EOFException;
0051:        import java.io.IOException;
0052:        import java.io.PrintWriter;
0053:        import java.io.StringReader;
0054:        import java.io.StringWriter;
0055:        import java.io.Writer;
0056:        import java.lang.ref.WeakReference;
0057:        import java.net.MalformedURLException;
0058:        import java.net.URI;
0059:        import java.net.URISyntaxException;
0060:        import java.net.URL;
0061:        import java.nio.charset.Charset;
0062:        import java.util.Collection;
0063:        import java.util.HashMap;
0064:        import java.util.Locale;
0065:        import java.util.Map;
0066:        import java.util.WeakHashMap;
0067:        import javax.xml.parsers.DocumentBuilder;
0068:        import javax.xml.parsers.ParserConfigurationException;
0069:        import org.apache.xerces.dom.events.MutationEventImpl;
0070:        import org.apache.xerces.util.EncodingMap;
0071:        import org.apache.xml.serialize.OutputFormat;
0072:        import org.openide.ErrorManager;
0073:        import org.openide.filesystems.FileObject;
0074:        import org.openide.filesystems.FileUtil;
0075:        import org.openide.loaders.DataObject;
0076:        import org.openide.util.Lookup;
0077:        import org.openide.util.NbBundle;
0078:        import org.netbeans.modules.visualweb.extension.openide.util.Trace;
0079:        import org.openide.windows.IOProvider;
0080:        import org.openide.windows.InputOutput;
0081:        import org.openide.windows.OutputEvent;
0082:        import org.openide.windows.OutputWriter;
0083:        import org.w3c.dom.Attr;
0084:        import org.w3c.dom.Document;
0085:        import org.w3c.dom.DocumentFragment;
0086:        import org.w3c.dom.Element;
0087:        import org.w3c.dom.NamedNodeMap;
0088:        import org.w3c.dom.Node;
0089:        import org.w3c.dom.NodeList;
0090:        import org.w3c.dom.Text;
0091:        import org.w3c.dom.events.DocumentEvent;
0092:        import org.w3c.dom.events.EventTarget;
0093:        import org.w3c.dom.events.MutationEvent;
0094:        import org.xml.sax.EntityResolver;
0095:        import org.xml.sax.ErrorHandler;
0096:        import org.xml.sax.SAXException;
0097:        import org.xml.sax.SAXParseException;
0098:        import org.netbeans.modules.visualweb.api.designer.markup.MarkupService;
0099:        import org.netbeans.modules.visualweb.insync.ParserAnnotation;
0100:        import org.netbeans.modules.visualweb.insync.SourceUnit;
0101:        import org.netbeans.modules.visualweb.insync.UndoManager;
0102:        import org.netbeans.modules.visualweb.insync.markup.JspxSerializer;
0103:        import org.openide.windows.OutputListener;
0104:        import org.w3c.dom.UserDataHandler;
0105:
0106:        /**
0107:         *
0108:         */
0109:        public class MarkupUnit extends SourceUnit implements 
0110:                org.w3c.dom.events.EventListener {
0111:
0112:            public static final int ALLOW_XML = 0x01;
0113:            public static final int ALLOW_HTML = 0x02;
0114:
0115:            int flags;
0116:            /** Original parsed DOM document. */
0117:            private Document sourceDocument;
0118:            /** For JSP/JSF page -> rendered DOM document. */
0119:            private Document renderedDocument;
0120:            HashMap namespaces = new HashMap(); // namespace URI => prefix mapping
0121:            Map<String, String> namespaceUriMap = new HashMap<String, String>(); // prefix ==> namespace URI mapping
0122:            URI baseURI;
0123:            URL base;
0124:            private boolean supportCss;
0125:            protected EventTarget registeredAsEventListenerOn;
0126:
0127:            //--------------------------------------------------------------------------------- Construction
0128:
0129:            /**
0130:             * Construct an MarkupUnit with a source doc
0131:             */
0132:            public MarkupUnit(FileObject fobj, int flags, boolean supportCss,
0133:                    UndoManager undoManager) {
0134:                super (fobj, undoManager);
0135:                this .flags = flags;
0136:                this .supportCss = supportCss;
0137:                //Trace.enableTraceCategory("insync.markup");
0138:            }
0139:
0140:            public void destroy() {
0141:                namespaces.clear();
0142:                namespaceUriMap.clear();
0143:                base = null;
0144:                baseURI = null;
0145:                //        XhtmlCssEngine engine = CssEngineServiceProvider.getDefault().getCssEngine(sourceDocument);
0146:                //        if (engine != null) {
0147:                //            engine.dispose();
0148:                //            engine = null;
0149:                //        }
0150:                //        CssProvider.getEngineService().removeCssEngineForDocument(sourceDocument);
0151:                CssProvider.getEngineService().removeCssEngineForDocument(
0152:                        renderedDocument);
0153:                synchronized (LOCK_RENDERED_DOCUMENT) {
0154:                    renderedDocument = null;
0155:                }
0156:
0157:                sourceDocument = null;
0158:                unregisterDomListeners();
0159:                super .destroy();
0160:            }
0161:
0162:            //------------------------------------------------------------------------ Document Node Helpers
0163:
0164:            /**
0165:             * Ensures that there is an element of a given type at the root of the document.
0166:             * @return the found or created element
0167:             */
0168:            public static Element ensureRoot(Document document, String tag) {
0169:                Element root = document.getDocumentElement();
0170:                if (root == null) {
0171:                    root = document.createElement(tag);
0172:                    document.appendChild(root);
0173:                    Trace.trace("insync.markup", "MU ensure created root "
0174:                            + root);
0175:                } else
0176:                    Trace
0177:                            .trace("insync.markup", "MU ensure found root "
0178:                                    + root);
0179:                return root;
0180:            }
0181:
0182:            /**
0183:             *
0184:             */
0185:            public static Element ensureElement(Element parent, String tag,
0186:                    Element after) {
0187:                Element elem = getFirstDescendantElement(parent, tag);
0188:                if (elem == null) {
0189:                    Document document = parent.getOwnerDocument();
0190:                    elem = document.createElement(tag);
0191:
0192:                    Element before = after != null ? getNextSiblingElement(after)
0193:                            : getFirstChildElement(parent);
0194:                    if (before != null)
0195:                        parent.insertBefore(elem, before);
0196:                    else
0197:                        parent.appendChild(elem);
0198:                    Trace.trace("insync.markup", "MU scan created " + elem
0199:                            + " under " + parent + " before " + before);
0200:                } else
0201:                    Trace.trace("insync.markup", "MU scan found " + elem
0202:                            + " under " + elem.getParentNode());
0203:                return elem;
0204:            }
0205:
0206:            /**
0207:             *
0208:             */
0209:            public Element addElement(Element parent, Node before,
0210:                    String taglibUri, String tagPrefix, String tag) {
0211:
0212:                String prefix = taglibUri != null && taglibUri.length() > 0 ? getNamespacePrefix(
0213:                        taglibUri, tagPrefix)
0214:                        + ":"
0215:                        : "";
0216:                Element element = sourceDocument.createElementNS(taglibUri,
0217:                        prefix + tag);
0218:
0219:                if (parent != null) {
0220:                    if (before != null)
0221:                        parent.insertBefore(element, before);
0222:                    else
0223:                        parent.appendChild(element);
0224:                } else {
0225:                    sourceDocument.appendChild(element);
0226:                }
0227:
0228:                return element;
0229:            }
0230:
0231:            /**
0232:             * Ensure that a given attribute of a given element exists. Create it with the default value if
0233:             * it does not, leave it alone if it is. Handles special case of xmlns definition attributes.
0234:             */
0235:            public void ensureAttributeExists(Element element, String attr,
0236:                    String defValue) {
0237:                if (element.getAttributeNode(attr) == null)
0238:                    ensureAttributeValue(element, attr, defValue);
0239:            }
0240:
0241:            /**
0242:             * Ensure that a given attribute of a given element is a specific value. Update it if it is not,
0243:             * leave it alone if it is. Handles special case of xmlns definition attributes.
0244:             */
0245:            public void ensureAttributeValue(Element element, String attr,
0246:                    String value) {
0247:                if (!element.getAttribute(attr).equals(value)) {
0248:                    element.setAttribute(attr, value);
0249:                    if (element == sourceDocument.getDocumentElement()
0250:                            && attr.startsWith("xmlns:")) {
0251:                        String prefix = attr.substring(6);
0252:                        namespaces.put(value, prefix);
0253:                        namespaceUriMap.put(prefix, value);
0254:                    }
0255:                }
0256:            }
0257:
0258:            /**
0259:             * Get the first descendant element with a given tag
0260:             */
0261:            public static Element getFirstDescendantElement(Element parent,
0262:                    String tag) {
0263:                NodeList childs = parent.getElementsByTagName(tag);
0264:                if (childs.getLength() >= 1)
0265:                    return (Element) childs.item(0);
0266:                return null;
0267:            }
0268:
0269:            /**
0270:             * Return the child element with a given value for a given attribute
0271:             */
0272:            public static Element getDescendantElementByAttr(Element parent,
0273:                    String tag, String attrName, String attrValue) {
0274:                NodeList elems = parent.getElementsByTagName(tag);
0275:                int elemcount = elems.getLength();
0276:                for (int i = 0; i < elemcount; i++) {
0277:                    Element e = (Element) elems.item(i);
0278:                    if (e.getAttribute(attrName).equals(attrValue))
0279:                        return e;
0280:                }
0281:                return null;
0282:            }
0283:
0284:            /**
0285:             * Return the child element with a given value for a given attribute
0286:             */
0287:            public static boolean isDescendent(Node parent, Node descendent) {
0288:                while (descendent != null) {
0289:                    if (descendent == parent)
0290:                        return true;
0291:                    else
0292:                        descendent = descendent.getParentNode();
0293:                }
0294:                return false;
0295:            }
0296:
0297:            /**
0298:             * Get the first child node that is an element
0299:             */
0300:            public static Element getFirstChildElement(Node parent) {
0301:                for (Node child = parent.getFirstChild(); child != null; child = child
0302:                        .getNextSibling()) {
0303:                    if (child instanceof  Element)
0304:                        return (Element) child;
0305:                }
0306:                return null;
0307:            }
0308:
0309:            /**
0310:             * Get the next sibling node that is an element
0311:             */
0312:            public static Element getNextSiblingElement(Node elem) {
0313:                for (Node sib = elem.getNextSibling(); sib != null; sib = sib
0314:                        .getNextSibling()) {
0315:                    if (sib instanceof  Element)
0316:                        return (Element) sib;
0317:
0318:                }
0319:                return null;
0320:            }
0321:
0322:            /**
0323:             * Get the text body of an element. Any markup is ignored.
0324:             */
0325:            public static String getElementText(Element elem) {
0326:                if (elem == null)
0327:                    return null;
0328:                StringBuffer sb = new StringBuffer();
0329:                for (Node child = elem.getFirstChild(); child != null; child = child
0330:                        .getNextSibling()) {
0331:                    if (child instanceof  Text)
0332:                        sb.append(((Text) child).getData());
0333:                }
0334:                return sb.toString();
0335:            }
0336:
0337:            /**
0338:             * Set the text body of an element. Any markup is lost.
0339:             */
0340:            public static void setElementText(Element elem, String text) {
0341:                for (Node child = elem.getFirstChild(); child != null; child = child
0342:                        .getNextSibling()) {
0343:                    if (child instanceof  Text)
0344:                        elem.removeChild(child);
0345:                }
0346:                if (text != null)
0347:                    elem.appendChild(elem.getOwnerDocument().createTextNode(
0348:                            text));
0349:            }
0350:
0351:            public String findTaglibUri(String prefix) {
0352:                return namespaceUriMap.get(prefix);
0353:            }
0354:
0355:            //---------------------------------------------------------------------------------------- Input
0356:
0357:            /**
0358:             * Parse the input source into a DOM Document using the configured JAXP DOM implementation
0359:             */
0360:            private Document parseDom(org.xml.sax.InputSource is) {
0361:                try {
0362:                    DocumentBuilder parser;
0363:                    parser = MarkupService
0364:                            .createRaveSourceDocumentBuilder(supportCss);
0365:
0366:                    parser.setErrorHandler(new ErrorHandler() {
0367:
0368:                        public void error(SAXParseException exception) {
0369:                            addError(exception, true);
0370:                        }
0371:
0372:                        public void fatalError(SAXParseException exception) {
0373:                            addError(exception, true);
0374:                        }
0375:
0376:                        public void warning(SAXParseException exception) {
0377:                            addError(exception, false);
0378:                        }
0379:                    });
0380:
0381:                    // TODO: only set this to empty if a first parse fails?
0382:                    parser.setEntityResolver(new XhtmlEntityResolver());
0383:
0384:                    Trace.trace("insync.markup", "DOM Parsing: " + getName());
0385:                    Trace.flush();
0386:
0387:                    // Catch empty file induced parse exceptions ahead of time & just gen a new DOM.
0388:                    //            if (!is.getCharacterStream().ready())
0389:                    //                return parser.newDocument();
0390:
0391:                    // Invoke the DOM parser
0392:                    Document doc = parser.parse(is);
0393:                    //            if (doc instanceof RaveDocument) {
0394:                    Document xdoc = doc;
0395:                    // <markup_separation>
0396:                    //                xdoc.setMarkupUnit(this);
0397:                    // ====
0398:                    setMarkupUnitForDocument(xdoc, this );
0399:                    // </markup_separation>
0400:
0401:                    // Figure out the best source encoding & use it. Either the .nbattr or the ?xml
0402:                    String encoding = getEncoding();
0403:                    //                String xencoding = xdoc.getEncoding();
0404:                    String xencoding = xdoc.getXmlEncoding();
0405:                    if (encoding != null && encoding.length() > 0) {
0406:                        if (xencoding == null || xencoding.length() == 0) {
0407:                            //                        ((RaveDocument)xdoc).setInputEncoding(encoding);
0408:                            MarkupService.setInputEncodingForDocument(xdoc,
0409:                                    encoding);
0410:                        }
0411:                    } else {
0412:                        if (xencoding != null && xencoding.length() > 0) {
0413:                            encoding = xencoding;
0414:                        }
0415:                    }
0416:                    //            }
0417:
0418:                    return doc;
0419:                } catch (ParserConfigurationException e) {
0420:                    Trace.trace("insync.markup", "DOM Parsing: " + getName());
0421:                    Trace.trace("insync.markup", e);
0422:                    setBusted();
0423:                } catch (SAXException e) {
0424:                    Trace.trace("insync.markup", "DOM Parsing: " + getName());
0425:                    Trace.trace("insync.markup", e);
0426:                    setBusted();
0427:                } catch (IOException e) {
0428:                    Trace.trace("insync.markup", "DOM Parsing: " + getName());
0429:                    Trace.trace("insync.markup", e);
0430:                    setBusted();
0431:                }
0432:
0433:                return null;
0434:            }
0435:
0436:            // TODO: only set this to empty if a first parse fails?
0437:            public static class XhtmlEntityResolver implements  EntityResolver {
0438:                public org.xml.sax.InputSource resolveEntity(String pubid,
0439:                        String sysid) {
0440:                    return new org.xml.sax.InputSource(
0441:                            new ByteArrayInputStream(new byte[0]));
0442:                }
0443:            }
0444:
0445:            /**
0446:             * The parser always bails after the first error, so we don't have to keep a "list" of errors
0447:             * (and chain them when they're on the same line) - we can just point directly to our one error.
0448:             * Null when there is no error.
0449:             *
0450:             * @todo Is this true? Will it bail if it sees a warning (as opposed to an error) ? What
0451:             * constitutes a warning from Xerces)
0452:             */
0453:            private ParserAnnotation error;
0454:
0455:            /**
0456:             * A new parse is about to begin - clear out existing errors
0457:             */
0458:            private void resetErrors() {
0459:                error = null;
0460:            }
0461:
0462:            /**
0463:             * Add a parser error to the hashmap for the given sax error
0464:             */
0465:            private void addError(SAXParseException exception, boolean isError) {
0466:                String message = exception.getMessage();
0467:                int line = exception.getLineNumber();
0468:                // If file is empty then saved, we get -1
0469:                if (line < 0)
0470:                    line = 1;
0471:                int column = exception.getColumnNumber();
0472:                if (column < 0)
0473:                    column = 0;
0474:                error = new ParserAnnotation(message, fobj, line, column);
0475:                if (isError)
0476:                    setBusted();
0477:            }
0478:
0479:            /**
0480:             * Return the list of errors if this unit does not compile. If there are no errors it returns an
0481:             * empty array - never null.
0482:             *
0483:             * @return An array of ParserAnnotations.
0484:             */
0485:            public ParserAnnotation[] getErrors() {
0486:                if (error != null)
0487:                    return new ParserAnnotation[] { error };
0488:                else
0489:                    return ParserAnnotation.EMPTY_ARRAY;
0490:            }
0491:
0492:            /**
0493:             * Read the actual characters from the source document's content and into our DOM source document
0494:             * object. Try an XML and/or an HTML parser depending on our flags setting.
0495:             */
0496:            protected void read(char[] buf, int len) {
0497:                Trace.trace("insync.markup", "MU.read"); // \"" + new String(buf, 0, len) + "\"");
0498:                //long start = System.currentTimeMillis();
0499:
0500:                // cleanup listeners on old document
0501:                Document oldDocument = sourceDocument;
0502:                Document newDocument = null;
0503:
0504:                InSyncServiceProvider.get().getRaveErrorHandler().clearErrors(
0505:                        true);
0506:                resetErrors();
0507:
0508:                // force reinitialization!!!
0509:                base = null;
0510:                baseURI = null;
0511:
0512:                // Input structure for JAXP SAX and DOM
0513:                org.xml.sax.InputSource is = new org.xml.sax.InputSource(
0514:                        new CharArrayReader(buf, 0, len));
0515:                is.setSystemId(getName());
0516:
0517:                // Try an XML parse first if it is allowed
0518:                if ((flags & ALLOW_XML) != 0) {
0519:                    newDocument = parseDom(is);
0520:                    if (newDocument == null) { // reset input source if parse aborted
0521:                        is = new org.xml.sax.InputSource(new CharArrayReader(
0522:                                buf, 0, len));
0523:                        is.setSystemId(getName());
0524:                    }
0525:                }
0526:
0527:                if (getState().isBusted())
0528:                    return;
0529:
0530:                // Force pre-init of style sheets, such that errors in the <style> tag section etc. will 
0531:                // get triggered. This doesn't initialize per-tag/local styles, only the <head> section 
0532:                // style sheets and the head <style> tag.
0533:                sourceDocument = newDocument; // for initializeStyleSheet
0534:
0535:                if (sourceDocument.getDocumentElement() != null) {
0536:                    MarkupService.markJspxSource(sourceDocument
0537:                            .getDocumentElement());
0538:                }
0539:
0540:                // Attempt to initialize stylesheets via Batik' CSS parser
0541:                if (supportCss)
0542:                    syncEngine();// Initialize default stylesheet
0543:
0544:                // style sheet parsing can cause errors too
0545:                if (getState().isBusted()) {
0546:                    sourceDocument = oldDocument;
0547:                    return;
0548:                }
0549:
0550:                // register change listener & notify listeners regarding replaced doc
0551:                unregisterDomListeners();
0552:
0553:                sourceDocument = newDocument;
0554:
0555:                //        // XXX Reinit also the rendered doc?
0556:                //        synchronized (LOCK_RENDERED_DOCUMENT) {
0557:                //            renderedDocument = null;
0558:                //        }
0559:                // XXX Is this the correct place (and thing to do)?
0560:                setMarkupUnitForDocument(getRenderedDom(), this );
0561:
0562:                if (sourceDocument != null) {
0563:                    registerDomListeners(sourceDocument);
0564:                    Element root = sourceDocument.getDocumentElement();
0565:                    NamedNodeMap attrs = root.getAttributes();
0566:                    for (int i = 0; i < attrs.getLength(); i++) {
0567:                        Attr attr = (Attr) attrs.item(i);
0568:                        if (attr.getName().startsWith("xmlns:")) {
0569:                            String prefix = attr.getName().substring(6);
0570:                            namespaces.put(attr.getValue(), prefix);
0571:                            namespaceUriMap.put(prefix, attr.getValue());
0572:                        }
0573:                    }
0574:                }
0575:
0576:                //long duration = System.currentTimeMillis() - start;
0577:                //System.err.println("MU.read: XML parse time: " + duration + "ms for " + getName());
0578:
0579:                if (oldDocument != null)
0580:                    fireDocumentReplaced(oldDocument);
0581:            }
0582:
0583:            //    private XhtmlCssEngine engine;
0584:
0585:            // XXX Not used, removing.
0586:            //    private static boolean reuseEngine = System.getProperty("designer.reuseCssEngine") != null;
0587:            private void syncEngine() {
0588:                //        Document doc = sourceDocument;
0589:                // XXX It seems we need to parse styles for both documents (source and rendered).
0590:                Document sourceDom = sourceDocument;
0591:                //        Document renderedDom = getRenderedDom();
0592:
0593:                //        doc.setUrl(getBase()); // needed by engine
0594:                //        setUrlForDocument(doc, getBase());
0595:                setUrlForDocument(sourceDom, getBase());
0596:                //        setUrlForDocument(renderedDom, getBase());
0597:
0598:                //        if (reuseEngine && engine != null) {
0599:                //            engine.setDocument(doc);
0600:                //// <moving RaveDoc refs outside> engine is not interested in registering itself somewhere.
0601:                //            doc.setCssEngine(engine);
0602:                //// </moving RaveDoc refs outside>
0603:                //            return;
0604:                //        }
0605:                // <markup_separation>
0606:                //        engine = XhtmlCssEngine.create(doc, this, doc.getUrl());
0607:                // ====
0608:                //        engine = XhtmlCssEngine.create(doc, doc.getUrl());
0609:                //        XhtmlCssEngine engine = XhtmlCssEngine.create(doc, getUrlForDocument(doc));
0610:                //// <moved from engine impl> it doesn't (shoudn't) know about RaveDocument.
0611:                //        if (doc != null) {
0612:                ////            doc.setCssEngine(engine);
0613:                //            CssEngineServiceProvider.getDefault().setCssEngine(doc, engine);
0614:                //        }
0615:                //// </moved from engine impl>
0616:                //        CssProvider.getEngineService().createCssEngineForDocument(doc, getUrlForDocument(doc));
0617:                CssProvider.getEngineService().createCssEngineForDocument(
0618:                        sourceDom, getUrlForDocument(sourceDom));
0619:                //        CssProvider.getEngineService().createCssEngineForDocument(renderedDom, getUrlForDocument(renderedDom));
0620:                // </markup_separation>
0621:            }
0622:
0623:            //    /** Return CSS engine associated with this unit */
0624:            //    public XhtmlCssEngine getCssEngine() {
0625:            ////        return engine;
0626:            //        return CssEngineServiceProvider.getDefault().getCssEngine(sourceDocument);
0627:            //    }
0628:
0629:            //--------------------------------------------------------------------------------------- Output
0630:
0631:            /**
0632:             * Return a Xerces-compatible IANA encoding given a Java or IANA encoding
0633:             * @param encoding Java or IANA encoding
0634:             * @return Xerces-compatible IANA encoding
0635:             */
0636:            public static String getIanaEncoding(String encoding) {
0637:                if (encoding != null) {
0638:                    // need to convert it to upper case:
0639:                    String upEncoding = encoding.toUpperCase(Locale.ENGLISH);
0640:
0641:                    // if it's a known IANA encoding, that's good enough for us
0642:                    if (EncodingMap.getIANA2JavaMapping(upEncoding) != null)
0643:                        return encoding;
0644:
0645:                    // if it is a java encoding try mapping it to IANA
0646:                    String ianaEncoding = EncodingMap
0647:                            .getJava2IANAMapping(upEncoding);
0648:                    if (ianaEncoding != null)
0649:                        return ianaEncoding;
0650:
0651:                    // if it's a known java encoding alias, that needs to be normalized...
0652:                    /*
0653:                    if (Charset.isSupported(encoding)) {
0654:                        Charset charset = Charset.forName(encoding);
0655:                        if (charset != null) {
0656:                            ianaEncoding = charset.name().toUpperCase(Locale.ENGLISH);
0657:                            EncodingMap.putIANA2JavaMapping(ianaEncoding, upEncoding);
0658:                            EncodingMap.putJava2IANAMapping(upEncoding, ianaEncoding);
0659:                            
0660:                            OutputFormat format = new OutputFormat(Method.XML, charset.name(), true);  // do-indent==true
0661:                            format.setAllowJavaNames(true);              
0662:                            EncodingInfo ei = null;
0663:                            try {
0664:                                ei = format.getEncodingInfo();
0665:                            }
0666:                            catch (UnsupportedEncodingException e) {
0667:                                System.err.println(e);
0668:                                return "UTF-8";
0669:                            }
0670:
0671:                            return charset.name();
0672:                        }
0673:                    }*/
0674:                }
0675:                return "UTF-8"; // Not an IANA or Xerces encoding, or was null for UTF8 default
0676:            }
0677:
0678:            /**
0679:             * @return the current encoding in IANA form, or null for default (UTF8)
0680:             */
0681:            public String getEncoding() {
0682:                Charset encodingCharset = FileEncodingQuery.getEncoding(fobj);
0683:                return (encodingCharset == null ? null : encodingCharset.name());
0684:            }
0685:
0686:            static final String BLANK = "                                                                                                                        ";
0687:
0688:            public void indent(PrintWriter w, int level) {
0689:                w.print(BLANK.substring(0, level * 4));
0690:            }
0691:
0692:            public void dump(org.w3c.dom.Node node, PrintWriter w, int level) {
0693:                indent(w, level);
0694:                if (node instanceof  Element)
0695:                    w.println("E lname:" + node.getLocalName());
0696:                else
0697:                    w.println(node.getClass().getName() + " lname:"
0698:                            + node.getLocalName());
0699:                org.w3c.dom.Node child = node.getFirstChild();
0700:                while (child != null) {
0701:                    dump(child, w, level + 1);
0702:                    child = child.getNextSibling();
0703:                }
0704:            }
0705:
0706:            public void dumpTo(PrintWriter w) {
0707:                if (sourceDocument != null) {
0708:                    dump(sourceDocument, w, 0);
0709:                }
0710:            }
0711:
0712:            /** Get the output format to be used when serializing this buffer */
0713:            public OutputFormat getOutputFormat() {
0714:                String xencoding = getIanaEncoding(getEncoding());
0715:                OutputFormat format = new OutputFormat(sourceDocument,
0716:                        xencoding, true); // do-indent==true
0717:                format.setLineWidth(160);
0718:                format.setIndent(4);
0719:                format.setAllowJavaNames(true);
0720:                return format;
0721:            }
0722:
0723:            public void writeTo(Writer w) throws java.io.IOException {
0724:                OutputFormat format = getOutputFormat();
0725:                JspxSerializer serializer = new JspxSerializer(w, format);
0726:                serializer.serialize(sourceDocument);
0727:            }
0728:
0729:            //------------------------------------------------------------------------------------ Accessors
0730:
0731:            public Document getSourceDom() {
0732:                return sourceDocument;
0733:            }
0734:
0735:            /** Lock for sync creating of rendered document. */
0736:            private final Object LOCK_RENDERED_DOCUMENT = new Object();
0737:
0738:            public Document getRenderedDom() {
0739:                boolean created = false;
0740:                synchronized (LOCK_RENDERED_DOCUMENT) {
0741:                    if (renderedDocument == null) {
0742:                        renderedDocument = createEmptyRenderedDocument();
0743:                        created = true;
0744:                    }
0745:                }
0746:                if (created) {
0747:                    initRenderedDocument();
0748:                }
0749:
0750:                return renderedDocument;
0751:            }
0752:
0753:            private void initRenderedDocument() {
0754:                Document renderedDom;
0755:                synchronized (LOCK_RENDERED_DOCUMENT) {
0756:                    renderedDom = renderedDocument;
0757:                }
0758:                setUrlForDocument(renderedDom, getBase());
0759:                CssProvider.getEngineService().createCssEngineForDocument(
0760:                        renderedDom, getUrlForDocument(renderedDom));
0761:            }
0762:
0763:            private static Document createEmptyRenderedDocument() {
0764:                try {
0765:                    org.xml.sax.InputSource is = new org.xml.sax.InputSource(
0766:                            new StringReader("<html></html>")); // TEMP
0767:                    DocumentBuilder parser = MarkupService
0768:                            .createRaveRenderedDocumentBuilder(true);
0769:                    Document doc = parser.parse(is);
0770:                    return doc;
0771:                } catch (java.io.IOException ex) {
0772:                    ex.printStackTrace();
0773:                } catch (org.xml.sax.SAXException ex) {
0774:                    ex.printStackTrace();
0775:                } catch (javax.xml.parsers.ParserConfigurationException ex) {
0776:                    ex.printStackTrace();
0777:                }
0778:                return null;
0779:            }
0780:
0781:            /**
0782:             * Gets the actual prefix in this document for a given namespace. Registers the default if it
0783:             * does not yet exist.
0784:             *
0785:             * @param namespaceUri
0786:             * @param suggPrefix
0787:             * @return the existing or newly registered prefix
0788:             */
0789:            public String getNamespacePrefix(String namespaceUri,
0790:                    String suggPrefix) {
0791:                String prefix = (String) namespaces.get(namespaceUri);
0792:                if (prefix != null)
0793:                    return prefix;
0794:
0795:                Collection prefixes = namespaces.values();
0796:
0797:                // try out the suggested prefix first if one was given
0798:                if (suggPrefix != null && !prefixes.contains(suggPrefix)) {
0799:                    prefix = suggPrefix;
0800:                } else {
0801:                    // first, try to make up a prefix from the last part of the URI
0802:                    int slash = namespaceUri.lastIndexOf('/');
0803:                    if (slash >= 0) {
0804:                        for (int l = 1; slash + 1 + l < namespaceUri.length(); l++) {
0805:                            String p = namespaceUri.substring(slash + 1, slash
0806:                                    + 1 + l);
0807:                            if (!prefixes.contains(p)) {
0808:                                prefix = p;
0809:                                break;
0810:                            }
0811:                        }
0812:                    }
0813:                    //            if (prefix == null) {
0814:                    //                // try something else...
0815:                    //            }
0816:                }
0817:
0818:                if (prefix != null) {
0819:                    Element root = sourceDocument.getDocumentElement();
0820:                    ensureAttributeValue(root, "xmlns:" + prefix, namespaceUri);
0821:                }
0822:
0823:                return prefix;
0824:            }
0825:
0826:            public URI getBaseURI() {
0827:                if (baseURI == null) {
0828:                    if (base == null) {
0829:                        base = getBase();
0830:                    } else {
0831:                        try {
0832:                            baseURI = new URI(base.toExternalForm());
0833:                        } catch (URISyntaxException use) {
0834:                            baseURI = null;
0835:                        }
0836:                    }
0837:                }
0838:                return baseURI;
0839:            }
0840:
0841:            /**
0842:             * Returns the location to resolve relative URLs against. By default this will be the document's
0843:             * URL if the document was loaded from a URL. If a base tag is found and can be parsed, it will
0844:             * be used as the base location.
0845:             *
0846:             * @return the base location
0847:             */
0848:            public URL getBase() {
0849:                if (base == null) {
0850:                    // First see if we have a <base> tag within the <head>
0851:
0852:                    // TODO - gather ALL <base> elements within the head
0853:                    // and process them
0854:                    Element root = sourceDocument.getDocumentElement();
0855:                    Element html = findHtmlTag(root);
0856:                    if (html != null) {
0857:                        Element head = Util.findChild("head", html, false);
0858:                        if (head != null) {
0859:                            Element baseElement = Util.findChild("base", head,
0860:                                    false);
0861:                            if (baseElement != null) {
0862:                                String href = baseElement.getAttribute("href");
0863:                                if (href != null && href.length() > 0) {
0864:                                    try {
0865:                                        try {
0866:                                            baseURI = new URI(href);
0867:                                            //base = new URL(href);
0868:                                            base = baseURI.toURL();
0869:                                        } catch (URISyntaxException ex) {
0870:                                            base = new URL(href);
0871:                                        }
0872:                                    } catch (MalformedURLException mue) {
0873:                                        ErrorManager
0874:                                                .getDefault()
0875:                                                .notify(
0876:                                                        ErrorManager.INFORMATIONAL,
0877:                                                        mue);
0878:                                    }
0879:                                    if (base != null) {
0880:                                        return base;
0881:                                    }
0882:                                }
0883:                            }
0884:                        }
0885:                    }
0886:
0887:                    // No <base>, so get the URL of the document file itself
0888:                    // and use that to resolve relative URLs.
0889:
0890:                    // Compute base
0891:                    /* These URLs don't seem to work - they become
0892:                       nbfs://<whatever> which Swing is not handling. So we've
0893:                       gotta do the file:// thing. This means for now, opening
0894:                       a web form inside a jar file with relative URLs won't work.
0895:                    try {
0896:                       base = dobj.getPrimaryFile().getParent().getURL();
0897:                    }
0898:                    catch (org.openide.filesystems.FileStateInvalidException e) {
0899:                       ErrorManager.getDefault().notify(e);
0900:                    }
0901:                     */
0902:                    if (fobj == null) // Testsuite
0903:                        return null;
0904:
0905:                    try {
0906:                        FileObject fp = fobj.getParent();
0907:                        baseURI = FileUtil.toFile(fp).toURI();
0908:                        base = baseURI.toURL();
0909:                    } catch (MalformedURLException e) {
0910:                        ErrorManager.getDefault().notify(e);
0911:                    }
0912:                }
0913:                return base;
0914:            }
0915:
0916:            /** Convert the given path to a URL: encode spaces to %20's, use
0917:             * only forward slashes, etc.
0918:             * @todo Find a better home for this method
0919:             */
0920:            public static String toURL(String path) {
0921:                // The URL encoder doesn't seem to do this - surprising
0922:                path = path.replace('\\', '/');
0923:                // This was also surprising - it makes spaces into +'es instead
0924:                path = path.replaceAll(" ", "%20");
0925:                StringWriter sw = new StringWriter();
0926:                try {
0927:                    // WriteURL signature changed in JSF1.2-02-b04
0928:                    com.sun.faces.util.HtmlUtils.writeURL(sw, path, null, null);
0929:                } catch (java.io.IOException ex) {
0930:                    ErrorManager.getDefault().notify(ex);
0931:                    return path;
0932:                }
0933:                return sw.toString();
0934:            }
0935:
0936:            // <markup_separation> moved to designer/markup/XhtmlCssEngine
0937:            //    /** Convert the given URL to a path: decode spaces from %20's, etc.
0938:            //     * If the url does not begin with "file:" it will not do anything.
0939:            //     * @todo Find a better home for this method
0940:            //     */
0941:            //    public static String fromURL(String url) {
0942:            //        if (url.startsWith("file:")) { // NOI18N
0943:            //            int n = url.length();
0944:            //            StringBuffer sb = new StringBuffer(n);
0945:            //            for (int i = 5; i < n; i++) {
0946:            //                char c = url.charAt(i);
0947:            //                // TODO -- any File.separatorChar manipulation perhaps?
0948:            //                if (c == '%' && i < n-3) {
0949:            //                    char d1 = url.charAt(i+1);
0950:            //                    char d2 = url.charAt(i+2);
0951:            //                    if (Character.isDigit(d1) && Character.isDigit(d2)) {
0952:            //                        String numString = ""+d1+d2;
0953:            //                        try {
0954:            //                            int num = Integer.parseInt(numString, 16);
0955:            //                            if (num >= 0 && num <= 255) {
0956:            //                                sb.append((char)num);
0957:            //                                i += 2;
0958:            //                                continue;
0959:            //                            }
0960:            //                        } catch (NumberFormatException nex) {
0961:            //                            ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, nex);
0962:            //                        }
0963:            //                    }
0964:            //                    sb.append(c);
0965:            //                } else {
0966:            //                    sb.append(c);
0967:            //                }
0968:            //            }
0969:            //            return sb.toString();
0970:            //        }
0971:            //        return url;
0972:            //    }
0973:            // </markup_separation>
0974:
0975:            /**
0976:             * Return true iff this web page should not be converted to a web form if it's missing a backing
0977:             * file. Web forms can be marked in this way if the user answers no to the conversion dialog.
0978:             */
0979:            public boolean isHtmlOnly() {
0980:                if (sourceDocument == null) {
0981:                    return false;
0982:                }
0983:                Element root = sourceDocument.getDocumentElement();
0984:                Element html = findHtmlTag(root);
0985:                if (html == null) { // We're hosed!!! This shouldn't happen
0986:                    Thread.dumpStack();
0987:                    return false;
0988:                }
0989:                Element head = Util.findChild("head", html, true);
0990:                if (head == null) {
0991:                    return false;
0992:                }
0993:                NodeList list = head.getChildNodes();
0994:                int len = list.getLength();
0995:                for (int i = 0; i < len; i++) {
0996:                    org.w3c.dom.Node child = list.item(i);
0997:                    if (child.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE) {
0998:                        Element meta = (Element) child;
0999:                        if ("meta".equals(meta.getTagName())) {
1000:                            if (!"creator.webform".equalsIgnoreCase(meta
1001:                                    .getAttribute("name"))) {
1002:                                continue;
1003:                            }
1004:                            String isForm = meta.getAttribute("content");
1005:                            return isForm != null && isForm.equals("no");
1006:                        }
1007:                    }
1008:                }
1009:                return false;
1010:            }
1011:
1012:            /**
1013:             * Mark this web form in such a way that in the future, isHtmlOnly will return false. In other
1014:             * words, if this web page should not be converted to a web form, call this method such that the
1015:             * conversion dialog is not shown next time this markup document is opened. This method should
1016:             * NOT be called on a file which already returns isHtmlOnly (it may add additional meta tags,
1017:             * not look for existing ones first).
1018:             */
1019:            public void markHtmlOnly() { // not called setHtmlOnly since we only
1020:                // support setting the property to
1021:                // true, not false
1022:                assert !isHtmlOnly();
1023:
1024:                Element root = sourceDocument.getDocumentElement();
1025:                Element html = findHtmlTag(root);
1026:                if (html == null) { // We're hosed!!! This shouldn't happen
1027:                    Thread.dumpStack();
1028:                    return;
1029:                }
1030:                Element head = ensureElement(html, "head", null);
1031:                Element meta = ensureElement(head, "meta", null);
1032:                meta.setAttribute("content", "no");
1033:                meta.setAttribute("name", "creator.webform");
1034:            }
1035:
1036:            /**
1037:             * Locate the &lt;html&gt; tag. In a normal xhtml/html document, it's the same as the root tag
1038:             * for the DOM, but in our JSF files, it might be nested within &lt;jsp:root&gt;,
1039:             * &lt;f:view&gt;, etc.
1040:             *
1041:             * @param root  The root tag
1042:             * @todo Just pass in the Document node instead?
1043:             * @return The html tag Element
1044:             */
1045:            public Element findHtmlTag(Node root) {
1046:                if (root.getNodeType() == Node.ELEMENT_NODE) {
1047:                    Element element = (Element) root;
1048:                    if ("html".equals(element.getTagName())) // Don't allow "HTML"
1049:                        return element;
1050:                }
1051:                NodeList list = root.getChildNodes();
1052:                int len = list.getLength();
1053:                for (int i = 0; i < len; i++) {
1054:                    Node child = list.item(i);
1055:                    Element match = findHtmlTag(child);
1056:                    if (match != null)
1057:                        return match;
1058:                }
1059:                return null;
1060:            }
1061:
1062:            //---------------------------------------------------------------------------------- Public CSS2
1063:
1064:            /** Add a parser error to the hashmap for the given CSS/SAC error */
1065:            /*
1066:            private void addError(CSSParseException exception, boolean isError) {
1067:                String message = exception.getMessage();
1068:                int line = exception.getLineNumber();
1069:                int column = exception.getColumnNumber();
1070:                //String uri = exception.getURI();
1071:
1072:                // XXX What is the file here? Gotta track that somehow, so
1073:                // I can either point to a particular stylesheet file, or
1074:                // a local style attribute, or a <style> tag section...
1075:
1076:                error = new ParserAnnotation(message, fobj, line, column);
1077:
1078:                if (isError)
1079:                    setInvalid();
1080:            }
1081:             */
1082:
1083:            //----------------------------------------------------------------------------------- Public DOM
1084:            /**
1085:             * Create a new document, from an xhtml fragment source string
1086:             */
1087:            private Document createDocument(Document ownerDom,
1088:                    final String source) {
1089:                try {
1090:                    // just a plain ol' XML DOM Document, use the regular XML DOM parser
1091:                    // wrap source with a fake root since it may contain more than one element
1092:                    // XXX Note: designer knows about the fake-root element
1093:                    // name. Don't change arbitrarily!
1094:                    String fullSource = "<!DOCTYPE html \nPUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"\"><fake-root>"
1095:                            + source + "</fake-root>";
1096:                    org.xml.sax.InputSource is = new org.xml.sax.InputSource(
1097:                            new StringReader(fullSource));
1098:                    ClassLoader oldClassLoader = Thread.currentThread()
1099:                            .getContextClassLoader();
1100:                    try {
1101:                        Thread.currentThread().setContextClassLoader(
1102:                                (ClassLoader) Lookup.getDefault().lookup(
1103:                                        ClassLoader.class));
1104:                        DocumentBuilder parser = MarkupService
1105:                                .createRaveSourceDocumentBuilder(supportCss);
1106:                        parser.setEntityResolver(new XhtmlEntityResolver());
1107:
1108:                        parser.setErrorHandler(new ErrorHandler() {
1109:                            // ---- Implements org.xml.sax.ErrorHandler ----------
1110:
1111:                            public void error(SAXParseException exception) {
1112:                                fragmentError(exception, true, source);
1113:                            }
1114:
1115:                            public void fatalError(SAXParseException exception) {
1116:                                fragmentError(exception, true, source);
1117:                            }
1118:
1119:                            public void warning(SAXParseException exception) {
1120:                                fragmentError(exception, false, source);
1121:                            }
1122:                        });
1123:
1124:                        Document fragdoc = parser.parse(is);
1125:                        //            if (fragdoc instanceof RaveDocument) {
1126:                        // <markup_separation>
1127:                        //                ((RaveDocument)fragdoc).setMarkupUnit(this);
1128:                        // ====
1129:                        setMarkupUnitForDocument(fragdoc, this );
1130:                        // </markup_separation>
1131:                        //                ((RaveDocument)fragdoc).setCssEngine(((RaveDocument)sourceDocument).getCssEngine());
1132:                        //                CssProvider.getEngineService().reuseCssEngineForDocument(fragdoc, sourceDocument);
1133:                        // XXX Not fragdoc but its rendered doc?!
1134:                        CssProvider.getEngineService()
1135:                                .reuseCssEngineForDocument(fragdoc, ownerDom);
1136:                        //            }
1137:
1138:                        return fragdoc;
1139:                    } finally {
1140:                        Thread.currentThread().setContextClassLoader(
1141:                                oldClassLoader);
1142:                    }
1143:                } catch (java.io.IOException e) {
1144:                    // should not happen reading from a string!
1145:                    //            Trace.trace("insync.markup", "Error in createDocumentFragment");
1146:                    //            Trace.trace("insync.markup", e);
1147:                    e.printStackTrace();
1148:                } catch (org.xml.sax.SAXException e) {
1149:                    //            Trace.trace("insync.markup", "Error in createDocumentFragment");
1150:                    //            Trace.trace("insync.markup", e);
1151:                    e.printStackTrace();
1152:                } catch (javax.xml.parsers.ParserConfigurationException e) {
1153:                    //            Trace.trace("insync.markup", "Error in createDocumentFragment");
1154:                    //            Trace.trace("insync.markup", e);
1155:                    e.printStackTrace();
1156:                }
1157:                return null;
1158:            }
1159:
1160:            //    /**
1161:            //     * Create a new source document fragment, from a source string, that will live in the current
1162:            //     * source document. The fragment needs to be added as a child to a specific node before it will really
1163:            //     * exist in the source document tree.
1164:            //     */
1165:            //    private DocumentFragment createDocumentFragment(Document ownerDom, String source) {
1166:            //        Document fragdoc = createDocument(ownerDom, source);
1167:            //        if (fragdoc != null) {
1168:            ////            DocumentFragment fragment = sourceDocument.createDocumentFragment();
1169:            //            DocumentFragment fragment = ownerDom.createDocumentFragment();
1170:            //                    
1171:            //            NodeList elems = fragdoc.getDocumentElement().getChildNodes();
1172:            //            // get the elems from our fake root
1173:            //            // import them into this sourceDocument, and add the copies to the fragment
1174:            //            int elemCount = elems.getLength();
1175:            //            for (int i = 0; i < elemCount; i++) {
1176:            ////                Node e = sourceDocument.importNode(elems.item(i), true);
1177:            //                Node e = ownerDom.importNode(elems.item(i), true);
1178:            //                
1179:            //                fragment.appendChild(e);
1180:            //            }
1181:            //            return fragment;
1182:            //        }
1183:            //        return null;
1184:            //    }
1185:
1186:            private void fragmentError(SAXParseException exception,
1187:                    boolean isError, String source) {
1188:                String message = exception.getMessage();
1189:                int line = exception.getLineNumber();
1190:                int column = exception.getColumnNumber();
1191:                //String publicId = exception.getPublicId();
1192:                //String systemId = exception.getSystemId();
1193:                if (source.length() > 80) {
1194:                    source = source.substring(0, 80) + "...";
1195:                }
1196:
1197:                // TODO: i18n.
1198:                String error = line + ":" + column + ": " + message + ": "
1199:                        + source;
1200:
1201:                InputOutput io = IOProvider.getDefault().getIO(
1202:                        NbBundle.getMessage(MarkupUnit.class, "WindowTitle"),
1203:                        false);
1204:                OutputWriter out = io.getOut();
1205:                try {
1206:                    out.reset();
1207:                    // XXX #102988 There can't be null listener now.
1208:                    out.println(error, new OutputListener() {
1209:                        public void outputLineSelected(OutputEvent evt) {
1210:                            // No op.
1211:                        }
1212:
1213:                        public void outputLineAction(OutputEvent evt) {
1214:                            // No op.
1215:                        }
1216:
1217:                        public void outputLineCleared(OutputEvent evt) {
1218:                            // No op.
1219:                        }
1220:                    });
1221:                } catch (IOException ex) {
1222:                    // This is lame - our own output window shouldn't throw
1223:                    // IO exceptions!
1224:                    ErrorManager.getDefault().notify(ex);
1225:                }
1226:            }
1227:
1228:            //    private Document createEmptyDocument() {
1229:            //        Document doc = createEmptyDocument(supportCss);
1230:            ////        if (doc instanceof RaveDocument)
1231:            ////            // <markup_separation>
1232:            //////            ((RaveDocument)doc).setMarkupUnit(this);
1233:            ////            // ====
1234:            ////        {
1235:            //            setMarkupUnitForDocument(doc, this);
1236:            ////        }
1237:            //            // </markup_separation>
1238:            //        return doc;
1239:            //    }
1240:            //
1241:            //    private static Document createEmptyDocument(boolean supportCss) {
1242:            //        try {
1243:            //            org.xml.sax.InputSource is =
1244:            //                new org.xml.sax.InputSource(new StringReader("<html><body><p/></body></html>"));
1245:            //            DocumentBuilder parser = MarkupService.createRaveSourceDocumentBuilder(supportCss);
1246:            //            Document doc = parser.parse(is);
1247:            //            return doc;
1248:            //        }
1249:            //        catch (java.io.IOException e) {
1250:            //            // should not happen reading from a string!
1251:            //            Trace.trace("insync.markup", "Error in createEmptyDocument");
1252:            //            Trace.trace("insync.markup", e);
1253:            //        }
1254:            //        catch (org.xml.sax.SAXException e) {
1255:            //            Trace.trace("insync.markup", "Error in createEmptyDocument");
1256:            //            Trace.trace("insync.markup", e);
1257:            //        }
1258:            //        catch (javax.xml.parsers.ParserConfigurationException e) {
1259:            //            Trace.trace("insync.markup", "Error in createEmptyDocument");
1260:            //            Trace.trace("insync.markup", e);
1261:            //        }
1262:            //        return null;
1263:            //    }
1264:
1265:            public void appendParsedString(Node parent, String xhtml,
1266:                    MarkupDesignBean bean) {
1267:                //        assert parent.getOwnerDocument() == sourceDocument;
1268:                Document ownerDom = parent.getOwnerDocument();
1269:
1270:                if (xhtml.startsWith("<?") || xhtml.startsWith("<!DOCTYPE")) {
1271:                    // Skip it -- we can't parse this.
1272:                    // Braveheart likes to throw in (literally)
1273:                    // <?xml version="1.0" encoding="UTF-8"?>
1274:                    // for example
1275:                    return;
1276:                }
1277:                Document fragdoc = createDocument(ownerDom, xhtml);
1278:                // NOTE - we don't mark this source jspx as is done in read();
1279:                // this source is part of rendered html from a component, and
1280:                // has already had entities expanded.
1281:                if (fragdoc == null) {
1282:                    // Parse error - for now just insert the xhtml directly as
1283:                    // text - e.g. the user may see something like "<b>Hello</b>"
1284:                    // instead of Hello in a bold font
1285:                    //            Node textNode = sourceDocument.createTextNode(xhtml);
1286:                    Node textNode = ownerDom.createTextNode(xhtml);
1287:                    parent.appendChild(textNode);
1288:                } else {
1289:                    NodeList elems = fragdoc.getDocumentElement()
1290:                            .getChildNodes();
1291:                    // get the elems from our fake root
1292:                    // import them into this source document, and add the copies to the fragment
1293:
1294:                    // Find Element containing the import location
1295:                    Element parentElement = null;
1296:                    Node curr = parent;
1297:                    while (curr != null) {
1298:                        if (curr instanceof  Element) {
1299:                            parentElement = (Element) curr;
1300:                            break;
1301:                        }
1302:                        curr = curr.getParentNode();
1303:                    }
1304:
1305:                    int elemCount = elems.getLength();
1306:                    for (int i = 0; i < elemCount; i++) {
1307:                        // XXX Can't I just bang them into my other documenet fragment?
1308:                        //                Node e = sourceDocument.importNode(elems.item(i), true);
1309:                        Node e = ownerDom.importNode(elems.item(i), true);
1310:
1311:                        // The xhtml fragment imported should participate in
1312:                        // the CSS context at the imported location
1313:                        if (parentElement != null && e instanceof  Element) {
1314:                            //                    RaveElement.setStyleParent((Element)e, parentElement);
1315:                            CssProvider.getEngineService()
1316:                                    .setStyleParentForElement((Element) e,
1317:                                            parentElement);
1318:                            // I have to set it on the Document too, because import node
1319:                            // will set up source pointers back to the derived document even
1320:                            // though it's not technically the jspx source (and the source
1321:                            // pointers are followed by the designer when computing text)
1322:                            // Consider fixing this later.
1323:                            //                    RaveElement.setStyleParent((Element)elems.item(i), parentElement);
1324:                            CssProvider.getEngineService()
1325:                                    .setStyleParentForElement(
1326:                                            (Element) elems.item(i),
1327:                                            parentElement);
1328:                        }
1329:                        parent.appendChild(e);
1330:                        setBean(e, bean);
1331:                    }
1332:                }
1333:            }
1334:
1335:            /** Set the DesignBean references recursively on the given node tree */
1336:            private void setBean(Node node, MarkupDesignBean bean) {
1337:                //        if (node instanceof RaveElement) {
1338:                //            ((RaveElement)node).setDesignBean(bean);
1339:                //        }
1340:                if (node instanceof  Element) {
1341:                    setMarkupDesignBeanForElement((Element) node, bean);
1342:                }
1343:
1344:                NodeList nl = node.getChildNodes();
1345:                for (int i = 0; i < nl.getLength(); i++) {
1346:                    setBean(nl.item(i), bean);
1347:                }
1348:            }
1349:
1350:            // XXX #123995 The apache impl of Document userData leaks, so we
1351:            // need to avoid using it for now. Returning to previous, but also
1352:            // using weak refs (because there is a link from MarkupDesignBean to Element).
1353:            /** Map <code>Element</code> to <code>MarkupDesignBean</code>. */
1354:            private static final Map element2markupDesignBean = new WeakHashMap(
1355:                    200);
1356:
1357:            //    private static final String KEY_MARKUP_DESIGN_BEAN = "vwpMarkupDesignBean"; // NOI18N
1358:
1359:            public static void setMarkupDesignBeanForElement(Element element,
1360:                    MarkupDesignBean markupDesignBean) {
1361:                synchronized (element2markupDesignBean) {
1362:                    element2markupDesignBean.put(element, new WeakReference(
1363:                            markupDesignBean));
1364:                }
1365:                //        if (element == null) {
1366:                //            // XXX Log problem?
1367:                //            return;
1368:                //        }
1369:                //        element.setUserData(KEY_MARKUP_DESIGN_BEAN, markupDesignBean, MarkupDesignBeanDataHandler.getDefault());
1370:            }
1371:
1372:            public static MarkupDesignBean getMarkupDesignBeanForElement(
1373:                    Element element) {
1374:                synchronized (element2markupDesignBean) {
1375:                    WeakReference ret = (WeakReference) element2markupDesignBean
1376:                            .get(element);
1377:                    return ret == null ? null : (MarkupDesignBean) ret.get();
1378:                }
1379:                //        if (element == null) {
1380:                //            // XXX Log problem?
1381:                //            return null;
1382:                //        }
1383:                //        return (MarkupDesignBean)element.getUserData(KEY_MARKUP_DESIGN_BEAN);
1384:            }
1385:
1386:            //    private static class MarkupDesignBeanDataHandler implements UserDataHandler {
1387:            //        private static final MarkupDesignBeanDataHandler INSTANCE = new MarkupDesignBeanDataHandler();
1388:            //        public static MarkupDesignBeanDataHandler getDefault() {
1389:            //            return INSTANCE;
1390:            //        }
1391:            //        public void handle(short operation, String key, Object data, Node src, Node dst) {
1392:            //            // No op.
1393:            //            // TODO Provide the copying (after remove the copying in the AbstractRaveElement).
1394:            //        }
1395:            //    } // End of MarkupDesignBeanUserData.
1396:
1397:            //------------------------------------------------------------------------ Change Event Handling
1398:
1399:            // <refactoring> why copy when one depends on it directly
1400:            //    // This section of constants copied from Xerces 2.5.0's MutationEventImpl class
1401:            //    // NON-DOM CONSTANTS: Storage efficiency, avoid risk of typos.
1402:            //    public static final String DOM_SUBTREE_MODIFIED = "DOMSubtreeModified";
1403:            //    public static final String DOM_NODE_INSERTED = "DOMNodeInserted";
1404:            //    public static final String DOM_NODE_REMOVED = "DOMNodeRemoved";
1405:            //    public static final String DOM_NODE_REMOVED_FROM_DOCUMENT = "DOMNodeRemovedFromDocument";
1406:            //    public static final String DOM_NODE_INSERTED_INTO_DOCUMENT = "DOMNodeInsertedIntoDocument";
1407:            //    public static final String DOM_ATTR_MODIFIED = "DOMAttrModified";
1408:            //    public static final String DOM_CHARACTER_DATA_MODIFIED = "DOMCharacterDataModified";
1409:            //
1410:            //    public static final String DOM_DOCUMENT_REPLACED = "DOMDocumentReplaced";
1411:            // ====
1412:            public static final String DOM_SUBTREE_MODIFIED = MutationEventImpl.DOM_SUBTREE_MODIFIED;
1413:            public static final String DOM_NODE_INSERTED = MutationEventImpl.DOM_NODE_INSERTED;
1414:            public static final String DOM_NODE_REMOVED = MutationEventImpl.DOM_NODE_REMOVED;
1415:            public static final String DOM_NODE_REMOVED_FROM_DOCUMENT = MutationEventImpl.DOM_NODE_REMOVED_FROM_DOCUMENT;
1416:            public static final String DOM_NODE_INSERTED_INTO_DOCUMENT = MutationEventImpl.DOM_NODE_INSERTED_INTO_DOCUMENT;
1417:            public static final String DOM_ATTR_MODIFIED = MutationEventImpl.DOM_ATTR_MODIFIED;
1418:            public static final String DOM_CHARACTER_DATA_MODIFIED = MutationEventImpl.DOM_CHARACTER_DATA_MODIFIED;
1419:
1420:            /** Insync extention of MutationEventImpl type (see insyc/MarkupUnit and xerces/MuationEventImpl). */
1421:            public static final String DOM_DOCUMENT_REPLACED = "DOMDocumentReplaced"; // NOI18N
1422:            // </refactoring>
1423:
1424:            private void registerDomListeners(Document document) {
1425:                Trace.trace("insync.markup", "MU.registerDomListeners "
1426:                        + document);
1427:                EventTarget target = (EventTarget) document;
1428:                target.addEventListener(DOM_ATTR_MODIFIED, this , false);
1429:                target.addEventListener(DOM_SUBTREE_MODIFIED, this , false);
1430:                registeredAsEventListenerOn = target;
1431:                /*
1432:                target.addEventListener(DOM_NODE_INSERTED, this, false);
1433:                target.addEventListener(DOM_NODE_INSERTED_INTO_DOCUMENT, this, false);
1434:                target.addEventListener(DOM_NODE_REMOVED, this, false);
1435:                target.addEventListener(DOM_NODE_REMOVED_FROM_DOCUMENT, this, false);
1436:                target.addEventListener(DOM_CHARACTER_DATA_MODIFIED, this, false);
1437:                 */
1438:            }
1439:
1440:            private void fireDocumentReplaced(Document document) {
1441:                Trace.trace("insync.markup", "MU.fireDomListeners " + document);
1442:                DocumentEvent doc = (DocumentEvent) document;
1443:                MutationEvent me = (MutationEvent) doc
1444:                        .createEvent("MutationEvents");
1445:                me.initMutationEvent(DOM_DOCUMENT_REPLACED, false, false,
1446:                        document, null, null, null, MutationEvent.REMOVAL);
1447:
1448:                EventTarget target = (EventTarget) document;
1449:                target.dispatchEvent(me);
1450:            }
1451:
1452:            protected void unregisterDomListeners() {
1453:                if (registeredAsEventListenerOn == null)
1454:                    return;
1455:                registeredAsEventListenerOn.removeEventListener(
1456:                        DOM_ATTR_MODIFIED, this , false);
1457:                registeredAsEventListenerOn.removeEventListener(
1458:                        DOM_SUBTREE_MODIFIED, this , false);
1459:                registeredAsEventListenerOn = null;
1460:            }
1461:
1462:            public void handleEvent(org.w3c.dom.events.Event e) {
1463:                setModelDirty();
1464:            }
1465:
1466:            //------------------------------------------------------------------------ Compute Buffer Positions
1467:
1468:            /**
1469:             * Return the buffer start position of a given node. Not currently very efficient or accurate
1470:             * @return the char offset of the node, -1 if not found
1471:             */
1472:            public int computeLine(Element element) {
1473:                LineCountingWriter w = new LineCountingWriter();
1474:                OutputFormat format = getOutputFormat();
1475:                TargetXMLSerializer serializer = new TargetXMLSerializer(w,
1476:                        format, element);
1477:                int pos = 0;
1478:                try {
1479:                    serializer.serialize(sourceDocument);
1480:                } catch (java.io.EOFException e) {
1481:                    // normal stop...
1482:                    pos = w.pos;
1483:                    if (!serializer.isAdjusted()) {
1484:                        pos++;
1485:                    }
1486:                } catch (java.io.IOException e) {
1487:                    assert Trace.trace("insync.java",
1488:                            "Error scanning for node position: " + e);
1489:                }
1490:
1491:                // It always includes an extra newline
1492:                return pos - 1;
1493:            }
1494:
1495:            /**
1496:             * Return the buffer start offset of a given node. Not currently very efficient or accurate
1497:             * @return the char offset of the node, -1 if not found
1498:             */
1499:            public int getOffset(Element element) {
1500:                LineCountingWriter w = new LineCountingWriter();
1501:                OutputFormat format = getOutputFormat();
1502:                TargetXMLSerializer serializer = new TargetXMLSerializer(w,
1503:                        format, element);
1504:                int offset = -1;
1505:                try {
1506:                    serializer.serialize(sourceDocument);
1507:                } catch (java.io.EOFException e) {
1508:                    // normal stop...
1509:                    offset = w.offset;
1510:                } catch (java.io.IOException e) {
1511:                    assert Trace.trace("insync.java",
1512:                            "Error scanning for node position: " + e);
1513:                }
1514:
1515:                return offset;
1516:            }
1517:
1518:            private class TargetXMLSerializer extends JspxSerializer {
1519:                private Element target;
1520:                private boolean adjusted = true;
1521:
1522:                private TargetXMLSerializer(java.io.Writer writer,
1523:                        OutputFormat format, Element target) {
1524:                    super (writer, format);
1525:                    this .target = target;
1526:                }
1527:
1528:                boolean isAdjusted() {
1529:                    return adjusted;
1530:                }
1531:
1532:                public void serializeElement(Element elem) throws IOException,
1533:                        EOFException {
1534:                    if (elem == target) {
1535:                        if (getElementState().empty) {
1536:                            adjusted = false;
1537:                        }
1538:                        //_printer.breakLine();
1539:                        _printer.flush();
1540:                        throw new EOFException();
1541:                    }
1542:                    super .serializeElement(elem);
1543:                }
1544:            }
1545:
1546:            public class LineCountingWriter extends Writer {
1547:                public int pos;
1548:                public int offset;
1549:
1550:                public void close() {
1551:                }
1552:
1553:                public void flush() {
1554:                }
1555:
1556:                public void write(char[] buf) {
1557:                    offset += buf.length;
1558:                    for (int i = 0; i < buf.length; i++) {
1559:                        if (buf[i] == '\n') {
1560:                            pos++;
1561:                        }
1562:                    }
1563:                }
1564:
1565:                public void write(char[] buf, int off, int len) {
1566:                    offset += len;
1567:                    for (int i = 0; i < len; i++) {
1568:                        if (buf[off + i] == '\n') {
1569:                            pos++;
1570:                        }
1571:                    }
1572:                }
1573:
1574:                public void write(int c) {
1575:                    offset++;
1576:                    if (c == '\n') {
1577:                        pos++;
1578:                    }
1579:                }
1580:
1581:                public void write(String str) {
1582:                    offset += str.length();
1583:                    for (int i = 0, n = str.length(); i < n; i++) {
1584:                        if (str.charAt(i) == '\n') {
1585:                            pos++;
1586:                        }
1587:                    }
1588:                }
1589:
1590:                public void write(String str, int off, int len) {
1591:                    offset += len;
1592:                    for (int i = 0; i < len; i++) {
1593:                        if (str.charAt(off + i) == '\n') {
1594:                            pos++;
1595:                        }
1596:                    }
1597:                }
1598:            }
1599:
1600:            //    // <markup_separation> Maintain the map between doc and unit, 
1601:            //    // and css engine and unit.
1602:            //    // Do not pass it directly into the doc or engine, it is not needed there.
1603:            //    /** Map between <code>org.w3c.dom.Document</code> and <code>MarkupUnit</code> */
1604:            //    private final static Map doc2markupUnit = new WeakHashMap();
1605:            //    private static final String KEY_MARKUP_UNIT = "vwpMarkupUnit"; // NOI18N
1606:
1607:            private static final Map<Document, MarkupUnit> doc2markupUnit = new WeakHashMap<Document, MarkupUnit>();
1608:
1609:            private static void setMarkupUnitForDocument(Document doc,
1610:                    MarkupUnit markupUnit) {
1611:                //        synchronized (doc2markupUnit) {
1612:                //            doc2markupUnit.put(doc, markupUnit);
1613:                //        }
1614:                if (doc == null) {
1615:                    return;
1616:                }
1617:                //        doc.setUserData(KEY_MARKUP_UNIT, markupUnit, MarkupUnitDataHandler.getDefault());
1618:                doc2markupUnit.put(doc, markupUnit);
1619:            }
1620:
1621:            public static MarkupUnit getMarkupUnitForDocument(Document doc) {
1622:                //        synchronized (doc2markupUnit) {
1623:                //            return (MarkupUnit)doc2markupUnit.get(doc);
1624:                //        }
1625:                if (doc == null) {
1626:                    return null;
1627:                }
1628:                //        return (MarkupUnit)doc.getUserData(KEY_MARKUP_UNIT);
1629:                return doc2markupUnit.get(doc);
1630:            }
1631:
1632:            //    private static class MarkupUnitDataHandler implements UserDataHandler {
1633:            //        private static final MarkupUnitDataHandler INSTANCE = new MarkupUnitDataHandler();
1634:            //        
1635:            //        public static MarkupUnitDataHandler getDefault() {
1636:            //            return INSTANCE;
1637:            //        }
1638:            //        
1639:            //        public void handle(short operation, String key, Object data, Node src, Node dst) {
1640:            //            // No op.
1641:            //        }
1642:            //    } // End of MarkupUnitDataHandler.
1643:
1644:            //    /** Map between <code>XhtmlCssEngine</code> and <code>MarkupUnit</code>. */
1645:            //    private final static Map cssEngine2markupUnit = new WeakHashMap();
1646:            //    
1647:            //    private void setMarkupUnitForCssEngine(XhtmlCssEngine cssEngine, MarkupUnit markupUnit) {
1648:            //        synchronized (cssEngine2markupUnit) {
1649:            //            cssEngine2markupUnit.put(cssEngine, markupUnit);
1650:            //        }
1651:            //    }
1652:            //    
1653:            //    public MarkupUnit getMarkupUnitForCssEngine(XhtmlCssEngine cssEngine) {
1654:            //        synchronized (cssEngine2MarkupUnit) {
1655:            //            return (MarkupUnit)cssEngine2markupUnit;
1656:            //        }
1657:            //    }
1658:            // </markup_separation>
1659:
1660:            //    /** Map between <code>org.w3c.dom.Document</code> and <code>URL</code> */
1661:            //    private final static Map doc2url = new WeakHashMap();
1662:            //    private static final String KEY_URL = "vwpUrl"; // NOI18N
1663:
1664:            private static final Map<Document, URL> doc2url = new WeakHashMap<Document, URL>();
1665:
1666:            public/*private*/static void setUrlForDocument(Document doc,
1667:                    URL url) {
1668:                //        synchronized (doc2url) {
1669:                //            doc2url.put(doc, url);
1670:                //        }
1671:                if (doc == null) {
1672:                    return;
1673:                }
1674:                //        doc.setUserData(KEY_URL, url, UrlDataHandler.getDefault());
1675:                doc2url.put(doc, url);
1676:            }
1677:
1678:            public static URL getUrlForDocument(Document doc) {
1679:                //        synchronized (doc2url) {
1680:                //            return (URL)doc2url.get(doc);
1681:                //        }
1682:                if (doc == null) {
1683:                    return null;
1684:                }
1685:                //        return (URL)doc.getUserData(KEY_URL);
1686:                return doc2url.get(doc);
1687:            }
1688:
1689:            //    private static class UrlDataHandler implements UserDataHandler {
1690:            //        private static final UrlDataHandler INSTANCE = new UrlDataHandler();
1691:            //        
1692:            //        public static UrlDataHandler getDefault() {
1693:            //            return INSTANCE;
1694:            //        }
1695:            //        
1696:            //        public void handle(short operation, String key, Object data, Node src, Node dst) {
1697:            //            // No op.
1698:            //        }
1699:            //    } // End of UrlDataHandler.
1700:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.