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.messaging.amf.process;
023    
024    import java.util.Date;
025    
026    import org.granite.config.GraniteConfig;
027    import org.granite.context.GraniteContext;
028    import org.granite.logging.Logger;
029    import org.granite.messaging.service.ServiceException;
030    import org.granite.messaging.service.ServiceFactory;
031    import org.granite.messaging.service.ServiceInvoker;
032    import org.granite.messaging.service.security.SecurityService;
033    import org.granite.messaging.service.security.SecurityServiceException;
034    import org.granite.messaging.webapp.ServletGraniteContext;
035    import org.granite.util.UUIDUtil;
036    
037    import flex.messaging.messages.AcknowledgeMessage;
038    import flex.messaging.messages.CommandMessage;
039    import flex.messaging.messages.ErrorMessage;
040    import flex.messaging.messages.Message;
041    import flex.messaging.messages.RemotingMessage;
042    
043    /**
044     * @author Franck WOLFF
045     */
046    public abstract class AMF3MessageProcessor {
047    
048        private static final Logger log = Logger.getLogger(AMF3MessageProcessor.class);
049    
050        public static Message process(Message request) {
051            GraniteContext context = GraniteContext.getCurrentInstance();
052            AMF3MessageInterceptor interceptor = context.getGraniteConfig().getAmf3MessageInterceptor();
053            
054            Message response = null;
055            try {
056                    if (interceptor != null)
057                        interceptor.before(request);
058                    
059                    if (request instanceof RemotingMessage)
060                        response = processRemotingMessage((RemotingMessage)request);
061                    else if (request instanceof CommandMessage)
062                        response = processCommandMessage((CommandMessage)request);
063                    else
064                        throw new IllegalArgumentException("Unknown request message type: " + request);
065            }
066            finally {
067                    if (interceptor != null)
068                        interceptor.after(request, response);
069            }
070            
071            if (context.getSessionId() != null) {
072                response.setHeader("org.granite.sessionId", context.getSessionId());
073                if (((ServletGraniteContext)context).getSession(false) != null) {
074                    long serverTime = new Date().getTime();
075                    ((ServletGraniteContext)context).getSession().setAttribute(GraniteContext.SESSION_LAST_ACCESSED_TIME_KEY, serverTime);
076                    response.setHeader("org.granite.time", serverTime);
077                        response.setHeader("org.granite.sessionExp", ((ServletGraniteContext)context).getSession().getMaxInactiveInterval());
078                }
079            }
080            
081            return response;
082        }
083    
084        public static Message processCommandMessage(CommandMessage request) {
085    
086            log.debug(">> Processing AMF3 request:\n%s", request);
087    
088            Message response = null;
089            if (request.isSecurityOperation()) {
090                GraniteContext context = GraniteContext.getCurrentInstance();
091                GraniteConfig config = context.getGraniteConfig();
092    
093                if (!config.hasSecurityService())
094                    log.warn("Ignored security operation (no security settings in granite-config.xml): %s", request);
095                else {
096                    SecurityService securityService = config.getSecurityService();
097                    try {
098                        if (request.isLoginOperation())
099                            securityService.login(request.getBody(), (String)request.getHeader(Message.CREDENTIALS_CHARSET_HEADER));
100                        else if (request.isLogoutOperation())
101                            securityService.logout();
102                        else
103                            log.warn("Unknown security operation: %s", request);
104                    } catch (Exception e) {
105                        if (e instanceof SecurityServiceException) {
106                            securityService.handleSecurityException((SecurityServiceException)e);
107                            log.debug(e, "Could not process security operation: %s", request);
108                        }
109                        else
110                            log.error(e, "Could not process security operation: %s", request);
111                        response = new ErrorMessage(request, e);
112                    }
113                }
114            }
115    
116            if (response == null) {
117                response = new AcknowledgeMessage(request);
118                // For SDK 2.0.1_Hotfix2.
119                if (request.isSecurityOperation())
120                    response.setBody("success");
121            }
122    
123            // For SDK 2.0.1_Hotfix2.
124            if ("nil".equals(request.getHeader(Message.DS_ID_HEADER)))
125                response.getHeaders().put(Message.DS_ID_HEADER, UUIDUtil.randomUUID());
126    
127            log.debug("<< Returning AMF3 response:\n%s", response);
128    
129            return response;
130        }
131    
132        public static Message processRemotingMessage(RemotingMessage request) {
133    
134            log.debug(">> Processing AMF3 request:\n%s", request);
135            
136            Message response = null;
137            try {
138                // Execute method on service.
139                ServiceFactory factory = ServiceFactory.getFactoryInstance(request);
140                ServiceInvoker<?> service = factory.getServiceInstance(request);
141                Object result = service.invoke(request);
142    
143                response = new AcknowledgeMessage(request);
144                response.setBody(result);
145            } catch (ServiceException e) {
146                log.debug(e, "Could not process remoting message: %s", request);
147                response = new ErrorMessage(request, e);
148            }
149    
150            log.debug("<< Returning AMF3 response:\n%s", response);
151    
152            return response;
153        }
154    }