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/*
023 * www.openamf.org
024 *
025 * Distributable under LGPL license.
026 * See terms of license at gnu.org.
027 */
028
029package org.granite.messaging.amf;
030
031import java.io.Serializable;
032import java.lang.reflect.Array;
033import java.util.ArrayList;
034import java.util.List;
035
036import flex.messaging.messages.Message;
037
038/**
039 * AMF Body
040 *
041 * @author Jason Calabrese <jasonc@missionvi.com>
042 * @author Pat Maddox <pergesu@users.sourceforge.net>
043 * @see AMF0Header
044 * @see AMF0Message
045 * @version $Revision: 1.19 $, $Date: 2003/09/20 01:05:24 $
046 */
047public class AMF0Body implements Serializable {
048
049    private static final long serialVersionUID = 1L;
050
051    protected String target;
052    protected String serviceName;
053    protected String serviceMethodName;
054    protected String response;
055    protected Object value;
056    protected byte type;
057    /**
058     * Unknow object type
059     */
060    public static final byte DATA_TYPE_UNKNOWN = -1;
061    /**
062     * Number object type
063     */
064    public static final byte DATA_TYPE_NUMBER = 0;
065    /**
066     * Boolean object type
067     */
068    public static final byte DATA_TYPE_BOOLEAN = 1;
069    /**
070     * String object type
071     */
072    public static final byte DATA_TYPE_STRING = 2;
073    /**
074     * Object object type
075     */
076    public static final byte DATA_TYPE_OBJECT = 3;
077    /**
078     * Movie clip object type
079     */
080    public static final byte DATA_TYPE_MOVIE_CLIP = 4;
081    /**
082     * NULL object type
083     */
084    public static final byte DATA_TYPE_NULL = 5;
085    /**
086     * Undefined object type
087     */
088    public static final byte DATA_TYPE_UNDEFINED = 6;
089    /**
090     * Reference object type
091     */
092    public static final byte DATA_TYPE_REFERENCE_OBJECT = 7;
093    /**
094     * Mixed Array Object type
095     */
096    public static final byte DATA_TYPE_MIXED_ARRAY = 8;
097    /**
098     * Object end type
099     */
100    public static final byte DATA_TYPE_OBJECT_END = 9;
101    /**
102     * Array Object type
103     */
104    public static final byte DATA_TYPE_ARRAY = 10;
105    /**
106     * Date object type
107     */
108    public static final byte DATA_TYPE_DATE = 11;
109    /**
110     * Long String object type
111     */
112    public static final byte DATA_TYPE_LONG_STRING = 12;
113    /**
114     * General Object type
115     */
116    public static final byte DATA_TYPE_AS_OBJECT = 13;
117    /**
118     * RecordSet object type
119     */
120    public static final byte DATA_TYPE_RECORDSET = 14;
121    /**
122     * XML Document object type
123     */
124    public static final byte DATA_TYPE_XML = 15;
125    /**
126     * Custom class object type
127     */
128    public static final byte DATA_TYPE_CUSTOM_CLASS = 16;
129    /**
130     * AMF3 data
131     */
132    public static final byte DATA_TYPE_AMF3_OBJECT = 17;
133
134    /**
135     * AMF body with unknown type
136     *
137     * @param target
138     * @param response
139     * @param value
140     */
141    public AMF0Body(String target, String response, Object value) {
142        this(target, response, value, DATA_TYPE_UNKNOWN);
143    }
144
145    /**
146     * AMF Body constructor
147     *
148     * @param target
149     * @param response
150     * @param value
151     * @param type
152     */
153    public AMF0Body(String target, String response, Object value, byte type) {
154        this.response = response;
155        this.value = value;
156        this.type = type;
157        setTarget(target);
158    }
159
160    public String getTarget() {
161        return target;
162    }
163
164    public void setTarget(String target) {
165        this.target = target;
166        int dotIndex = target.lastIndexOf('.');
167        if (dotIndex > 0) {
168            this.serviceName = target.substring(0, dotIndex);
169            this.serviceMethodName = target.substring(dotIndex + 1);
170        }
171    }
172
173    public String getServiceName() {
174        return serviceName;
175    }
176
177    public String getServiceMethodName() {
178        return serviceMethodName;
179    }
180
181    public String getResponse() {
182        return response;
183    }
184
185    public void setResponse(String response) {
186        this.response = response;
187    }
188
189    public boolean isFirstBody() {
190        return "/1".equals(response);
191    }
192
193    public int getBodyIndex() {
194        if (response != null && response.length() > 1) {
195            try {
196                return Integer.parseInt(response.substring(1));
197            } catch (Exception e) {
198            }
199        }
200        return 0; // response starts with 1.
201    }
202
203    public Object getValue() {
204        return value;
205    }
206
207    public void setValue(Object value) {
208        this.value = value;
209    }
210    /**
211     * Returns object type
212     *
213     * @return the object type.
214     */
215    public byte getType() {
216        return type;
217    }
218    /**
219     * Sets object type
220     *
221     * @param type
222     */
223    public void setType(byte type) {
224        this.type = type;
225    }
226    /**
227     * Returns String description of object type
228     *
229     * @param type object type
230     * @return the object type description
231     */
232    public static String getObjectTypeDescription(byte type) {
233        switch (type) {
234            case DATA_TYPE_UNKNOWN:
235                return "UNKNOWN";
236            case DATA_TYPE_NUMBER:
237                return "NUMBER";
238            case DATA_TYPE_BOOLEAN:
239                return "BOOLEAN";
240            case DATA_TYPE_STRING:
241                return "STRING";
242            case DATA_TYPE_OBJECT:
243                return "OBJECT";
244            case DATA_TYPE_MOVIE_CLIP:
245                return "MOVIECLIP";
246            case DATA_TYPE_NULL:
247                return "NULL";
248            case DATA_TYPE_UNDEFINED:
249                return "UNDEFINED";
250            case DATA_TYPE_REFERENCE_OBJECT:
251                return "REFERENCE";
252            case DATA_TYPE_MIXED_ARRAY:
253                return "MIXED_ARRAY";
254            case DATA_TYPE_OBJECT_END:
255                return "OBJECT_END";
256            case DATA_TYPE_ARRAY:
257                return "ARRAY";
258            case DATA_TYPE_DATE:
259                return "DATE";
260            case DATA_TYPE_LONG_STRING:
261                return "LONG_STRING";
262            case DATA_TYPE_AS_OBJECT:
263                return "AS_OBJECT";
264            case DATA_TYPE_RECORDSET:
265                return "RECORDSET";
266            case DATA_TYPE_XML:
267                return "XML";
268            case DATA_TYPE_CUSTOM_CLASS:
269                return "CUSTOM_CLASS";
270            case DATA_TYPE_AMF3_OBJECT:
271                return "AMF3_OBJECT";
272            default:
273                return "UNKNOWN: 0x" + Integer.toBinaryString(type);
274        }
275    }
276
277    @Override
278    public String toString() {
279        return toString("");
280    }
281
282    public String toString(String indent) {
283        return (new StringBuffer(1024)
284            .append('\n').append(indent).append(AMF0Body.class.getName()).append(" {")
285            .append('\n').append(indent).append("  target = ").append(getTarget())
286            .append('\n').append(indent).append("  serviceName = ").append(getServiceName())
287            .append('\n').append(indent).append("  serviceMethodName = ").append(getServiceMethodName())
288            .append('\n').append(indent).append("  response = ").append(getResponse())
289            .append('\n').append(indent).append("  type = ").append(getObjectTypeDescription(type))
290            .append('\n').append(indent).append("  value = ").append(printValue(value, indent + "  "))
291            .append('\n').append(indent).append('}')
292            .toString()
293        );
294    }
295
296    private static String printValue(Object value, String indent) {
297
298        if (value == null)
299            return "null";
300
301        if (value instanceof AMF3Object)
302            return ((AMF3Object)value).toString(indent);
303        if (value instanceof Message)
304            return ((Message)value).toString(indent);
305
306        if (value.getClass().isArray()) {
307            final int length = Array.getLength(value);
308            List<Object> list = new ArrayList<Object>(length);
309            for (int i = 0; i < length; i++)
310                list.add(Array.get(value, i));
311            value = list;
312        }
313
314        if (value instanceof List<?>) {
315            List<?> list = (List<?>)value;
316
317            StringBuilder sb = new StringBuilder(512);
318
319            final String innerIndent = indent + "  ";
320            sb.append('[');
321            for (int i = 0; i < list.size(); i++) {
322                if (i > 0)
323                    sb.append(',');
324                sb.append('\n').append(indent).append("  ").append(printValue(list.get(i), innerIndent));
325            }
326            if (list.size() > 0)
327                sb.append('\n').append(indent);
328            sb.append(']');
329
330            return sb.toString();
331        }
332
333        return value.toString();
334    }
335}