releng: Transition to jdt.annotation 2.0
[deliverable/tracecompass.git] / tmf / org.eclipse.tracecompass.tmf.analysis.xml.core / src / org / eclipse / tracecompass / tmf / analysis / xml / core / module / XmlUtils.java
1 /*******************************************************************************
2 * Copyright (c) 2014 École Polytechnique de Montréal
3 *
4 * All rights reserved. This program and the accompanying materials are
5 * made available under the terms of the Eclipse Public License v1.0 which
6 * accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
8 *
9 * Contributors:
10 * Geneviève Bastien - Initial API and implementation
11 *******************************************************************************/
12
13 package org.eclipse.tracecompass.tmf.analysis.xml.core.module;
14
15 import java.io.File;
16 import java.io.FileInputStream;
17 import java.io.FileOutputStream;
18 import java.io.IOException;
19 import java.net.URL;
20 import java.nio.channels.FileChannel;
21 import java.util.ArrayList;
22 import java.util.List;
23
24 import javax.xml.XMLConstants;
25 import javax.xml.parsers.DocumentBuilder;
26 import javax.xml.parsers.DocumentBuilderFactory;
27 import javax.xml.parsers.ParserConfigurationException;
28 import javax.xml.transform.Source;
29 import javax.xml.transform.stream.StreamSource;
30 import javax.xml.validation.Schema;
31 import javax.xml.validation.SchemaFactory;
32 import javax.xml.validation.Validator;
33
34 import org.eclipse.core.runtime.IPath;
35 import org.eclipse.core.runtime.IStatus;
36 import org.eclipse.core.runtime.Path;
37 import org.eclipse.core.runtime.Status;
38 import org.eclipse.jdt.annotation.NonNull;
39 import org.eclipse.jdt.annotation.Nullable;
40 import org.eclipse.osgi.util.NLS;
41 import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.Activator;
42 import org.eclipse.tracecompass.tmf.analysis.xml.core.stateprovider.TmfXmlStrings;
43 import org.w3c.dom.Document;
44 import org.w3c.dom.Element;
45 import org.w3c.dom.Node;
46 import org.w3c.dom.NodeList;
47 import org.xml.sax.SAXException;
48 import org.xml.sax.SAXParseException;
49
50 /**
51 * Class containing some utilities for the XML plug-in packages: for example, it
52 * manages the XML files and validates them
53 *
54 * @author Geneviève Bastien
55 */
56 public class XmlUtils {
57
58 /** Sub-directory of the plug-in where XML files are stored */
59 private static final String XML_DIRECTORY = "xml_files"; //$NON-NLS-1$
60
61 /** Name of the XSD schema file */
62 private static final String XSD = "xmlDefinition.xsd"; //$NON-NLS-1$
63
64 /** Make this class non-instantiable */
65 private XmlUtils() {
66
67 }
68
69 /**
70 * Get the path where the XML files are stored. Create it if it does not
71 * exist
72 *
73 * @return path to XML files
74 */
75 public static IPath getXmlFilesPath() {
76 IPath path = Activator.getDefault().getStateLocation();
77 path = path.addTrailingSeparator().append(XML_DIRECTORY);
78
79 /* Check if directory exists, otherwise create it */
80 File dir = path.toFile();
81 if (!dir.exists() || !dir.isDirectory()) {
82 dir.mkdirs();
83 }
84
85 return path;
86 }
87
88 /**
89 * Validate the XML file input with the XSD schema
90 *
91 * @param xmlFile
92 * XML file to validate
93 * @return True if the XML validates
94 */
95 public static IStatus xmlValidate(File xmlFile) {
96 URL url = XmlUtils.class.getResource(XSD);
97 SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
98 Source xmlSource = new StreamSource(xmlFile);
99 try {
100 Schema schema = schemaFactory.newSchema(url);
101 Validator validator = schema.newValidator();
102 validator.validate(xmlSource);
103 } catch (SAXParseException e) {
104 String error = NLS.bind(Messages.XmlUtils_XmlParseError, e.getLineNumber(), e.getLocalizedMessage());
105 Activator.logError(error);
106 return new Status(IStatus.ERROR, Activator.PLUGIN_ID, error, e);
107 } catch (SAXException e) {
108 String error = NLS.bind(Messages.XmlUtils_XmlValidationError, e.getLocalizedMessage());
109 Activator.logError(error);
110 return new Status(IStatus.ERROR, Activator.PLUGIN_ID, error, e);
111 } catch (IOException e) {
112 String error = Messages.XmlUtils_XmlValidateError;
113 Activator.logError("IO exception occurred", e); //$NON-NLS-1$
114 return new Status(IStatus.ERROR, Activator.PLUGIN_ID, error, e);
115 }
116 return Status.OK_STATUS;
117 }
118
119 /**
120 * Adds an XML file to the plugin's path. The XML file should have been
121 * validated using the {@link XmlUtils#xmlValidate(File)} method before
122 * calling this method.
123 *
124 * @param fromFile
125 * The XML file to add
126 * @return Whether the file was successfully added
127 */
128 public static IStatus addXmlFile(File fromFile) {
129
130 /* Copy file to path */
131 File toFile = getXmlFilesPath().addTrailingSeparator().append(fromFile.getName()).toFile();
132
133 try {
134 if (!toFile.exists()) {
135 toFile.createNewFile();
136 }
137 } catch (IOException e) {
138 String error = Messages.XmlUtils_ErrorCopyingFile;
139 Activator.logError(error, e);
140 return new Status(IStatus.ERROR, Activator.PLUGIN_ID, error, e);
141 }
142
143 try (FileInputStream fis = new FileInputStream(fromFile);
144 FileOutputStream fos = new FileOutputStream(toFile);
145 FileChannel source = fis.getChannel();
146 FileChannel destination = fos.getChannel();) {
147 destination.transferFrom(source, 0, source.size());
148 } catch (IOException e) {
149 String error = Messages.XmlUtils_ErrorCopyingFile;
150 Activator.logError(error, e);
151 return new Status(IStatus.ERROR, Activator.PLUGIN_ID, error, e);
152 }
153 return Status.OK_STATUS;
154 }
155
156 /**
157 * Get only the XML element children of an XML element.
158 *
159 * @param parent
160 * The parent element to get children from
161 * @return The list of children Element of the parent
162 */
163 public static List<@Nullable Element> getChildElements(Element parent) {
164 NodeList childNodes = parent.getChildNodes();
165 List<@Nullable Element> childElements = new ArrayList<>();
166 for (int index = 0; index < childNodes.getLength(); index++) {
167 if (childNodes.item(index).getNodeType() == Node.ELEMENT_NODE) {
168 childElements.add((Element) childNodes.item(index));
169 }
170 }
171 return childElements;
172 }
173
174 /**
175 * Get the XML children element of an XML element, but only those of a
176 * certain type
177 *
178 * @param parent
179 * The parent element to get the children from
180 * @param elementTag
181 * The tag of the elements to return
182 * @return The list of children {@link Element} of the parent
183 */
184 public static List<@NonNull Element> getChildElements(Element parent, String elementTag) {
185 /* get the state providers and find the corresponding one */
186 NodeList nodes = parent.getElementsByTagName(elementTag);
187 List<@NonNull Element> childElements = new ArrayList<>();
188
189 for (int i = 0; i < nodes.getLength(); i++) {
190 Element node = (Element) nodes.item(i);
191 if (node.getParentNode().equals(parent)) {
192 childElements.add(node);
193 }
194 }
195 return childElements;
196 }
197
198 /**
199 * Return the node element corresponding to the requested type in the file.
200 *
201 * TODO: Nothing prevents from having duplicate type -> id in a same file.
202 * That should not be allowed. If you want an element with the same ID as
203 * another one, it should be in a different file and we should check it at
204 * validation time.
205 *
206 * @param filePath
207 * The absolute path to the XML file
208 * @param elementType
209 * The type of top level element to search for
210 * @param elementId
211 * The ID of the desired element
212 * @return The XML element or <code>null</code> if not found
213 */
214 public static Element getElementInFile(String filePath, @NonNull String elementType, @NonNull String elementId) {
215
216 if (filePath == null) {
217 return null;
218 }
219
220 IPath path = new Path(filePath);
221 File file = path.toFile();
222 if (file == null || !file.exists() || !file.isFile() || !xmlValidate(file).isOK()) {
223 return null;
224 }
225
226 try {
227 /* Load the XML File */
228 DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
229 DocumentBuilder dBuilder;
230
231 dBuilder = dbFactory.newDocumentBuilder();
232 Document doc = dBuilder.parse(file);
233 doc.getDocumentElement().normalize();
234
235 /* get the state providers and find the corresponding one */
236 NodeList nodes = doc.getElementsByTagName(elementType);
237 Element foundNode = null;
238
239 for (int i = 0; i < nodes.getLength(); i++) {
240 Element node = (Element) nodes.item(i);
241 String id = node.getAttribute(TmfXmlStrings.ID);
242 if (id.equals(elementId)) {
243 foundNode = node;
244 }
245 }
246 return foundNode;
247 } catch (ParserConfigurationException | SAXException | IOException e) {
248 return null;
249 }
250
251 }
252
253 }
This page took 0.038123 seconds and 5 git commands to generate.