is-collector/src/org/gcube/informationsystem/collector/impl/resources/GCUBEXMLResource.java

447 lines
14 KiB
Java

package org.gcube.informationsystem.collector.impl.resources;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.TimeZone;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathFactory;
import org.gcube.common.core.utils.logging.GCUBELog;
import org.gcube.informationsystem.collector.impl.resources.DAIXResource.MalformedResourceException;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.xml.sax.InputSource;
/**
*
*
* @author Manuele Simi (ISTI-CNR)
*
*/
public class GCUBEXMLResource {
/**
* the resource type states if the resource contains a profile or generic WS-ResourceProperties
*/
public enum RESOURCETYPE {
Profile, Properties
}
protected RESOURCETYPE type = null;
protected static GCUBELog logger = new GCUBELog(GCUBEXMLResource.class);
protected Calendar terminationTime = null, lastUpdateTime = null;
protected String entryKey, groupKey, source, sourceKey = "", completeSourceKey = "";
// xpath factory to evaluate Xpath expressions
private XPath path = XPathFactory.newInstance().newXPath();
private DAIXResource resource;
public GCUBEXMLResource(DAIXResource resource) throws MalformedXMLResourceException {
this.resource = resource;
this.terminationTime = new GregorianCalendar();
this.terminationTime.setTimeZone(TimeZone.getTimeZone("GMT"));
this.lastUpdateTime = new GregorianCalendar();
this.lastUpdateTime.setTimeZone(TimeZone.getTimeZone("GMT"));
try {
if (resource.getResourceName() == null)
throw new MalformedXMLResourceException("Invalid resource name");
} catch (MalformedResourceException e) {
throw new MalformedXMLResourceException("Invalid resource name");
}
}
/**
* @return the name of the collection including the resource
* @throws MalformedResourceException
*/
public String getCollectionName() throws MalformedXMLResourceException {
try {
return this.resource.getCollectionName();
} catch (MalformedResourceException e) {
throw new MalformedXMLResourceException(e);
}
}
/**
* @return the resource name
* @throws MalformedResourceException
*/
public String getResourceName() throws MalformedXMLResourceException {
try {
return this.resource.getResourceName();
} catch (MalformedResourceException e) {
throw new MalformedXMLResourceException(e);
}
}
/**
* @return the terminationTime of this resource
*/
public Calendar getTerminationTime() {
return this.terminationTime;
}
/**
* @return the lastUpdateTime of this resource
*/
public Calendar getLastUpdateTime() {
return this.lastUpdateTime;
}
/**
* @param terminationTime
* the terminationTime to set
*/
public void setTerminationTime(final Calendar terminationTime) {
this.terminationTime = (Calendar) terminationTime.clone();
this.terminationTime.setTimeZone(TimeZone.getTimeZone("GMT"));
}
/**
* @return the lastUpdateTime in milliseconds
* @throws Exception
* if an error occurs when accessing the LastUpdateMs field
*/
public long getLastUpdateTimeinMills() throws MalformedResourceException {
if (lastUpdateTime != null)
return lastUpdateTime.getTimeInMillis();
else
throw new MalformedResourceException("unable to retrieve last update time for resource " + this.resource.getResourceName());
}
/**
* Accesses the source GroupKey
*
* @return the ID
*/
public String getGroupKey() {
return this.groupKey;
}
/**
* Sets the source GroupKey
*
* @param groupKey
* the new group key
*
*/
public void setGroupKey(String groupKey) {
this.groupKey = groupKey;
}
/**
* Accesses the source EntryKey
*
* @return the ID
*/
public String getEntryKey() {
return this.entryKey;
}
/**
* Sets the source EntryKey
*
* @param entryKey
* the new entry key
*/
public void setEntryKey(String entryKey) {
this.entryKey = entryKey;
}
/**
* Sets the source address of the RI that publishes resource as reported in the servicegroup
* entry
*
* @param source
* the new source address
*/
public void setSource(String source) {
this.source = source;
}
/**
* Accesses the source address of the service that published the data
*
* @return the source
*/
public String getSource() {
return this.source;
}
/**
* Sets the key of the WS-Resource that published the data
*
* @param key
* the new source key
*/
public void setSourceKey(String key) {
this.sourceKey = key;
}
/**
* Gets the key of the WS-Resource that published the data
*
* @return the key
*/
public String getSourceKey() {
return this.sourceKey;
}
/**
* Sets the complete source key
*
* @param completeKey
* the new complete key
*/
public void setCompleteSourceKey(String completeKey) {
this.completeSourceKey = completeKey;
}
/**
* Gets the complete source key
*
* @return the complete source key
/*
if ((lastUpdateTime == null) && (this.resource.getContent() != null)) {
String value = "";
try {
value = path.evaluate("Document/LastUpdateMs", this.resource.getContent());
} catch (XPathExpressionException xpee) {
logger.error("" + xpee.getMessage());
logger.error("" + xpee.getStackTrace());
throw new MalformedResourceException("XPath evaluation error");
}
try {
return Long.parseLong(value);
} catch (NumberFormatException nfe) {
logger.error("Invalid last update time format found in resource " + this.resource.getContent());
logger.error("Parsed string was " + value);
throw new MalformedResourceException("Unable to retrieve last update time for resource " + this.resource.getContent());
}
} else
throw new MalformedResourceException("unable to retrieve last update time for resource " + this.resource.getResourceName());
*/
public String getCompleteSourceKey() {
return this.completeSourceKey;
}
public void setContent(String content, boolean... enveloped) {
try {
if (enveloped != null && enveloped.length > 0 && enveloped[0]) {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
StringReader reader = new StringReader(content);
InputSource source = new InputSource(reader);
Document doc = builder.parse(source);
this.parseEnvelop(doc);
resource.setContent(this.removeEnvelop(doc));
}
else
resource.setContent(content);
} catch (Exception e) {
}
}
/**
* Extract the resource informantion from the envelop
* @param doc the enveloped content
* @throws MalformedXMLResourceException
*/
private void parseEnvelop(Document doc) throws MalformedXMLResourceException {
String value = "";
try {
value = path.evaluate("Document/LastUpdateMs", doc);
this.lastUpdateTime.setTimeInMillis(Long.parseLong(value));
value = path.evaluate("Document/TerminationTime", doc);
this.terminationTime.setTimeInMillis(Long.parseLong(value));
value = path.evaluate("Document/Source", doc);
this.setSource(value);
value = path.evaluate("Document/SourceKey", doc);
this.setCompleteSourceKey(value);
value = path.evaluate("Document/EntryKey", doc);
this.setEntryKey(value);
value = path.evaluate("Document/GroupKey", doc);
this.setGroupKey(value);
} catch (Exception xpee) {
logger.error("" + xpee.getMessage());
logger.error("" + xpee.getStackTrace());
throw new MalformedXMLResourceException("Unable to retrieve last update time for resource");
}
}
public String toString() {
// we do not use an XML parser for performance reasons
StringBuilder resource = new StringBuilder("<Document>\n");
try {
resource.append("<ID>" + this.resource.getResourceName() + "</ID>\n");
resource.append("<Source>" + this.getSource() + "</Source>\n");
resource.append("<SourceKey>" + this.getSourceKey() + "</SourceKey>\n");
resource.append("<CompleteSourceKey>" + this.getCompleteSourceKey() + "</CompleteSourceKey>\n");
resource.append("<EntryKey>" + this.getEntryKey() + "</EntryKey>\n");
resource.append("<GroupKey>" + this.getGroupKey() + "</GroupKey>\n");
resource.append("<TerminationTime>" + this.getTerminationTime().getTimeInMillis() + "</TerminationTime>\n");
resource.append("<TerminationTimeHuman>" + this.getTerminationTime().getTime().toString() + "</TerminationTimeHuman>\n");
resource.append("<LastUpdateMs>" + this.lastUpdateTime.getTimeInMillis() + "</LastUpdateMs>\n");
resource.append("<LastUpdateHuman>" + this.lastUpdateTime.getTime().toString() + "</LastUpdateHuman>\n");
resource.append("<Data>\n");
resource.append(this.resource.toString() + "\n");
resource.append("</Data>\n");
resource.append("</Document>\n");
} catch (MalformedResourceException e) {
logger.error("invalid content", e);
}
return resource.toString();
}
/**
* Removes the document envelop from the document
*
* @param doc the content to clean up
* @return the content string without the document envelop
* @throws MalformedResourceException
*/
private String removeEnvelop(Document doc) throws MalformedXMLResourceException {
try {
return this.toStringFromElement(doc, "Data"); // Data/*
} catch (Exception e) {
logger.error("unable to retrieve parse the resource's content ", e);
}
throw new MalformedXMLResourceException("unable to retrieve parse the resource's content");
}
/**
* Returns a sub-serialization of the given XML, starting from the element name
*
* @param xml
* the source XML serialization
* @param elementName
* the name of the element
* @return the node content serialized as string
* @throws Exception
* if the serialization fails
*/
private String toStringFromElement(String xml, String elementName) throws MalformedXMLResourceException {
try {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
StringReader reader = new StringReader(xml);
InputSource source = new InputSource(reader);
return toStringFromElement(builder.parse(source), elementName);
} catch (Exception e) {
logger.error("Unable to deserialise content data", e);
throw new MalformedXMLResourceException("Unable to deserialise the resource");
}
}
/**
* Returns a sub-serialization of the given XML, starting from the element name
*
* @param xml
* the source XML serialization
* @param elementName
* the name of the element
* @return the node content serialized as string
* @throws Exception
* if the serialization fails
*/
private String toStringFromElement(Document xml, String elementName) throws MalformedXMLResourceException {
try {
Node targetNode = xml.getElementsByTagName(elementName).item(0);
TransformerFactory transFactory = TransformerFactory.newInstance();
Transformer transformer = transFactory.newTransformer();
StringBuilder ret = new StringBuilder();
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
int index = 0;
Node node = targetNode.getChildNodes().item(index);
while (node != null) {
StringWriter buffer = new StringWriter();
transformer.transform(new DOMSource(node), new StreamResult(buffer));
ret.append(buffer.toString().trim());
node = targetNode.getChildNodes().item(index++);
}
return ret.toString();
} catch (Exception e) {
logger.error("Unable to deserialise content data", e);
throw new MalformedXMLResourceException("Unable to deserialise the resource");
}
}
/**
*
* Malformed XML resource exception
*
* @author Manuele Simi (ISTI-CNR)
*
*/
public static class MalformedXMLResourceException extends Exception {
private static final long serialVersionUID = 1L;
public MalformedXMLResourceException(Exception e) {
super(e);
}
public MalformedXMLResourceException(String message) {
super(message);
}
}
/**
* Gets the wrapped {@link BaseDAIXResource}'s content
* @return
* @throws MalformedXMLResourceException
*/
public Document getContent() throws MalformedXMLResourceException {
try {
try {
return resource.getContent();
} catch (Exception e) {
//try to wrap with a root element
StringBuilder resource = new StringBuilder("<Data>\n");
resource.append(this.resource.toString() + "\n");
resource.append("</Data>\n");
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
StringReader reader = new StringReader(resource.toString());
InputSource source = new InputSource(reader);
return builder.parse(source);
}
} catch (Exception e) {
logger.error("Invalid data", e);
throw new MalformedXMLResourceException("Invalid data");
}
}
}