/** * GRANITE DATA SERVICES * Copyright (C) 2006-2015 GRANITE DATA SERVICES S.A.S. * * This file is part of the Granite Data Services Platform. * * Granite Data Services is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * Granite Data Services is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser * General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA, or see <http://www.gnu.org/licenses/>. */ package org.granite.client.messaging.channel.amf; import java.io.UnsupportedEncodingException; import java.net.URI; import java.util.ArrayList; import java.util.List; import org.granite.client.messaging.channel.AbstractHTTPChannel; import org.granite.client.messaging.channel.Credentials; import org.granite.client.messaging.channel.UsernamePasswordCredentials; import org.granite.client.messaging.messages.RequestMessage; import org.granite.client.messaging.messages.push.TopicMessage; import org.granite.client.messaging.messages.requests.InvocationMessage; import org.granite.client.messaging.messages.requests.LoginMessage; import org.granite.client.messaging.messages.requests.PublishMessage; import org.granite.client.messaging.messages.requests.ReplyMessage; import org.granite.client.messaging.messages.requests.SubscribeMessage; import org.granite.client.messaging.messages.requests.UnsubscribeMessage; import org.granite.client.messaging.messages.responses.AbstractResponseMessage; import org.granite.client.messaging.messages.responses.FaultMessage; import org.granite.client.messaging.messages.responses.FaultMessage.Code; import org.granite.client.messaging.messages.responses.ResultMessage; import org.granite.client.messaging.transport.Transport; import org.granite.messaging.service.security.SecurityServiceException; import flex.messaging.messages.AcknowledgeMessage; import flex.messaging.messages.AsyncMessage; import flex.messaging.messages.CommandMessage; import flex.messaging.messages.ErrorMessage; import flex.messaging.messages.Message; import flex.messaging.messages.RemotingMessage; /** * @author Franck WOLFF */ public abstract class AbstractAMFChannel extends AbstractHTTPChannel { public AbstractAMFChannel(Transport transport, String id, URI uri, int maxConcurrentRequests) { super(transport, id, uri, maxConcurrentRequests); } protected Message[] convertToAmf(RequestMessage request) throws UnsupportedEncodingException { Message[] messages = null; switch (request.getType()) { case PING: { CommandMessage commandMessage = new CommandMessage(); commandMessage.setOperation(CommandMessage.CLIENT_PING_OPERATION); commandMessage.setMessageId(request.getId()); commandMessage.setTimestamp(request.getTimestamp()); commandMessage.setTimeToLive(request.getTimeToLive()); commandMessage.setHeaders(request.getHeaders()); messages = new Message[]{commandMessage}; break; } case LOGIN: { LoginMessage login = (LoginMessage)request; CommandMessage commandMessage = new CommandMessage(); commandMessage.setOperation(CommandMessage.LOGIN_OPERATION); commandMessage.setMessageId(request.getId()); commandMessage.setTimestamp(request.getTimestamp()); commandMessage.setTimeToLive(request.getTimeToLive()); commandMessage.setHeaders(request.getHeaders()); Credentials credentials = login.getCredentials(); if (credentials instanceof UsernamePasswordCredentials) commandMessage.setBody(((UsernamePasswordCredentials)credentials).encodeBase64()); else throw new UnsupportedOperationException("Unsupported credentials type: " + credentials); messages = new Message[]{commandMessage}; break; } case LOGOUT: { CommandMessage commandMessage = new CommandMessage(); commandMessage.setOperation(CommandMessage.LOGOUT_OPERATION); commandMessage.setMessageId(request.getId()); commandMessage.setTimestamp(request.getTimestamp()); commandMessage.setTimeToLive(request.getTimeToLive()); commandMessage.setHeaders(request.getHeaders()); messages = new Message[]{commandMessage}; break; } case PUBLISH: { PublishMessage publish = (PublishMessage)request; AsyncMessage asyncMessage = new AsyncMessage(); asyncMessage.setMessageId(publish.getId()); asyncMessage.setTimestamp(publish.getTimestamp()); asyncMessage.setTimeToLive(publish.getTimeToLive()); asyncMessage.setHeaders(publish.getHeaders()); asyncMessage.setDestination(publish.getDestination()); asyncMessage.setHeader(AsyncMessage.SUBTOPIC_HEADER, publish.getTopic()); asyncMessage.setBody(publish.getBody()); messages = new Message[]{asyncMessage}; break; } case REPLY: { ReplyMessage reply = (ReplyMessage)request; AsyncMessage asyncMessage = new AsyncMessage(); asyncMessage.setMessageId(reply.getId()); asyncMessage.setTimestamp(reply.getTimestamp()); asyncMessage.setTimeToLive(reply.getTimeToLive()); asyncMessage.setHeaders(reply.getHeaders()); asyncMessage.setDestination(reply.getDestination()); asyncMessage.setHeader(AsyncMessage.SUBTOPIC_HEADER, reply.getTopic()); asyncMessage.setCorrelationId(reply.getCorrelationId()); asyncMessage.setBody(reply.getBody()); messages = new Message[]{asyncMessage}; break; } case SUBSCRIBE: { SubscribeMessage subscribe = (SubscribeMessage)request; CommandMessage commandMessage = new CommandMessage(); commandMessage.setOperation(CommandMessage.SUBSCRIBE_OPERATION); commandMessage.setMessageId(subscribe.getId()); commandMessage.setTimestamp(subscribe.getTimestamp()); commandMessage.setTimeToLive(subscribe.getTimeToLive()); commandMessage.setHeaders(subscribe.getHeaders()); commandMessage.setDestination(subscribe.getDestination()); commandMessage.setHeader(AsyncMessage.SUBTOPIC_HEADER, subscribe.getTopic()); if (subscribe.getSubscriptionId() != null) commandMessage.setHeader(CommandMessage.DESTINATION_CLIENT_ID_HEADER, subscribe.getSubscriptionId()); if (subscribe.getSelector() != null) commandMessage.setHeader(CommandMessage.SELECTOR_HEADER, subscribe.getSelector()); messages = new Message[]{commandMessage}; break; } case UNSUBSCRIBE: { UnsubscribeMessage unsubscribe = (UnsubscribeMessage)request; CommandMessage commandMessage = new CommandMessage(); commandMessage.setOperation(CommandMessage.UNSUBSCRIBE_OPERATION); commandMessage.setMessageId(unsubscribe.getId()); commandMessage.setTimestamp(unsubscribe.getTimestamp()); commandMessage.setTimeToLive(unsubscribe.getTimeToLive()); commandMessage.setHeaders(unsubscribe.getHeaders()); commandMessage.setDestination(unsubscribe.getDestination()); commandMessage.setHeader(AsyncMessage.SUBTOPIC_HEADER, unsubscribe.getTopic()); commandMessage.setHeader(AsyncMessage.DESTINATION_CLIENT_ID_HEADER, unsubscribe.getSubscriptionId()); messages = new Message[]{commandMessage}; break; } case INVOCATION: { List<Message> remotingMessages = new ArrayList<Message>(); for (InvocationMessage invocation : (InvocationMessage)request) { RemotingMessage remotingMessage = new RemotingMessage(); remotingMessage.setDestination(invocation.getServiceId()); remotingMessage.setOperation(invocation.getMethod()); remotingMessage.setBody(invocation.getParameters() != null ? invocation.getParameters() : new Object[0]); remotingMessage.setMessageId(invocation.getId()); remotingMessage.setTimestamp(invocation.getTimestamp()); remotingMessage.setTimeToLive(invocation.getTimeToLive()); remotingMessage.setHeaders(invocation.getHeaders()); remotingMessages.add(remotingMessage); } messages = remotingMessages.toArray(new Message[remotingMessages.size()]); break; } case DISCONNECT: { CommandMessage commandMessage = new CommandMessage(); commandMessage.setOperation(CommandMessage.DISCONNECT_OPERATION); commandMessage.setMessageId(request.getId()); commandMessage.setTimestamp(request.getTimestamp()); commandMessage.setTimeToLive(request.getTimeToLive()); commandMessage.setHeaders(request.getHeaders()); messages = new Message[]{commandMessage}; break; } default: throw new IllegalArgumentException("Unsupported message type: " + request); } for (Message message : messages) { message.setClientId(getClientId()); message.setHeader(Message.ENDPOINT_HEADER, getId()); } return messages; } protected TopicMessage convertFromAmf(AsyncMessage message) { return new TopicMessage( message.getMessageId(), (String)message.getClientId(), message.getTimestamp(), message.getTimeToLive(), message.getHeaders(), message.getBody() ); } protected AbstractResponseMessage convertFromAmf(AcknowledgeMessage message) { if (message instanceof ErrorMessage) { ErrorMessage errorMessage = (ErrorMessage)message; Code code = Code.UNKNOWN; boolean deauthenticate = false; String flexCode = errorMessage.getFaultCode(); if (ErrorMessage.CODE_SERVER_CALL_FAILED.equals(flexCode)) code = Code.SERVER_CALL_FAILED; else if (SecurityServiceException.CODE_ACCESS_DENIED.equals(flexCode)) code = Code.ACCESS_DENIED; else if (SecurityServiceException.CODE_INVALID_CREDENTIALS.equals(flexCode)) { deauthenticate = true; code = Code.INVALID_CREDENTIALS; } else if (SecurityServiceException.CODE_AUTHENTICATION_FAILED.equals(flexCode)) { deauthenticate = true; code = Code.AUTHENTICATION_FAILED; } else if (SecurityServiceException.CODE_NOT_LOGGED_IN.equals(flexCode)) { deauthenticate = true; code = Code.NOT_LOGGED_IN; } else if (SecurityServiceException.CODE_SESSION_EXPIRED.equals(flexCode)) { deauthenticate = true; code = Code.SESSION_EXPIRED; } else if ("Validation.Failed".equals(flexCode)) code = Code.VALIDATION_FAILED; else if ("Persistence.OptimisticLock".equals(flexCode)) code = Code.OPTIMISTIC_LOCK; FaultMessage fault = new FaultMessage( errorMessage.getMessageId(), (String)errorMessage.getClientId(), errorMessage.getTimestamp(), errorMessage.getTimeToLive(), errorMessage.getHeaders(), errorMessage.getCorrelationId(), code, errorMessage.getFaultString(), errorMessage.getFaultDetail(), errorMessage.getRootCause(), errorMessage.getExtendedData() ); if (code == Code.UNKNOWN) fault.setUnknownCode(flexCode); if (isAuthenticated() && deauthenticate) setAuthenticated(false, fault); return fault; } return new ResultMessage( message.getMessageId(), (String)message.getClientId(), message.getTimestamp(), message.getTimeToLive(), message.getHeaders(), message.getCorrelationId(), message.getBody() ); } }