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 */ 022package org.granite.tide.util; 023 024import java.lang.reflect.Method; 025import java.util.ArrayList; 026import java.util.HashMap; 027import java.util.List; 028import java.util.Map; 029import java.util.Set; 030 031import org.granite.logging.Logger; 032import org.granite.tide.invocation.ContextEvent; 033 034/** 035 * @author Franck WOLFF 036 */ 037public 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}