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 */
022 package org.granite.gravity.adapters;
023
024 import java.io.Serializable;
025 import java.util.ArrayList;
026 import java.util.List;
027 import java.util.Map;
028 import java.util.concurrent.ConcurrentHashMap;
029 import java.util.concurrent.locks.ReentrantLock;
030
031 import org.granite.config.flex.Adapter;
032 import org.granite.config.flex.Destination;
033 import org.granite.context.GraniteContext;
034 import org.granite.gravity.Gravity;
035 import org.granite.logging.Logger;
036 import org.granite.messaging.service.ServiceException;
037 import org.granite.util.TypeUtil;
038
039 import flex.messaging.messages.AsyncMessage;
040 import flex.messaging.messages.CommandMessage;
041 import flex.messaging.messages.Message;
042
043 /**
044 * @author William DRAI
045 */
046 public class AdapterFactory implements Serializable {
047
048 private static final long serialVersionUID = 1L;
049
050
051 private static final Logger log = Logger.getLogger(AdapterFactory.class);
052 private static final ReentrantLock lock = new ReentrantLock();
053
054 private Gravity gravity;
055 private Map<String, ServiceAdapter> adaptersCache = new ConcurrentHashMap<String, ServiceAdapter>();
056 private List<ServiceAdapter> adapters = new ArrayList<ServiceAdapter>();
057 private static Class<SimpleServiceAdapter> defaultAdapterClass = SimpleServiceAdapter.class;
058
059
060 public AdapterFactory(Gravity gravity) {
061 this.gravity = gravity;
062 }
063
064
065 public ServiceAdapter getServiceAdapter(Message request) throws ServiceException {
066
067 String messageType = request.getClass().getName();
068 if (request instanceof CommandMessage)
069 messageType = ((CommandMessage)request).getMessageRefType();
070 if (messageType == null)
071 messageType = AsyncMessage.class.getName();
072 String destinationId = request.getDestination();
073
074 return getServiceAdapter(messageType, destinationId);
075 }
076
077 public ServiceAdapter getServiceAdapter(String messageType, String destinationId) throws ServiceException {
078 GraniteContext context = GraniteContext.getCurrentInstance();
079
080 log.debug(">> Finding serviceAdapter for messageType: %s and destinationId: %s", messageType, destinationId);
081
082 Destination destination = context.getServicesConfig().findDestinationById(messageType, destinationId);
083 if (destination == null) {
084 log.debug(">> No destination found: %s", destinationId);
085 return null;
086 }
087 Adapter adapter = destination.getAdapter();
088
089 String key = null;
090
091 if (adapter != null) {
092 log.debug(">> Found adapterRef: %s", adapter.getId());
093 key = AdapterFactory.class.getName() + '@' + destination.getId() + '.' + adapter.getId();
094 }
095 else
096 key = defaultAdapterClass.getName() + '@' + destination.getId();
097
098 return getServiceAdapter(adaptersCache, context, destination, key, adapter != null ? adapter.getId() : null);
099 }
100
101 private ServiceAdapter getServiceAdapter(Map<String, ServiceAdapter> cache, GraniteContext context, Destination destination, String key, String adapterId) {
102 lock.lock();
103 try {
104 ServiceAdapter serviceAdapter = cache.get(key);
105 if (serviceAdapter == null) {
106 log.debug(">> No cached factory for: %s", adapterId);
107
108 Adapter config = destination.getAdapter();
109 try {
110 Class<? extends ServiceAdapter> clazz = (adapterId != null)
111 ? TypeUtil.forName(config.getClassName(), ServiceAdapter.class)
112 : defaultAdapterClass;
113 serviceAdapter = clazz.newInstance();
114 serviceAdapter.setId(adapterId);
115 serviceAdapter.setGravity(gravity);
116 serviceAdapter.configure(config.getProperties(), destination.getProperties());
117 serviceAdapter.start();
118
119 adapters.add(serviceAdapter);
120 }
121 catch (ServiceException e) {
122 throw e;
123 }
124 catch (Exception e) {
125 throw new ServiceException("Could not instantiate serviceAdapter: " + config, e);
126 }
127 cache.put(key, serviceAdapter);
128 }
129 else
130 log.debug(">> Found a cached serviceAdapter for ref: %s", destination.getAdapter());
131
132 log.debug("<< Returning serviceAdapter: %s", serviceAdapter);
133
134 serviceAdapter.setDestination(destination);
135 return serviceAdapter;
136 } finally {
137 lock.unlock();
138 }
139 }
140
141
142 public void stopAll() {
143 for (ServiceAdapter adapter : adapters) {
144 adapter.stop();
145 }
146 }
147
148
149 @Override
150 public String toString() {
151 return toString(null);
152 }
153
154 public String toString(String append) {
155 return super.toString() + " {" +
156 (append != null ? append : "") +
157 "\n}";
158 }
159 }