Author: echatellier Date: 2010-06-04 12:43:55 +0200 (Fri, 04 Jun 2010) New Revision: 91 Url: http://nuiton.org/repositories/revision/wikitty/91 Log: Modify cache listener into wikitty service listener. Cache is now a wikitty service listener. Add options to not use jgroups synchronisation. Added: trunk/wikitty-api/src/main/java/org/nuiton/wikitty/JGroupsNotifier.java trunk/wikitty-api/src/main/java/org/nuiton/wikitty/WikittyServiceEvent.java trunk/wikitty-api/src/main/java/org/nuiton/wikitty/WikittyServiceListener.java trunk/wikitty-api/src/main/java/org/nuiton/wikitty/WikittyServiceNotifier.java Removed: trunk/wikitty-api/src/main/java/org/nuiton/wikitty/JGroupsCacheNotifier.java Modified: trunk/wikitty-api/src/main/java/org/nuiton/wikitty/WikittyCache.java trunk/wikitty-api/src/main/java/org/nuiton/wikitty/WikittyService.java trunk/wikitty-api/src/main/java/org/nuiton/wikitty/WikittyServiceCached.java trunk/wikitty-api/src/main/java/org/nuiton/wikitty/WikittyServiceImpl.java Deleted: trunk/wikitty-api/src/main/java/org/nuiton/wikitty/JGroupsCacheNotifier.java =================================================================== --- trunk/wikitty-api/src/main/java/org/nuiton/wikitty/JGroupsCacheNotifier.java 2010-06-02 19:12:32 UTC (rev 90) +++ trunk/wikitty-api/src/main/java/org/nuiton/wikitty/JGroupsCacheNotifier.java 2010-06-04 10:43:55 UTC (rev 91) @@ -1,253 +0,0 @@ -/* *##% - * Copyright (C) 2010 Code Lutin, Chatellier Eric - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - *##%*/ - -package org.nuiton.wikitty; - -import java.io.Serializable; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.jgroups.Channel; -import org.jgroups.ChannelClosedException; -import org.jgroups.ChannelException; -import org.jgroups.ChannelNotConnectedException; -import org.jgroups.JChannel; -import org.jgroups.Message; -import org.jgroups.ReceiverAdapter; -import org.nuiton.wikitty.WikittyCache.WikittyCacheListener; - -/** - * JGroups notifier. - * - * @author chatellier - * @version $Revision$ - * - * Last update : $Date$ - * By : $Author$ - */ -public class JGroupsCacheNotifier extends ReceiverAdapter implements WikittyCacheListener { - - /** to use log facility, just put in your code: log.info(\"...\"); */ - static private Log log = LogFactory.getLog(JGroupsCacheNotifier.class); - - /** Cache reference. */ - protected WikittyCache cache; - - /** Message type (put, remove, clear...). */ - static enum WikittyJGroupType { - PUT_WIKITTY, - REMOVE_WIKITTY, - CLEAR_WIKITTY, - PUT_EXTENSION, - REMOVE_EXTENSION, - CLEAR_EXTENSION - } - - static class WikittyJGroupMessage implements Serializable { - /** serialVersionUID. */ - private static final long serialVersionUID = 1914969328584238081L; - - public WikittyJGroupType type; - public String wikittyId; - public String wikittyVersion; - - private WikittyJGroupMessage(WikittyJGroupType type, String wikittyId, String wikittyVersion) { - this.type = type; - this.wikittyId = wikittyId; - this.wikittyVersion = wikittyVersion; - } - - public String toString() { - String toString = type + " " + wikittyId + "[" + wikittyVersion + "]"; - return toString; - } - } - - /** - * Indique si les objects sont propages (true) vers les autres caches ou - * simplement supprimes des autres caches (false). - * - * @see WikittyServiceCached#WIKITTY_PROPAGATE_CACHE_OPTION - */ - protected boolean propagateCache = false; - - /** JGroup channel. */ - protected JChannel channel; - - public JGroupsCacheNotifier(WikittyCache cache, boolean propagateCache) { - this.cache = cache; - this.propagateCache = propagateCache; - initChannel(); - } - - /** - * Init jgroup channel. - */ - protected void initChannel() { - if (log.isDebugEnabled()) { - log.debug("Init jgroup communication channel..."); - } - - try { - // use default udp.xml in classpath - channel = new JChannel(); - channel.connect("wikitty"); - channel.setReceiver(this); - - // don't receive messages sent by myself - channel.setOpt(Channel.LOCAL, false); - - if (log.isDebugEnabled()) { - log.debug("JGroup communication channel initialized to " + channel.getAddressAsString()); - } - } - catch (ChannelException eee) { - if (log.isErrorEnabled()) { - log.error("Can't init jgroup channel"); - } - } - } - - /** - * Send a jgroup message to all other channel member. - * - * @param wikittyMessage message to send - */ - protected void sendJGroupMessage(WikittyJGroupMessage wikittyMessage) { - if (log.isInfoEnabled()) { - log.info("Send message : " + wikittyMessage); - } - Message msg = new Message(null, null, wikittyMessage); - try { - channel.send(msg); - } catch (ChannelNotConnectedException eee) { - if (log.isErrorEnabled()) { - log.error("Can't send jgroup message", eee); - } - } catch (ChannelClosedException eee) { - if (log.isErrorEnabled()) { - log.error("Can't send jgroup message", eee); - } - } - } - - /* - * @see org.nuiton.wikitty.WikittyCache.WikittyCacheListener#putWikitty(org.nuiton.wikitty.Wikitty[]) - */ - @Override - public void putWikitty(Wikitty... ws) { - if (propagateCache) { - // TODO EC20100602 maybe send only one message for all wikitties - for (Wikitty wikitty : ws) { - WikittyJGroupMessage wikittyMessage = new WikittyJGroupMessage( - WikittyJGroupType.PUT_WIKITTY, wikitty.getId(), wikitty.getVersion()); - sendJGroupMessage(wikittyMessage); - } - } - } - - /* - * @see org.nuiton.wikitty.WikittyCache.WikittyCacheListener#removeWikitty(java.lang.String[]) - */ - @Override - public void removeWikitty(String... ids) { - if (propagateCache) { - // TODO EC20100602 maybe send only one message for all wikitties - for (String id : ids) { - WikittyJGroupMessage wikittyMessage = new WikittyJGroupMessage( - WikittyJGroupType.REMOVE_WIKITTY, id, null); - sendJGroupMessage(wikittyMessage); - } - } - } - - /* - * @see org.nuiton.wikitty.WikittyCache.WikittyCacheListener#clearWikitty() - */ - @Override - public void clearWikitty() { - if (propagateCache) { - WikittyJGroupMessage wikittyMessage = new WikittyJGroupMessage( - WikittyJGroupType.CLEAR_WIKITTY, null, null); - sendJGroupMessage(wikittyMessage); - } - } - - /* - * @see org.nuiton.wikitty.WikittyCache.WikittyCacheListener#putExtension(org.nuiton.wikitty.WikittyExtension[]) - */ - @Override - public void putExtension(WikittyExtension... es) { - - } - - /* - * @see org.nuiton.wikitty.WikittyCache.WikittyCacheListener#removeExtension(java.lang.String[]) - */ - @Override - public void removeExtension(String... ids) { - - } - - /* - * @see org.nuiton.wikitty.WikittyCache.WikittyCacheListener#clearExtension() - */ - @Override - public void clearExtension() { - - } - - /* - * @see org.jgroups.ReceiverAdapter#receive(org.jgroups.Message) - */ - @Override - public void receive(Message msg) { - - Object message = msg.getObject(); - - if (log.isInfoEnabled()) { - log.info("Receive message : " + msg.getObject()); - } - - if (message instanceof WikittyJGroupMessage) { - WikittyJGroupMessage wikittyMessage = (WikittyJGroupMessage)message; - - switch(wikittyMessage.type) { - case PUT_WIKITTY: - // put on server, remove it from local cache - Wikitty currentWikitty = cache.getWikitty(wikittyMessage.wikittyId); - if (currentWikitty != null - && WikittyUtil.versionGreaterThan(wikittyMessage.wikittyVersion, currentWikitty.getVersion())) { - cache.removeWikitty(wikittyMessage.wikittyId); - } - - break; - case REMOVE_WIKITTY: - cache.removeWikitty(wikittyMessage.wikittyId); - break; - case CLEAR_WIKITTY: - cache.clearWikitty(); - break; - default: - if (log.isDebugEnabled()) { - log.debug("Not managed jgroup message " + wikittyMessage.type); - } - } - } - } -} Copied: trunk/wikitty-api/src/main/java/org/nuiton/wikitty/JGroupsNotifier.java (from rev 90, trunk/wikitty-api/src/main/java/org/nuiton/wikitty/JGroupsCacheNotifier.java) =================================================================== --- trunk/wikitty-api/src/main/java/org/nuiton/wikitty/JGroupsNotifier.java (rev 0) +++ trunk/wikitty-api/src/main/java/org/nuiton/wikitty/JGroupsNotifier.java 2010-06-04 10:43:55 UTC (rev 91) @@ -0,0 +1,277 @@ +/* *##% + * Copyright (C) 2010 Code Lutin, Chatellier Eric + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + *##%*/ + +package org.nuiton.wikitty; + +import java.io.Serializable; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.jgroups.Channel; +import org.jgroups.ChannelClosedException; +import org.jgroups.ChannelException; +import org.jgroups.ChannelNotConnectedException; +import org.jgroups.JChannel; +import org.jgroups.Message; +import org.jgroups.ReceiverAdapter; + +/** + * JGroups notifier. + * + * @author chatellier + * @version $Revision$ + * + * Last update : $Date$ + * By : $Author$ + */ +public class JGroupsNotifier extends ReceiverAdapter implements WikittyServiceListener { + + /** to use log facility, just put in your code: log.info(\"...\"); */ + static private Log log = LogFactory.getLog(JGroupsNotifier.class); + + /** Notifier service reference reference. */ + protected WikittyServiceNotifier ws; + + /** Message type (put, remove, clear...). */ + static enum WikittyJGroupType { + PUT_WIKITTY, + REMOVE_WIKITTY, + CLEAR_WIKITTY, + PUT_EXTENSION, + REMOVE_EXTENSION, + CLEAR_EXTENSION + } + + static class WikittyJGroupMessage implements Serializable { + /** serialVersionUID. */ + private static final long serialVersionUID = 1914969328584238081L; + + public WikittyJGroupType type; + public WikittyServiceEvent event; + + private WikittyJGroupMessage(WikittyJGroupType type, WikittyServiceEvent event) { + this.type = type; + this.event = event; + } + + public String toString() { + String toString = type + " " + event; + return toString; + } + } + + /** + * Indique si les objects sont propages (true) vers les autres caches ou + * simplement supprimes des autres caches (false). + * + * @see WikittyServiceCached#WIKITTY_PROPAGATE_CACHE_OPTION + */ + protected boolean propagateCache = false; + + /** JGroup channel. */ + protected JChannel channel; + + public JGroupsNotifier(WikittyServiceNotifier ws, boolean propagateCache) { + this.ws = ws; + this.propagateCache = propagateCache; + initChannel(); + } + + /** + * Init jgroup channel. + */ + protected void initChannel() { + if (log.isDebugEnabled()) { + log.debug("Init jgroup communication channel..."); + } + + try { + // use default udp.xml in classpath + channel = new JChannel(); + channel.connect("wikitty"); + channel.setReceiver(this); + + // don't receive messages sent by myself + channel.setOpt(Channel.LOCAL, false); + + if (log.isDebugEnabled()) { + log.debug("JGroup communication channel initialized to " + channel.getAddressAsString()); + } + } + catch (ChannelException eee) { + if (log.isErrorEnabled()) { + log.error("Can't init jgroup channel"); + } + } + } + + /** + * Send a jgroup message to all other channel member. + * + * @param wikittyMessage message to send + */ + protected void sendJGroupMessage(WikittyJGroupMessage wikittyMessage) { + if (log.isInfoEnabled()) { + log.info("Send message : " + wikittyMessage); + } + Message msg = new Message(null, null, wikittyMessage); + try { + channel.send(msg); + } catch (ChannelNotConnectedException eee) { + if (log.isErrorEnabled()) { + log.error("Can't send jgroup message", eee); + } + } catch (ChannelClosedException eee) { + if (log.isErrorEnabled()) { + log.error("Can't send jgroup message", eee); + } + } + } + + /* + * @see org.jgroups.ReceiverAdapter#receive(org.jgroups.Message) + */ + @Override + public void receive(Message msg) { + + Object message = msg.getObject(); + + if (log.isInfoEnabled()) { + log.info("Receive message : " + msg.getObject()); + } + + if (message instanceof WikittyJGroupMessage) { + WikittyJGroupMessage wikittyMessage = (WikittyJGroupMessage)message; + WikittyJGroupType type = wikittyMessage.type; + WikittyServiceEvent event = wikittyMessage.event; + + //source is transient, add it here : + event.setSource(ws); + event.setRemote(true); // received event became remote + + switch(type) { + case PUT_WIKITTY: + ws.firePutWikitty(event); break; + case REMOVE_WIKITTY: + ws.fireRemoveWikitty(event); break; + case CLEAR_WIKITTY: + ws.fireClearWikitty(event); break; + /*case PUT_EXTENSION: + ws.firePutExtension(event); break; + case REMOVE_EXTENSION: + ws.firePutExtension(event); break; + case CLEAR_EXTENSION: + ws.firePutExtension(event); break;*/ + default: + if (log.isDebugEnabled()) { + log.debug("Not managed jgroup message " + wikittyMessage.type); + } + } + } + } + + /* + * @see org.nuiton.wikitty.WikittyServiceListener#putWikitty(org.nuiton.wikitty.Wikitty[]) + */ + @Override + public void putWikitty(WikittyServiceEvent event) { + if (propagateCache) { + sendJGroupMessage(new WikittyJGroupMessage(WikittyJGroupType.PUT_WIKITTY, event)); + } + else { + if (log.isDebugEnabled()) { + log.debug("Put wikitty event skipped"); + } + } + } + + /* + * @see org.nuiton.wikitty.WikittyServiceListener#removeWikitty(java.lang.String[]) + */ + @Override + public void removeWikitty(WikittyServiceEvent event) { + if (propagateCache) { + sendJGroupMessage(new WikittyJGroupMessage(WikittyJGroupType.REMOVE_WIKITTY, event)); + } + else { + if (log.isDebugEnabled()) { + log.debug("Remove wikitty event skipped"); + } + } + } + + /* + * @see org.nuiton.wikitty.WikittyServiceListener#clearWikitty() + */ + @Override + public void clearWikitty(WikittyServiceEvent event) { + if (propagateCache) { + sendJGroupMessage(new WikittyJGroupMessage(WikittyJGroupType.CLEAR_WIKITTY, event)); + } + else { + if (log.isDebugEnabled()) { + log.debug("Clear wikitty event skipped"); + } + } + } + + /* + * @see org.nuiton.wikitty.WikittyServiceListener#putExtension(org.nuiton.wikitty.WikittyExtension[]) + */ + @Override + public void putExtension(WikittyServiceEvent event) { + if (propagateCache) { + sendJGroupMessage(new WikittyJGroupMessage(WikittyJGroupType.PUT_EXTENSION, event)); + } + else { + if (log.isDebugEnabled()) { + log.debug("Put extension event skipped"); + } + } + } + + /* + * @see org.nuiton.wikitty.WikittyServiceListener#removeExtension(java.lang.String[]) + */ + @Override + public void removeExtension(WikittyServiceEvent event) { + if (propagateCache) { + sendJGroupMessage(new WikittyJGroupMessage(WikittyJGroupType.REMOVE_EXTENSION, event)); + } + else { + if (log.isDebugEnabled()) { + log.debug("Remove extension event skipped"); + } + } + } + + /* + * @see org.nuiton.wikitty.WikittyServiceListener#clearExtension() + */ + @Override + public void clearExtension(WikittyServiceEvent event) { + if (propagateCache) { + sendJGroupMessage(new WikittyJGroupMessage(WikittyJGroupType.CLEAR_EXTENSION, event)); + } + else { + if (log.isDebugEnabled()) { + log.debug("Clear extension event skipped"); + } + } + } +} Modified: trunk/wikitty-api/src/main/java/org/nuiton/wikitty/WikittyCache.java =================================================================== --- trunk/wikitty-api/src/main/java/org/nuiton/wikitty/WikittyCache.java 2010-06-02 19:12:32 UTC (rev 90) +++ trunk/wikitty-api/src/main/java/org/nuiton/wikitty/WikittyCache.java 2010-06-04 10:43:55 UTC (rev 91) @@ -18,14 +18,9 @@ package org.nuiton.wikitty; import java.util.Collection; -import java.util.HashSet; import java.util.Map; -import java.util.Properties; -import java.util.Set; import org.apache.commons.collections.map.ReferenceMap; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; /** * Cette classe sert a introduire du cache dans wikitty. Elle sert a centraliser @@ -38,92 +33,24 @@ * Last update: $Date$ * by : $Author$ */ -public class WikittyCache { +public class WikittyCache implements WikittyServiceListener { - /** to use log facility, just put in your code: log.info(\"...\"); */ - static private Log log = LogFactory.getLog(WikittyCache.class); - - public static interface WikittyCacheListener { - public void putWikitty(Wikitty ... ws); - public void removeWikitty(String ... ids); - public void clearWikitty(); - - public void putExtension(WikittyExtension ... es); - public void removeExtension(String ... ids); - public void clearExtension(); - } - + /** Singleton wikitty cache instance. */ static protected WikittyCache instance = null; - /** - * indique si les objects sont propages (true) vers les autres caches ou - * simplement supprimes des autres caches (false). - * - * @see WikittyServiceCached#WIKITTY_PROPAGATE_CACHE_OPTION - */ - protected boolean propagateCache = false; - protected Map<String, Wikitty> wikittyCache; - protected Set<WikittyCacheListener> listeners; - - protected WikittyCache(Properties props) { - - // get propagate cache property - String propagateCacheOption = props.getProperty(WikittyServiceCached.WIKITTY_PROPAGATE_CACHE_OPTION, "false"); - propagateCache = "true".equalsIgnoreCase(propagateCacheOption); - if (log.isDebugEnabled()) { - log.debug("Set propagateCache option to " + propagateCache); - } - + protected WikittyCache() { wikittyCache = new ReferenceMap(ReferenceMap.HARD, ReferenceMap.SOFT); - listeners = new HashSet<WikittyCacheListener>(); - addListener(new JGroupsCacheNotifier(this, propagateCache)); - } - public static synchronized WikittyCache getInstance(Properties props) { + public static synchronized WikittyCache getInstance() { if (instance == null) { - instance = new WikittyCache(props); + instance = new WikittyCache(); } return instance; } - /** - * Notifie les autres caches d'une action: ajout, mise a jour - * - * @param w - */ - // FIXME poussin 20100520 send message to other cache - protected void firePutWikitty(Wikitty ... ws) { - WikittyCacheListener[] ls = - listeners.toArray(new WikittyCacheListener[listeners.size()]); - for (WikittyCacheListener l : ls) { - l.putWikitty(ws); - } - } - - /** - * Notifie les autres caches d'une action: suppression - * - * @param w - */ - protected void fireRemoveWikitty(String ... ids) { - WikittyCacheListener[] ls = - listeners.toArray(new WikittyCacheListener[listeners.size()]); - for (WikittyCacheListener l : ls) { - l.removeWikitty(ids); - } - } - - protected void fireClearWikitty() { - WikittyCacheListener[] ls = - listeners.toArray(new WikittyCacheListener[listeners.size()]); - for (WikittyCacheListener l : ls) { - l.clearWikitty(); - } - } - public boolean existsWikitty(String id) { Object o = wikittyCache.get(id); boolean result = (o != null); @@ -131,7 +58,8 @@ } /** - * Return wikitty object if is in the cache, null otherwize + * Return wikitty object if is in the cache, null otherwize. + * * @param id * @return wikitty object or null */ @@ -150,50 +78,106 @@ if (old == null || WikittyUtil.versionGreaterThan(e.getVersion(), old.getVersion())) { wikittyCache.put(e.getId(), e); - firePutWikitty(e); } } /** * batched put - * @param e + * @param all */ public void putAllWikitty(Collection<Wikitty> all) { for (Wikitty w : all) { - wikittyCache.put(w.getId(), w); + putWikitty(w); } - firePutWikitty(all.toArray(new Wikitty[all.size()])); } + /** + * Remove wikitty from cache. + * + * @param id wikitty id to remove + */ public void removeWikitty(String id) { wikittyCache.remove(id); - fireRemoveWikitty(id); } /** - * clear all wikitty objet in cache + * batched remove + * @param ids */ + public void removeAllWikitty(Collection<String> ids) { + for (String id : ids) { + removeWikitty(id); + } + } + + /** + * Clear all cache. + */ public void clearWikitty() { wikittyCache.clear(); - fireClearWikitty(); } - /** - * batched remove - * @param ids + /* + * @see org.nuiton.wikitty.WikittyServiceListener#clearWikitty() */ - public void removeAllWikitty(Collection<String> ids) { + @Override + public void clearWikitty(WikittyServiceEvent event) { + clearWikitty(); + } + + /* + * @see org.nuiton.wikitty.WikittyServiceListener#putWikitty(org.nuiton.wikitty.Wikitty[]) + */ + @Override + public void putWikitty(WikittyServiceEvent event) { + + Collection<String> ids = event.getIds(); + Map<String, String> idsVersions = event.getIdVersions(); + for (String id : ids) { - wikittyCache.remove(id); + // put on server, remove it from local cache + Wikitty currentWikitty = getWikitty(id); + if (currentWikitty != null) { + String version = idsVersions.get(id); + if (WikittyUtil.versionGreaterThan(version, currentWikitty.getVersion())) { + removeWikitty(id); + } + } } - fireRemoveWikitty(ids.toArray(new String[ids.size()])); + } - public void addListener(WikittyCacheListener l) { - listeners.add(l); + /* + * @see org.nuiton.wikitty.WikittyServiceListener#removeWikitty(java.lang.String[]) + */ + @Override + public void removeWikitty(WikittyServiceEvent event) { + for (String id : event.getIds()) { + removeWikitty(id); + } } - public void removeListener(WikittyCacheListener l) { - listeners.remove(l); + /* + * @see org.nuiton.wikitty.WikittyServiceListener#putExtension(org.nuiton.wikitty.WikittyExtension[]) + */ + @Override + public void putExtension(WikittyServiceEvent event) { + } + + /* + * @see org.nuiton.wikitty.WikittyServiceListener#removeExtension(java.lang.String[]) + */ + @Override + public void removeExtension(WikittyServiceEvent event) { + + } + + /* + * @see org.nuiton.wikitty.WikittyServiceListener#clearExtension() + */ + @Override + public void clearExtension(WikittyServiceEvent event) { + + } } Modified: trunk/wikitty-api/src/main/java/org/nuiton/wikitty/WikittyService.java =================================================================== --- trunk/wikitty-api/src/main/java/org/nuiton/wikitty/WikittyService.java 2010-06-02 19:12:32 UTC (rev 90) +++ trunk/wikitty-api/src/main/java/org/nuiton/wikitty/WikittyService.java 2010-06-04 10:43:55 UTC (rev 91) @@ -23,7 +23,8 @@ import java.util.Set; /** - * + * Wikitty service. + * * @author poussin * @version $Revision$ * @@ -33,6 +34,41 @@ public interface WikittyService { /* + * listeners + */ + + /** Event listener type. */ + public enum ServiceListenerType { + ALL, LOCAL, REMOTE + } + + /** + * Add new wikitty service listener. + * + * Warning, {@code listener} is referenced as WeakReference, but sure to + * another reference to work. + * + * @param listener listener to add + * @param type type of event to listen + * + * @see ServiceListenerType + */ + public void addWikittyServiceListener(WikittyServiceListener listener, ServiceListenerType type); + + /** + * Remove wikitty service listener. + * + * Warning, {@code listener} is referenced as WeakReference, but sure to + * another reference to work. + * + * @param listener listener to remove + * @param type type of event to listen + * + * @see ServiceListenerType + */ + public void removeWikittyServiceListener(WikittyServiceListener listener, ServiceListenerType type); + + /* * Storage */ Modified: trunk/wikitty-api/src/main/java/org/nuiton/wikitty/WikittyServiceCached.java =================================================================== --- trunk/wikitty-api/src/main/java/org/nuiton/wikitty/WikittyServiceCached.java 2010-06-02 19:12:32 UTC (rev 90) +++ trunk/wikitty-api/src/main/java/org/nuiton/wikitty/WikittyServiceCached.java 2010-06-04 10:43:55 UTC (rev 91) @@ -17,19 +17,14 @@ package org.nuiton.wikitty; - import java.util.ArrayList; import java.util.Collection; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; -import java.util.Properties; import java.util.Set; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - /** * Override some method of WikittyService to use cache * @@ -41,29 +36,30 @@ */ public class WikittyServiceCached implements WikittyService { - /** to use log facility, just put in your code: log.info(\"...\"); */ - static private Log log = LogFactory.getLog(WikittyServiceCached.class); - - /** - * Indique si les objects sont propages (true) vers les autres caches ou - * simplement supprimes des autres caches (false). Default to {@code false}. - */ - static public final String WIKITTY_PROPAGATE_CACHE_OPTION = "wikitty.service.cache.propagateCache"; - protected WikittyCache cache = null; protected WikittyService ws; - - public WikittyServiceCached(WikittyService ws, Properties props) { - cache = WikittyCache.getInstance(props); + + public WikittyServiceCached(WikittyService ws) { + cache = WikittyCache.getInstance(); this.ws = ws; + + // add service listener for synchronisation + // listener des remote event + addWikittyServiceListener(cache, ServiceListenerType.REMOTE); } - public WikittyServiceCached(WikittyService ws) { - this(ws, new Properties()); + @Override + public void addWikittyServiceListener(WikittyServiceListener listener, ServiceListenerType type) { + ws.addWikittyServiceListener(listener, type); } @Override + public void removeWikittyServiceListener(WikittyServiceListener listener, ServiceListenerType type) { + ws.removeWikittyServiceListener(listener, type); + } + + @Override public void clear() { ws.clear(); cache.clearWikitty(); Added: trunk/wikitty-api/src/main/java/org/nuiton/wikitty/WikittyServiceEvent.java =================================================================== --- trunk/wikitty-api/src/main/java/org/nuiton/wikitty/WikittyServiceEvent.java (rev 0) +++ trunk/wikitty-api/src/main/java/org/nuiton/wikitty/WikittyServiceEvent.java 2010-06-04 10:43:55 UTC (rev 91) @@ -0,0 +1,160 @@ +/* *##% + * Copyright (C) 2010 Code Lutin, Chatellier Eric + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + *##%*/ + +package org.nuiton.wikitty; + +import java.util.EventObject; +import java.util.Map; +import java.util.Set; + +/** + * Wikitty service event. + * + * Contains : + * <ul> + * <li>Wikitty service as source + * <li>ids : wikitty ids or extensions ids + * <li>ids & version : only for put : version of added wikitties + * <li>ids & extension : only for put : extension of added ids + * </ul> + * + * @author chatellier + * @version $Revision$ + * + * Last update : $Date$ + * By : $Author$ + */ +public class WikittyServiceEvent extends EventObject { + + /** serialVersionUID. */ + private static final long serialVersionUID = 9017732163643700599L; + + /** Remote event (received from jgroup). */ + protected boolean remote; + + /** + * Id managed by event. + * + * Can be : + * <ul> + * <li>wikitty ids (uuid) + * <li>extension ids (ex : toto[2.1]) + * </ul> + */ + protected Set<String> ids; + + /** + * Map between extensions set for each id. + */ + protected Map<String, Set<String>> idExtensions; + + /** + * Map between versions for each id. + */ + protected Map<String, String> idVersions; + + /** + * Constructor with source {@link WikittyService}. + * + * @param source wikitty service + */ + public WikittyServiceEvent(Object source) { + super(source); + } + + /** + * To allow set transient source after deserialisation. + * + * @param source source + */ + public void setSource(Object source) { + this.source = source; + } + + /** + * Is event remote. + * + * @return remote event + */ + public boolean isRemote() { + return remote; + } + + /** + * Change remote event property. + * + * @param remote remote + */ + public void setRemote(boolean remote) { + this.remote = remote; + } + + /** + * Get ids. + * + * @return ids or {@code null} if no ids is related to event + */ + public Set<String> getIds() { + return ids; + } + + /** + * Set ids. + * + * @param ids ids to set + */ + public void setIds(Set<String> ids) { + this.ids = ids; + } + + /** + * Get id and extensions map. + * + * @return map with extension set for each id or {@code null} if no ids is related to event + */ + public Map<String, Set<String>> getIdExtensions() { + return idExtensions; + } + + /** + * Change id and extensions map. + * + * @param idExtensions id and extensions map + */ + public void setIdExtensions(Map<String, Set<String>> idExtensions) { + this.idExtensions = idExtensions; + } + + /** + * Get id and version map. + * + * @return map with version for each id + */ + public Map<String, String> getIdVersions() { + return idVersions; + } + + /** + * Set id and version map. + * + * @param idVersions id and versions + */ + public void setIdVersions(Map<String, String> idVersions) { + this.idVersions = idVersions; + } +} Property changes on: trunk/wikitty-api/src/main/java/org/nuiton/wikitty/WikittyServiceEvent.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL Modified: trunk/wikitty-api/src/main/java/org/nuiton/wikitty/WikittyServiceImpl.java =================================================================== --- trunk/wikitty-api/src/main/java/org/nuiton/wikitty/WikittyServiceImpl.java 2010-06-02 19:12:32 UTC (rev 90) +++ trunk/wikitty-api/src/main/java/org/nuiton/wikitty/WikittyServiceImpl.java 2010-06-04 10:43:55 UTC (rev 91) @@ -88,7 +88,23 @@ return wikittyStorage; } + /* + * @see org.nuiton.wikitty.WikittyService#addWikittyServiceListener(org.nuiton.wikitty.WikittyServiceListener, org.nuiton.wikitty.WikittyService.ServiceListenerType) + */ @Override + public void addWikittyServiceListener(WikittyServiceListener listener, ServiceListenerType type) { + throw new UnsupportedOperationException("Can't add listener on " + WikittyServiceImpl.class.getName()); + } + + /* + * @see org.nuiton.wikitty.WikittyService#removeWikittyServiceListener(org.nuiton.wikitty.WikittyServiceListener, org.nuiton.wikitty.WikittyService.ServiceListenerType) + */ + @Override + public void removeWikittyServiceListener(WikittyServiceListener listener, ServiceListenerType type) { + throw new UnsupportedOperationException("Can't remove listener on " + WikittyServiceImpl.class.getName()); + } + + @Override public UpdateResponse store(WikittyTransaction transaction, Collection<Wikitty> wikitties, boolean disableAutoVersionIncrement) { // update/store extension if necessary Added: trunk/wikitty-api/src/main/java/org/nuiton/wikitty/WikittyServiceListener.java =================================================================== --- trunk/wikitty-api/src/main/java/org/nuiton/wikitty/WikittyServiceListener.java (rev 0) +++ trunk/wikitty-api/src/main/java/org/nuiton/wikitty/WikittyServiceListener.java 2010-06-04 10:43:55 UTC (rev 91) @@ -0,0 +1,40 @@ +/* *##% + * Copyright (C) 2010 Code Lutin, Chatellier Eric + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + *##%*/ + +package org.nuiton.wikitty; + +/** + * TODO add comment here. + * + * @author chatellier + * @version $Revision$ + * + * Last update : $Date$ + * By : $Author$ + */ +public interface WikittyServiceListener { + + public void putWikitty(WikittyServiceEvent event); + public void removeWikitty(WikittyServiceEvent event); + public void clearWikitty(WikittyServiceEvent event); + + /** toto[1.0] */ + public void putExtension(WikittyServiceEvent event); + public void removeExtension(WikittyServiceEvent event); + public void clearExtension(WikittyServiceEvent event); +} Property changes on: trunk/wikitty-api/src/main/java/org/nuiton/wikitty/WikittyServiceListener.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL Added: trunk/wikitty-api/src/main/java/org/nuiton/wikitty/WikittyServiceNotifier.java =================================================================== --- trunk/wikitty-api/src/main/java/org/nuiton/wikitty/WikittyServiceNotifier.java (rev 0) +++ trunk/wikitty-api/src/main/java/org/nuiton/wikitty/WikittyServiceNotifier.java 2010-06-04 10:43:55 UTC (rev 91) @@ -0,0 +1,437 @@ +/* *##% + * Copyright (C) 2010 Code Lutin, Chatellier Eric + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + *##%*/ + +package org.nuiton.wikitty; + +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Properties; +import java.util.Set; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.util.ListenerSet; + +/** + * Wikitty service notifier. + * + * Currently based on jgroups. + * + * @author chatellier + * @version $Revision$ + * + * Last update : $Date$ + * By : $Author$ + */ +public class WikittyServiceNotifier implements WikittyService { + + /** to use log facility, just put in your code: log.info(\"...\"); */ + static private Log log = LogFactory.getLog(WikittyServiceNotifier.class); + + /** + * Ajout du listener jgroup par default. Default to false, not used. + * + * If {@link #WIKITTY_EVENT_PROPAGATE_OPTION} is {@code true}, this + * configuration is skipped and considered as {@code true}. + */ + static public final String WIKITTY_EVENT_JGROUP_OPTION = "wikitty.service.event.useJGroups"; + + /** + * Indique si les objects sont propages (true) vers les autres caches ou + * simplement supprimes des autres caches (false). Default to {@code false}. + */ + static public final String WIKITTY_EVENT_PROPAGATE_OPTION = "wikitty.service.event.propagateEvent"; + + /** + * Indique si les evenement sont propagés aux autres listener. Sinon on est + * juste listener des evenements recus. C'est pourquoi le listener + * {@link #notifier} doit toujours être ajouté. + * + * @see WikittyServiceNotifier#WIKITTY_EVENT_PROPAGATE_OPTION + */ + protected boolean propagateCache = false; + + /** Service to delegate. */ + protected WikittyService ws; + + /** Wikitty service listener (all event). */ + protected ListenerSet<WikittyServiceListener> allWikittyServiceListeners; + + /** Wikitty service listener (only for local event). */ + protected ListenerSet<WikittyServiceListener> localWikittyServiceListeners; + + /** Wikitty service listener (only for remote event). */ + protected ListenerSet<WikittyServiceListener> remoteWikittyServiceListeners; + + /** JGroup notifier. */ + protected WikittyServiceListener notifier; + + public WikittyServiceNotifier() { + this(null); + } + + public WikittyServiceNotifier(Properties props) { + allWikittyServiceListeners = new ListenerSet<WikittyServiceListener>(); + localWikittyServiceListeners = new ListenerSet<WikittyServiceListener>(); + remoteWikittyServiceListeners = new ListenerSet<WikittyServiceListener>(); + + addJGroupNotifier(props); + } + + /** + * Add jgroup listener if enabled by configuration. + */ + protected void addJGroupNotifier(Properties props) { + + // can be null according to default constructor + if (props != null) { + + // get propagate cache property + String propagateCacheOption = props.getProperty(WIKITTY_EVENT_PROPAGATE_OPTION, "false"); + propagateCache = "true".equalsIgnoreCase(propagateCacheOption); + if (log.isDebugEnabled()) { + log.debug("Set propagateCache option to " + propagateCache); + } + + // add notifier as listener + String useJGroup = props.getProperty(WIKITTY_EVENT_JGROUP_OPTION, "false"); + if (propagateCache || "true".equalsIgnoreCase(useJGroup)) { + notifier = new JGroupsNotifier(this, propagateCache); + addWikittyServiceListener(notifier, ServiceListenerType.ALL); // weak reference + } + else if (log.isDebugEnabled()) { + log.debug("JGroup synchronisation channel not used "); + } + } + + } + + @Override + public void addWikittyServiceListener(WikittyServiceListener listener, ServiceListenerType type) { + // not delegated + switch (type) { + case ALL : allWikittyServiceListeners.add(listener); break; + case LOCAL : localWikittyServiceListeners.add(listener); break; + case REMOTE : remoteWikittyServiceListeners.add(listener); break; + } + } + + @Override + public void removeWikittyServiceListener(WikittyServiceListener listener, ServiceListenerType type) { + // not delegated + switch (type) { + case ALL : allWikittyServiceListeners.remove(listener); break; + case LOCAL : localWikittyServiceListeners.remove(listener); break; + case REMOTE : remoteWikittyServiceListeners.remove(listener); break; + } + } + + public void clear() { + ws.clear(); + } + + @Override + public UpdateResponse store(Wikitty wikitty) { + UpdateResponse updateResponse = ws.store(wikitty); + // notify listeners + firePutWikitty(wikitty); + return updateResponse; + } + + @Override + public UpdateResponse store(Collection<Wikitty> wikitties) { + UpdateResponse updateResponse = ws.store(wikitties); + // notify listeners + firePutWikitty(wikitties.toArray(new Wikitty[wikitties.size()])); + return updateResponse; + } + + @Override + public UpdateResponse store(Collection<Wikitty> wikitties, + boolean disableAutoVersionIncrement) { + UpdateResponse updateResponse = ws.store(wikitties, disableAutoVersionIncrement); + // notify listeners + firePutWikitty(wikitties.toArray(new Wikitty[wikitties.size()])); + return updateResponse; + } + + @Override + public UpdateResponse store(WikittyTransaction transaction, + Collection<Wikitty> wikitties, boolean disableAutoVersionIncrement) { + return ws.store(transaction, wikitties, + disableAutoVersionIncrement); + } + + @Override + public List<String> getAllExtensionIds() { + return ws.getAllExtensionIds(); + } + + @Override + public List<String> getAllExtensionsRequires(String extensionName) { + return ws.getAllExtensionsRequires(extensionName); + } + + @Override + public UpdateResponse storeExtension(WikittyExtension ext) { + return ws.storeExtension(ext); + } + + @Override + public UpdateResponse storeExtension(Collection<WikittyExtension> exts) { + return ws.storeExtension(exts); + } + + @Override + public UpdateResponse storeExtension(WikittyTransaction transaction, + Collection<WikittyExtension> exts) { + return ws.storeExtension(transaction, exts); + } + + @Override + public WikittyExtension restoreExtension(String id) { + return ws.restoreExtension(id); + } + + @Override + public WikittyExtension restoreExtension(WikittyTransaction transaction, + String id) { + return ws.restoreExtension(transaction, id); + } + + @Override + public WikittyExtension restoreExtensionLastVersion(String name) { + return ws.restoreExtensionLastVersion(name); + } + + @Override + public Wikitty restore(String id) { + return ws.restore(id); + } + + @Override + public List<Wikitty> restore(List<String> id) { + return ws.restore(id); + } + + @Override + public void delete(String id) { + ws.delete(id); + } + + @Override + public void delete(Collection<String> ids) { + ws.delete(ids); + } + + @Override + public PagedResult<Wikitty> findAllByCriteria(Criteria criteria) { + return ws.findAllByCriteria(criteria); + } + + @Override + public PagedResult<Wikitty> findAllByCriteria( + WikittyTransaction transaction, Criteria criteria) { + return ws.findAllByCriteria(transaction, criteria); + } + + @Override + public Wikitty findByCriteria(Criteria criteria) { + return ws.findByCriteria(criteria); + } + + @Override + public void addLabel(String wikittyId, String label) { + ws.addLabel(wikittyId, label); + } + + @Override + public PagedResult<Wikitty> findAllByLabel(String label, int firstIndex, + int endIndex) { + return ws.findAllByLabel(label, firstIndex, endIndex); + } + + @Override + public Wikitty findByLabel(String label) { + return ws.findByLabel(label); + } + + @Override + public Set<String> findAllAppliedLabels(String wikittyId) { + return ws.findAllAppliedLabels(wikittyId); + } + + @Override + public Tree restoreTree(String wikittyId) { + return ws.restoreTree(wikittyId); + } + + @Override + public Entry<TreeNode, Integer> restoreNode(String wikittyId, + Criteria filter) { + return ws.restoreNode(wikittyId, filter); + } + + @Override + public Map<TreeNode, Integer> restoreChildren(String wikittyId, + Criteria filter) { + return ws.restoreChildren(wikittyId, filter); + } + + @Override + public Wikitty restoreVersion(String wikittyId, String version) { + return ws.restoreVersion(wikittyId, version); + } + + @Override + public UpdateResponse syncEngin() { + return ws.syncEngin(); + } + + /** + * Build event to fire and call {@link #firePutWikitty(WikittyServiceEvent)}. + * + * @param ws data + */ + protected void firePutWikitty(Wikitty ... ws) { + + WikittyServiceEvent event = new WikittyServiceEvent(ws); + Set<String> ids = new HashSet<String>(); + Map<String, Set<String>> idsExtension = new HashMap<String, Set<String>>(); + Map<String, String> idsVersion = new HashMap<String, String>(); + + for (Wikitty w : ws) { + // ids + ids.add(w.getId()); + // extension + Set<String> extension = new HashSet<String>(); + extension.addAll(w.getExtensionNames()); + idsExtension.put(w.getId(), extension); + // version + idsVersion.put(w.getId(), w.getVersion()); + } + + event.setIds(ids); + event.setIdExtensions(idsExtension); + event.setIdVersions(idsVersion); + firePutWikitty(event); + } + + /** + * Build event to fire and call {@link #fireRemoveWikitty(WikittyServiceEvent)}. + * + * @param ws ids + */ + protected void fireRemoveWikitty(String ... wikittyIds) { + + WikittyServiceEvent event = new WikittyServiceEvent(ws); + Set<String> ids = new HashSet<String>(); + + for (String wikittyId : wikittyIds) { + // ids + ids.add(wikittyId); + } + + event.setIds(ids); + fireRemoveWikitty(event); + } + + /** + * Build event to fire and call {@link #fireClearWikitty(WikittyServiceEvent)}. + * + * @param ws ids + */ + protected void fireClearWikitty() { + + WikittyServiceEvent event = new WikittyServiceEvent(ws); + fireClearWikitty(event); + } + + /** + * Fire event to all registred listener. + * + * Take care about {@link WikittyServiceEvent#isRemote()} for fire. + * + * @param event + */ + protected void firePutWikitty(WikittyServiceEvent event) { + for (WikittyServiceListener l : allWikittyServiceListeners) { + l.putWikitty(event); + } + if (event.isRemote()) { + for (WikittyServiceListener l : localWikittyServiceListeners) { + l.putWikitty(event); + } + } + else { + for (WikittyServiceListener l : remoteWikittyServiceListeners) { + l.putWikitty(event); + } + } + } + + /** + * Fire event to all registred listener. + * + * Take care about {@link WikittyServiceEvent#isRemote()} for fire. + * + * @param event + */ + protected void fireRemoveWikitty(WikittyServiceEvent event) { + for (WikittyServiceListener l : allWikittyServiceListeners) { + l.removeWikitty(event); + } + if (event.isRemote()) { + for (WikittyServiceListener l : localWikittyServiceListeners) { + l.removeWikitty(event); + } + } + else { + for (WikittyServiceListener l : remoteWikittyServiceListeners) { + l.removeWikitty(event); + } + } + } + + /** + * Fire event to all registred listener. + * + * Take care about {@link WikittyServiceEvent#isRemote()} for fire. + * + * @param event + */ + protected void fireClearWikitty(WikittyServiceEvent event) { + for (WikittyServiceListener l : allWikittyServiceListeners) { + l.clearWikitty(event); + } + if (event.isRemote()) { + for (WikittyServiceListener l : localWikittyServiceListeners) { + l.clearWikitty(event); + } + } + else { + for (WikittyServiceListener l : remoteWikittyServiceListeners) { + l.clearWikitty(event); + } + } + } +} Property changes on: trunk/wikitty-api/src/main/java/org/nuiton/wikitty/WikittyServiceNotifier.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL