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