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    
021    package org.granite.messaging.service;
022    
023    import flex.messaging.messages.RemotingMessage;
024    
025    import org.granite.config.flex.Destination;
026    import org.granite.config.flex.DestinationRemoveListener;
027    import org.granite.context.GraniteContext;
028    
029    import java.util.Collections;
030    import java.util.HashSet;
031    import java.util.Map;
032    import java.util.Set;
033    
034    /**
035     * @author Franck WOLFF
036     */
037    public class SimpleServiceFactory extends ServiceFactory implements DestinationRemoveListener {
038        
039        private Set<String> invalidKeys = new HashSet<String>();
040        
041    
042        @Override
043        public ServiceInvoker<?> getServiceInstance(RemotingMessage request) throws ServiceException {
044            String messageType = request.getClass().getName();
045            String destinationId = request.getDestination();
046    
047            GraniteContext context = GraniteContext.getCurrentInstance();
048            Destination destination = context.getServicesConfig().findDestinationById(messageType, destinationId);
049            if (destination == null)
050                throw new ServiceException("No matching destination: " + destinationId);
051    
052            destination.addRemoveListener(this);
053            Map<String, Object> cache = getCache(destination);
054            
055            String key = SimpleServiceInvoker.class.getName() + '.' + destination.getId();
056            if (invalidKeys.contains(key)) {
057                    cache.remove(key);
058                    invalidKeys.remove(key);
059            }
060            
061            SimpleServiceInvoker service = (SimpleServiceInvoker)cache.get(key);
062            if (service == null) {
063                service = new SimpleServiceInvoker(destination, this);
064                cache.put(key, service);
065            }
066            return service;
067        }
068        
069        public void destinationRemoved(Destination destination) throws ServiceException {
070            synchronized (invalidKeys) {
071                    invalidKeys.add(SimpleServiceInvoker.class.getName() + '.' + destination.getId());
072            }
073        }
074        
075        
076        private Map<String, Object> getCache(Destination destination) throws ServiceException {
077            GraniteContext context = GraniteContext.getCurrentInstance();
078            String scope = destination.getProperties().get("scope");
079    
080            Map<String, Object> cache = null;
081            if (scope == null || "request".equals(scope))
082                cache = context.getRequestMap();
083            else if ("session".equals(scope))
084                cache = context.getSessionMap();
085            else if ("application".equals(scope))
086                cache = Collections.synchronizedMap(context.getApplicationMap());
087            else
088                throw new ServiceException("Illegal scope in destination: " + destination);
089            
090            return cache;
091        }
092    }