001/* 002 * www.openamf.org 003 * 004 * Distributable under LGPL license. 005 * See terms of license at gnu.org. 006 */ 007 008package org.granite.messaging.amf; 009 010import java.io.Serializable; 011import java.lang.reflect.Array; 012import java.util.ArrayList; 013import java.util.List; 014 015import 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 */ 026public 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}