001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041:
042: package org.netbeans.spi.xml.cookies;
043:
044: import java.io.Reader;
045: import java.net.URI;
046: import java.net.URISyntaxException;
047: import java.net.URL;
048: import javax.swing.text.Document;
049: import javax.xml.parsers.ParserConfigurationException;
050: import javax.xml.parsers.SAXParser;
051: import javax.xml.parsers.SAXParserFactory;
052: import javax.xml.transform.Source;
053: import javax.xml.transform.sax.SAXSource;
054: import org.netbeans.api.xml.parsers.DocumentInputSource;
055: import org.netbeans.api.xml.services.UserCatalog;
056: import org.openide.cookies.EditorCookie;
057: import org.openide.filesystems.FileObject;
058: import org.openide.filesystems.FileStateInvalidException;
059: import org.openide.loaders.DataObject;
060: import org.xml.sax.EntityResolver;
061: import org.xml.sax.InputSource;
062: import org.xml.sax.SAXException;
063: import org.xml.sax.SAXNotRecognizedException;
064: import org.xml.sax.SAXNotSupportedException;
065: import org.xml.sax.XMLReader;
066:
067: /**
068: * Adapt <code>DataObject</code> to other common XML interfaces.
069: *
070: * @author Petr Kuzel
071: * @since 0.9
072: */
073: public final class DataObjectAdapters {
074:
075: /** SAX feature: Perform namespace processing. */
076: private static final String SAX_FEATURES_NAMESPACES = "http://xml.org/sax/features/namespaces"; // NOI18N
077:
078: /** cached SAXParserFactory instance. */
079: private static SAXParserFactory saxParserFactory;
080:
081: private DataObjectAdapters() {
082: }
083:
084: /**
085: * Create InputSource from DataObject. Default implementation prefers opened
086: * Swing <code>Document</code> over primary file URL.
087: * @return <code>DataObject</code> never <code>null</code>
088: */
089: public static InputSource inputSource(DataObject dataObject) {
090: if (dataObject == null)
091: throw new NullPointerException();
092: return new DataObjectInputSource(dataObject);
093: }
094:
095: /**
096: * Lazy evaluated wrapper.
097: */
098: private static class DataObjectInputSource extends InputSource {
099:
100: private final DataObject dataObject;
101:
102: public DataObjectInputSource(DataObject dataObject) {
103: this .dataObject = dataObject;
104: }
105:
106: public String getSystemId() {
107: return DataObjectAdapters.getSystemId(dataObject);
108: }
109:
110: public Reader getCharacterStream() {
111:
112: EditorCookie editor = (EditorCookie) dataObject
113: .getCookie(EditorCookie.class);
114:
115: if (editor != null) {
116: Document doc = editor.getDocument();
117: if (doc != null) {
118: return new DocumentInputSource(doc)
119: .getCharacterStream();
120: }
121: }
122:
123: return null;
124: }
125:
126: }
127:
128: /**
129: * Create Source from DataObject. Default implementation prefers opened
130: * Swing <code>Document</code> over primary file URL.
131: * @return <code>DataObject</code> never <code>null</code>
132: */
133: public static Source source(DataObject dataObject) {
134: if (dataObject == null)
135: throw new NullPointerException();
136: return new DataObjectSAXSource(dataObject);
137: }
138:
139: /**
140: * Lazy evaluated wrapper.
141: */
142: private static class DataObjectSAXSource extends SAXSource {
143:
144: private final DataObject dataObject;
145:
146: public DataObjectSAXSource(DataObject dataObject) {
147: this .dataObject = dataObject;
148: }
149:
150: public String getSystemId() {
151: return DataObjectAdapters.getSystemId(dataObject);
152: }
153:
154: public XMLReader getXMLReader() {
155: try {
156: XMLReader reader = newXMLReader();
157: reader.setEntityResolver(getEntityResolver());
158: return reader;
159: } catch (ParserConfigurationException ex) {
160: Util.THIS.debug(ex);
161: } catch (SAXNotRecognizedException ex) {
162: Util.THIS.debug(ex);
163: } catch (SAXNotSupportedException ex) {
164: Util.THIS.debug(ex);
165: } catch (SAXException ex) {
166: Util.THIS.debug(ex);
167: }
168: return null;
169: }
170:
171: public InputSource getInputSource() {
172: return inputSource(dataObject);
173: }
174:
175: } // class DataObjectSAXSource
176:
177: /** Try to find the best URL name of <code>dataObject</code>.
178: * @return system Id of <code>dataObject</code>
179: */
180: private static String getSystemId(DataObject dataObject) {
181: String systemId = null;
182: try {
183: FileObject fileObject = dataObject.getPrimaryFile();
184: URL url = fileObject.getURL();
185: try {
186: systemId = new URI(url.toString()).toASCIIString();
187: } catch (URISyntaxException ex) {
188: // if cannot be converted to URI, return at least external form
189: // instead of returning null
190: systemId = url.toExternalForm();
191: Util.THIS.debug(ex);
192: }
193: } catch (FileStateInvalidException exc) {
194: if (Util.THIS.isLoggable()) /* then */
195: Util.THIS.debug(exc);
196:
197: // nothing to do -> return null; //???
198: }
199: return systemId;
200: }
201:
202: private static synchronized SAXParserFactory getSAXParserFactory()
203: throws ParserConfigurationException,
204: SAXNotRecognizedException, SAXNotSupportedException {
205: if (saxParserFactory == null) {
206: saxParserFactory = SAXParserFactory.newInstance();
207: saxParserFactory.setFeature(SAX_FEATURES_NAMESPACES, true);
208: }
209: return saxParserFactory;
210: }
211:
212: /**
213: *
214: * @throws ParserConfigurationException if a parser cannot
215: * be created which satisfies the requested configuration.
216: * @throws SAXException if a parser cannot be created which satisfies the requested configuration.
217: */
218: private static XMLReader newXMLReader()
219: throws ParserConfigurationException, SAXException {
220: SAXParser parser = getSAXParserFactory().newSAXParser(); //!!! it is expensive!
221: return parser.getXMLReader();
222: }
223:
224: private static EntityResolver getEntityResolver() {
225: UserCatalog catalog = UserCatalog.getDefault();
226: EntityResolver res = (catalog == null ? null : catalog
227: .getEntityResolver());
228: return res;
229: }
230: }
|