/* * Copyright © 2008, 2012 Pedro Agulló Soliveres. * * This file is part of DirectJNgine. * * DirectJNgine is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License. * * Commercial use is permitted to the extent that the code/component(s) * do NOT become part of another Open Source or Commercially developed * licensed development library or toolkit without explicit permission. * * DirectJNgine 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with DirectJNgine. If not, see <http://www.gnu.org/licenses/>. * * This software uses the ExtJs library (http://extjs.com), which is * distributed under the GPL v3 license (see http://extjs.com/license). */ package com.softwarementors.extjs.djn.servlet.ssm; import java.util.HashMap; import java.util.Map; import javax.servlet.ServletContext; import javax.servlet.http.HttpSession; import org.apache.log4j.Logger; import com.softwarementors.extjs.djn.api.RegisteredMethod; import com.softwarementors.extjs.djn.router.dispatcher.DispatcherBase; import edu.umd.cs.findbugs.annotations.NonNull; public class SsmDispatcher extends DispatcherBase { @NonNull private static final Map<Class<?>, Scope> methodScopeCache = new HashMap<Class<?>, Scope>(); @NonNull private static final Logger logger = Logger.getLogger(SsmDispatcher.class); @Override protected Object getInvokeInstanceForNonStaticMethod(RegisteredMethod method) throws Exception { assert method != null; Class<?> instanceClass = method.getActionClass(); Scope scope = methodScopeCache.get(instanceClass); if( scope == null ) { ActionScope methodScope = instanceClass.getAnnotation(ActionScope.class); if( methodScope == null ) { scope = Scope.STATELESS; } else { scope = methodScope.scope(); } methodScopeCache.put( instanceClass, scope); if( logger.isDebugEnabled() ) { logger.debug( "Action class '" + instanceClass + "' will be instantiated with " + scope.toString() + "' scope." ); } } assert scope != null; Object result = getAction(method, scope); return result; } @edu.umd.cs.findbugs.annotations.SuppressWarnings(value="SF_SWITCH_NO_DEFAULT", justification="Missing a 'default' branch is not a problem with enums, given the appropriate compiler settings") private Object getAction(RegisteredMethod method, Scope scope) throws Exception{ Object result = null; switch( scope ) { case SESSION: result = getSessionMethodInstance(method); break; case APPLICATION: result = getApplicationMethodInstance(method); break; case STATELESS: result = getStatelessMethodInstance(method); break; } assert result != null; return result; } private Object getStatelessMethodInstance(RegisteredMethod method) throws Exception { assert method != null; return createInvokeInstanceForMethodWithDefaultConstructor(method); } /* MUST be synchronized so that two competing threads do no instantiate and store two actions "at the same time". */ private synchronized Object getSessionMethodInstance(RegisteredMethod method) throws Exception { assert method != null; HttpSession context = WebContextManager.get().getSession(); Object result = WebContextManager.get().getSessionScopedObject(method.getActionName()); if( result == null ) { String key = WebContext.getSessionScopedActionName(method.getActionName()); result = createInvokeInstanceForMethodWithDefaultConstructor(method); context.setAttribute(key, result); } return result; } /* MUST be synchronized so that two competing threads do no instantiate and store two actions "at the same time". */ private synchronized Object getApplicationMethodInstance(RegisteredMethod method) throws Exception { assert method != null; ServletContext context = WebContextManager.get().getServletContext(); Object result = WebContextManager.get().getApplicationScopedObject(method.getActionName()); if( result == null ) { result = createInvokeInstanceForMethodWithDefaultConstructor(method); String key = WebContext.getApplicationScopedActionName(method.getActionName()); context.setAttribute(key, result); } return result; } }