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 */
022package org.granite.gravity.adapters;
023
024import java.io.Serializable;
025import java.util.ArrayList;
026import java.util.List;
027import java.util.Map;
028import java.util.concurrent.ConcurrentHashMap;
029import java.util.concurrent.locks.ReentrantLock;
030
031import org.granite.config.flex.Adapter;
032import org.granite.config.flex.Destination;
033import org.granite.context.GraniteContext;
034import org.granite.gravity.Gravity;
035import org.granite.logging.Logger;
036import org.granite.messaging.service.ServiceException;
037import org.granite.util.TypeUtil;
038
039import flex.messaging.messages.AsyncMessage;
040import flex.messaging.messages.CommandMessage;
041import flex.messaging.messages.Message;
042
043/**
044 * @author William DRAI
045 */
046public 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}