blob: 0fdf3b5e06b1c3036ad30a2090e13eca60126971 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2010 Dieter Krachtus and The University of Tennessee,
* 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:
* Dieter Krachtus (dieter.krachtus@gmail.com) and Roland Schulz - initial API and implementation
*******************************************************************************/
package org.eclipse.ptp.rm.proxy.core.parser;
import java.beans.IntrospectionException;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringReader;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.eclipse.ptp.rm.proxy.core.attributes.AttributeDefinition;
import org.eclipse.ptp.rm.proxy.core.element.IElement;
import org.eclipse.ptp.rm.proxy.core.element.IElement.UnknownValueExecption;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
/**
* XML file reader.
*/
public class XMLReader implements IParser {
/**
* This class ensures that the InputStream has only valid XML unicode
* characters as specified by the XML 1.0 standard. For reference, please
* see <a href="http://www.w3.org/TR/2000/REC-xml-20001006#NT-Char">the
* standard</a>. This method will return an empty String if the input is
* null or empty.
*
* From: http://cse-mjmcl.cse.bris.ac.uk/blog/2007/02/14/1171465494443.html
* Not OK for UTF longer than 2 bytes
*
* If the XML is empty it provides "<D></D>"
*
*/
class FixInValidXMLReader extends InputStreamReader {
boolean isEmpty = false;
int totalBytesRead = 0;
Reader emptyInput = null;
public FixInValidXMLReader(InputStream in) {
super(in);
}
@Override
public int read() throws IOException {
char cbuf[] = new char[1];
int ret;
while ((ret = read(cbuf, 0, 1)) != -1)
;
if (ret > 0)
return cbuf[0];
else
return -1;
}
@Override
public int read(char cbuf[], int offset, int length) throws IOException {
if (emptyInput!=null)
return emptyInput.read(cbuf, offset, length);
int ret = super.read(cbuf, offset, length);
int skip = 0;
if (totalBytesRead==0 && ret<1) { /*Send non-empty valid XML if input stream is empty*/
emptyInput = new StringReader("<D></D>");
return emptyInput.read(cbuf, offset, length);
}
for (int i = offset; i < offset + ret; i++) {
char current = cbuf[i];
if (!((current == 0x9) || (current == 0xA) || (current == 0xD) || ((current >= 0x20) && (current <= 0xD7FF))
|| ((current >= 0xE000) && (current <= 0xFFFD)) || ((current >= 0x10000) && (current <= 0x10FFFF)))) {
skip++;
continue;
}
if (skip > 0) {
cbuf[i - skip] = cbuf[i];
}
}
ret-=skip;
totalBytesRead+=ret;
return ret;
}
}
/** The DEBUG. */
private static boolean DEBUG = false;
/**
* Testing method
*
* @param argv
* the arguments
*/
public static void main(String argv[]) throws IntrospectionException, IllegalAccessException, InvocationTargetException,
InstantiationException, FileNotFoundException {
DEBUG = true;
// parseXML(ModelQstatJob.class, new File("qstat_valid.xml"));
// new XMLReader().parse(ModelNode.class, new FileInputStream(new
// File("pbsnodes.helics.xml")));
}
private NodeList getXMLChildren(InputStream in) throws SAXException, IOException, ParserConfigurationException {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse(new InputSource(new FixInValidXMLReader(in)));
// Document doc = builder.parse(in);
Element root = doc.getDocumentElement();
root.normalize();
return root.getChildNodes();
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.ptp.rm.proxy.core.parser.IParser#parse(org.eclipse.ptp.rm
* .proxy.core.attributes.AttributeDefinition, java.io.InputStream)
*/
public Set<IElement> parse(AttributeDefinition attrDef, InputStream in) throws SAXException, IOException,
ParserConfigurationException, UnknownValueExecption {
// public <T extends IElement> Set<T> parse(Class<IElement> pojoClazz,
// InputStream in) {
Set<IElement> elementList = null;
NodeList xmlNodes = null;
xmlNodes = getXMLChildren(in);
in.close();
elementList = new HashSet<IElement>(xmlNodes.getLength());
for (int i = 0; i < xmlNodes.getLength(); i++) {
Node node = xmlNodes.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE) {
Map<String, String> input = populateInput(node, null);
IElement element = populateElement(attrDef, input);
if (DEBUG) {
System.out.println(element);
System.out.println();
}
elementList.add(element);
}
}
if (DEBUG) {
System.out.println(elementList.size());
}
return elementList;
}
private IElement populateElement(AttributeDefinition attrDef, Map<String, String> input) throws UnknownValueExecption {
IElement element = attrDef.createElement();
// PropertyDescriptor[] properties =
// Introspector.getBeanInfo(attrDef).getPropertyDescriptors();
// for (PropertyDescriptor property : properties) {
for (String attr : attrDef.getRequiredAttributes()) {
element.setAttribute(attr, input.get(attr));
// String name = property.getName();
// Method writeAccess = property.getWriteMethod();
// if (writeAccess != null &&
// !Modifier.isStatic(writeAccess.getModifiers())) {
// System.out.println(name + " <- " + input.get(name));
// writeAccess.invoke(pojo, new Object[]{input.get(name)});
// }
}
return element;
}
protected Map<String, String> populateInput(Node node, Map<String, String> input) {
if (input == null) {
input = new HashMap<String, String>();
}
// if (node.getNodeType() == Node.ELEMENT_NODE)
// System.out.println(node.getNodeName());
NodeList childNodes = node.getChildNodes();
for (int i = 0; i < childNodes.getLength(); i++) {
Node childNode = childNodes.item(i);
if (childNode.getNodeType() == Node.ELEMENT_NODE) {
if (childNode.getChildNodes().getLength() > 1) {
populateInput(childNode, input);
} else {
input.put(childNode.getNodeName().toLowerCase(), childNode.getTextContent());
}
}
// if (childNode.getNodeType() == Node.ELEMENT_NODE)
// System.out.println("\t" + childNode.getNodeName().toLowerCase() +
// " -> " + childNode.getTextContent());
}
return input;
}
}