/**
* GRANITE DATA SERVICES
* Copyright (C) 2006-2015 GRANITE DATA SERVICES S.A.S.
*
* This file is part of the Granite Data Services Platform.
*
* Granite Data Services 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 2.1 of the License, or (at your option) any later version.
*
* Granite Data Services 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 this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA, or see <http://www.gnu.org/licenses/>.
*/
package org.granite.messaging.service;
import java.util.Map;
import java.util.Properties;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import org.granite.config.flex.Destination;
import org.granite.config.flex.ServicesConfig;
import org.granite.context.GraniteContext;
import org.granite.logging.Logger;
import org.granite.util.XMap;
import flex.messaging.messages.RemotingMessage;
/**
* @author Franck WOLFF
*/
public class EjbServiceFactory extends ServiceFactory {
private static final Logger log = Logger.getLogger(EjbServiceFactory.class);
private Properties environment = null;
private transient InitialContext initialContext = null;
private String lookup = null;
public EjbServiceFactory() throws ServiceException {
}
public synchronized Object lookup(String name) throws NamingException {
if (initialContext == null) {
if (environment == null || environment.isEmpty())
initialContext = new InitialContext();
else
initialContext = new InitialContext(environment);
}
return initialContext.lookup(name);
}
public String getLookup() {
return lookup;
}
@Override
public void configure(XMap properties) throws ServiceException {
super.configure(properties);
try {
environment = new Properties();
for (XMap property : properties.getAll("initial-context-environment/property")) {
String name = property.get("name");
String value = property.get("value");
if ("Context.PROVIDER_URL".equals(name))
environment.put(Context.PROVIDER_URL, value);
else if ("Context.INITIAL_CONTEXT_FACTORY".equals(name))
environment.put(Context.INITIAL_CONTEXT_FACTORY, value);
else if ("Context.URL_PKG_PREFIXES".equals(name))
environment.put(Context.URL_PKG_PREFIXES, value);
else if ("Context.SECURITY_PRINCIPAL".equals(name))
environment.put(Context.SECURITY_PRINCIPAL, value);
else if ("Context.SECURITY_CREDENTIALS".equals(name))
environment.put(Context.SECURITY_CREDENTIALS, value);
else
log.warn("Unknown InitialContext property: %s (ignored)", name);
}
initialContext = new InitialContext(environment.size() > 0 ? environment : null);
} catch (Exception e) {
throw new ServiceException("Could not create InitialContext", e);
}
lookup = properties.get("lookup");
}
@Override
public ServiceInvoker<?> getServiceInstance(RemotingMessage request) throws ServiceException {
GraniteContext context = GraniteContext.getCurrentInstance();
String destinationId = request.getDestination();
String key = getUniqueKey(destinationId);
EjbServiceInvoker invoker = null;
// Synchronize on unique key.
synchronized (key) {
// Retrieve cached instance.
invoker = (EjbServiceInvoker)context.getApplicationMap().get(key);
if (invoker == null) {
Map<String, Object> sessionMap = context.getSessionMap(false);
if (sessionMap != null)
invoker = (EjbServiceInvoker)sessionMap.get(key);
}
}
// Not found, lookup and cache.
if (invoker == null) {
Destination destination = ((ServicesConfig)context.getServicesConfig()).findDestinationById(
request.getClass().getName(),
destinationId
);
invoker = new EjbServiceInvoker(destination, this);
Map<String, Object> cache = invoker.getMetadata().isStateful() ?
context.getSessionMap(true) :
context.getApplicationMap();
// Synchronize on unique key (put if absent)...
synchronized (key) {
EjbServiceInvoker previousInvoker = (EjbServiceInvoker)cache.get(key);
if (previousInvoker != null)
invoker = previousInvoker;
else
cache.put(key, invoker);
}
}
return invoker;
}
protected String getUniqueKey(String destinationId) {
return new StringBuilder(EjbServiceInvoker.class.getName().length() + 1 + destinationId.length())
.append(EjbServiceInvoker.class.getName())
.append('.')
.append(destinationId)
.toString()
.intern();
}
public void removeFromCache(String destinationId) {
GraniteContext context = GraniteContext.getCurrentInstance();
String key = getUniqueKey(destinationId);
// Synchronize on unique key.
synchronized (key) {
context.getApplicationMap().remove(key);
Map<String, Object> sessionMap = context.getSessionMap(false);
if (sessionMap != null)
context.getSessionMap().remove(key);
}
}
@Override
public String toString() {
return toString("\n lookup: " + lookup);
}
}