/*******************************************************************************
* Copyright (c) 2010 Red Hat, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Red Hat - initial API and implementation
*******************************************************************************/
package org.eclipse.linuxtools.internal.oprofile.core.opxml.sessions;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.eclipse.linuxtools.internal.oprofile.core.OprofileCorePlugin;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
/**
* This class manipulates the XML data output from the command 'opxml sessions'
*/
public class SessionManager {
public final static String PLUGIN_LOC = OprofileCorePlugin.getDefault().getStateLocation().toOSString();
public final static String SESSIONS = "sessions"; //$NON-NLS-1$
public final static String EVENT = "event"; //$NON-NLS-1$
public final static String SESSION = "session"; //$NON-NLS-1$
public final static String NAME = "name"; //$NON-NLS-1$
public final static String CURRENT = "current"; //$NON-NLS-1$
public final static String OPXML_PREFIX = PLUGIN_LOC + "/opxml_"; //$NON-NLS-1$
public final static String SESSION_LOCATION = OPXML_PREFIX + SESSIONS;
public final static String MODEL_DATA = "model-data"; //$NON-NLS-1$
public Document doc;
public Element root;
public String absfilePath;
public SessionManager(String filePath) {
this(new File(filePath));
absfilePath = filePath;
write();
}
/**
* Session manager class constructor to manipulate the XML data
*
* @param file
* the xml file
*/
public SessionManager(File file) {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder;
try {
builder = factory.newDocumentBuilder();
if (!file.exists()) {
file.createNewFile();
doc = builder.newDocument();
root = doc.createElement(SESSIONS);
doc.appendChild(root);
} else {
InputStream is = new FileInputStream(file);
doc = builder.parse(is);
Element elem = (Element) doc.getElementsByTagName(SESSIONS).item(0);
root = elem;
}
} catch (ParserConfigurationException | SAXException | IOException e) {
e.printStackTrace();
}
}
/**
* Add a session to the specified event element if it does not exist.
*
* @param sessionName
* the name of the session
* @param eventName
* the name of the event
*/
public void addSession(String sessionName, String eventName) {
Element event = null;
Element session = find(root, SESSION, NAME, sessionName);
if (session == null) {
session = doc.createElement(SESSION);
session.setAttribute(NAME, sessionName);
root.appendChild(session);
} else {
event = find(session, EVENT, NAME, eventName);
}
if (event == null) {
event = doc.createElement(EVENT);
event.setAttribute(NAME, eventName);
session.appendChild(event);
}
}
/**
* Check if a session exists
*
* @param sessionName
* the name of the session
* @return true if the session exists, otherwise false
*/
public boolean existsSession(String sessionName) {
return find(root, SESSION, NAME, sessionName) != null ? true : false;
}
/**
* Find an element in the XML
*
* @param elem
* the element to look under
* @param tagName
* the name of the tag
* @param attName
* the name of the attribute
* @param attVal
* the name of the attribute value
* @return the element that matches the search, or null if none is found.
*/
private Element find(Element elem, String tagName, String attName, String attVal) {
NodeList list = elem.getElementsByTagName(tagName);
for (int i = 0; i < list.getLength(); i++) {
if (list.item(i) instanceof Element) {
Element e = (Element) list.item(i);
if (e.getAttribute(attName).equals(attVal)) {
return e;
}
}
}
return null;
}
/**
* Remove all sessions under any event that have the name 'current'
*/
public void removeAllCurrentSessions() {
NodeList sessionList = root.getElementsByTagName(SESSION);
for (int i = 0; i < sessionList.getLength(); i++) {
Element session = (Element) sessionList.item(i);
String sessionName = session.getAttribute(NAME);
if (CURRENT.equals(sessionName)) {
NodeList eventList = session.getElementsByTagName(EVENT);
for (int j = 0; j < eventList.getLength(); j++) {
Element event = (Element) eventList.item(j);
String eventName = event.getAttribute(NAME);
session.removeChild(event);
File file = new File(SessionManager.OPXML_PREFIX + SessionManager.MODEL_DATA + eventName
+ SessionManager.CURRENT);
file.delete();
if (sessionList.getLength() == 0) {
root.removeChild(session);
}
}
}
}
}
/**
* Remove a session named sessionName that is under eventName if it exists.
*
* @param sessionName
* @param eventName
*/
public void removeSession(String sessionName, String eventName) {
NodeList list = root.getElementsByTagName(SESSION);
for (int i = 0; i < list.getLength(); i++) {
if (list.item(i) instanceof Element) {
Element session = (Element) list.item(i);
if (session.getAttribute(NAME).equals(sessionName)) {
Element event = find((Element) list.item(i), EVENT, NAME, eventName);
if (event != null) {
removeSessionHelper(sessionName, event);
}
}
}
}
}
/**
* remove event elem for given session sessionName , also remove session if
* there is no event under it.
*
* @param sessionName
* @param elem
*
*/
private void removeSessionHelper(String sessionName, Element elem) {
NodeList list = root.getElementsByTagName(SESSION);
for (int i = 0; i < list.getLength(); i++) {
if (list.item(i) instanceof Element) {
Element e = (Element) list.item(i);
if (e.getAttribute(NAME).equals(sessionName)) {
NodeList events = e.getElementsByTagName(EVENT);
for (int j = 0; j < events.getLength(); j++) {
Element event = (Element) events.item(j);
if (event.getAttribute(NAME).equals(elem.getAttribute(NAME))) {
e.removeChild(event);
}
if (events.getLength() == 0) {
root.removeChild(e);
}
}
}
}
}
}
/**
* Return a list of the events run with the given session
*
* @param sessionName
* the name of the session
* @return A String ArrayList of event names that were run with the given
* session.
*/
public ArrayList<String> getSessionEvents(String sessionName) {
ArrayList<String> ret = new ArrayList<>();
NodeList eventList = root.getElementsByTagName(SESSION);
for (int i = 0; i < eventList.getLength(); i++) {
if (eventList.item(i) instanceof Element) {
Element event = ((Element) eventList.item(i));
if (event.getAttribute(NAME).equals(sessionName)) {
NodeList sessionList = event.getElementsByTagName(EVENT);
for (int j = 0; j < sessionList.getLength(); j++) {
if (sessionList.item(j) instanceof Element) {
Element session = ((Element) sessionList.item(j));
ret.add(session.getAttribute(NAME));
}
}
}
}
}
return ret;
}
/**
* Write back to the same file, that the data was loaded from.
*/
public void write() {
writeToFile(absfilePath);
}
/**
* Write the contents of the given Document to a file.
*/
private void writeToFile(String filePath) {
Source source = new DOMSource(doc);
Result result = new StreamResult(new File(filePath));
TransformerFactory factory = TransformerFactory.newInstance();
Transformer xformer;
try {
xformer = factory.newTransformer();
xformer.transform(source, result);
} catch (TransformerException e) {
e.printStackTrace();
}
}
public static void saveSession(String name) {
SessionManager sessMan;
try {
sessMan = new SessionManager(SessionManager.SESSION_LOCATION);
for (String event : sessMan.getSessionEvents(SessionManager.CURRENT)) {
sessMan.addSession(name, event);
String oldFile = SessionManager.OPXML_PREFIX + SessionManager.MODEL_DATA + event
+ SessionManager.CURRENT;
String newFile = SessionManager.OPXML_PREFIX + SessionManager.MODEL_DATA + event + name;
Process p = Runtime.getRuntime().exec("cp " + oldFile + " " + newFile); //$NON-NLS-1$ //$NON-NLS-2$
p.waitFor();
}
sessMan.write();
} catch (FileNotFoundException e) {
// intentionally blank
// during a save, the session file will exist
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
}
public static void deleteSession(String sessionName, String eventName) {
File file = new File(SessionManager.OPXML_PREFIX + SessionManager.MODEL_DATA + eventName + sessionName);
file.delete();
SessionManager sessMan = new SessionManager(SessionManager.SESSION_LOCATION);
sessMan.removeSession(sessionName, eventName);
sessMan.write();
}
}