KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > batik > apps > svgbrowser > XMLInputHandler


1 /*
2
3    Copyright 2002-2003 The Apache Software Foundation
4
5    Licensed under the Apache License, Version 2.0 (the "License");
6    you may not use this file except in compliance with the License.
7    You may obtain a copy of the License at
8
9        http://www.apache.org/licenses/LICENSE-2.0
10
11    Unless required by applicable law or agreed to in writing, software
12    distributed under the License is distributed on an "AS IS" BASIS,
13    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14    See the License for the specific language governing permissions and
15    limitations under the License.
16
17  */

18 package org.apache.batik.apps.svgbrowser;
19
20 import java.io.File JavaDoc;
21 import java.io.StringReader JavaDoc;
22 import java.io.StringWriter JavaDoc;
23
24 import javax.xml.parsers.DocumentBuilder JavaDoc;
25 import javax.xml.parsers.DocumentBuilderFactory JavaDoc;
26 import javax.xml.transform.Source JavaDoc;
27 import javax.xml.transform.Transformer JavaDoc;
28 import javax.xml.transform.TransformerFactory JavaDoc;
29 import javax.xml.transform.URIResolver JavaDoc;
30 import javax.xml.transform.dom.DOMSource JavaDoc;
31 import javax.xml.transform.stream.StreamResult JavaDoc;
32 import javax.xml.transform.stream.StreamSource JavaDoc;
33
34 import org.apache.batik.dom.svg.SAXSVGDocumentFactory;
35 import org.apache.batik.dom.svg.SVGDOMImplementation;
36 import org.apache.batik.dom.util.DOMUtilities;
37 import org.apache.batik.dom.util.HashTable;
38 import org.apache.batik.util.ParsedURL;
39 import org.apache.batik.util.SVGConstants;
40 import org.apache.batik.util.XMLResourceDescriptor;
41 import org.w3c.dom.Attr JavaDoc;
42 import org.w3c.dom.Document JavaDoc;
43 import org.w3c.dom.Element JavaDoc;
44 import org.w3c.dom.NamedNodeMap JavaDoc;
45 import org.w3c.dom.Node JavaDoc;
46 import org.w3c.dom.ProcessingInstruction JavaDoc;
47 import org.w3c.dom.svg.SVGDocument;
48
49 /**
50  * A <tt>SquiggleInputHandler</tt> that handles XSLT transformable
51  * XML documents.
52  * This implementation of the <tt>SquiggleInputHandler</tt> class
53  * handles XML files by looking for the first
54  * &lt;?xml-stylesheet ... ?&gt; processing instruction referencing
55  * an xsl document. In case there is one, the transform is applied to the
56  * input XML file and the handler checks that the result is an
57  * SVG document with an SVG root.
58  *
59  * @author <a mailto="vincent.hardy@sun.com">Vincent Hardy</a>
60  * @version $Id: XMLInputHandler.java,v 1.9 2005/03/27 08:58:30 cam Exp $
61  */

62 public class XMLInputHandler implements SquiggleInputHandler {
63     public static final String JavaDoc[] XVG_MIME_TYPES =
64     { "image/xml+xsl+svg" };
65
66     public static final String JavaDoc[] XVG_FILE_EXTENSIONS =
67     { ".xml", ".xsl" };
68
69     public static final String JavaDoc ERROR_NO_XML_STYLESHEET_PROCESSING_INSTRUCTION
70         = "XMLInputHandler.error.no.xml.stylesheet.processing.instruction";
71
72     public static final String JavaDoc ERROR_TRANSFORM_OUTPUT_NOT_SVG
73         = "XMLInputHandler.error.transform.output.not.svg";
74
75     public static final String JavaDoc ERROR_TRANSFORM_PRODUCED_NO_CONTENT
76         = "XMLInputHandler.error.transform.produced.no.content";
77
78     public static final String JavaDoc ERROR_TRANSFORM_OUTPUT_WRONG_NS
79         = "XMLInputHandler.error.transform.output.wrong.ns";
80
81     public static final String JavaDoc ERROR_RESULT_GENERATED_EXCEPTION
82         = "XMLInputHandler.error.result.generated.exception";
83
84     public static final String JavaDoc XSL_PROCESSING_INSTRUCTION_TYPE
85         = "text/xsl";
86
87     public static final String JavaDoc PSEUDO_ATTRIBUTE_TYPE
88         = "type";
89
90     public static final String JavaDoc PSEUDO_ATTRIBUTE_HREF
91         = "href";
92
93     /**
94      * Returns the list of mime types handled by this handler.
95      */

96     public String JavaDoc[] getHandledMimeTypes() {
97         return XVG_MIME_TYPES;
98     }
99     
100     /**
101      * Returns the list of file extensions handled by this handler
102      */

103     public String JavaDoc[] getHandledExtensions() {
104         return XVG_FILE_EXTENSIONS;
105     }
106
107     /**
108      * Returns a description for this handler
109      */

110     public String JavaDoc getDescription() {
111         return "";
112     }
113
114     /**
115      * Returns true if the input file can be handled by the handler
116      */

117     public boolean accept(File JavaDoc f) {
118         return f.isFile() && accept(f.getPath());
119     }
120
121     /**
122      * Returns true if the input URI can be handled by the handler
123      */

124     public boolean accept(ParsedURL purl) {
125         if (purl == null) {
126             return false;
127         }
128
129         // <!> Note: this should be improved to rely on Mime Type
130
// when the http protocol is used. This will use the
131
// ParsedURL.getContentType method.
132

133         String JavaDoc path = purl.getPath();
134         return accept(path);
135     }
136
137     /**
138      * Return true if the resource with the given path can
139      * be handled.
140      */

141     public boolean accept(String JavaDoc path) {
142         if (path == null) {
143             return false;
144         }
145
146         for (int i=0; i<XVG_FILE_EXTENSIONS.length; i++) {
147             if (path.endsWith(XVG_FILE_EXTENSIONS[i])) {
148                 return true;
149             }
150         }
151
152         return false;
153     }
154
155     /**
156      * Handles the given input for the given JSVGViewerFrame
157      */

158     public void handle(ParsedURL purl, JSVGViewerFrame svgViewerFrame) throws Exception JavaDoc {
159         String JavaDoc uri = purl.toString();
160
161         TransformerFactory JavaDoc tFactory
162             = TransformerFactory.newInstance();
163         
164         // First, load the input XML document into a generic DOM tree
165
DocumentBuilderFactory JavaDoc dbf = DocumentBuilderFactory.newInstance();
166         dbf.setValidating(false);
167         dbf.setNamespaceAware(true);
168
169         DocumentBuilder JavaDoc db = dbf.newDocumentBuilder();
170
171         Document JavaDoc inDoc = db.parse(uri);
172        
173         // Now, look for <?xml-stylesheet ...?> processing instructions
174
String JavaDoc xslStyleSheetURI
175             = extractXSLProcessingInstruction(inDoc);
176         
177         if (xslStyleSheetURI == null) {
178             // Assume that the input file is a literal result template
179
xslStyleSheetURI = uri;
180         }
181
182         ParsedURL parsedXSLStyleSheetURI
183             = new ParsedURL(uri, xslStyleSheetURI);
184
185         Transformer JavaDoc transformer
186             = tFactory.newTransformer
187             (new StreamSource JavaDoc(parsedXSLStyleSheetURI.toString()));
188
189         // Set the URIResolver to properly handle document() and xsl:include
190
transformer.setURIResolver
191             (new DocumentURIResolver(parsedXSLStyleSheetURI.toString()));
192
193         // Now, apply the transformation to the input document.
194
//
195
// <!> Due to issues with namespaces, the transform creates the
196
// result in a stream which is parsed. This is sub-optimal
197
// but this was the only solution found to be able to
198
// generate content in the proper namespaces.
199
//
200
// SVGOMDocument outDoc =
201
// (SVGOMDocument)impl.createDocument(svgNS, "svg", null);
202
// outDoc.setURLObject(new URL(uri));
203
// transformer.transform
204
// (new DOMSource(inDoc),
205
// new DOMResult(outDoc.getDocumentElement()));
206
//
207
StringWriter JavaDoc sw = new StringWriter JavaDoc();
208         StreamResult JavaDoc result = new StreamResult JavaDoc(sw);
209         transformer.transform(new DOMSource JavaDoc(inDoc),
210                               result);
211         sw.flush();
212         sw.close();
213
214         String JavaDoc parser = XMLResourceDescriptor.getXMLParserClassName();
215         SAXSVGDocumentFactory f = new SAXSVGDocumentFactory(parser);
216         SVGDocument outDoc = null;
217
218         try {
219             outDoc = f.createSVGDocument
220                 (uri, new StringReader JavaDoc(sw.toString()));
221         } catch (Exception JavaDoc e) {
222             System.err.println("======================================");
223             System.err.println(sw.toString());
224             System.err.println("======================================");
225             
226             throw new IllegalArgumentException JavaDoc
227                 (Resources.getString(ERROR_RESULT_GENERATED_EXCEPTION));
228         }
229
230         // Patch the result tree to go under the root node
231
// checkAndPatch(outDoc);
232

233         svgViewerFrame.getJSVGCanvas().setSVGDocument(outDoc);
234         svgViewerFrame.setSVGDocument(outDoc,
235                                       uri,
236                                       outDoc.getTitle());
237     }
238
239     /**
240      * This method checks that the generated content is SVG.
241      *
242      * This method accounts for the fact that the root svg's first child
243      * is the result of the transform. It moves all its children under the root
244      * and sets the attributes
245      */

246     protected void checkAndPatch(Document JavaDoc doc) {
247         Element JavaDoc root = doc.getDocumentElement();
248         Node JavaDoc realRoot = root.getFirstChild();
249         String JavaDoc svgNS = SVGDOMImplementation.SVG_NAMESPACE_URI;
250
251         if (realRoot == null) {
252             throw new IllegalArgumentException JavaDoc
253                 (Resources.getString(ERROR_TRANSFORM_PRODUCED_NO_CONTENT));
254         }
255
256         if (realRoot.getNodeType() != Node.ELEMENT_NODE
257             ||
258             !SVGConstants.SVG_SVG_TAG.equals(realRoot.getLocalName())) {
259             throw new IllegalArgumentException JavaDoc
260                 (Resources.getString(ERROR_TRANSFORM_OUTPUT_NOT_SVG));
261         }
262
263         if (!svgNS.equals(realRoot.getNamespaceURI())) {
264             throw new IllegalArgumentException JavaDoc
265                 (Resources.getString(ERROR_TRANSFORM_OUTPUT_WRONG_NS));
266         }
267
268         Node JavaDoc child = realRoot.getFirstChild();
269         while ( child != null ) {
270             root.appendChild(child);
271             child = realRoot.getFirstChild();
272         }
273
274         NamedNodeMap JavaDoc attrs = realRoot.getAttributes();
275         int n = attrs.getLength();
276         for (int i=0; i<n; i++) {
277             root.setAttributeNode((Attr JavaDoc)attrs.item(i));
278         }
279
280         root.removeChild(realRoot);
281     }
282
283     /**
284      * Extracts the first XSL processing instruction from the input
285      * XML document.
286      */

287     protected String JavaDoc extractXSLProcessingInstruction(Document JavaDoc doc) {
288         Node JavaDoc child = doc.getFirstChild();
289         while (child != null) {
290             if (child.getNodeType() == Node.PROCESSING_INSTRUCTION_NODE) {
291                 ProcessingInstruction JavaDoc pi
292                     = (ProcessingInstruction JavaDoc)child;
293                 
294                 HashTable table = new HashTable();
295                 DOMUtilities.parseStyleSheetPIData(pi.getData(),
296                                                    table);
297
298                 Object JavaDoc type = table.get(PSEUDO_ATTRIBUTE_TYPE);
299                 if (XSL_PROCESSING_INSTRUCTION_TYPE.equals(type)) {
300                     Object JavaDoc href = table.get(PSEUDO_ATTRIBUTE_HREF);
301                     if (href != null) {
302                         return href.toString();
303                     } else {
304                         return null;
305                     }
306                 }
307             }
308             child = child.getNextSibling();
309         }
310
311         return null;
312     }
313
314     /**
315      * Implements the URIResolver interface so that relative urls used in
316      * transformations are resolved properly.
317      */

318     public class DocumentURIResolver implements URIResolver JavaDoc {
319         String JavaDoc documentURI;
320
321         public DocumentURIResolver(String JavaDoc documentURI) {
322             this.documentURI = documentURI;
323         }
324
325         public Source JavaDoc resolve(String JavaDoc href, String JavaDoc base) {
326             if (base == null || "".equals(base)) {
327                 base = documentURI;
328             }
329
330             ParsedURL purl = new ParsedURL(base, href);
331
332             return new StreamSource JavaDoc(purl.toString());
333         }
334     }
335 }
336
Popular Tags