Permalink
Browse files

[SM-2108] Added StoreListener interface. Store and StoreFactory are S…

…toreListener aware. Added base implementations for Store and StoreFactory. All implementations now throw the appropriate events. Added some unit test cases inside MemoryStoreTest that test how StoreListener works.

git-svn-id: https://svn.apache.org/repos/asf/servicemix/utils/trunk@1146047 13f79535-47bb-0310-9956-ffa450edef68
  • Loading branch information...
iocanel committed Jul 13, 2011
1 parent 36f0dde commit 31afc6a50c4680b689bc1f310b6f6e4e2fa109a2
View
@@ -163,6 +163,12 @@
<version>4.4</version>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymock</artifactId>
+ <version>3.0</version>
+ <scope>test</scope>
+ </dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
@@ -17,6 +17,8 @@
package org.apache.servicemix.store;
import java.io.IOException;
+import java.util.List;
+import java.util.Set;
/**
* A Store is an interface representing a storage where objects can be
@@ -28,7 +30,7 @@
*
* @author gnodet
*/
-public interface Store {
+public interface Store {
String PERSISTENT = "Persistent";
@@ -83,5 +85,25 @@
* @throws IOException if an error occurs
*/
Object peek(String id) throws IOException;
-
+
+
+
+ /***
+ * Registers a {@link StoreListener}.
+ * @param listener
+ */
+ void addListener(StoreListener listener);
+
+
+ /***
+ * Unregisters a {@link StoreListener}.
+ * @param listener
+ */
+ void removeListener(StoreListener listener);
+
+ /***
+ * Lists all {@link StoreListener}s.
+ */
+ public Set<StoreListener> getStoreListeners();
+
}
@@ -18,10 +18,21 @@
import java.io.IOException;
-public interface StoreFactory {
+public interface StoreFactory {
+ /**
+ * Opens a {@link Store} with the specified name.
+ * @param name
+ * @return
+ * @throws IOException
+ */
Store open(String name) throws IOException;
-
+
+ /**
+ * Closes a {@link Store} with the specified name,
+ * @param store
+ * @throws IOException
+ */
void close(Store store) throws IOException;
}
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.servicemix.store;
+
+/**
+ * A listener interface for {@link Store} implementations.
+ * @author: iocanel
+ */
+public interface StoreListener {
+
+ /**
+ * Method that is called each time an item is added.
+ * @param id
+ * @param data
+ */
+ public void onAdd(String id, Object data);
+
+ /**
+ * Method that is called each time an item is removed.
+ * @param id
+ * @param data
+ */
+ public void onRemove(String id, Object data);
+
+ /**
+ * Method that is called each time an item is evicted.
+ * Please note that not all {@link Store}s support eviction.
+ * @param id
+ * @param data
+ */
+ public void onEvict(String id, Object data);
+}
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.servicemix.store.base;
+
+import org.apache.servicemix.store.Store;
+import org.apache.servicemix.store.StoreListener;
+
+import java.io.Serializable;
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+/**
+ * @author: iocanel
+ */
+public abstract class BaseStore implements Store, Serializable {
+
+ protected final Set<StoreListener> storeListeners = new LinkedHashSet<StoreListener>();
+
+ /**
+ * Notify all registered {@link StoreListener}s that an item has been added.
+ * @param id
+ * @param data
+ */
+ public void fireAddedEvent(String id, Object data) {
+ for(StoreListener listener:storeListeners) {
+ listener.onAdd(id,data);
+ }
+ }
+
+ /**
+ * Notify all registered {@link StoreListener}s that an item has been removed.
+ * @param id
+ * @param data
+ */
+ public void fireRemovedEvent(String id, Object data) {
+ for(StoreListener listener:storeListeners) {
+ listener.onRemove(id, data);
+ }
+ }
+
+ /**
+ * Notify all registered {@link StoreListener}s that an item has been evicted.
+ * @param id
+ * @param data
+ */
+ public void fireEvictedEvent(String id, Object data) {
+ for(StoreListener listener:storeListeners) {
+ listener.onEvict(id, data);
+ }
+ }
+
+ /***
+ * Registers a {@link StoreListener}.
+ * @param listener
+ */
+ public void addListener(StoreListener listener) {
+ storeListeners.add(listener);
+ }
+
+ /***
+ * Unregisters a {@link StoreListener}.
+ * @param listener
+ */
+ public void removeListener(StoreListener listener) {
+ storeListeners.remove(listener);
+ }
+
+ /***
+ * Lists all {@link StoreListener}s.
+ */
+ public Set<StoreListener> getStoreListeners() {
+ return storeListeners;
+ }
+}
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.servicemix.store.base;
+
+import org.apache.servicemix.store.StoreFactory;
+import org.apache.servicemix.store.StoreListener;
+
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+/**
+ * @author: iocanel
+ */
+public abstract class BaseStoreFactory implements StoreFactory {
+
+ protected Set<StoreListener> storeListeners = new LinkedHashSet<StoreListener>();
+
+ public Set<StoreListener> getStoreListeners() {
+ return storeListeners;
+ }
+
+ public void setStoreListeners(Set<StoreListener> storeListeners) {
+ this.storeListeners = storeListeners;
+ }
+}
@@ -21,18 +21,18 @@
import com.hazelcast.core.HazelcastInstance;
import com.hazelcast.core.IdGenerator;
import java.io.IOException;
-import java.io.Serializable;
import java.util.Map;
+
+import org.apache.servicemix.store.base.BaseStore;
import org.apache.servicemix.store.Entry;
-import org.apache.servicemix.store.Store;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
* @author iocanel
*/
-public class HazelcastStore implements Store, Serializable {
+public class HazelcastStore extends BaseStore {
private static final Logger LOG = LoggerFactory.getLogger(HazelcastStore.class);
@@ -106,6 +106,7 @@ public boolean hasFeature(String feature) {
public void store(String id, Object data) throws IOException {
LOG.debug("Storing object with id: " + id);
datas.put(id, new Entry(data));
+ fireAddedEvent(id,data);
}
/**
@@ -138,7 +139,10 @@ public Object load(String id) throws IOException {
evict();
}
Entry entry = datas.remove(id);
- return entry != null ? entry.getData() : null;
+ if(entry != null) {
+ fireRemovedEvent(id,entry.getData());
+ return entry.getData();
+ } else return null;
}
/**
@@ -163,7 +167,12 @@ private void evict() {
long age = now - datas.get(key).getTime();
if (age > timeout) {
LOG.debug("Removing object with id " + key + " from store after " + age + " ms");
+ Entry entry = datas.get(key);
datas.remove(key);
+
+ if(entry != null) {
+ fireEvictedEvent(key,entry.getData());
+ }
}
}
}
@@ -25,13 +25,14 @@
import java.util.Map;
import org.apache.servicemix.store.Store;
-import org.apache.servicemix.store.StoreFactory;
+import org.apache.servicemix.store.StoreListener;
+import org.apache.servicemix.store.base.BaseStoreFactory;
/**
* @author iocanel
*/
-public class HazelcastStoreFactory implements StoreFactory {
+public class HazelcastStoreFactory extends BaseStoreFactory {
private Map<String, HazelcastStore> stores;
@@ -54,6 +55,10 @@ public synchronized Store open(String name) throws IOException {
} else {
store = new HazelcastStore(hazelcastInstance, storeName, timeout);
}
+
+ for(StoreListener listener:storeListeners) {
+ store.addListener(listener);
+ }
stores.put(name, store);
}
return store;
@@ -23,11 +23,11 @@
import java.io.ObjectOutputStream;
import java.sql.Connection;
-import org.apache.servicemix.store.Store;
+import org.apache.servicemix.store.base.BaseStore;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-public class JdbcStore implements Store {
+public class JdbcStore extends BaseStore {
private static final Logger LOG = LoggerFactory.getLogger(JdbcStore.class);
@@ -55,6 +55,7 @@ public void store(String id, Object data) throws IOException {
out.close();
connection = factory.getDataSource().getConnection();
factory.getAdapter().doStoreData(connection, name + ":" + id, buffer.toByteArray());
+ fireAddedEvent(id,data);
} catch (Exception e) {
throw (IOException) new IOException("Error storing object").initCause(e);
} finally {
@@ -79,6 +80,7 @@ public Object load(String id) throws IOException {
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(data));
result = ois.readObject();
factory.getAdapter().doRemoveData(connection, name + ":" + id);
+ fireRemovedEvent(id, data);
}
return result;
} catch (Exception e) {
@@ -29,9 +29,10 @@
import org.apache.servicemix.jdbc.JDBCAdapterFactory;
import org.apache.servicemix.jdbc.Statements;
import org.apache.servicemix.store.Store;
-import org.apache.servicemix.store.StoreFactory;
+import org.apache.servicemix.store.StoreListener;
+import org.apache.servicemix.store.base.BaseStoreFactory;
-public class JdbcStoreFactory implements StoreFactory {
+public class JdbcStoreFactory extends BaseStoreFactory {
private boolean transactional;
private boolean clustered;
@@ -77,6 +78,9 @@ public synchronized Store open(String name) throws IOException {
JdbcStore store = stores.get(name);
if (store == null) {
store = new JdbcStore(this, name);
+ for(StoreListener listener:storeListeners) {
+ store.addListener(listener);
+ }
stores.put(name, store);
}
return store;
Oops, something went wrong.

0 comments on commit 31afc6a

Please sign in to comment.