1 /*
2  * This file is part of the LibreOffice project.
3  *
4  * This Source Code Form is subject to the terms of the Mozilla Public
5  * License, v. 2.0. If a copy of the MPL was not distributed with this
6  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7  *
8  * This file incorporates work covered by the following license notice:
9  *
10  *   Licensed to the Apache Software Foundation (ASF) under one or more
11  *   contributor license agreements. See the NOTICE file distributed
12  *   with this work for additional information regarding copyright
13  *   ownership. The ASF licenses this file to you under the Apache
14  *   License, Version 2.0 (the "License"); you may not use this file
15  *   except in compliance with the License. You may obtain a copy of
16  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
17  */
18 package com.sun.star.script.framework.container;
19 
20 import java.io.ByteArrayInputStream;
21 import java.io.File;
22 import java.io.FileInputStream;
23 import java.io.IOException;
24 import java.io.InputStream;
25 import java.io.OutputStream;
26 
27 import java.util.ArrayList;
28 import java.util.HashMap;
29 import java.util.Iterator;
30 import java.util.Map;
31 
32 import org.w3c.dom.CharacterData;
33 import org.w3c.dom.DOMException;
34 import org.w3c.dom.Document;
35 import org.w3c.dom.Element;
36 import org.w3c.dom.NodeList;
37 
38 public class ParcelDescriptor {
39 
40     // File name to be used for parcel descriptor files
41     public static final String
42     PARCEL_DESCRIPTOR_NAME = "parcel-descriptor.xml";
43 
44     // This is the default contents of a parcel descriptor to be used when
45     // creating empty descriptors
46     private static final byte[] EMPTY_DOCUMENT =
47         ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
48          "<parcel xmlns:parcel=\"scripting.dtd\" language=\"Java\">\n" +
49          "</parcel>").getBytes();
50 
51     private Document document = null;
52     private String language = null;
53     private final Map<String, String> languagedepprops = new HashMap<String, String>(3);
54 
ParcelDescriptor()55     public ParcelDescriptor() throws IOException {
56         ByteArrayInputStream bis = null;
57 
58         try {
59             bis = new ByteArrayInputStream(EMPTY_DOCUMENT);
60             this.document = XMLParserFactory.getParser().parse(bis);
61         } finally {
62             if (bis != null)
63                 bis.close();
64         }
65     }
66 
ParcelDescriptor(Document document)67     private ParcelDescriptor(Document document) {
68         this.document = document;
69         initLanguageProperties();
70     }
71 
ParcelDescriptor(InputStream is)72     public ParcelDescriptor(InputStream is) throws IOException {
73         this(XMLParserFactory.getParser().parse(is));
74     }
75 
ParcelDescriptor(File file)76     public ParcelDescriptor(File file) throws IOException {
77         this(file, "Java");
78     }
79 
ParcelDescriptor(File file, String language)80     private ParcelDescriptor(File file, String language) throws IOException {
81         if (file.exists()) {
82             FileInputStream fis = null;
83 
84             try {
85                 fis = new FileInputStream(file);
86                 this.document = XMLParserFactory.getParser().parse(fis);
87             } finally {
88                 if (fis != null)
89                     fis.close();
90             }
91         } else {
92             ByteArrayInputStream bis = null;
93 
94             try {
95                 bis = new ByteArrayInputStream(EMPTY_DOCUMENT);
96                 this.document = XMLParserFactory.getParser().parse(bis);
97             } finally {
98                 if (bis != null)
99                     bis.close();
100             }
101 
102             setLanguage(language);
103         }
104 
105         initLanguageProperties();
106     }
107 
write(OutputStream out)108     public void write(OutputStream out) throws IOException {
109         XMLParserFactory.getParser().write(document, out);
110     }
111 
getDocument()112     public Document getDocument() {
113         return document;
114     }
115 
getLanguage()116     public String getLanguage() {
117         if (language == null && document != null) {
118             Element e = document.getDocumentElement();
119             language = e.getAttribute("language");
120         }
121 
122         return language;
123     }
124 
setLanguage(String language)125     public void setLanguage(String language) {
126         this.language = language;
127 
128         if (document != null) {
129             try {
130                 Element e = document.getDocumentElement();
131                 e.setAttribute("language", language);
132             } catch (DOMException de) {
133             }
134         }
135     }
136 
getScriptEntries()137     public ScriptEntry[] getScriptEntries() {
138 
139         ArrayList<ScriptEntry> scripts = new ArrayList<ScriptEntry>();
140         NodeList scriptNodes;
141         int len;
142 
143         if (document == null ||
144             (scriptNodes = document.getElementsByTagName("script")) == null ||
145             (len = scriptNodes.getLength()) == 0)
146             return new ScriptEntry[0];
147 
148         for (int i = 0; i < len; i++) {
149             String language, languagename, description = "";
150             Map<String, String> langProps = new HashMap<String, String>();
151             NodeList nl;
152 
153             Element scriptElement = (Element)scriptNodes.item(i);
154             language = scriptElement.getAttribute("language");
155 
156             // get the text of the description element
157             nl = scriptElement.getElementsByTagName("locale");
158 
159             if (nl != null) {
160                 nl = nl.item(0).getChildNodes();
161 
162                 if (nl != null) {
163                     for (int j = 0 ; j < nl.getLength(); j++) {
164                         if (nl.item(j).getNodeName().equals("description")) {
165                             CharacterData cd =
166                                 (CharacterData)nl.item(j).getFirstChild();
167                             description = cd.getData().trim();
168                         }
169                     }
170                 }
171             }
172 
173             nl = scriptElement.getElementsByTagName("functionname");
174 
175             if (nl == null) {
176                 languagename = "";
177             } else {
178                 Element tmp = (Element)nl.item(0);
179                 languagename = tmp.getAttribute("value");
180             }
181 
182             nl = scriptElement.getElementsByTagName("languagedepprops");
183 
184             if (nl != null && nl.getLength() > 0) {
185 
186                 NodeList props = ((Element)nl.item(0)).getElementsByTagName("prop");
187 
188                 if (props != null) {
189                     for (int j = 0; j < props.getLength(); j++) {
190                         Element tmp = (Element)props.item(j);
191                         String key = tmp.getAttribute("name");
192                         String val = tmp.getAttribute("value");
193                         langProps.put(key, val);
194                     }
195                 }
196             }
197 
198             ScriptEntry entry =
199                 new ScriptEntry(language, languagename, langProps, description);
200             scripts.add(entry);
201         }
202 
203         return scripts.toArray(new ScriptEntry[scripts.size()]);
204     }
205 
setScriptEntries(ScriptEntry[] scripts)206     public void setScriptEntries(ScriptEntry[] scripts) {
207         clearEntries();
208 
209         for (ScriptEntry script : scripts) {
210             addScriptEntry(script);
211         }
212     }
213 
setScriptEntries(Iterator<ScriptEntry> scripts)214     public void setScriptEntries(Iterator<ScriptEntry> scripts) {
215         clearEntries();
216 
217         while (scripts.hasNext()) {
218             addScriptEntry(scripts.next());
219         }
220     }
221 
getLanguageProperty(String name)222     private String getLanguageProperty(String name) {
223         return languagedepprops.get(name);
224     }
225 
226 
227 
initLanguageProperties()228     private void initLanguageProperties() {
229         NodeList nl = document.getElementsByTagName("languagedepprops");
230         int len;
231 
232         if (nl != null && (len = nl.getLength()) != 0) {
233 
234             for (int i = 0; i < len; i++) {
235                 Element e = (Element)nl.item(i);
236                 NodeList nl2 = e.getElementsByTagName("prop");
237                 int len2;
238 
239                 if (nl2 != null && (len2 = nl2.getLength()) != 0) {
240                     for (int j = 0; j < len2; j++) {
241                         Element e2 = (Element)nl2.item(j);
242 
243                         String name = e2.getAttribute("name");
244                         String value = e2.getAttribute("value");
245 
246                         if (getLanguageProperty(name) == null) {
247                             languagedepprops.put(name, value);
248                         }
249                     }
250                 }
251             }
252         }
253     }
254 
clearEntries()255     private void clearEntries() {
256         NodeList scriptNodes;
257         Element main = document.getDocumentElement();
258         int len;
259 
260         if ((scriptNodes = document.getElementsByTagName("script")) != null &&
261             (len = scriptNodes.getLength()) != 0) {
262             for (int i = len - 1; i >= 0; i--) {
263                 try {
264                     main.removeChild(scriptNodes.item(i));
265                 } catch (DOMException de) {
266                     // ignore
267                 }
268             }
269         }
270     }
271 
removeScriptEntry(ScriptEntry script)272     public void removeScriptEntry(ScriptEntry script) {
273         NodeList scriptNodes;
274         Element main = document.getDocumentElement();
275         int len;
276 
277         if ((scriptNodes = document.getElementsByTagName("script")) != null &&
278             (len = scriptNodes.getLength()) != 0) {
279             for (int i = len - 1; i >= 0; i--) {
280                 try {
281                     Element scriptElement = (Element)scriptNodes.item(i);
282                     String languagename = "";
283 
284                     NodeList nl =
285                         scriptElement.getElementsByTagName("functionname");
286 
287                     if (nl == null) {
288                         continue;
289                     } else {
290                         Element tmp = (Element)nl.item(0);
291                         languagename = tmp.getAttribute("value");
292                     }
293 
294                     if (languagename.equals(script.getLanguageName())) {
295                         main.removeChild(scriptElement);
296                     }
297                 } catch (DOMException de) {
298                     // ignore
299                 }
300             }
301         }
302     }
303 
addScriptEntry(ScriptEntry script)304     public void addScriptEntry(ScriptEntry script) {
305         Element main = document.getDocumentElement();
306         Element root, item, tempitem;
307 
308         root = document.createElement("script");
309         root.setAttribute("language", script.getLanguage());
310 
311         item = document.createElement("locale");
312         item.setAttribute("lang", "en");
313         tempitem = document.createElement("displayname");
314         tempitem.setAttribute("value", script.getLogicalName());
315         item.appendChild(tempitem);
316 
317         tempitem = document.createElement("description");
318         String description = script.getDescription();
319 
320         if (description == null || description.length() == 0) {
321             description = script.getLogicalName();
322         }
323 
324         tempitem.appendChild(document.createTextNode(description));
325         item.appendChild(tempitem);
326 
327         root.appendChild(item);
328 
329         item = document.createElement("logicalname");
330         item.setAttribute("value", script.getLogicalName());
331         root.appendChild(item);
332 
333         item = document.createElement("functionname");
334         item.setAttribute("value", script.getLanguageName());
335         root.appendChild(item);
336 
337         if (languagedepprops != null && !languagedepprops.isEmpty()) {
338             String key;
339             item = document.createElement("languagedepprops");
340 
341             for (Map.Entry<String, String> entry : languagedepprops.entrySet()) {
342                 tempitem = document.createElement("prop");
343                 tempitem.setAttribute("name", entry.getKey());
344                 tempitem.setAttribute("value", entry.getValue());
345                 item.appendChild(tempitem);
346             }
347 
348             root.appendChild(item);
349         }
350 
351         //add to the Top Element
352         main.appendChild(root);
353     }
354 }
355