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 021package org.granite.messaging.amf.process; 022 023import java.util.Iterator; 024import java.util.List; 025 026import org.granite.context.AMFContextImpl; 027import org.granite.context.GraniteContext; 028import org.granite.logging.Logger; 029import org.granite.messaging.amf.AMF0Body; 030import org.granite.messaging.amf.AMF0Message; 031import org.granite.messaging.amf.AMF3Object; 032import org.granite.util.UUIDUtil; 033 034import flex.messaging.messages.ErrorMessage; 035import flex.messaging.messages.Message; 036 037/** 038 * @author Franck WOLFF 039 */ 040public abstract class AMF0MessageProcessor { 041 042 private static final Logger log = Logger.getLogger(AMF0MessageProcessor.class); 043 044 public static AMF0Message process(AMF0Message amf0RequestMessage) { 045 046 log.debug(">> Processing AMF0 request:%s", amf0RequestMessage); 047 048 GraniteContext context = GraniteContext.getCurrentInstance(); 049 AMFContextImpl amf = (AMFContextImpl)context.getAMFContext(); 050 051 AMF0Message amf0ResponseMessage = new AMF0Message(); 052 amf0ResponseMessage.setVersion(amf0RequestMessage.getVersion()); 053 054 ErrorMessage loginError = null; 055 String dsId = null; 056 for (Iterator<AMF0Body> bodies = amf0RequestMessage.getBodies(); bodies.hasNext(); ) { 057 AMF0Body requestBody = bodies.next(); 058 059 Object value = requestBody.getValue(); 060 061 Message amf3RequestMessage = null; 062 063 if (value instanceof List<?>) 064 amf3RequestMessage = (Message)((List<?>)value).get(0); 065 else 066 amf3RequestMessage = (Message)((Object[])value)[0]; 067 068 log.debug(">> Processing AMF3 request:\n%s", amf3RequestMessage); 069 070 // If we get a login error (setCredentials on flex side), we don't execute subsequent requests and 071 // just copy the initial login error (GDS specific, otherwise the FaultEvent dispatched by the 072 // RemoteObject is not the login error but an authorization error after actual service call). 073 Message amf3ResponseMessage = null; 074 if (loginError == null) { 075 amf.setCurrentAmf3Message(amf3RequestMessage); 076 077 amf.getCustomResponseHeaders().clear(); 078 amf3ResponseMessage = AMF3MessageProcessor.process(amf3RequestMessage); 079 080 if ((amf3ResponseMessage instanceof ErrorMessage) && ((ErrorMessage)amf3ResponseMessage).loginError()) 081 loginError = (ErrorMessage)amf3ResponseMessage; 082 083 // For SDK 2.0.1_Hotfix2+ (LCDS 2.5+). 084 if ("nil".equals(amf3ResponseMessage.getHeader(Message.DS_ID_HEADER))) { 085 amf3ResponseMessage.getHeaders().put( 086 Message.DS_ID_HEADER, 087 (dsId == null ? (dsId = UUIDUtil.randomUUID()) : dsId) 088 ); 089 } 090 amf3ResponseMessage.getHeaders().putAll(amf.getCustomResponseHeaders()); 091 } 092 else 093 amf3ResponseMessage = loginError.copy(amf3RequestMessage); 094 095 log.debug("<< Got AMF3 response:\n%s", amf3ResponseMessage); 096 097 AMF3Object data = new AMF3Object(amf3ResponseMessage); 098 AMF0Body responseBody = new AMF0Body( 099 getResponseTarget(requestBody, amf3ResponseMessage), "", data, AMF0Body.DATA_TYPE_AMF3_OBJECT 100 ); 101 amf0ResponseMessage.addBody(responseBody); 102 } 103 104 log.debug("<< Returning AMF0 response:%s", amf0ResponseMessage); 105 106 return amf0ResponseMessage; 107 } 108 109 private static String getResponseTarget(AMF0Body requestBody, Message responseMessage) { 110 if (responseMessage instanceof ErrorMessage) 111 return requestBody.getResponse() + "/onStatus"; 112 return requestBody.getResponse() + "/onResult"; 113 } 114}