001/* 002 GRANITE DATA SERVICES 003 Copyright (C) 2011 GRANITE DATA SERVICES S.A.S. 004 005 This file is part of Granite Data Services. 006 007 Granite Data Services is free software; you can redistribute it and/or modify 008 it under the terms of the GNU Library General Public License as published by 009 the Free Software Foundation; either version 2 of the License, or (at your 010 option) any later version. 011 012 Granite Data Services is distributed in the hope that it will be useful, but 013 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 014 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License 015 for more details. 016 017 You should have received a copy of the GNU Library General Public License 018 along with this library; if not, see <http://www.gnu.org/licenses/>. 019*/ 020 021package org.granite.messaging.service; 022 023import java.util.Map; 024import java.util.concurrent.locks.ReentrantLock; 025 026import org.granite.config.flex.Destination; 027import org.granite.config.flex.Factory; 028import org.granite.context.GraniteContext; 029import org.granite.logging.Logger; 030import org.granite.util.TypeUtil; 031import org.granite.util.XMap; 032 033import flex.messaging.messages.RemotingMessage; 034 035/** 036 * @author Franck WOLFF 037 */ 038public abstract class ServiceFactory { 039 040 private static final Logger log = Logger.getLogger(ServiceFactory.class); 041 private static final ReentrantLock lock = new ReentrantLock(); 042 043 private ServiceExceptionHandler serviceExceptionHandler; 044 045 public static ServiceFactory getFactoryInstance(RemotingMessage request) throws ServiceException { 046 047 GraniteContext context = GraniteContext.getCurrentInstance(); 048 049 String messageType = request.getClass().getName(); 050 String destinationId = request.getDestination(); 051 052 log.debug(">> Finding factoryId for messageType: %s and destinationId: %s", messageType, destinationId); 053 054 Destination destination = context.getServicesConfig().findDestinationById(messageType, destinationId); 055 if (destination == null) 056 throw new ServiceException("Destination not found: " + destinationId); 057 String factoryId = destination.getProperties().get("factory"); 058 059 log.debug(">> Found factoryId: %s", factoryId); 060 061 Map<String, Object> cache = context.getApplicationMap(); 062 String key = ServiceFactory.class.getName() + '.' + factoryId; 063 064 return getServiceFactory(cache, context, factoryId, key); 065 } 066 067 private static ServiceFactory getServiceFactory(Map<String, Object> cache, GraniteContext context, String factoryId, String key) { 068 lock.lock(); 069 try { 070 ServiceFactory factory = (ServiceFactory)cache.get(key); 071 if (factory == null) { 072 073 log.debug(">> No cached factory for: %s", factoryId); 074 075 Factory config = context.getServicesConfig().findFactoryById(factoryId); 076 if (config == null) 077 config = getDefaultFactoryConfig(); 078 try { 079 Class<? extends ServiceFactory> clazz = TypeUtil.forName(config.getClassName(), ServiceFactory.class); 080 factory = clazz.newInstance(); 081 factory.configure(config.getProperties()); 082 } catch (Exception e) { 083 throw new ServiceException("Could not instantiate factory: " + factory, e); 084 } 085 cache.put(key, factory); 086 } 087 else 088 log.debug(">> Found a cached factory for: %s", factoryId); 089 090 log.debug("<< Returning factory: %s", factory); 091 092 return factory; 093 } finally { 094 lock.unlock(); 095 } 096 } 097 098 private static Factory getDefaultFactoryConfig() { 099 return Factory.DEFAULT_FACTORY; 100 } 101 102 public void configure(XMap properties) throws ServiceException { 103 104 log.debug(">> Configuring factory with: %s", properties); 105 106 // service exception handler 107 String sServiceExceptionHandler = properties.get("service-exception-handler"); 108 String enableLogging = properties.get("enable-exception-logging"); 109 if (sServiceExceptionHandler != null) { 110 try { 111 if (Boolean.TRUE.toString().equals(enableLogging) || Boolean.FALSE.toString().equals(enableLogging)) 112 this.serviceExceptionHandler = (ServiceExceptionHandler)TypeUtil.newInstance(sServiceExceptionHandler.trim(), 113 new Class<?>[] { boolean.class }, new Object[] { Boolean.valueOf(enableLogging) }); 114 else 115 this.serviceExceptionHandler = (ServiceExceptionHandler)TypeUtil.newInstance(sServiceExceptionHandler.trim()); 116 } catch (Exception e) { 117 throw new ServiceException("Could not instantiate service exception handler: " + sServiceExceptionHandler, e); 118 } 119 } 120 else { 121 if (Boolean.TRUE.toString().equals(enableLogging) || Boolean.FALSE.toString().equals(enableLogging)) 122 this.serviceExceptionHandler = new DefaultServiceExceptionHandler(Boolean.valueOf(enableLogging)); 123 else 124 this.serviceExceptionHandler = new DefaultServiceExceptionHandler(); 125 } 126 127 log.debug("<< Configuring factory done: %s", this); 128 } 129 130 public abstract ServiceInvoker<?> getServiceInstance(RemotingMessage request) throws ServiceException; 131 132 public ServiceExceptionHandler getServiceExceptionHandler() { 133 return serviceExceptionHandler; 134 } 135 136 @Override 137 public String toString() { 138 return toString(null); 139 } 140 141 public String toString(String append) { 142 return super.toString() + " {" + 143 (append != null ? append : "") + 144 "\n serviceExceptionHandler: " + serviceExceptionHandler + 145 "\n}"; 146 } 147}