001 /**
002 * GRANITE DATA SERVICES
003 * Copyright (C) 2006-2013 GRANITE DATA SERVICES S.A.S.
004 *
005 * This file is part of the Granite Data Services Platform.
006 *
007 * Granite Data Services is free software; you can redistribute it and/or
008 * modify it under the terms of the GNU Lesser General Public
009 * License as published by the Free Software Foundation; either
010 * version 2.1 of the License, or (at your option) any later version.
011 *
012 * Granite Data Services is distributed in the hope that it will be useful,
013 * but WITHOUT ANY WARRANTY; without even the implied warranty of
014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
015 * General Public License for more details.
016 *
017 * You should have received a copy of the GNU Lesser General Public
018 * License along with this library; if not, write to the Free Software
019 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
020 * USA, or see <http://www.gnu.org/licenses/>.
021 */
022 package org.granite.tide.util;
023
024 import java.lang.reflect.Method;
025 import java.util.ArrayList;
026 import java.util.HashMap;
027 import java.util.List;
028 import java.util.Map;
029 import java.util.Set;
030
031 import org.granite.logging.Logger;
032 import org.granite.tide.invocation.ContextEvent;
033
034 /**
035 * @author Franck WOLFF
036 */
037 public abstract class AbstractContext extends HashMap<String, Object> {
038
039 private static final long serialVersionUID = 1L;
040 private static final Logger log = Logger.getLogger(AbstractContext.class);
041 private static final ThreadLocal<AbstractContext> contexts = new ThreadLocal<AbstractContext>();
042
043 private final Map<String, Set<Method>> observers;
044 private final List<ContextEvent> remoteEvents;
045
046 protected AbstractContext(Map<String, Set<Method>> observers) {
047 synchronized (contexts) {
048 if (contexts.get() != null)
049 throw new IllegalStateException("Context already created");
050
051 this.observers = observers;
052 this.remoteEvents = new ArrayList<ContextEvent>();
053
054 contexts.set(this);
055 }
056 }
057
058 public List<ContextEvent> getRemoteEvents() {
059 return remoteEvents;
060 }
061
062 protected abstract Set<String> getRemoteObservers();
063 protected abstract Object callMethod(Method method, Object... args) throws Exception;
064
065 public static AbstractContext instance() {
066 return contexts.get();
067 }
068
069 public static void raiseEvent(String name, Object... args) {
070 AbstractContext instance = instance();
071 Map<String, Set<Method>> observers = instance.observers;
072 if (observers.containsKey(name)) {
073 for (Method method : observers.get(name)) {
074 try {
075 instance.callMethod(method, args);
076 }
077 catch (Exception e) {
078 log.error(e, "Could not call method: %s", method);
079 }
080 }
081 }
082 Set<String> remoteObservers = instance.getRemoteObservers();
083 if (remoteObservers.contains(name))
084 instance.remoteEvents.add(new ContextEvent(name, args));
085 }
086
087 public static void remove() {
088 AbstractContext context = contexts.get();
089 if (context != null) {
090 try {
091 context.clear();
092 context.remoteEvents.clear();
093 }
094 finally {
095 contexts.remove();
096 }
097 }
098 }
099 }