summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Terry2013-07-11 10:36:02 (EDT)
committer David Terry2013-07-11 14:01:59 (EDT)
commitd6dbe27678fad54faa8958967381a38cc87d43f0 (patch)
treede7c69cc56e598ef306d05d1fc03c19a3a5fcbd8
parentef7ebcef9807ac888a5d73866ee6e5cd267f480d (diff)
downloadorg.eclipse.lyo.rio-d6dbe27678fad54faa8958967381a38cc87d43f0.zip
org.eclipse.lyo.rio-d6dbe27678fad54faa8958967381a38cc87d43f0.tar.gz
org.eclipse.lyo.rio-d6dbe27678fad54faa8958967381a38cc87d43f0.tar.bz2
[412773] Persist change log for the TRS reference application refs/changes/75/14475/3
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