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    }