001 /**
002 * GRANITE DATA SERVICES
003 * Copyright (C) 2006-2013 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 package org.granite.client.messaging.channel.amf;
021
022 import java.io.UnsupportedEncodingException;
023 import java.net.URI;
024 import java.util.ArrayList;
025 import java.util.List;
026
027 import org.granite.client.messaging.channel.AbstractHTTPChannel;
028 import org.granite.client.messaging.channel.Credentials;
029 import org.granite.client.messaging.channel.UsernamePasswordCredentials;
030 import org.granite.client.messaging.messages.RequestMessage;
031 import org.granite.client.messaging.messages.push.TopicMessage;
032 import org.granite.client.messaging.messages.requests.InvocationMessage;
033 import org.granite.client.messaging.messages.requests.LoginMessage;
034 import org.granite.client.messaging.messages.requests.PublishMessage;
035 import org.granite.client.messaging.messages.requests.SubscribeMessage;
036 import org.granite.client.messaging.messages.requests.UnsubscribeMessage;
037 import org.granite.client.messaging.messages.responses.AbstractResponseMessage;
038 import org.granite.client.messaging.messages.responses.FaultMessage;
039 import org.granite.client.messaging.messages.responses.FaultMessage.Code;
040 import org.granite.client.messaging.messages.responses.ResultMessage;
041 import org.granite.client.messaging.transport.Transport;
042 import org.granite.messaging.service.security.SecurityServiceException;
043
044 import flex.messaging.messages.AcknowledgeMessage;
045 import flex.messaging.messages.AsyncMessage;
046 import flex.messaging.messages.CommandMessage;
047 import flex.messaging.messages.ErrorMessage;
048 import flex.messaging.messages.Message;
049 import flex.messaging.messages.RemotingMessage;
050
051 /**
052 * @author Franck WOLFF
053 */
054 public abstract class AbstractAMFChannel extends AbstractHTTPChannel {
055
056 public AbstractAMFChannel(Transport transport, String id, URI uri, int maxConcurrentRequests) {
057 super(transport, id, uri, maxConcurrentRequests);
058 }
059
060 protected Message[] convertToAmf(RequestMessage request) throws UnsupportedEncodingException {
061 Message[] messages = null;
062
063 switch (request.getType()) {
064 case PING: {
065 CommandMessage commandMessage = new CommandMessage();
066 commandMessage.setOperation(CommandMessage.CLIENT_PING_OPERATION);
067 commandMessage.setMessageId(request.getId());
068 commandMessage.setTimestamp(request.getTimestamp());
069 commandMessage.setTimeToLive(request.getTimeToLive());
070 commandMessage.setHeaders(request.getHeaders());
071 messages = new Message[]{commandMessage};
072 break;
073 }
074 case LOGIN: {
075 LoginMessage login = (LoginMessage)request;
076 CommandMessage commandMessage = new CommandMessage();
077 commandMessage.setOperation(CommandMessage.LOGIN_OPERATION);
078 commandMessage.setMessageId(request.getId());
079 commandMessage.setTimestamp(request.getTimestamp());
080 commandMessage.setTimeToLive(request.getTimeToLive());
081 commandMessage.setHeaders(request.getHeaders());
082 Credentials credentials = login.getCredentials();
083 if (credentials instanceof UsernamePasswordCredentials)
084 commandMessage.setBody(((UsernamePasswordCredentials)credentials).encodeBase64());
085 else
086 throw new UnsupportedOperationException("Unsupported credentials type: " + credentials);
087 messages = new Message[]{commandMessage};
088 break;
089 }
090 case LOGOUT: {
091 CommandMessage commandMessage = new CommandMessage();
092 commandMessage.setOperation(CommandMessage.LOGOUT_OPERATION);
093 commandMessage.setMessageId(request.getId());
094 commandMessage.setTimestamp(request.getTimestamp());
095 commandMessage.setTimeToLive(request.getTimeToLive());
096 commandMessage.setHeaders(request.getHeaders());
097 messages = new Message[]{commandMessage};
098 break;
099 }
100 case PUBLISH: {
101 PublishMessage publish = (PublishMessage)request;
102 AsyncMessage asyncMessage = new AsyncMessage();
103 asyncMessage.setMessageId(publish.getId());
104 asyncMessage.setTimestamp(publish.getTimestamp());
105 asyncMessage.setTimeToLive(publish.getTimeToLive());
106 asyncMessage.setHeaders(publish.getHeaders());
107 asyncMessage.setDestination(publish.getDestination());
108 asyncMessage.setHeader(AsyncMessage.SUBTOPIC_HEADER, publish.getTopic());
109 asyncMessage.setBody(publish.getBody());
110 messages = new Message[]{asyncMessage};
111 break;
112 }
113 case SUBSCRIBE: {
114 SubscribeMessage subscribe = (SubscribeMessage)request;
115 CommandMessage commandMessage = new CommandMessage();
116 commandMessage.setOperation(CommandMessage.SUBSCRIBE_OPERATION);
117 commandMessage.setMessageId(subscribe.getId());
118 commandMessage.setTimestamp(subscribe.getTimestamp());
119 commandMessage.setTimeToLive(subscribe.getTimeToLive());
120 commandMessage.setHeaders(subscribe.getHeaders());
121 commandMessage.setDestination(subscribe.getDestination());
122 commandMessage.setHeader(AsyncMessage.SUBTOPIC_HEADER, subscribe.getTopic());
123 if (subscribe.getSelector() != null)
124 commandMessage.setHeader(CommandMessage.SELECTOR_HEADER, subscribe.getSelector());
125 messages = new Message[]{commandMessage};
126 break;
127 }
128 case UNSUBSCRIBE: {
129 UnsubscribeMessage unsubscribe = (UnsubscribeMessage)request;
130 CommandMessage commandMessage = new CommandMessage();
131 commandMessage.setOperation(CommandMessage.UNSUBSCRIBE_OPERATION);
132 commandMessage.setMessageId(unsubscribe.getId());
133 commandMessage.setTimestamp(unsubscribe.getTimestamp());
134 commandMessage.setTimeToLive(unsubscribe.getTimeToLive());
135 commandMessage.setHeaders(unsubscribe.getHeaders());
136 commandMessage.setDestination(unsubscribe.getDestination());
137 commandMessage.setHeader(AsyncMessage.SUBTOPIC_HEADER, unsubscribe.getTopic());
138 commandMessage.setHeader(AsyncMessage.DESTINATION_CLIENT_ID_HEADER, unsubscribe.getSubscriptionId());
139 messages = new Message[]{commandMessage};
140 break;
141 }
142 case INVOCATION: {
143 List<Message> remotingMessages = new ArrayList<Message>();
144
145 for (InvocationMessage invocation : (InvocationMessage)request) {
146 RemotingMessage remotingMessage = new RemotingMessage();
147 remotingMessage.setDestination(invocation.getServiceId());
148 remotingMessage.setOperation(invocation.getMethod());
149 remotingMessage.setBody(invocation.getParameters() != null ? invocation.getParameters() : new Object[0]);
150 remotingMessage.setMessageId(invocation.getId());
151 remotingMessage.setTimestamp(invocation.getTimestamp());
152 remotingMessage.setTimeToLive(invocation.getTimeToLive());
153 remotingMessage.setHeaders(invocation.getHeaders());
154 remotingMessages.add(remotingMessage);
155 }
156
157 messages = remotingMessages.toArray(new Message[remotingMessages.size()]);
158 break;
159 }
160 case DISCONNECT: {
161 CommandMessage commandMessage = new CommandMessage();
162 commandMessage.setOperation(CommandMessage.DISCONNECT_OPERATION);
163 commandMessage.setMessageId(request.getId());
164 commandMessage.setTimestamp(request.getTimestamp());
165 commandMessage.setTimeToLive(request.getTimeToLive());
166 commandMessage.setHeaders(request.getHeaders());
167 messages = new Message[]{commandMessage};
168 break;
169 }
170 default:
171 throw new IllegalArgumentException("Unsupported message type: " + request);
172 }
173
174 for (Message message : messages) {
175 message.setClientId(getClientId());
176 message.setHeader(Message.ENDPOINT_HEADER, getId());
177 }
178
179 return messages;
180 }
181
182 protected TopicMessage convertFromAmf(AsyncMessage message) {
183 return new TopicMessage(
184 message.getMessageId(),
185 (String)message.getClientId(),
186 message.getTimestamp(),
187 message.getTimeToLive(),
188 message.getHeaders(),
189 message.getBody()
190 );
191 }
192
193 protected AbstractResponseMessage convertFromAmf(AcknowledgeMessage message) {
194 if (message instanceof ErrorMessage) {
195 ErrorMessage errorMessage = (ErrorMessage)message;
196
197 Code code = Code.UNKNOWN;
198
199 String flexCode = errorMessage.getFaultCode();
200 if (ErrorMessage.CODE_SERVER_CALL_FAILED.equals(flexCode))
201 code = Code.SERVER_CALL_FAILED;
202 else if (SecurityServiceException.CODE_ACCESS_DENIED.equals(flexCode))
203 code = Code.ACCESS_DENIED;
204 else if (SecurityServiceException.CODE_INVALID_CREDENTIALS.equals(flexCode)) {
205 authenticated = false;
206 code = Code.INVALID_CREDENTIALS;
207 }
208 else if (SecurityServiceException.CODE_AUTHENTICATION_FAILED.equals(flexCode)) {
209 authenticated = false;
210 code = Code.AUTHENTICATION_FAILED;
211 }
212 else if (SecurityServiceException.CODE_NOT_LOGGED_IN.equals(flexCode)) {
213 authenticated = false;
214 code = Code.NOT_LOGGED_IN;
215 }
216 else if (SecurityServiceException.CODE_SESSION_EXPIRED.equals(flexCode)) {
217 authenticated = false;
218 code = Code.SESSION_EXPIRED;
219 }
220 else if ("Validation.Failed".equals(flexCode))
221 code = Code.VALIDATION_FAILED;
222 else if ("Persistence.OptimisticLock".equals(flexCode))
223 code = Code.OPTIMISTIC_LOCK;
224
225 FaultMessage fault = new FaultMessage(
226 errorMessage.getMessageId(),
227 (String)errorMessage.getClientId(),
228 errorMessage.getTimestamp(),
229 errorMessage.getTimeToLive(),
230 errorMessage.getHeaders(),
231 errorMessage.getCorrelationId(),
232 code,
233 errorMessage.getFaultString(),
234 errorMessage.getFaultDetail(),
235 errorMessage.getRootCause(),
236 errorMessage.getExtendedData()
237 );
238
239 if (code == Code.UNKNOWN)
240 fault.setUnknownCode(flexCode);
241
242 return fault;
243 }
244
245 return new ResultMessage(
246 message.getMessageId(),
247 (String)message.getClientId(),
248 message.getTimestamp(),
249 message.getTimeToLive(),
250 message.getHeaders(),
251 message.getCorrelationId(),
252 message.getBody()
253 );
254 }
255 }