Commit | Line | Data |
---|---|---|
500d5c41 GM |
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 | * Guilliano Molaire - Initial API and implementation | |
11 | *********************************************************************/ | |
8e8c0226 | 12 | package org.eclipse.linuxtools.lttng2.control.core.session; |
500d5c41 GM |
13 | |
14 | import java.io.File; | |
15 | import java.io.IOException; | |
16 | import java.net.URL; | |
17 | import java.util.Set; | |
18 | ||
19 | import javax.xml.XMLConstants; | |
20 | import javax.xml.parsers.DocumentBuilder; | |
21 | import javax.xml.parsers.DocumentBuilderFactory; | |
22 | import javax.xml.parsers.ParserConfigurationException; | |
23 | import javax.xml.transform.OutputKeys; | |
24 | import javax.xml.transform.Source; | |
25 | import javax.xml.transform.Transformer; | |
26 | import javax.xml.transform.TransformerException; | |
27 | import javax.xml.transform.TransformerFactory; | |
28 | import javax.xml.transform.dom.DOMSource; | |
29 | import javax.xml.transform.stream.StreamResult; | |
30 | import javax.xml.transform.stream.StreamSource; | |
31 | import javax.xml.validation.Schema; | |
32 | import javax.xml.validation.SchemaFactory; | |
33 | import javax.xml.validation.Validator; | |
34 | ||
35 | import org.eclipse.core.runtime.IPath; | |
36 | import org.eclipse.core.runtime.IStatus; | |
37 | import org.eclipse.core.runtime.Status; | |
8e8c0226 AM |
38 | import org.eclipse.linuxtools.internal.lttng2.control.core.Activator; |
39 | import org.eclipse.linuxtools.internal.lttng2.control.core.model.IChannelInfo; | |
40 | import org.eclipse.linuxtools.internal.lttng2.control.core.model.IDomainInfo; | |
41 | import org.eclipse.linuxtools.internal.lttng2.control.core.model.IEventInfo; | |
42 | import org.eclipse.linuxtools.internal.lttng2.control.core.model.ISessionInfo; | |
43 | import org.eclipse.linuxtools.internal.lttng2.control.core.model.TraceEnablement; | |
44 | import org.eclipse.linuxtools.internal.lttng2.control.core.model.TraceEventType; | |
45 | import org.eclipse.linuxtools.internal.lttng2.control.core.model.TraceLogLevel; | |
46 | import org.eclipse.linuxtools.internal.lttng2.control.core.model.TraceSessionState; | |
500d5c41 GM |
47 | import org.eclipse.osgi.util.NLS; |
48 | import org.w3c.dom.Document; | |
49 | import org.w3c.dom.Element; | |
50 | import org.xml.sax.SAXException; | |
51 | import org.xml.sax.SAXParseException; | |
52 | ||
53 | /** | |
54 | * Class for generating a session configuration file. A session configuration is | |
55 | * used to configure a trace session. It is a XML formatted file that contains | |
56 | * values defining the behavior of that specific trace session. | |
57 | * <p> | |
58 | * Kernel session configuration example: | |
59 | * | |
60 | * <pre> | |
61 | * {@code | |
62 | * <sessions> | |
63 | * <session> | |
64 | * <name>test_kernel</name> | |
65 | * <domains> | |
66 | * <domain> | |
67 | * <type>KERNEL</type> | |
68 | * <buffer_type>GLOBAL</buffer_type> | |
69 | * <channels> | |
70 | * <channel> | |
71 | * <name>channel0</name> | |
72 | * <enabled>false</enabled> | |
73 | * <overwrite_mode>DISCARD</overwrite_mode> | |
74 | * <subbuffer_size>262144</subbuffer_size> | |
75 | * <subbuffer_count>4</subbuffer_count> | |
76 | * <switch_timer_interval>0</switch_timer_interval> | |
77 | * <read_timer_interval>200000</read_timer_interval> | |
78 | * <output_type>SPLICE</output_type> | |
79 | * <tracefile_size>0</tracefile_size> | |
80 | * <tracefile_count>0</tracefile_count> | |
81 | * <live_timer_interval>0</live_timer_interval> | |
82 | * <events> | |
83 | * <event> | |
84 | * <enabled>true</enabled> | |
85 | * <type>SYSCALL</type> | |
86 | * </event> | |
87 | * <event> | |
88 | * <name>snd_soc_cache_sync</name> | |
89 | * <enabled>true</enabled> | |
90 | * <type>TRACEPOINT</type> | |
91 | * </event> | |
92 | * </events> | |
93 | * </channel> | |
94 | * </channels> | |
95 | * </domain> | |
96 | * </domains> | |
97 | * <started>false</started> | |
98 | * <output> | |
99 | * <consumer_output> | |
100 | * <enabled>true</enabled> | |
101 | * <destination> | |
102 | * <path>/home/user/lttng-traces/test_kernel</path> | |
103 | * </destination> | |
104 | * </consumer_output> | |
105 | * </output> | |
106 | * </session> | |
107 | * </sessions> | |
108 | * } | |
109 | * </pre> | |
110 | * | |
111 | * </p> | |
112 | * | |
113 | * @author Guilliano Molaire | |
114 | * @since 3.0 | |
115 | */ | |
116 | public final class SessionConfigGenerator { | |
117 | ||
118 | /** The name of the session schema */ | |
119 | private static final String SESSION_XSD_FILENAME = "session.xsd"; //$NON-NLS-1$ | |
120 | ||
121 | /** The indent size used for the session configuration XML file */ | |
122 | private static final String INDENT_AMOUNT_PROPERTY_NAME = "{http://xml.apache.org/xslt}indent-amount"; //$NON-NLS-1$ | |
123 | private static final String INDENT_AMOUNT_PROPERTY_VALUE = "4"; //$NON-NLS-1$ | |
124 | ||
125 | /** | |
126 | * Private constructor. The class should not be instantiated. | |
127 | */ | |
128 | private SessionConfigGenerator() { | |
129 | } | |
130 | ||
131 | // --------------------------------------------------------- | |
132 | // Methods to generate session configuration files | |
133 | // --------------------------------------------------------- | |
134 | ||
135 | /** | |
136 | * Generates a session configuration file from a set of session information. | |
137 | * | |
138 | * @param sessions | |
139 | * The session informations | |
140 | * @param sessionFileDestination | |
141 | * The path of the locally saved session configuration file | |
142 | * @return The status of the session configuration generation | |
143 | */ | |
144 | public static IStatus generateSessionConfig(Set<ISessionInfo> sessions, IPath sessionFileDestination) { | |
145 | /* Parameters validation */ | |
146 | if (sessions == null || sessions.isEmpty()) { | |
147 | return new Status(IStatus.ERROR, Activator.PLUGIN_ID, Messages.SessionConfigXML_InvalidSessionInfoList); | |
148 | } else if (sessionFileDestination == null) { | |
149 | return new Status(IStatus.ERROR, Activator.PLUGIN_ID, Messages.SessionConfigXML_InvalidTraceSessionPath); | |
150 | } | |
151 | ||
152 | /* Generate the session configuration file */ | |
153 | try { | |
154 | Document sessionConfigDocument = generateSessionConfig(sessions); | |
155 | ||
156 | if (sessionConfigDocument != null) { | |
157 | saveSessionConfig(sessionConfigDocument, sessionFileDestination.toString()); | |
158 | } else { | |
159 | return new Status(IStatus.ERROR, Activator.PLUGIN_ID, Messages.SessionConfigXML_SessionConfigGenerationError); | |
160 | } | |
161 | } catch (TransformerException | IllegalArgumentException | ParserConfigurationException e) { | |
162 | Activator.getDefault().logError("Error generating the session configuration file: " + sessionFileDestination.toString(), e); //$NON-NLS-1$ | |
163 | return new Status(IStatus.ERROR, Activator.PLUGIN_ID, e.getMessage()); | |
164 | } | |
165 | ||
166 | return Status.OK_STATUS; | |
167 | } | |
168 | ||
169 | /** | |
170 | * Generates a session configuration from a set of session informations. | |
171 | * | |
172 | * @param sessions | |
173 | * The session informations | |
174 | * @return The document with all session configuration nodes | |
175 | * @throws IllegalArgumentException | |
176 | * On an illegal argument inside sessions | |
177 | * @throws ParserConfigurationException | |
178 | * On an parser configuration error | |
179 | */ | |
180 | private static Document generateSessionConfig(Iterable<ISessionInfo> sessions) throws IllegalArgumentException, ParserConfigurationException { | |
181 | DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); | |
182 | DocumentBuilder docBuilder = docFactory.newDocumentBuilder(); | |
183 | ||
184 | Document document = docBuilder.newDocument(); | |
185 | ||
186 | Element rootElement = document.createElement(SessionConfigStrings.CONFIG_ELEMENT_SESSIONS); | |
187 | document.appendChild(rootElement); | |
188 | ||
189 | for (ISessionInfo session : sessions) { | |
190 | /* All elements under "sessions" elements */ | |
191 | Element sessionElement = document.createElement(SessionConfigStrings.CONFIG_ELEMENT_SESSION); | |
192 | ||
193 | /* Contents of session element */ | |
194 | String enabled = session.getSessionState().equals(TraceSessionState.ACTIVE) ? SessionConfigStrings.CONFIG_STRING_TRUE : SessionConfigStrings.CONFIG_STRING_FALSE; | |
195 | ||
196 | addElementContent(document, sessionElement, SessionConfigStrings.CONFIG_ELEMENT_NAME, session.getName()); | |
197 | addElementContent(document, sessionElement, SessionConfigStrings.CONFIG_ELEMENT_STARTED, enabled); | |
198 | ||
199 | if (session.isSnapshotSession()) { | |
200 | /* If it's a snapshot, we must add an attribute telling it is */ | |
201 | Element attributesElement = document.createElement(SessionConfigStrings.CONFIG_ELEMENT_ATTRIBUTES); | |
202 | addElementContent(document, attributesElement, SessionConfigStrings.CONFIG_ELEMENT_SNAPSHOT_MODE, SessionConfigStrings.CONFIG_STRING_TRUE); | |
203 | sessionElement.appendChild(attributesElement); | |
204 | } | |
205 | ||
206 | sessionElement.appendChild(getDomainsElement(document, session)); | |
207 | sessionElement.appendChild(getOutputElement(document, session)); | |
208 | rootElement.appendChild(sessionElement); | |
209 | } | |
210 | ||
211 | return document; | |
212 | } | |
213 | ||
214 | // --------------------------------------------------------- | |
215 | // Getters for each element of the configuration file | |
216 | // --------------------------------------------------------- | |
217 | ||
218 | /** | |
219 | * Gets the 'domains' element after creating it. | |
220 | * | |
221 | * @param document | |
222 | * The document in which the nodes are being added | |
223 | * @param session | |
224 | * The session informations | |
225 | * @return The domains element as an XML element | |
226 | */ | |
227 | private static Element getDomainsElement(Document document, ISessionInfo session) { | |
228 | Element domainsElement = document.createElement(SessionConfigStrings.CONFIG_ELEMENT_DOMAINS); | |
229 | ||
230 | for (IDomainInfo domain : session.getDomains()) { | |
231 | Element domainElement = document.createElement(SessionConfigStrings.CONFIG_ELEMENT_DOMAIN); | |
232 | ||
233 | /* | |
234 | * Add everything specific to a domain | |
235 | * | |
236 | * TODO: We suppose here that domain is either kernel or UST. It | |
237 | * will have to change if other domains are supported | |
238 | */ | |
239 | String domainType = domain.isKernel() ? SessionConfigStrings.CONFIG_DOMAIN_TYPE_KERNEL : SessionConfigStrings.CONFIG_DOMAIN_TYPE_UST; | |
240 | addElementContent(document, domainElement, SessionConfigStrings.CONFIG_ELEMENT_TYPE, domainType); | |
241 | ||
242 | String bufferType = null; | |
243 | switch (domain.getBufferType()) { | |
244 | case BUFFER_PER_UID: | |
245 | bufferType = SessionConfigStrings.CONFIG_BUFFER_TYPE_PER_UID; | |
246 | break; | |
247 | case BUFFER_PER_PID: | |
248 | bufferType = SessionConfigStrings.CONFIG_BUFFER_TYPE_PER_PID; | |
249 | break; | |
250 | case BUFFER_SHARED: | |
251 | bufferType = SessionConfigStrings.CONFIG_BUFFER_TYPE_GLOBAL; | |
252 | break; | |
253 | case BUFFER_TYPE_UNKNOWN: | |
254 | default: | |
255 | throw new IllegalArgumentException(Messages.SessionConfigXML_UnknownDomainBufferType); | |
256 | } | |
257 | addElementContent(document, domainElement, SessionConfigStrings.CONFIG_ELEMENT_DOMAIN_BUFFER_TYPE, bufferType); | |
258 | ||
259 | /* Add the channels */ | |
260 | domainElement.appendChild(getChannelsElement(document, domain.isKernel(), domain.getChannels())); | |
261 | domainsElement.appendChild(domainElement); | |
262 | } | |
263 | ||
264 | return domainsElement; | |
265 | } | |
266 | ||
267 | /** | |
268 | * Gets the 'output' element after creating it. If the session is a | |
269 | * snapshot, it will be composed of a snapshot outputs element. Otherwise, | |
270 | * it will contain the consumer output element. | |
271 | * | |
272 | * @param document | |
273 | * The document in which the nodes are being added | |
274 | * @param session | |
275 | * The session informations | |
276 | * @return The output element as an XML node | |
277 | */ | |
278 | private static Element getOutputElement(Document document, ISessionInfo session) { | |
279 | Element outputElement = document.createElement(SessionConfigStrings.CONFIG_ELEMENT_OUTPUT); | |
280 | ||
281 | if (session.isSnapshotSession()) { | |
282 | outputElement.appendChild(getSnapshotOuputsElement(document, session)); | |
283 | } else if (session.isStreamedTrace()) { | |
284 | outputElement.appendChild(getNetOutputElement(document, session)); | |
285 | } else { | |
286 | outputElement.appendChild(getConsumerOutputElement(document, session)); | |
287 | } | |
288 | ||
289 | return outputElement; | |
290 | } | |
291 | ||
292 | /** | |
293 | * Gets the 'channels' element after creating it. | |
294 | * | |
295 | * @param document | |
296 | * The document in which the nodes are being added | |
297 | * @param isKernel | |
298 | * Is it a kernel domain type | |
299 | * @param channels | |
300 | * The channels to be added as elements | |
301 | * @return The channels element as an XML element | |
302 | */ | |
303 | private static Element getChannelsElement(Document document, boolean isKernel, IChannelInfo[] channels) { | |
304 | Element channelsElement = document.createElement(SessionConfigStrings.CONFIG_ELEMENT_CHANNELS); | |
305 | ||
306 | for (IChannelInfo channel : channels) { | |
307 | Element channelElement = document.createElement(SessionConfigStrings.CONFIG_ELEMENT_CHANNEL); | |
308 | ||
309 | /* Add everything related to a channel */ | |
310 | addElementContent(document, channelElement, SessionConfigStrings.CONFIG_ELEMENT_NAME, channel.getName()); | |
311 | ||
312 | String overwriteMode = channel.isOverwriteMode() ? SessionConfigStrings.CONFIG_OVERWRITE_MODE_OVERWRITE : SessionConfigStrings.CONFIG_OVERWRITE_MODE_DISCARD; | |
313 | String enabled = channel.getState().equals(TraceEnablement.ENABLED) ? SessionConfigStrings.CONFIG_STRING_TRUE : SessionConfigStrings.CONFIG_STRING_FALSE; | |
314 | ||
315 | addElementContent(document, channelElement, SessionConfigStrings.CONFIG_ELEMENT_ENABLED, enabled); | |
316 | addElementContent(document, channelElement, SessionConfigStrings.CONFIG_ELEMENT_OVERWRITE_MODE, overwriteMode); | |
317 | addElementContent(document, channelElement, SessionConfigStrings.CONFIG_ELEMENT_SUBBUFFER_SIZE, channel.getSubBufferSize()); | |
318 | addElementContent(document, channelElement, SessionConfigStrings.CONFIG_ELEMENT_SUBBUFFER_COUNT, channel.getNumberOfSubBuffers()); | |
319 | addElementContent(document, channelElement, SessionConfigStrings.CONFIG_ELEMENT_SWITCH_TIMER_INTERVAL, channel.getSwitchTimer()); | |
320 | addElementContent(document, channelElement, SessionConfigStrings.CONFIG_ELEMENT_READ_TIMER_INTERVAL, channel.getReadTimer()); | |
321 | ||
322 | String outputType = channel.getOutputType().startsWith(SessionConfigStrings.CONFIG_OUTPUT_TYPE_MMAP) ? | |
323 | outputType = SessionConfigStrings.CONFIG_OUTPUT_TYPE_MMAP : SessionConfigStrings.CONFIG_OUTPUT_TYPE_SPLICE; | |
324 | addElementContent(document, channelElement, SessionConfigStrings.CONFIG_ELEMENT_OUTPUT_TYPE, outputType); | |
325 | addElementContent(document, channelElement, SessionConfigStrings.CONFIG_ELEMENT_TRACEFILE_SIZE, channel.getMaxSizeTraceFiles()); | |
326 | addElementContent(document, channelElement, SessionConfigStrings.CONFIG_ELEMENT_TRACEFILE_COUNT, channel.getMaxNumberTraceFiles()); | |
327 | ||
328 | /* | |
329 | * TODO: Replace the 0 value by the channel live timer property from | |
330 | * SessionInfo once live session tracing is supported | |
331 | */ | |
332 | addElementContent(document, channelElement, SessionConfigStrings.CONFIG_ELEMENT_LIVE_TIMER_INTERVAL, SessionConfigStrings.CONFIG_STRING_ZERO); | |
333 | ||
334 | /* Add the events */ | |
335 | channelElement.appendChild(getEventsElement(document, isKernel, channel.getEvents())); | |
336 | channelsElement.appendChild(channelElement); | |
337 | } | |
338 | ||
339 | return channelsElement; | |
340 | } | |
341 | ||
342 | /** | |
343 | * Gets the 'events' element after creating it. It is composed of the event | |
344 | * informations from a list of IEventInfo. | |
345 | * | |
346 | * @param document | |
347 | * The document in which the nodes are being added | |
348 | * @param isKernel | |
349 | * Is the domain type kernel | |
350 | * @param events | |
351 | * The event informations to be added | |
352 | * @return An element containing all the event informations as XML elements | |
353 | */ | |
354 | private static Element getEventsElement(Document document, boolean isKernel, IEventInfo[] events) { | |
355 | Element eventsElement = document.createElement(SessionConfigStrings.CONFIG_ELEMENT_EVENTS); | |
356 | ||
357 | for (IEventInfo event : events) { | |
358 | Element eventElement = document.createElement(SessionConfigStrings.CONFIG_ELEMENT_EVENT); | |
359 | ||
360 | /* Enabled attribute */ | |
361 | String enabled = event.getState().equals(TraceEnablement.ENABLED) ? SessionConfigStrings.CONFIG_STRING_TRUE : SessionConfigStrings.CONFIG_STRING_FALSE; | |
362 | ||
363 | /* Add the attributes to the event node */ | |
364 | addElementContent(document, eventElement, SessionConfigStrings.CONFIG_ELEMENT_NAME, event.getName()); | |
365 | addElementContent(document, eventElement, SessionConfigStrings.CONFIG_ELEMENT_ENABLED, enabled); | |
366 | TraceEventType eventType = event.getEventType(); | |
367 | if (!eventType.equals(TraceEventType.UNKNOWN)) { | |
368 | addElementContent(document, eventElement, SessionConfigStrings.CONFIG_ELEMENT_TYPE, eventType.getInName().toUpperCase()); | |
369 | } else { | |
370 | throw new IllegalArgumentException(Messages.SessionConfigXML_UnknownEventType); | |
371 | } | |
372 | ||
373 | /* Specific to UST session config: the log level */ | |
374 | if (!isKernel && !event.getLogLevel().equals(TraceLogLevel.LEVEL_UNKNOWN)) { | |
375 | addElementContent(document, eventElement, SessionConfigStrings.CONFIG_ELEMENT_LOGLEVEL, event.getLogLevel().ordinal()); | |
376 | } | |
377 | ||
378 | /* Add the node to the parent node events */ | |
379 | eventsElement.appendChild(eventElement); | |
380 | } | |
381 | ||
382 | return eventsElement; | |
383 | } | |
384 | ||
385 | /** | |
386 | * Gets the 'consumer_output' element after creating it. | |
387 | * | |
388 | * @param document | |
389 | * The document in which the nodes are being added | |
390 | * @param session | |
391 | * The session informations | |
392 | * @return The consumer output element with his informations as XML elements | |
393 | */ | |
394 | private static Element getConsumerOutputElement(Document document, ISessionInfo session) { | |
395 | Element consumerOutputElement = document.createElement(SessionConfigStrings.CONFIG_ELEMENT_CONSUMER_OUTPUT); | |
396 | Element destinationElement = document.createElement(SessionConfigStrings.CONFIG_ELEMENT_DESTINATION); | |
397 | ||
398 | /* Value of consumer output element */ | |
399 | addElementContent(document, consumerOutputElement, SessionConfigStrings.CONFIG_ELEMENT_ENABLED, SessionConfigStrings.CONFIG_STRING_TRUE); | |
400 | ||
401 | if (session.isStreamedTrace()) { | |
402 | /* If it is a streamed session, add the net output element */ | |
403 | destinationElement.appendChild(getNetOutputElement(document, session)); | |
404 | } else { | |
405 | addElementContent(document, destinationElement, SessionConfigStrings.CONFIG_ELEMENT_PATH, session.getSessionPath()); | |
406 | } | |
407 | ||
408 | consumerOutputElement.appendChild(destinationElement); | |
409 | return consumerOutputElement; | |
410 | } | |
411 | ||
412 | /** | |
413 | * Gets the 'net_output' element after creating it. It is composed of the | |
414 | * control and data URIs. | |
415 | * | |
416 | * @param document | |
417 | * The document in which the nodes are being added | |
418 | * @param session | |
419 | * The session informations | |
420 | * @return The net output element | |
421 | */ | |
422 | private static Element getNetOutputElement(Document document, ISessionInfo session) { | |
423 | Element netOutputElement = document.createElement(SessionConfigStrings.CONFIG_ELEMENT_NET_OUTPUT); | |
424 | ||
425 | String networkUrl = session.getNetworkUrl(); | |
426 | String controlUri = networkUrl == null ? session.getControlUrl() : networkUrl; | |
427 | String dataUri = networkUrl == null ? session.getDataUrl() : networkUrl; | |
428 | addElementContent(document, netOutputElement, SessionConfigStrings.CONFIG_ELEMENT_CONTROL_URI, controlUri); | |
429 | addElementContent(document, netOutputElement, SessionConfigStrings.CONFIG_ELEMENT_DATA_URI, dataUri); | |
430 | ||
431 | return netOutputElement; | |
432 | } | |
433 | ||
434 | /** | |
435 | * Gets the 'snapshot_outputs' element after creating it. | |
436 | * | |
437 | * @param document | |
438 | * The document in which the nodes are being added | |
439 | * @param session | |
440 | * The session informations | |
441 | * @return The snapshot outputs element with snapshot informations as XML | |
442 | * elements | |
443 | */ | |
444 | private static Element getSnapshotOuputsElement(Document document, ISessionInfo session) { | |
445 | Element snapshotOutputsElement = document.createElement(SessionConfigStrings.CONFIG_ELEMENT_SNAPSHOT_OUTPUTS); | |
446 | Element outputElement = document.createElement(SessionConfigStrings.CONFIG_ELEMENT_OUTPUT); | |
447 | ||
448 | /* Add the name of the snapshot and the max size element */ | |
449 | addElementContent(document, outputElement, SessionConfigStrings.CONFIG_ELEMENT_NAME, session.getSnapshotInfo().getName()); | |
450 | ||
451 | /* | |
452 | * TODO: find the proper max size value of output element. For now it is | |
453 | * set to the default 0 value which means unlimited for lttng. | |
454 | */ | |
455 | addElementContent(document, outputElement, SessionConfigStrings.CONFIG_ELEMENT_MAX_SIZE, SessionConfigStrings.CONFIG_STRING_ZERO); | |
456 | outputElement.appendChild(getConsumerOutputElement(document, session)); | |
457 | ||
458 | snapshotOutputsElement.appendChild(outputElement); | |
459 | return snapshotOutputsElement; | |
460 | } | |
461 | ||
462 | // --------------------------------------------------------- | |
463 | // Utilities | |
464 | // --------------------------------------------------------- | |
465 | ||
466 | /** | |
467 | * Validates the session configuration file against its schema. | |
468 | * | |
469 | * @param sessionFile | |
470 | * The session configuration file | |
471 | * @return The status of the validation | |
472 | */ | |
473 | public static IStatus sessionValidate(File sessionFile) { | |
474 | URL url = SessionConfigGenerator.class.getResource(SESSION_XSD_FILENAME); | |
475 | SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); | |
476 | Source xmlSource = new StreamSource(sessionFile); | |
477 | ||
478 | try { | |
479 | Schema schema = schemaFactory.newSchema(url); | |
480 | Validator validator = schema.newValidator(); | |
481 | validator.validate(xmlSource); | |
482 | } catch (SAXParseException e) { | |
483 | String error = NLS.bind(Messages.SessionConfigXML_XmlParseError, e.getLineNumber(), e.getLocalizedMessage()); | |
484 | Activator.getDefault().logError(error); | |
485 | return new Status(IStatus.ERROR, Activator.PLUGIN_ID, error, e); | |
486 | } catch (SAXException e) { | |
487 | String error = NLS.bind(Messages.SessionConfigXML_XmlValidationError, e.getLocalizedMessage()); | |
488 | Activator.getDefault().logError(error); | |
489 | return new Status(IStatus.ERROR, Activator.PLUGIN_ID, error, e); | |
490 | } catch (IOException e) { | |
491 | String error = Messages.SessionConfigXML_XmlValidateError; | |
492 | Activator.getDefault().logError("IO exception occurred", e); //$NON-NLS-1$ | |
493 | return new Status(IStatus.ERROR, Activator.PLUGIN_ID, error, e); | |
494 | } | |
495 | return Status.OK_STATUS; | |
496 | } | |
497 | ||
498 | /** | |
499 | * Saves the session configuration into a XML file. | |
500 | * | |
501 | * @param document | |
502 | * The document representing the session configuration file | |
503 | * @param destination | |
504 | * The path of the locally saved session configuration file | |
505 | * @throws TransformerException | |
506 | * On an transformation process | |
507 | */ | |
508 | private static void saveSessionConfig(Document document, String destination) throws TransformerException { | |
509 | /* Write the content into a XML file */ | |
510 | TransformerFactory transformerFactory = TransformerFactory.newInstance(); | |
511 | Transformer transformer = transformerFactory.newTransformer(); | |
512 | ||
513 | transformer.setOutputProperty(OutputKeys.INDENT, "yes"); //$NON-NLS-1$ | |
514 | transformer.setOutputProperty(INDENT_AMOUNT_PROPERTY_NAME, INDENT_AMOUNT_PROPERTY_VALUE); | |
515 | ||
516 | DOMSource source = new DOMSource(document); | |
517 | StreamResult result = new StreamResult(new File(destination)); | |
518 | ||
519 | transformer.transform(source, result); | |
520 | } | |
521 | ||
522 | /** | |
523 | * Adds to a parent node an element with his content. | |
524 | * | |
525 | * @param document | |
526 | * The document in which the nodes are being added | |
527 | * @param parent | |
528 | * The parent node that contains the element and his content | |
529 | * @param elementName | |
530 | * The element container name | |
531 | * @param elementContent | |
532 | * The content itself | |
533 | */ | |
534 | private static void addElementContent(Document document, Element parent, String elementName, Object elementContent) { | |
535 | Element contentElement = document.createElement(elementName); | |
536 | contentElement.appendChild(document.createTextNode(elementContent.toString())); | |
537 | parent.appendChild(contentElement); | |
538 | } | |
539 | } |