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 */ 022package org.granite.messaging.amf.io; 023 024import java.io.DataOutputStream; 025import java.io.Externalizable; 026import java.io.IOException; 027import java.io.ObjectOutput; 028import java.io.OutputStream; 029import java.lang.reflect.Array; 030import java.math.BigDecimal; 031import java.math.BigInteger; 032import java.util.Calendar; 033import java.util.Collection; 034import java.util.Date; 035import java.util.HashMap; 036import java.util.IdentityHashMap; 037import java.util.Map; 038 039import org.granite.config.flex.Channel; 040import org.granite.context.GraniteContext; 041import org.granite.logging.Logger; 042import org.granite.messaging.amf.AMF3Constants; 043import org.granite.messaging.amf.io.convert.Converters; 044import org.granite.messaging.amf.io.util.ClassGetter; 045import org.granite.messaging.amf.io.util.DefaultJavaClassDescriptor; 046import org.granite.messaging.amf.io.util.IndexedJavaClassDescriptor; 047import org.granite.messaging.amf.io.util.JavaClassDescriptor; 048import org.granite.messaging.amf.io.util.externalizer.Externalizer; 049import org.granite.messaging.amf.types.AMFDictionaryValue; 050import org.granite.messaging.amf.types.AMFSpecialValue; 051import org.granite.messaging.amf.types.AMFSpecialValueFactory; 052import org.granite.messaging.amf.types.AMFVectorIntValue; 053import org.granite.messaging.amf.types.AMFVectorNumberValue; 054import org.granite.messaging.amf.types.AMFVectorObjectValue; 055import org.granite.messaging.amf.types.AMFVectorUintValue; 056import org.granite.util.TypeUtil; 057import org.granite.util.XMLUtil; 058import org.granite.util.XMLUtilFactory; 059import org.w3c.dom.Document; 060 061import flex.messaging.io.ArrayCollection; 062 063/** 064 * @author Franck WOLFF 065 */ 066public class AMF3Serializer extends DataOutputStream implements ObjectOutput, AMF3Constants { 067 068 /////////////////////////////////////////////////////////////////////////// 069 // Fields. 070 071 protected static final Logger log = Logger.getLogger(AMF3Serializer.class); 072 protected static final Logger logMore = Logger.getLogger(AMF3Serializer.class.getName() + "_MORE"); 073 074 protected final Map<String, Integer> storedStrings = new HashMap<String, Integer>(); 075 protected final Map<Object, Integer> storedObjects = new IdentityHashMap<Object, Integer>(); 076 protected final Map<String, IndexedJavaClassDescriptor> storedClassDescriptors 077 = new HashMap<String, IndexedJavaClassDescriptor>(); 078 079 protected final GraniteContext context = GraniteContext.getCurrentInstance(); 080 protected final Converters converters = context.getGraniteConfig().getConverters(); 081 082 protected final boolean externalizeLong 083 = (context.getGraniteConfig().getExternalizer(Long.class.getName()) != null); 084 protected final boolean externalizeBigInteger 085 = (context.getGraniteConfig().getExternalizer(BigInteger.class.getName()) != null); 086 protected final boolean externalizeBigDecimal 087 = (context.getGraniteConfig().getExternalizer(BigDecimal.class.getName()) != null); 088 089 protected final XMLUtil xmlUtil = XMLUtilFactory.getXMLUtil(); 090 091 // TODO: allow aliaser configuration in granite-config.xml 092 protected final AMFSpecialValueFactory specialValueFactory = new AMFSpecialValueFactory(); 093 094 protected final boolean debug = log.isDebugEnabled(); 095 protected final boolean debugMore = logMore.isDebugEnabled(); 096 097 protected Channel channel = null; 098 099 /////////////////////////////////////////////////////////////////////////// 100 // Constructor. 101 102 public AMF3Serializer(OutputStream out) { 103 super(out); 104 105 if (debugMore) logMore.debug("new AMF3Serializer(out=%s)", out); 106 } 107 108 /////////////////////////////////////////////////////////////////////////// 109 // ObjectOutput implementation. 110 111 public void writeObject(Object o) throws IOException { 112 if (debugMore) logMore.debug("writeObject(o=%s)", o); 113 114 try { 115 if (o == null) 116 write(AMF3_NULL); 117 else if (o instanceof AMFSpecialValue) 118 writeAMF3SpecialValue((AMFSpecialValue<?>)o); 119 else if (!(o instanceof Externalizable)) { 120 121 if (converters.hasReverters()) 122 o = converters.revert(o); 123 124 if (o == null) 125 write(AMF3_NULL); 126 else if (o instanceof String || o instanceof Character) 127 writeAMF3String(o.toString()); 128 else if (o instanceof Boolean) 129 write(((Boolean)o).booleanValue() ? AMF3_BOOLEAN_TRUE : AMF3_BOOLEAN_FALSE); 130 else if (o instanceof Number) { 131 if (o instanceof Integer || o instanceof Short || o instanceof Byte) 132 writeAMF3Integer(((Number)o).intValue()); 133 else if (externalizeLong && o instanceof Long) 134 writeAMF3Object(o); 135 else if (externalizeBigInteger && o instanceof BigInteger) 136 writeAMF3Object(o); 137 else if (externalizeBigDecimal && o instanceof BigDecimal) 138 writeAMF3Object(o); 139 else 140 writeAMF3Number(((Number)o).doubleValue()); 141 } 142 else if (o instanceof Date) 143 writeAMF3Date((Date)o); 144 else if (o instanceof Calendar) 145 writeAMF3Date(((Calendar)o).getTime()); 146 else if (o instanceof Document) 147 writeAMF3Xml((Document)o); 148 else if (o instanceof Collection<?>) 149 writeAMF3Collection((Collection<?>)o); 150 else if (o.getClass().isArray()) { 151 if (o.getClass().getComponentType() == Byte.TYPE) 152 writeAMF3ByteArray((byte[])o); 153 else 154 writeAMF3Array(o); 155 } 156 else 157 writeAMF3Object(o); 158 } 159 else 160 writeAMF3Object(o); 161 } 162 catch (IOException e) { 163 throw e; 164 } 165 catch (Exception e) { 166 throw new AMF3SerializationException(e); 167 } 168 } 169 170 /////////////////////////////////////////////////////////////////////////// 171 // AMF3 serialization. 172 173 protected void writeAMF3SpecialValue(AMFSpecialValue<?> value) throws IOException { 174 if (debugMore) logMore.debug("writeAMF3SpecialValue(value=%s)", value); 175 176 switch (value.type) { 177 case AMF3_DICTIONARY: 178 writeAMF3Dictionary((AMFDictionaryValue)value); 179 break; 180 case AMF3_VECTOR_INT: 181 writeAMF3VectorInt((AMFVectorIntValue)value); 182 break; 183 case AMF3_VECTOR_NUMBER: 184 writeAMF3VectorNumber((AMFVectorNumberValue)value); 185 break; 186 case AMF3_VECTOR_UINT: 187 writeAMF3VectorUint((AMFVectorUintValue)value); 188 break; 189 case AMF3_VECTOR_OBJECT: 190 writeAMF3VectorObject((AMFVectorObjectValue)value); 191 break; 192 default: 193 throw new RuntimeException("Unsupported AMF special value: " + value); 194 } 195 } 196 197 protected void writeAMF3VectorObject(AMFVectorObjectValue value) throws IOException { 198 if (debugMore) logMore.debug("writeAMF3VectorObject(value=%s)", value); 199 200 write(AMF3_VECTOR_OBJECT); 201 202 Object o = value.value; 203 204 int index = indexOfStoredObjects(o); 205 if (index >= 0) 206 writeAMF3IntegerData(index << 1); 207 else { 208 addToStoredObjects(o); 209 210 int length = getArrayOrCollectionLength(o); 211 writeAMF3IntegerData(length << 1 | 0x01); 212 write(value.fixed ? 0x01 : 0x00); 213 writeAMF3StringData(value.type); 214 215 if (o.getClass().isArray()) { 216 for (int i = 0; i < length; i++) 217 writeObject(Array.get(o, i)); 218 } 219 else { 220 for (Object item : (Collection<?>)o) 221 writeObject(item); 222 } 223 } 224 } 225 226 protected void writeAMF3VectorInt(AMFVectorIntValue value) throws IOException { 227 if (debugMore) logMore.debug("writeAMF3VectorInt(value=%s)", value); 228 229 write(AMF3_VECTOR_INT); 230 231 Object o = value.value; 232 233 int index = indexOfStoredObjects(o); 234 if (index >= 0) 235 writeAMF3IntegerData(index << 1); 236 else { 237 addToStoredObjects(o); 238 239 int length = getArrayOrCollectionLength(o); 240 writeAMF3IntegerData(length << 1 | 0x01); 241 write(value.fixed ? 0x01 : 0x00); 242 243 if (o.getClass().isArray()) { 244 for (int i = 0; i < length; i++) 245 writeInt(((Number)Array.get(o, i)).intValue()); 246 } 247 else { 248 for (Object item : (Collection<?>)o) 249 writeInt(((Number)item).intValue()); 250 } 251 } 252 } 253 254 protected void writeAMF3VectorNumber(AMFVectorNumberValue value) throws IOException { 255 if (debugMore) logMore.debug("writeAMF3VectorNumber(value=%s)", value); 256 257 write(AMF3_VECTOR_NUMBER); 258 259 Object o = value.value; 260 261 int index = indexOfStoredObjects(o); 262 if (index >= 0) 263 writeAMF3IntegerData(index << 1); 264 else { 265 addToStoredObjects(o); 266 267 int length = getArrayOrCollectionLength(o); 268 writeAMF3IntegerData(length << 1 | 0x01); 269 write(value.fixed ? 0x01 : 0x00); 270 271 if (o.getClass().isArray()) { 272 for (int i = 0; i < length; i++) 273 writeDouble(((Number)Array.get(o, i)).doubleValue()); 274 } 275 else { 276 for (Object item : (Collection<?>)o) 277 writeDouble(((Number)item).doubleValue()); 278 } 279 } 280 } 281 282 protected void writeAMF3VectorUint(AMFVectorUintValue value) throws IOException { 283 if (debugMore) logMore.debug("writeAMF3VectorUint(value=%s)", value); 284 285 write(AMF3_VECTOR_UINT); 286 287 Object o = value.value; 288 289 int index = indexOfStoredObjects(o); 290 if (index >= 0) 291 writeAMF3IntegerData(index << 1); 292 else { 293 addToStoredObjects(o); 294 295 int length = getArrayOrCollectionLength(o); 296 writeAMF3IntegerData(length << 1 | 0x01); 297 write(value.fixed ? 0x01 : 0x00); 298 299 if (o.getClass().isArray()) { 300 for (int i = 0; i < length; i++) 301 writeInt(((Number)Array.get(o, i)).intValue()); 302 } 303 else { 304 for (Object item : (Collection<?>)o) 305 writeInt(((Number)item).intValue()); 306 } 307 } 308 } 309 310 protected void writeAMF3Dictionary(AMFDictionaryValue value) throws IOException { 311 if (debugMore) logMore.debug("writeAMFDictionary(value=%s)", value); 312 313 write(AMF3_DICTIONARY); 314 315 Map<?, ?> o = value.value; 316 317 int index = indexOfStoredObjects(o); 318 if (index >= 0) 319 writeAMF3IntegerData(index << 1); 320 else { 321 addToStoredObjects(o); 322 323 int length = o.size(); 324 writeAMF3IntegerData(length << 1 | 0x01); 325 write(value.weakKeys ? 0x01 : 0x00); 326 327 for (Map.Entry<?, ?> entry : o.entrySet()) { 328 writeObject(entry.getKey()); 329 writeObject(entry.getValue()); 330 } 331 } 332 } 333 334 protected int getArrayOrCollectionLength(Object o) { 335 if (o.getClass().isArray()) 336 return Array.getLength(o); 337 return ((Collection<?>)o).size(); 338 } 339 340 protected void writeAMF3Integer(int i) throws IOException { 341 if (debugMore) logMore.debug("writeAMF3Integer(i=%d)", i); 342 343 if (i < AMF3_INTEGER_MIN || i > AMF3_INTEGER_MAX) { 344 if (debugMore) logMore.debug("writeAMF3Integer() - %d is out of AMF3 int range, writing it as a Number", i); 345 writeAMF3Number(i); 346 } 347 else { 348 write(AMF3_INTEGER); 349 writeAMF3IntegerData(i); 350 } 351 } 352 353 protected void writeAMF3IntegerData(int i) throws IOException { 354 if (debugMore) logMore.debug("writeAMF3IntegerData(i=%d)", i); 355 356 if (i < AMF3_INTEGER_MIN || i > AMF3_INTEGER_MAX) 357 throw new IllegalArgumentException("Integer out of range: " + i); 358 359 if (i < 0 || i >= 0x200000) { 360 write(((i >> 22) & 0x7F) | 0x80); 361 write(((i >> 15) & 0x7F) | 0x80); 362 write(((i >> 8) & 0x7F) | 0x80); 363 write(i & 0xFF); 364 } 365 else { 366 if (i >= 0x4000) 367 write(((i >> 14) & 0x7F) | 0x80); 368 if (i >= 0x80) 369 write(((i >> 7) & 0x7F) | 0x80); 370 write(i & 0x7F); 371 } 372 } 373 374 protected void writeAMF3Number(double d) throws IOException { 375 if (debugMore) logMore.debug("writeAMF3Number(d=%f)", d); 376 377 write(AMF3_NUMBER); 378 writeDouble(d); 379 } 380 381 protected void writeAMF3String(String s) throws IOException { 382 if (debugMore) logMore.debug("writeAMF3String(s=%s)", s); 383 384 write(AMF3_STRING); 385 writeAMF3StringData(s); 386 } 387 388 protected void writeAMF3StringData(String s) throws IOException { 389 if (debugMore) logMore.debug("writeAMF3StringData(s=%s)", s); 390 391 if (s.length() == 0) { 392 write(0x01); 393 return; 394 } 395 396 int index = indexOfStoredStrings(s); 397 398 if (index >= 0) 399 writeAMF3IntegerData(index << 1); 400 else { 401 addToStoredStrings(s); 402 403 final int sLength = s.length(); 404 405 // Compute and write modified UTF-8 string length. 406 int uLength = 0; 407 for (int i = 0; i < sLength; i++) { 408 int c = s.charAt(i); 409 if ((c >= 0x0001) && (c <= 0x007F)) 410 uLength++; 411 else if (c > 0x07FF) 412 uLength += 3; 413 else 414 uLength += 2; 415 } 416 writeAMF3IntegerData((uLength << 1) | 0x01); 417 418 // Write modified UTF-8 bytes. 419 for (int i = 0; i < sLength; i++) { 420 int c = s.charAt(i); 421 if ((c >= 0x0001) && (c <= 0x007F)) { 422 write(c); 423 } 424 else if (c > 0x07FF) { 425 write(0xE0 | ((c >> 12) & 0x0F)); 426 write(0x80 | ((c >> 6) & 0x3F)); 427 write(0x80 | ((c >> 0) & 0x3F)); 428 } 429 else { 430 write(0xC0 | ((c >> 6) & 0x1F)); 431 write(0x80 | ((c >> 0) & 0x3F)); 432 } 433 } 434 } 435 } 436 437 protected void writeAMF3Xml(Document doc) throws IOException { 438 if (debugMore) logMore.debug("writeAMF3Xml(doc=%s)", doc); 439 440 byte xmlType = AMF3_XMLSTRING; 441 Channel channel = getChannel(); 442 if (channel != null && channel.isLegacyXmlSerialization()) 443 xmlType = AMF3_XML; 444 write(xmlType); 445 446 int index = indexOfStoredObjects(doc); 447 if (index >= 0) 448 writeAMF3IntegerData(index << 1); 449 else { 450 addToStoredObjects(doc); 451 452 byte[] bytes = xmlUtil.toString(doc).getBytes("UTF-8"); 453 writeAMF3IntegerData((bytes.length << 1) | 0x01); 454 write(bytes); 455 } 456 } 457 458 protected void writeAMF3Date(Date date) throws IOException { 459 if (debugMore) logMore.debug("writeAMF3Date(date=%s)", date); 460 461 write(AMF3_DATE); 462 463 int index = indexOfStoredObjects(date); 464 if (index >= 0) 465 writeAMF3IntegerData(index << 1); 466 else { 467 addToStoredObjects(date); 468 writeAMF3IntegerData(0x01); 469 writeDouble(date.getTime()); 470 } 471 } 472 473 protected void writeAMF3Array(Object array) throws IOException { 474 if (debugMore) logMore.debug("writeAMF3Array(array=%s)", array); 475 476 write(AMF3_ARRAY); 477 478 int index = indexOfStoredObjects(array); 479 if (index >= 0) 480 writeAMF3IntegerData(index << 1); 481 else { 482 addToStoredObjects(array); 483 484 int length = Array.getLength(array); 485 writeAMF3IntegerData(length << 1 | 0x01); 486 write(0x01); 487 for (int i = 0; i < length; i++) 488 writeObject(Array.get(array, i)); 489 } 490 } 491 492 protected void writeAMF3ByteArray(byte[] bytes) throws IOException { 493 if (debugMore) logMore.debug("writeAMF3ByteArray(bytes=%s)", bytes); 494 495 write(AMF3_BYTEARRAY); 496 497 int index = indexOfStoredObjects(bytes); 498 if (index >= 0) 499 writeAMF3IntegerData(index << 1); 500 else { 501 addToStoredObjects(bytes); 502 503 writeAMF3IntegerData(bytes.length << 1 | 0x01); 504 //write(bytes); 505 506 for (int i = 0; i < bytes.length; i++) 507 out.write(bytes[i]); 508 } 509 } 510 511 protected void writeAMF3Collection(Collection<?> c) throws IOException { 512 if (debugMore) logMore.debug("writeAMF3Collection(c=%s)", c); 513 514 Channel channel = getChannel(); 515 if (channel != null && channel.isLegacyCollectionSerialization()) 516 writeAMF3Array(c.toArray()); 517 else { 518 ArrayCollection ac = (c instanceof ArrayCollection ? (ArrayCollection)c : new ArrayCollection(c)); 519 writeAMF3Object(ac); 520 } 521 } 522 523 protected void writeAMF3Object(Object o) throws IOException { 524 if (debug) log.debug("writeAMF3Object(o=%s)...", o); 525 526 write(AMF3_OBJECT); 527 528 int index = indexOfStoredObjects(o); 529 if (index >= 0) 530 writeAMF3IntegerData(index << 1); 531 else { 532 addToStoredObjects(o); 533 534 ClassGetter classGetter = context.getGraniteConfig().getClassGetter(); 535 if (debug) log.debug("writeAMF3Object() - classGetter=%s", classGetter); 536 537 Class<?> oClass = classGetter.getClass(o); 538 if (debug) log.debug("writeAMF3Object() - oClass=%s", oClass); 539 540 JavaClassDescriptor desc = null; 541 542 // write class description. 543 IndexedJavaClassDescriptor iDesc = getFromStoredClassDescriptors(oClass); 544 if (iDesc != null) { 545 desc = iDesc.getDescriptor(); 546 writeAMF3IntegerData(iDesc.getIndex() << 2 | 0x01); 547 } 548 else { 549 iDesc = addToStoredClassDescriptors(oClass); 550 desc = iDesc.getDescriptor(); 551 552 writeAMF3IntegerData((desc.getPropertiesCount() << 4) | (desc.getEncoding() << 2) | 0x03); 553 writeAMF3StringData(desc.getName()); 554 555 for (int i = 0; i < desc.getPropertiesCount(); i++) 556 writeAMF3StringData(desc.getPropertyName(i)); 557 } 558 if (debug) log.debug("writeAMF3Object() - desc=%s", desc); 559 560 // write object content. 561 if (desc.isExternalizable()) { 562 Externalizer externalizer = desc.getExternalizer(); 563 564 if (externalizer != null) { 565 if (debug) log.debug("writeAMF3Object() - using externalizer=%s", externalizer); 566 try { 567 externalizer.writeExternal(o, this); 568 } 569 catch (IOException e) { 570 throw e; 571 } 572 catch (Exception e) { 573 throw new RuntimeException("Could not externalize object: " + o, e); 574 } 575 } 576 else { 577 if (debug) log.debug("writeAMF3Object() - legacy Externalizable=%s", o); 578 ((Externalizable)o).writeExternal(this); 579 } 580 } 581 else { 582 if (debug) log.debug("writeAMF3Object() - writing defined properties..."); 583 for (int i = 0; i < desc.getPropertiesCount(); i++) { 584 Object obj = desc.getPropertyValue(i, o); 585 if (debug) log.debug("writeAMF3Object() - writing defined property: %s=%s", desc.getPropertyName(i), obj); 586 writeObject(specialValueFactory.createSpecialValue(desc.getProperty(i), obj)); 587 } 588 589 if (desc.isDynamic()) { 590 if (debug) log.debug("writeAMF3Object() - writing dynamic properties..."); 591 Map<?, ?> oMap = (Map<?, ?>)o; 592 for (Map.Entry<?, ?> entry : oMap.entrySet()) { 593 Object key = entry.getKey(); 594 if (key != null) { 595 String propertyName = key.toString(); 596 if (propertyName.length() > 0) { 597 if (debug) log.debug( 598 "writeAMF3Object() - writing dynamic property: %s=%s", 599 propertyName, entry.getValue() 600 ); 601 writeAMF3StringData(propertyName); 602 writeObject(entry.getValue()); 603 } 604 } 605 } 606 writeAMF3StringData(""); 607 } 608 } 609 } 610 611 if (debug) log.debug("writeAMF3Object(o=%s) - Done", o); 612 } 613 614 /////////////////////////////////////////////////////////////////////////// 615 // Cached objects methods. 616 617 protected void addToStoredStrings(String s) { 618 if (!storedStrings.containsKey(s)) { 619 Integer index = Integer.valueOf(storedStrings.size()); 620 if (debug) log.debug("addToStoredStrings(s=%s) at index=%d", s, index); 621 storedStrings.put(s, index); 622 } 623 } 624 625 protected int indexOfStoredStrings(String s) { 626 Integer index = storedStrings.get(s); 627 if (debug) log.debug("indexOfStoredStrings(s=%s) -> %d", s, (index != null ? index : -1)); 628 return (index != null ? index : -1); 629 } 630 631 protected void addToStoredObjects(Object o) { 632 if (o != null && !storedObjects.containsKey(o)) { 633 Integer index = Integer.valueOf(storedObjects.size()); 634 if (debug) log.debug("addToStoredObjects(o=%s) at index=%d", o, index); 635 storedObjects.put(o, index); 636 } 637 } 638 639 protected int indexOfStoredObjects(Object o) { 640 Integer index = storedObjects.get(o); 641 if (debug) log.debug("indexOfStoredObjects(o=%s) -> %d", o, (index != null ? index : -1)); 642 return (index != null ? index : -1); 643 } 644 645 protected IndexedJavaClassDescriptor addToStoredClassDescriptors(Class<?> clazz) { 646 final String name = JavaClassDescriptor.getClassName(clazz); 647 648 if (debug) log.debug("addToStoredClassDescriptors(clazz=%s)", clazz); 649 650 if (storedClassDescriptors.containsKey(name)) 651 throw new RuntimeException( 652 "Descriptor of \"" + name + "\" is already stored at index: " + 653 getFromStoredClassDescriptors(clazz).getIndex() 654 ); 655 656 // find custom class descriptor and instantiate if any 657 JavaClassDescriptor desc = null; 658 659 Class<? extends JavaClassDescriptor> descriptorType 660 = context.getGraniteConfig().getJavaDescriptor(clazz.getName()); 661 if (descriptorType != null) { 662 Class<?>[] argsDef = new Class[]{Class.class}; 663 Object[] argsVal = new Object[]{clazz}; 664 try { 665 desc = TypeUtil.newInstance(descriptorType, argsDef, argsVal); 666 } 667 catch (Exception e) { 668 throw new RuntimeException("Could not instantiate Java descriptor: " + descriptorType); 669 } 670 } 671 672 if (desc == null) 673 desc = new DefaultJavaClassDescriptor(clazz); 674 675 IndexedJavaClassDescriptor iDesc = new IndexedJavaClassDescriptor(storedClassDescriptors.size(), desc); 676 677 if (debug) log.debug("addToStoredClassDescriptors() - putting: name=%s, iDesc=%s", name, iDesc); 678 679 storedClassDescriptors.put(name, iDesc); 680 681 return iDesc; 682 } 683 684 protected IndexedJavaClassDescriptor getFromStoredClassDescriptors(Class<?> clazz) { 685 if (debug) log.debug("getFromStoredClassDescriptors(clazz=%s)", clazz); 686 687 String name = JavaClassDescriptor.getClassName(clazz); 688 IndexedJavaClassDescriptor iDesc = storedClassDescriptors.get(name); 689 690 if (debug) log.debug("getFromStoredClassDescriptors() -> %s", iDesc); 691 692 return iDesc; 693 } 694 695 /////////////////////////////////////////////////////////////////////////// 696 // Utilities. 697 698 protected Channel getChannel() { 699 if (channel == null) { 700 String channelId = context.getAMFContext().getChannelId(); 701 if (channelId != null) 702 channel = context.getServicesConfig().findChannelById(channelId); 703 if (channel == null) 704 log.debug("Could not get channel for channel id: %s", channelId); 705 } 706 return channel; 707 } 708}