1 /*******************************************************************************
2 * Copyright (c) 2014, 2015 École Polytechnique de Montréal and others
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
10 * Geneviève Bastien - Initial API and implementation
11 * Bernd Hufmann - Ensure backwards compatibility to Linux Tools
12 *******************************************************************************/
14 package org
.eclipse
.tracecompass
.tmf
.analysis
.xml
.ui
.module
;
17 import java
.io
.FileInputStream
;
18 import java
.io
.FileNotFoundException
;
19 import java
.io
.FileOutputStream
;
20 import java
.io
.IOException
;
22 import java
.nio
.channels
.FileChannel
;
23 import java
.util
.ArrayList
;
24 import java
.util
.List
;
26 import javax
.xml
.parsers
.DocumentBuilder
;
27 import javax
.xml
.parsers
.DocumentBuilderFactory
;
28 import javax
.xml
.parsers
.ParserConfigurationException
;
30 import org
.eclipse
.core
.runtime
.FileLocator
;
31 import org
.eclipse
.core
.runtime
.IConfigurationElement
;
32 import org
.eclipse
.core
.runtime
.IPath
;
33 import org
.eclipse
.core
.runtime
.ISafeRunnable
;
34 import org
.eclipse
.core
.runtime
.Platform
;
35 import org
.eclipse
.core
.runtime
.SafeRunner
;
36 import org
.eclipse
.jdt
.annotation
.NonNull
;
37 import org
.eclipse
.tracecompass
.internal
.tmf
.analysis
.xml
.ui
.Activator
;
38 import org
.eclipse
.tracecompass
.tmf
.analysis
.xml
.core
.module
.Messages
;
39 import org
.eclipse
.tracecompass
.tmf
.analysis
.xml
.core
.module
.XmlUtils
;
40 import org
.eclipse
.tracecompass
.tmf
.analysis
.xml
.core
.stateprovider
.TmfXmlStrings
;
41 import org
.eclipse
.tracecompass
.tmf
.analysis
.xml
.ui
.module
.TmfAnalysisModuleHelperXml
.XmlAnalysisModuleType
;
42 import org
.eclipse
.tracecompass
.tmf
.core
.analysis
.IAnalysisModuleHelper
;
43 import org
.eclipse
.tracecompass
.tmf
.core
.analysis
.IAnalysisModuleSource
;
44 import org
.eclipse
.tracecompass
.tmf
.core
.analysis
.TmfAnalysisManager
;
45 import org
.osgi
.framework
.Bundle
;
46 import org
.w3c
.dom
.Document
;
47 import org
.w3c
.dom
.Element
;
48 import org
.w3c
.dom
.NodeList
;
49 import org
.xml
.sax
.SAXException
;
52 * Analysis module source who creates helpers for the analysis modules described
53 * in the imported XML files
55 * @author Geneviève Bastien
57 public class XmlAnalysisModuleSource
implements IAnalysisModuleSource
{
59 /** Extension point ID */
60 private static final String TMF_XML_BUILTIN_ID
= "org.eclipse.linuxtools.tmf.analysis.xml.core.files"; //$NON-NLS-1$
61 private static final String XML_FILE_ELEMENT
= "xmlfile"; //$NON-NLS-1$
63 private static final String XML_FILE_ATTRIB
= "file"; //$NON-NLS-1$
66 * Legacy (Linux Tools) XML directory.
67 * TODO Remove once we feel the transition phase is over.
69 private static final IPath XML_DIRECTORY_LEGACY
=
70 Activator
.getDefault().getStateLocation().removeLastSegments(1)
71 .append("org.eclipse.linuxtools.tmf.analysis.xml.core") //$NON-NLS-1$
72 .append("xml_files"); //$NON-NLS-1$
74 private static List
<@NonNull IAnalysisModuleHelper
> fModules
= null;
77 * Constructor. It adds the new module listener to the analysis manager.
79 public XmlAnalysisModuleSource() {
80 TmfAnalysisManager
.addNewModuleListener(new TmfXmlAnalysisOutputSource());
84 public synchronized Iterable
<IAnalysisModuleHelper
> getAnalysisModules() {
85 List
<@NonNull IAnalysisModuleHelper
> modules
= fModules
;
86 if (modules
== null) {
87 modules
= new ArrayList
<>();
89 populateBuiltinModules();
90 populateAnalysisModules();
95 private static void processFile(File xmlFile
) {
96 if (!XmlUtils
.xmlValidate(xmlFile
).isOK()) {
101 /* Load the XML File */
102 DocumentBuilderFactory dbFactory
= DocumentBuilderFactory
.newInstance();
103 DocumentBuilder dBuilder
= dbFactory
.newDocumentBuilder();
104 Document doc
= dBuilder
.parse(xmlFile
);
105 doc
.getDocumentElement().normalize();
107 /* get State Providers modules */
108 NodeList stateproviderNodes
= doc
.getElementsByTagName(TmfXmlStrings
.STATE_PROVIDER
);
109 for (int i
= 0; i
< stateproviderNodes
.getLength(); i
++) {
110 Element node
= (Element
) stateproviderNodes
.item(i
);
112 IAnalysisModuleHelper helper
= new TmfAnalysisModuleHelperXml(xmlFile
, node
, XmlAnalysisModuleType
.STATE_SYSTEM
);
113 fModules
.add(helper
);
115 } catch (ParserConfigurationException
| SAXException
| IOException e
) {
116 Activator
.logError("Error opening XML file", e
); //$NON-NLS-1$
120 private static void populateBuiltinModules() {
121 /* Get the XML files advertised through the extension point */
122 IConfigurationElement
[] elements
= Platform
.getExtensionRegistry().getConfigurationElementsFor(TMF_XML_BUILTIN_ID
);
123 for (IConfigurationElement element
: elements
) {
124 if (element
.getName().equals(XML_FILE_ELEMENT
)) {
125 final String filename
= element
.getAttribute(XML_FILE_ATTRIB
);
126 final String name
= element
.getContributor().getName();
127 // Run this in a safe runner in case there is an exception
128 // (IOException, FileNotFoundException, NPE, etc).
129 // This makes sure other extensions are not prevented from
130 // working if one is faulty.
131 SafeRunner
.run(new ISafeRunnable() {
134 public void run() throws Exception
{
136 Bundle bundle
= Platform
.getBundle(name
);
137 if (bundle
!= null) {
138 URL xmlUrl
= bundle
.getResource(filename
);
139 if (xmlUrl
== null) {
140 throw new FileNotFoundException(filename
);
142 URL locatedURL
= FileLocator
.toFileURL(xmlUrl
);
143 processFile(new File(locatedURL
.getFile()));
149 public void handleException(Throwable exception
) {
150 // Handled sufficiently in SafeRunner
157 private static void populateAnalysisModules() {
158 IPath pathToFiles
= XmlUtils
.getXmlFilesPath();
159 File fFolder
= pathToFiles
.toFile();
160 if (!(fFolder
.isDirectory() && fFolder
.exists())) {
165 * Transfer files from Linux Tools directory.
167 File fOldFolder
= XML_DIRECTORY_LEGACY
.toFile();
168 if ((fOldFolder
.isDirectory() && fOldFolder
.exists())) {
169 for (File fromFile
: fOldFolder
.listFiles()) {
170 File toFile
= pathToFiles
.append(fromFile
.getName()).toFile();
171 if (!toFile
.exists() && !fromFile
.isDirectory()) {
172 try (FileInputStream fis
= new FileInputStream(fromFile
);
173 FileOutputStream fos
= new FileOutputStream(toFile
);
174 FileChannel source
= fis
.getChannel();
175 FileChannel destination
= fos
.getChannel();) {
176 destination
.transferFrom(source
, 0, source
.size());
177 } catch (IOException e
) {
178 String error
= Messages
.XmlUtils_ErrorCopyingFile
;
179 Activator
.logError(error
, e
);
185 for (File xmlFile
: fFolder
.listFiles()) {
186 processFile(xmlFile
);
191 * Notifies the main XML analysis module that the executable modules list
192 * may have changed and needs to be refreshed.
194 public static void notifyModuleChange() {
196 TmfAnalysisManager
.refreshModules();