aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Terry2013-07-11 10:36:02 -0400
committerDavid Terry2013-07-11 14:01:59 -0400
commitd6dbe27678fad54faa8958967381a38cc87d43f0 (patch)
treede7c69cc56e598ef306d05d1fc03c19a3a5fcbd8
parentef7ebcef9807ac888a5d73866ee6e5cd267f480d (diff)
downloadorg.eclipse.lyo.rio-d6dbe27678fad54faa8958967381a38cc87d43f0.zip
org.eclipse.lyo.rio-d6dbe27678fad54faa8958967381a38cc87d43f0.tar.gz
org.eclipse.lyo.rio-d6dbe27678fad54faa8958967381a38cc87d43f0.tar.xz
[412773] Persist change log for the TRS reference application
These changes persist the change events that occur during system operation so that they may be reloaded if the server is restarted. Change-Id: I8762451335e30a20f8b68aadd69ab55ee07aee69 Signed-off-by: David Terry <dgterry@us.ibm.com>
-rw-r--r--org.eclipse.lyo.rio.trs/src/main/java/org/eclipse/lyo/rio/trs/util/ConfigUtil.java48
-rw-r--r--org.eclipse.lyo.rio.trs/src/main/java/org/eclipse/lyo/rio/trs/util/FileUtil.java80
-rw-r--r--org.eclipse.lyo.rio.trs/src/main/java/org/eclipse/lyo/rio/trs/util/TRSObject.java123
-rw-r--r--org.eclipse.lyo.rio.trs/src/main/java/org/eclipse/lyo/rio/trs/util/TRSUtil.java2
-rw-r--r--org.eclipse.lyo.rio.trs/src/main/resources/config.properties4
5 files changed, 250 insertions, 7 deletions
diff --git a/org.eclipse.lyo.rio.trs/src/main/java/org/eclipse/lyo/rio/trs/util/ConfigUtil.java b/org.eclipse.lyo.rio.trs/src/main/java/org/eclipse/lyo/rio/trs/util/ConfigUtil.java
new file mode 100644
index 0000000..d31c089
--- /dev/null
+++ b/org.eclipse.lyo.rio.trs/src/main/java/org/eclipse/lyo/rio/trs/util/ConfigUtil.java
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * Copyright (c) 2013 IBM Corporation.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v. 1.0 which accompanies this distribution.
+ *
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *
+ * Ernest Mah - Initial implementation
+ *******************************************************************************/
+
+package org.eclipse.lyo.rio.trs.util;
+
+import java.io.IOException;
+import java.util.Properties;
+
+public class ConfigUtil {
+ private static final String CONFIG_PROPERTIES = "config.properties";
+
+ private static Properties prop = null;
+
+ /**
+ * This method returns the list of properties found in the config.properties
+ * file. This file provides a mechanism for users to control the operation
+ * of the reference application.
+ */
+ public static Properties getPropertiesInstance()
+ {
+ if (prop == null) {
+ prop = new Properties();
+
+ try {
+ prop.load(ConfigUtil.class.getClassLoader().getResourceAsStream(CONFIG_PROPERTIES));
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ throw new IllegalStateException();
+ }
+ }
+
+ return prop;
+ }
+}
diff --git a/org.eclipse.lyo.rio.trs/src/main/java/org/eclipse/lyo/rio/trs/util/FileUtil.java b/org.eclipse.lyo.rio.trs/src/main/java/org/eclipse/lyo/rio/trs/util/FileUtil.java
new file mode 100644
index 0000000..1e42728
--- /dev/null
+++ b/org.eclipse.lyo.rio.trs/src/main/java/org/eclipse/lyo/rio/trs/util/FileUtil.java
@@ -0,0 +1,80 @@
+/*******************************************************************************
+ * Copyright (c) 2013 IBM Corporation.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v. 1.0 which accompanies this distribution.
+ *
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *
+ * Ernest Mah - Initial implementation
+ *******************************************************************************/
+
+package org.eclipse.lyo.rio.trs.util;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.lang.reflect.InvocationTargetException;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import javax.ws.rs.WebApplicationException;
+import javax.xml.datatype.DatatypeConfigurationException;
+
+import org.eclipse.lyo.core.utils.marshallers.OSLC4JContext;
+import org.eclipse.lyo.core.utils.marshallers.OSLC4JMarshaller;
+import org.eclipse.lyo.oslc4j.core.exception.OslcCoreApplicationException;
+import org.eclipse.lyo.oslc4j.provider.jena.JenaModelHelper;
+
+import com.hp.hpl.jena.rdf.model.Model;
+import com.hp.hpl.jena.util.FileManager;
+
+
+public class FileUtil {
+
+ public static Object[] fileload(final String fileName, List<Class<?>> objectTypes)
+ throws DatatypeConfigurationException, FileNotFoundException,
+ IllegalAccessException, IllegalArgumentException,
+ InstantiationException, InvocationTargetException,
+ OslcCoreApplicationException, URISyntaxException,
+ SecurityException, NoSuchMethodException {
+
+ final File file = new File(fileName);
+
+ if ((file.exists()) && (file.isFile()) && (file.canRead())) {
+ final Model model = FileManager.get().loadModel(fileName);
+
+ ArrayList<Object> objects = new ArrayList<Object>();
+
+ for (Class<?> objectType : objectTypes) {
+ Object[] objectResources = JenaModelHelper.fromJenaModel(model,
+ objectType);
+ objects.addAll(Arrays.asList(objectResources));
+ }
+
+ return objects.toArray();
+ }
+
+ return null;
+ }
+
+ public static void save(Object[] objects, final String fileName) {
+
+ OSLC4JContext context = OSLC4JContext.newInstance();
+ OSLC4JMarshaller marshaller = context.createMarshaller();
+ try {
+ marshaller.marshal(objects, new FileOutputStream(fileName));
+ } catch (WebApplicationException e) {
+ e.printStackTrace();
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/org.eclipse.lyo.rio.trs/src/main/java/org/eclipse/lyo/rio/trs/util/TRSObject.java b/org.eclipse.lyo.rio.trs/src/main/java/org/eclipse/lyo/rio/trs/util/TRSObject.java
index d8524a0..30f063f 100644
--- a/org.eclipse.lyo.rio.trs/src/main/java/org/eclipse/lyo/rio/trs/util/TRSObject.java
+++ b/org.eclipse.lyo.rio.trs/src/main/java/org/eclipse/lyo/rio/trs/util/TRSObject.java
@@ -17,13 +17,22 @@
package org.eclipse.lyo.rio.trs.util;
+import java.io.FileNotFoundException;
+import java.lang.reflect.InvocationTargetException;
import java.net.URI;
import java.net.URISyntaxException;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
+import java.util.Date;
import java.util.List;
+import java.util.NavigableSet;
import java.util.TreeMap;
+import javax.xml.datatype.DatatypeConfigurationException;
+
import org.eclipse.lyo.core.trs.AbstractChangeLog;
import org.eclipse.lyo.core.trs.Base;
import org.eclipse.lyo.core.trs.ChangeEvent;
@@ -34,6 +43,7 @@ import org.eclipse.lyo.core.trs.EmptyChangeLog;
import org.eclipse.lyo.core.trs.Modification;
import org.eclipse.lyo.core.trs.Page;
import org.eclipse.lyo.core.trs.TRSConstants;
+import org.eclipse.lyo.oslc4j.core.exception.OslcCoreApplicationException;
import org.eclipse.lyo.oslc4j.core.model.AbstractResource;
/**
@@ -53,6 +63,8 @@ public class TRSObject {
private final TreeMap<Long, Base> trs_base_map = new TreeMap<Long, Base>();
private final TreeMap<Long, ChangeLog> trs_changelog_map = new TreeMap<Long, ChangeLog>();
+ private final List<ChangeEvent> change_events = new ArrayList<ChangeEvent>();
+
private URI trs_uri = null;
private int trs_curr_changelog_size = 0;
private Long trs_curr_changelog_page = -1L;
@@ -63,15 +75,26 @@ public class TRSObject {
public boolean trs_base_initialized = false;
private IResourceUtil resourceUtil;
private int PAGE_SIZE = 3;
+ private long MILLISECONDS_IN_DAY = 86400000;
+ private static String URN_PREFIX = "urn:urn-3:cm1.example.com:";
+
+ String changeEventsFilename = null;
/**
- * @param resourceUtil - IResourceUtil object capable of return an array of all the resources known to the
- * server to prime the Base resources.
- * @param trs_uri - uri root for where the trs endpoints begin. This is used for setting the urls for references
- * to other resources in the TRS feed.
+ * @param resourceUtil
+ * IResourceUtil object capable of return an array of all the
+ * resources known to the server to prime the Base resources.
+ * @param trs_uri
+ * uri root for where the trs endpoints begin. This is used for
+ * setting the urls for references to other resources in the TRS
+ * feed.
+ * @param changeEventsFilename
+ * An absolute path to a file on disk containing the persisted
+ * change log.
*/
- public TRSObject(IResourceUtil resourceUtil, URI trs_uri) {
+ public TRSObject(IResourceUtil resourceUtil, URI trs_uri, String changeEventsFilename) {
super();
+ this.changeEventsFilename = changeEventsFilename;
this.resourceUtil = resourceUtil;
this.trs_uri = trs_uri;
initialize();
@@ -132,6 +155,61 @@ public class TRSObject {
}
}
}
+ loadChangeEvents();
+ }
+
+ /**
+ * Loads change events from the config.properties' ChangeEventsFile
+ * file into the change log when the TRSObject is initialized.
+ * It should be noted that this method will prune the change log if it is
+ * greater than x days old (configurable via the PruneTimeInDays
+ * config.properties parameter).
+ */
+ private void loadChangeEvents() {
+ Object[] changeEvents;
+ try {
+ Class<?> [] objectTypes = {Creation.class, Modification.class, Deletion.class};
+ changeEvents = FileUtil.fileload(this.changeEventsFilename, Arrays.asList(objectTypes));
+
+ TreeMap <Integer, ChangeEvent> sortedTree = new TreeMap <Integer, ChangeEvent>();
+
+ if (changeEvents != null) {
+ boolean pruned = false;
+
+ // Loop over all change events we found on disk and put them in
+ // the treemap sorted by order. Prune events greater than
+ // PruneTimeInDays (found in config.properties).
+ for (int i = 0; i < changeEvents.length; i++) {
+ ChangeEvent changeEvent = (ChangeEvent) changeEvents[i];
+
+ if (isPrunningNecessary(changeEvent.getAbout())) {
+ pruned = true;
+ continue;
+ }
+
+ sortedTree.put(changeEvent.getOrder(), changeEvent);
+ }
+
+ NavigableSet<Integer> keys = sortedTree.navigableKeySet();
+
+ // Insert the sorted in-memory change events into the log
+ for (int key : keys) {
+ ChangeEvent changeEvent = sortedTree.get(key);
+ insertEventToPagedChangeLog(changeEvent, changeEvent.getChanged());
+ }
+
+ change_events.addAll(sortedTree.values());
+
+ // If pruning took place persist the new list of change events
+ // to disk so we don't have to prune them again.
+ if (pruned) {
+ FileUtil.save(change_events.toArray(), this.changeEventsFilename);
+ }
+ }
+ } catch (Exception e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
}
/**
@@ -198,8 +276,10 @@ public class TRSObject {
eventNumber);
}
+ change_events.add(event);
+ FileUtil.save(change_events.toArray(), this.changeEventsFilename);
+
insertEventToPagedChangeLog(event, resource);
-
}
/**
@@ -418,4 +498,35 @@ public class TRSObject {
}
}
}
+
+ /**
+ * Compares the time portion of the change event's URN value with the current
+ * time. If the time is older than PruneTimeInDays (see setting in
+ * config.properties) then the event is not included in the current change log.
+ *
+ * @param urn
+ * @return
+ * @throws ParseException
+ */
+ private boolean isPrunningNecessary(URI urn) throws ParseException {
+ // Get the time of the event in milliseconds
+ String urnWithTime = urn.toString();
+ String eventTime = urnWithTime.split(URN_PREFIX)[1];
+
+ SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-ddHH:mm:ss.SS");
+ Date eventDate = formatter.parse(eventTime);
+ long eventMilliseconds = eventDate.getTime();
+
+ // Calculate the pruneTime
+ String numDays = ConfigUtil.getPropertiesInstance().getProperty("PruneTimeInDays");
+ long pruneTime = System.currentTimeMillis() - (Integer.parseInt(numDays) * MILLISECONDS_IN_DAY);
+
+ // If an event is older than the prune time (less time since the epoch
+ // has elapsed) indicate we need to prune this event.
+ if (pruneTime >= eventMilliseconds) {
+ return true;
+ }
+
+ return false;
+ }
}
diff --git a/org.eclipse.lyo.rio.trs/src/main/java/org/eclipse/lyo/rio/trs/util/TRSUtil.java b/org.eclipse.lyo.rio.trs/src/main/java/org/eclipse/lyo/rio/trs/util/TRSUtil.java
index 4c185fe..a0fcc97 100644
--- a/org.eclipse.lyo.rio.trs/src/main/java/org/eclipse/lyo/rio/trs/util/TRSUtil.java
+++ b/org.eclipse.lyo.rio.trs/src/main/java/org/eclipse/lyo/rio/trs/util/TRSUtil.java
@@ -101,7 +101,7 @@ public class TRSUtil {
else{
trs_Uri = resource.resolve("/" + sContext + TRS_URI_PATH2);
}
- innerHelpr[i] = new TRSObject(resourceUtil, trs_Uri);
+ innerHelpr[i] = new TRSObject(resourceUtil, trs_Uri, ConfigUtil.getPropertiesInstance().getProperty("ChangeEventsFile"));
}
}
}
diff --git a/org.eclipse.lyo.rio.trs/src/main/resources/config.properties b/org.eclipse.lyo.rio.trs/src/main/resources/config.properties
new file mode 100644
index 0000000..471c283
--- /dev/null
+++ b/org.eclipse.lyo.rio.trs/src/main/resources/config.properties
@@ -0,0 +1,4 @@
+# Change events in the ChangeLogFile older than this number of days will be removed at startup
+PruneTimeInDays = 7
+# The file on disk where change events will be stored
+ChangeEventsFile=C:/temp/changeEvents.xml \ No newline at end of file