/*******************************************************************************
* Copyright (c) 2012, 2014 Wind River Systems, Inc. and others. 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:
* Wind River Systems - initial API and implementation
*******************************************************************************/
package org.eclipse.tcf.te.launch.core.persistence;
import java.io.IOException;
import java.util.List;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.tcf.te.launch.core.activator.CoreBundleActivator;
import org.eclipse.tcf.te.runtime.persistence.PersistenceManager;
import org.eclipse.tcf.te.runtime.persistence.interfaces.IPersistenceDelegate;
import org.osgi.framework.Bundle;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
/**
* AbstractItemListXMLParser
*/
public abstract class AbstractItemListXMLParser<ItemType> extends DefaultHandler {
private final static int IN_ITEMS_DEFINITION = 1;
private final static int IN_ITEM_DEFINITION = 2;
private SAXParser parser;
private int parseState;
private String lastData;
private String lastType;
private List<ItemType> items;
private final String containerTag;
private final String itemTag;
public static final String ATTR_TYPE = "type"; //$NON-NLS-1$
/**
* Constructor
*/
public AbstractItemListXMLParser(String tagName) {
super();
Assert.isNotNull(tagName);
containerTag = tagName + "s"; //$NON-NLS-1$
itemTag = tagName;
SAXParserFactory factory = SAXParserFactory.newInstance();
factory.setNamespaceAware(false);
factory.setValidating(false);
try {
parser = factory.newSAXParser();
}
catch (ParserConfigurationException e) {
IStatus status = new Status(IStatus.ERROR, CoreBundleActivator.getUniqueIdentifier(), e.getClass().getName(), e);
Platform.getLog(CoreBundleActivator.getContext().getBundle()).log(status);
}
catch (SAXException e) {
IStatus status = new Status(IStatus.ERROR, CoreBundleActivator.getUniqueIdentifier(), e.getClass().getName(), e);
Platform.getLog(CoreBundleActivator.getContext().getBundle()).log(status);
}
}
/**
* Returns the associated XML parser instance.
*/
public SAXParser getXMLReader() {
return parser;
}
/**
* Reset the XML parser to a defined start point.
*/
public void initXMLParser() {
parseState = 0;
lastData = null;
lastType = null;
items = null;
}
/**
* Associate the list instance to store the identified contexts.
*/
public void setItems(List<ItemType> items) {
this.items = items;
}
/*
* (non-Javadoc)
* @see org.xml.sax.helpers.DefaultHandler#endElement(java.lang.String, java.lang.String,
* java.lang.String)
*/
@Override
public void endElement(String uri, String localName, String name) throws SAXException {
if (containerTag.equalsIgnoreCase(name) && (parseState & IN_ITEMS_DEFINITION) == IN_ITEMS_DEFINITION) {
parseState ^= IN_ITEMS_DEFINITION;
}
if (itemTag.equalsIgnoreCase(name) && (parseState & IN_ITEM_DEFINITION) == IN_ITEM_DEFINITION) {
parseState ^= IN_ITEM_DEFINITION;
// The item encoded string is in last data
if (lastType != null && lastData != null) {
Class<?> clazz = null;
try {
clazz = CoreBundleActivator.getContext().getBundle().loadClass(lastType);
}
catch (ClassNotFoundException e) {
}
// If the class could not be loaded by our own bundle class loader, try to find
// the bundle from the class name and try to load the class through the bundle.
if (clazz == null) {
String bundleId = lastType;
Bundle bundle = null;
while (bundleId != null && bundle == null) {
bundle = Platform.getBundle(bundleId);
if (bundle == null) {
int i = bundleId.lastIndexOf('.');
if (i != -1) {
bundleId = bundleId.substring(0, i);
} else {
bundleId = null;
}
}
}
if (bundle != null) {
try {
clazz = bundle.loadClass(lastType);
}
catch (ClassNotFoundException e) {
if (Platform.inDebugMode()) {
IStatus status = new Status(IStatus.ERROR, CoreBundleActivator.getUniqueIdentifier(),
"Launch framework internal error: " + e.getLocalizedMessage(), e); //$NON-NLS-1$
Platform.getLog(CoreBundleActivator.getContext().getBundle()).log(status);
}
}
}
}
if (clazz != null) {
IPersistenceDelegate delegate = PersistenceManager.getInstance().getDelegate(clazz, lastData);
if (delegate != null) {
try {
@SuppressWarnings("unchecked")
ItemType item = (ItemType)delegate.read(getReadClass(), lastData);
if (items != null && !items.contains(item)) {
items.add(item);
}
}
catch (IOException e) {
if (Platform.inDebugMode()) {
IStatus status = new Status(IStatus.ERROR, CoreBundleActivator.getUniqueIdentifier(),
"Launch framework internal error: " + e.getLocalizedMessage(), e); //$NON-NLS-1$
Platform.getLog(CoreBundleActivator.getContext().getBundle()).log(status);
}
}
}
}
}
}
}
protected abstract Class<?> getReadClass();
/* (non-Javadoc)
* @see org.xml.sax.helpers.DefaultHandler#startElement(java.lang.String, java.lang.String, java.lang.String, org.xml.sax.Attributes)
*/
@Override
public void startElement(String uri, String localName, String name, Attributes attributes) throws SAXException {
// Each time we start a new element, throw away the lastData content
lastData = null;
if (containerTag.equalsIgnoreCase(name)) {
parseState |= IN_ITEMS_DEFINITION;
}
if (itemTag.equalsIgnoreCase(name) && (parseState & IN_ITEMS_DEFINITION) == IN_ITEMS_DEFINITION) {
parseState |= IN_ITEM_DEFINITION;
lastType = attributes.getValue(ATTR_TYPE);
}
}
/* (non-Javadoc)
* @see org.xml.sax.helpers.DefaultHandler#characters(char[], int, int)
*/
@Override
public void characters(char ch[], int start, int length) {
if (lastData == null) {
lastData = new String(ch, start, length).trim();
}
else {
lastData += new String(ch, start, length).trim();
}
}
}