package org.gcube.informationsystem.collector.impl.persistence; import org.gcube.common.core.utils.logging.GCUBELog; import org.gcube.informationsystem.collector.impl.persistence.AggregatorPersistentResource; import org.gcube.informationsystem.collector.impl.xmlstorage.exist.State; import org.xmldb.api.modules.XMLResource; import org.xmldb.api.base.XMLDBException; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.StringReader; import java.util.Calendar; import java.util.GregorianCalendar; import java.util.TimeZone; import java.lang.Exception; import org.w3c.dom.*; import org.xml.sax.InputSource; import javax.xml.parsers.*; import javax.xml.xpath.*; /** * AggregatorPersistentResource represents a resource in the XML Storage * repository * * @author Manuele Simi (ISTI-CNR) * */ public class AggregatorPersistentResource extends PersistentResource { private String resourceID = null; private String resource_string = null; // the resource type states if the resource contains a profile or generic // WS-ResourceProperties private RESOURCETYPE type = null; // the profile type states which kind of profiles the resource contains // (RunningInstance, Service, etc.) private String profile_type = null; // the various parts of the resource private String data, /* service_class, service_id, ri_id, ghn_id, scope, */ entryKey, groupKey, source, sourceKey = "", completeSourceKey = ""; private Calendar terminationTime = null, lastUpdateTime = null; private static GCUBELog logger = new GCUBELog( AggregatorPersistentResource.class); // the source XMLResource (if any) private XMLResource originalSource = null; // the XML DOM loaded from the resource string private Document internalDOM = null; // xpath factory to evaluate Xpath expressions private XPath path = XPathFactory.newInstance().newXPath(); /** * Builds a new empty DISPersinstentresource * */ public AggregatorPersistentResource() { // defatult termination time is now Calendar cal = new GregorianCalendar(); cal.setTimeZone(TimeZone.getTimeZone("GMT")); this.setTerminationTime(cal); lastUpdateTime = new GregorianCalendar(); lastUpdateTime.setTimeZone(TimeZone.getTimeZone("GMT")); } /** * Builds a DISPersinstentresource starting from an eXist resource * * @param resource * the input eXist resource * @throws Exception * if the resource is invalid */ public AggregatorPersistentResource(XMLResource resource) throws Exception { try { this.resourceID = resource.getId(); this.originalSource = resource; this.resource_string = resource.getContent().toString(); this.parseResource(); } catch (XMLDBException dbe) { throw new Exception("invalid resource"); } } /** * Sets the content of the resource * * @param data * the new content * */ public void setData(String data) { this.data = data; } /** * Sets the content of the resource using the content of a file * * @param f * the file to use as content source * * @throws IOException * if the access to the given file fails * */ public void setData(File f) throws IOException { try { FileInputStream fin = new FileInputStream(f); this.data = fin.toString(); } catch (IOException ioe) { System.out.print(State.logPrefix + "unable to set content from file " + f.getAbsolutePath()); throw ioe; } } /** * Accesses the resource content * * @return the content */ public String getData() { return this.data; } /** * * @return the original XMLResource from which the resource has been * generated (if any) */ public XMLResource getOriginalXMLResource() { return this.originalSource; } /** * Accesses the resource ID * * @return the ID */ public String getID() { // create a unique ID unless the resource contains a profile if (this.resourceID == null) this.resourceID = this.getGroupKey() + this.getEntryKey(); return this.resourceID; } /** * 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 */ public String getCompleteSourceKey() { return this.completeSourceKey; } /** * Sets the resource type. The actual implementation supports "Profile" and * "Properties" as type * * @param type * "Profile" or "Properties" */ public void setType(RESOURCETYPE type) { this.type = type; } /** * Accesses the resource type. The actual implementation supports "Profile" * and "Properties" as type * * @return the type */ public RESOURCETYPE getType() { return this.type; } /** * Updates the resource body * * @param data * the new body * */ public void updateData(String data) { this.data = data; } /** * Builds a XML representation of the resource * * @return a String in the form of <Document>... <Data> resource * content </Data> </Document> */ private String toXML() { String rep = "\n"; rep += "" + this.getID() + "\n"; rep += "" + this.getSource() + "\n"; rep += "" + this.getSourceKey() + "\n"; rep += "" + this.getCompleteSourceKey() + "\n"; rep += "" + this.getEntryKey() + "\n"; rep += "" + this.getGroupKey() + "\n"; rep += "" + this.getTerminationTime().getTimeInMillis() + "\n"; rep += "" + this.getTerminationTime().getTime().toString() + "\n"; rep += "" + this.lastUpdateTime.getTimeInMillis() + "\n"; rep += "" + this.lastUpdateTime.getTime().toString() + "\n"; rep += this.getData() + "\n"; rep += "\n"; return rep; } /** * * @return a String representation of the resource */ public String toString() { if (this.resource_string == null) return this.toXML(); else return this.resource_string; } /** * Accesses the type of resource to which the profile is related to (if any) * * @return null if the resource does not contain a profile */ public String getProfileType() { if (this.profile_type != null) { // the profile type has been already extracted return this.profile_type; } if ((this.type != null) && (type == RESOURCETYPE.Profile)) { try { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); StringReader reader = new StringReader(this.toXML()); InputSource source = new InputSource(reader); Document internalDOM = builder.parse(source); // gets the type XPath path = XPathFactory.newInstance().newXPath(); this.profile_type = path .evaluate( "/Document/Data/child::*[local-name()='Profile']/Resource/Type", internalDOM); // uses the DILIGENT ID as resource ID this.resourceID = path .evaluate( "/Document/Data/child::*[local-name()='Profile']/Resource/ID", internalDOM); } catch (Exception e) { logger .error(State.logPrefix + "Unable to extract the profile type from the resource " + e.getMessage()); } } return this.profile_type; } /** * @return the terminationTime of this resource */ public Calendar getTerminationTime() { return terminationTime; } /** * @param terminationTime * the terminationTime to set */ public void setTerminationTime(Calendar terminationTime) { this.terminationTime = (Calendar) terminationTime.clone(); this.terminationTime.setTimeZone(TimeZone.getTimeZone("GMT")); } /** * Compares two resources * * @param o * the resource to compare * @return true if the resources have the same ID */ public boolean equals(Object o) { // check the class this object is instance of if (!(o instanceof AggregatorPersistentResource)) return false; // compare the two objects AggregatorPersistentResource key = (AggregatorPersistentResource) o; if (key.getID() == this.getID()) return true; else return false; } /** * @return the lastUpdateTime in milliseconds * @throws Exception if an error occurs when accessing the LastUpdateMs field */ public long getLastUpdateTimeinMills() throws Exception { if (lastUpdateTime != null) return lastUpdateTime.getTimeInMillis(); if ((lastUpdateTime == null) && (this.internalDOM != null)) { String value = ""; try { value = path.evaluate("Document/LastUpdateMs", this.internalDOM); } catch (XPathExpressionException xpee) { logger.error(State.logPrefix + "" + xpee.getMessage()); logger.error(State.logPrefix + "" + xpee.getStackTrace()); throw new Exception("XPath evaluation error"); } try { return Long.parseLong(value); } catch (NumberFormatException nfe) { logger.error("Invalid last update time format found in resource " + this.getID()); logger.error("Parsed string was " + value); throw new Exception("Unable to retrieve last update time for resource " + this.getID()); } } else throw new Exception("unable to retrieve last update time for resource " + this.getID()); } /** * Loads the XML DOM from the resource string * */ private void parseResource() throws Exception { logger.debug("Parsing resource: " + this.resource_string); DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); StringReader reader = new StringReader(this.resource_string); InputSource source = new InputSource(reader); this.internalDOM = builder.parse(source); } /* * (non-Javadoc) * * @see * org.gcube.informationsystem.collector.impl.persistence.PersistentResource * #getPublisher() */ @Override public String getPublisher() { return null; } /* * (non-Javadoc) * * @see * org.gcube.informationsystem.collector.impl.persistence.PersistentResource * #setPublisher(java.lang.String) */ @Override public void setPublisher(String publisher) { } }