1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 package org.openoffice.xmerge.util.registry;
25 
26 import java.io.*;
27 import java.util.*;
28 import java.util.jar.*;
29 import org.xml.sax.*;
30 import org.w3c.dom.*;
31 import javax.xml.parsers.*;
32 import java.net.URL;
33 import java.net.JarURLConnection;
34 
35 /**
36  *  The <code>ConverterInfoReader</code> pulls a META-INF/converter.xml
37  *  file out of a jar file and parses it, providing access to this
38  *  information in a <code>Vector</code> of <code>ConverterInfo</code>
39  *  objects.
40  *
41  *  @author  Brian Cameron
42  */
43 public class ConverterInfoReader {
44 
45     private final static String TAG_CONVERTER      = "converter";
46     private final static String ATTRIB_OFFICE_TYPE = "type";
47     private final static String ATTRIB_VERSION     = "version";
48     private final static String TAG_NAME           = "converter-display-name";
49     private final static String TAG_DESC           = "converter-description";
50     private final static String TAG_VENDOR         = "converter-vendor";
51     private final static String TAG_CLASS_IMPL     = "converter-class-impl";
52     private final static String TAG_TARGET         = "converter-target";
53     private final static String ATTRIB_DEVICE_TYPE = "type";
54     private final static String TAG_XSLT_DESERIAL     = "converter-xslt-deserialize";
55     private final static String TAG_XSLT_SERIAL     = "converter-xslt-serialize";
56     private String   jarfilename;
57     private Document document;
58     private Vector   converterInfoList;
59 
60 
61     /**
62      *  Constructor.  A jar file is passed in.  The jar file is
63      *  parsed and the <code>Vector</code> of <code>ConverterInfo</code>
64      *  objects is built.
65      *
66      *  @param  jar  The URL of the jar file to process.
67      *  @param  shouldvalidate Boolean to enable or disable xml validation.
68      *
69      *  @throws  IOException                   If the jar file cannot
70      *                                         be read or if the
71      *                                         META-INF/converter.xml
72      *                                         can not be read in the
73      *                                         jar file.
74      *  @throws  ParserConfigurationException  If the DocumentBuilder
75      *                                         can not be built.
76      *  @throws  org.xml.sax.SAXException      If the converter.xml
77      *                                         file can not be parsed.
78      *  @throws  RegistryException             If the ConverterFactory
79      *                                         implementation of a
80      *                                         plug-in cannot be loaded.
81      */
ConverterInfoReader(String jar,boolean shouldvalidate)82     public ConverterInfoReader(String jar,boolean shouldvalidate) throws IOException,
83         ParserConfigurationException, org.xml.sax.SAXException,
84         RegistryException  {
85 
86         InputStream            istream;
87         InputSource            isource;
88         DocumentBuilderFactory builderFactory;
89         DocumentBuilder        builder;
90         JarURLConnection       jarConnection;
91         JarEntry               jarentry;
92         JarFile                jarfile;
93         URL                    url;
94 
95         converterInfoList = new Vector();
96         jarfilename       = jar;
97 
98         // Get Jar via URL
99         //
100         url               = new URL("jar:" + jar + "!/META-INF/converter.xml");
101         jarConnection     = (JarURLConnection)url.openConnection();
102         jarentry          = jarConnection.getJarEntry();
103         jarfile           = jarConnection.getJarFile();
104 
105         // Build the InputSource
106         //
107         istream           = jarfile.getInputStream(jarentry);
108         isource           = new InputSource(istream);
109 
110         // Get the DOM builder and build the document.
111         //
112         builderFactory    = DocumentBuilderFactory.newInstance();
113 
114 	//DTD validation
115 	if (shouldvalidate){
116 	    System.out.println("Validating xml...");
117 		builderFactory.setValidating(true);
118 	    }
119 	//
120         builder           = builderFactory.newDocumentBuilder();
121 	document          = builder.parse(isource);
122 
123         // Parse the document.
124         //
125         parseDocument();
126     }
127 
128 
129     /**
130      *  Loops over the <i>converter</i> <code>Node</code> in the converter.xml
131      *  file and processes them.
132      *
133      *  @throws  RegistryException  If the plug-in associated with a
134      *                              specific <i>converter</i> <code>Node</code>
135      *                              cannot be loaded.
136      */
parseDocument()137     private void parseDocument() throws RegistryException {
138 
139         Node     converterNode;
140         NodeList converterNodes = document.getElementsByTagName(TAG_CONVERTER);
141 
142         for (int i=0; i < converterNodes.getLength(); i++) {
143             converterNode = converterNodes.item(i);
144             if (converterNode.getNodeType() == Node.ELEMENT_NODE) {
145                 parseConverterNode((Element)converterNode);
146             }
147         }
148     }
149 
150 
151     /**
152      *  Parses a <i>converter</i> node, pulling the information out of
153      *  the <code>Node</code> and placing it in a <code>ConverterInfo</code>
154      *  object, and adds that object to a <code>Vector</code> of
155      *  <code>ConverterInfo</code> objects.
156      *
157      *  @param  e  The <code>Element</code> corresponding to the
158      *             <i>converter</i> XML tag.
159      *
160      *
161      *  @throws  RegistryException  If the plug-in cannot be loaded.
162      */
parseConverterNode(Element e)163     private void parseConverterNode(Element e) throws RegistryException {
164 
165         Element detailElement;
166         Node    detailNode;
167         String  elementTagName;
168         String  officeMime  = null;
169         Vector  deviceMime  = new Vector();
170         String  name        = null;
171         String  desc        = null;
172         String  version     = null;
173         String  vendor      = null;
174         String  classImpl   = null;
175 	String  xsltSerial  = null;
176 	String  xsltDeserial= null;
177         String  temp;
178 
179         temp = e.getAttribute(ATTRIB_OFFICE_TYPE);
180         if (temp.length() != 0) {
181            officeMime = temp;
182         }
183 
184         temp = e.getAttribute(ATTRIB_VERSION);
185         if (temp.length() != 0) {
186            version = temp;
187         }
188 
189         NodeList detailNodes = e.getChildNodes();
190         for (int i=0; i < detailNodes.getLength(); i++) {
191 
192             detailNode = detailNodes.item(i);
193             if (detailNode.getNodeType() == Node.ELEMENT_NODE) {
194 
195                 detailElement  = (Element)detailNode;
196                 elementTagName = detailElement.getTagName();
197 
198                 if (TAG_NAME.equalsIgnoreCase(elementTagName)) {
199                     name = getTextValue(detailElement);
200                 } else if (TAG_DESC.equalsIgnoreCase(elementTagName)) {
201                     desc = getTextValue(detailElement);
202                 } else if (TAG_VENDOR.equalsIgnoreCase(elementTagName)) {
203                     vendor = getTextValue(detailElement);
204 		} else if (TAG_XSLT_SERIAL.equalsIgnoreCase(elementTagName)) {
205                     xsltSerial = getTextValue(detailElement);
206                 } else if (TAG_XSLT_DESERIAL.equalsIgnoreCase(elementTagName)) {
207                     xsltDeserial = getTextValue(detailElement);
208                 } else if (TAG_CLASS_IMPL.equalsIgnoreCase(elementTagName)) {
209                     classImpl = getTextValue(detailElement);
210                 } else if (TAG_TARGET.equalsIgnoreCase(elementTagName)) {
211 
212                     temp = detailElement.getAttribute(ATTRIB_DEVICE_TYPE);
213                     if (temp.length() != 0) {
214                         deviceMime.add(temp);
215                     }
216                 }
217             }
218         }
219 	ConverterInfo converterInfo;
220 	if ((xsltSerial==null) || (xsltDeserial==null)){
221 	    converterInfo = new ConverterInfo(jarfilename,
222 			    officeMime, deviceMime, name,
223 			    desc, version, vendor,classImpl);
224 	}
225 	else{
226 	    converterInfo = new ConverterInfo(jarfilename,
227 			    officeMime, deviceMime, name,
228 			    desc, version, vendor,classImpl,
229 			    xsltSerial,xsltDeserial);
230 	    }
231         /*ConverterInfo converterInfo = new ConverterInfo(jarfilename,
232             officeMime, deviceMime, name, desc, version, vendor,
233             classImpl);*/
234         converterInfoList.add(converterInfo);
235     }
236 
237 
238     /**
239      *  Helper function to get the text value of an
240      *  <code>Element</code>.
241      *
242      *  @param  e  The <code>Element</code> to process.
243      *
244      *  @return  The text value of the <code>Element</code>.
245      */
getTextValue(Element e)246     private String getTextValue(Element e) {
247 
248         NodeList tempNodes = e.getChildNodes();
249         String   text      = null;
250         Node     tempNode;
251 
252         for (int j=0; j < tempNodes.getLength(); j++) {
253             tempNode = tempNodes.item(j);
254             if (tempNode.getNodeType() == Node.TEXT_NODE) {
255                text = tempNode.getNodeValue().trim();
256                break;
257             }
258         }
259 
260         return text;
261     }
262 
263 
264     /**
265      *  Returns an <code>Enumeration</code> of <code>ConverterInfo</code>
266      *  objects.
267      *
268      *  @return  An <code>Enumeration</code> of <code>ConverterInfo</code>
269      *           objects.
270      */
getConverterInfoEnumeration()271     public Enumeration getConverterInfoEnumeration() {
272        return (converterInfoList.elements());
273     }
274 }
275 
276