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