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.messaging.service; 023 024import java.util.Map; 025import java.util.Properties; 026 027import javax.naming.Context; 028import javax.naming.InitialContext; 029import javax.naming.NamingException; 030 031import org.granite.config.flex.Destination; 032import org.granite.context.GraniteContext; 033import org.granite.logging.Logger; 034import org.granite.util.XMap; 035 036import flex.messaging.messages.RemotingMessage; 037 038/** 039 * @author Franck WOLFF 040 */ 041public class EjbServiceFactory extends ServiceFactory { 042 043 private static final Logger log = Logger.getLogger(EjbServiceFactory.class); 044 045 private Properties environment = null; 046 private transient InitialContext initialContext = null; 047 private String lookup = null; 048 049 public EjbServiceFactory() throws ServiceException { 050 } 051 052 public synchronized Object lookup(String name) throws NamingException { 053 if (initialContext == null) { 054 if (environment == null || environment.isEmpty()) 055 initialContext = new InitialContext(); 056 else 057 initialContext = new InitialContext(environment); 058 } 059 return initialContext.lookup(name); 060 } 061 062 public String getLookup() { 063 return lookup; 064 } 065 066 @Override 067 public void configure(XMap properties) throws ServiceException { 068 super.configure(properties); 069 070 try { 071 environment = new Properties(); 072 073 for (XMap property : properties.getAll("initial-context-environment/property")) { 074 String name = property.get("name"); 075 String value = property.get("value"); 076 077 if ("Context.PROVIDER_URL".equals(name)) 078 environment.put(Context.PROVIDER_URL, value); 079 else if ("Context.INITIAL_CONTEXT_FACTORY".equals(name)) 080 environment.put(Context.INITIAL_CONTEXT_FACTORY, value); 081 else if ("Context.URL_PKG_PREFIXES".equals(name)) 082 environment.put(Context.URL_PKG_PREFIXES, value); 083 else if ("Context.SECURITY_PRINCIPAL".equals(name)) 084 environment.put(Context.SECURITY_PRINCIPAL, value); 085 else if ("Context.SECURITY_CREDENTIALS".equals(name)) 086 environment.put(Context.SECURITY_CREDENTIALS, value); 087 else 088 log.warn("Unknown InitialContext property: %s (ignored)", name); 089 } 090 091 initialContext = new InitialContext(environment.size() > 0 ? environment : null); 092 } catch (Exception e) { 093 throw new ServiceException("Could not create InitialContext", e); 094 } 095 096 lookup = properties.get("lookup"); 097 } 098 099 @Override 100 public ServiceInvoker<?> getServiceInstance(RemotingMessage request) throws ServiceException { 101 GraniteContext context = GraniteContext.getCurrentInstance(); 102 103 String destinationId = request.getDestination(); 104 String key = getUniqueKey(destinationId); 105 106 EjbServiceInvoker invoker = null; 107 108 // Synchronize on unique key. 109 synchronized (key) { 110 // Retrieve cached instance. 111 invoker = (EjbServiceInvoker)context.getApplicationMap().get(key); 112 if (invoker == null) { 113 Map<String, Object> sessionMap = context.getSessionMap(false); 114 if (sessionMap != null) 115 invoker = (EjbServiceInvoker)sessionMap.get(key); 116 } 117 } 118 119 // Not found, lookup and cache. 120 if (invoker == null) { 121 Destination destination = context.getServicesConfig().findDestinationById( 122 request.getClass().getName(), 123 destinationId 124 ); 125 invoker = new EjbServiceInvoker(destination, this); 126 127 Map<String, Object> cache = invoker.getMetadata().isStateful() ? 128 context.getSessionMap(true) : 129 context.getApplicationMap(); 130 131 // Synchronize on unique key (put if absent)... 132 synchronized (key) { 133 EjbServiceInvoker previousInvoker = (EjbServiceInvoker)cache.get(key); 134 if (previousInvoker != null) 135 invoker = previousInvoker; 136 else 137 cache.put(key, invoker); 138 } 139 } 140 141 return invoker; 142 } 143 144 protected String getUniqueKey(String destinationId) { 145 return new StringBuilder(EjbServiceInvoker.class.getName().length() + 1 + destinationId.length()) 146 .append(EjbServiceInvoker.class.getName()) 147 .append('.') 148 .append(destinationId) 149 .toString() 150 .intern(); 151 } 152 153 public void removeFromCache(String destinationId) { 154 GraniteContext context = GraniteContext.getCurrentInstance(); 155 String key = getUniqueKey(destinationId); 156 // Synchronize on unique key. 157 synchronized (key) { 158 context.getApplicationMap().remove(key); 159 Map<String, Object> sessionMap = context.getSessionMap(false); 160 if (sessionMap != null) 161 context.getSessionMap().remove(key); 162 } 163 } 164 165 @Override 166 public String toString() { 167 return toString("\n lookup: " + lookup); 168 } 169}