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