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 }