001/** 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.activemq.openwire.v12; 018 019import static org.apache.activemq.openwire.OpenWireUtil.convertJmsPackage; 020 021import java.io.DataInput; 022import java.io.DataOutput; 023import java.io.IOException; 024import java.lang.reflect.Constructor; 025import org.apache.activemq.command.DataStructure; 026import org.apache.activemq.openwire.BooleanStream; 027import org.apache.activemq.openwire.DataStreamMarshaller; 028import org.apache.activemq.openwire.OpenWireFormat; 029import org.apache.activemq.openwire.OpenWireUtil; 030import org.apache.activemq.util.ByteSequence; 031 032public abstract class BaseDataStreamMarshaller implements DataStreamMarshaller { 033 034 public static final Constructor STACK_TRACE_ELEMENT_CONSTRUCTOR; 035 036 static { 037 Constructor constructor = null; 038 try { 039 constructor = StackTraceElement.class.getConstructor(new Class[] {String.class, String.class, 040 String.class, int.class}); 041 } catch (Throwable e) { 042 } 043 STACK_TRACE_ELEMENT_CONSTRUCTOR = constructor; 044 } 045 046 public abstract byte getDataStructureType(); 047 048 public abstract DataStructure createObject(); 049 050 public int tightMarshal1(OpenWireFormat wireFormat, Object o, BooleanStream bs) throws IOException { 051 return 0; 052 } 053 054 public void tightMarshal2(OpenWireFormat wireFormat, Object o, DataOutput dataOut, BooleanStream bs) 055 throws IOException { 056 } 057 058 public void tightUnmarshal(OpenWireFormat wireFormat, Object o, DataInput dataIn, BooleanStream bs) 059 throws IOException { 060 } 061 062 public int tightMarshalLong1(OpenWireFormat wireFormat, long o, BooleanStream bs) throws IOException { 063 if (o == 0) { 064 bs.writeBoolean(false); 065 bs.writeBoolean(false); 066 return 0; 067 } else if ((o & 0xFFFFFFFFFFFF0000L) == 0) { 068 bs.writeBoolean(false); 069 bs.writeBoolean(true); 070 return 2; 071 } else if ((o & 0xFFFFFFFF00000000L) == 0) { 072 bs.writeBoolean(true); 073 bs.writeBoolean(false); 074 return 4; 075 } else { 076 bs.writeBoolean(true); 077 bs.writeBoolean(true); 078 return 8; 079 } 080 } 081 082 public void tightMarshalLong2(OpenWireFormat wireFormat, long o, DataOutput dataOut, BooleanStream bs) 083 throws IOException { 084 if (bs.readBoolean()) { 085 if (bs.readBoolean()) { 086 dataOut.writeLong(o); 087 } else { 088 dataOut.writeInt((int)o); 089 } 090 } else { 091 if (bs.readBoolean()) { 092 dataOut.writeShort((int)o); 093 } 094 } 095 } 096 097 public long tightUnmarshalLong(OpenWireFormat wireFormat, DataInput dataIn, BooleanStream bs) 098 throws IOException { 099 if (bs.readBoolean()) { 100 if (bs.readBoolean()) { 101 return dataIn.readLong(); 102 } else { 103 return toLong(dataIn.readInt()); 104 } 105 } else { 106 if (bs.readBoolean()) { 107 return toLong(dataIn.readShort()); 108 } else { 109 return 0; 110 } 111 } 112 } 113 114 protected long toLong(short value) { 115 // lets handle negative values 116 long answer = value; 117 return answer & 0xffffL; 118 } 119 120 protected long toLong(int value) { 121 // lets handle negative values 122 long answer = value; 123 return answer & 0xffffffffL; 124 } 125 126 protected DataStructure tightUnmarsalNestedObject(OpenWireFormat wireFormat, DataInput dataIn, 127 BooleanStream bs) throws IOException { 128 return wireFormat.tightUnmarshalNestedObject(dataIn, bs); 129 } 130 131 protected int tightMarshalNestedObject1(OpenWireFormat wireFormat, DataStructure o, BooleanStream bs) 132 throws IOException { 133 return wireFormat.tightMarshalNestedObject1(o, bs); 134 } 135 136 protected void tightMarshalNestedObject2(OpenWireFormat wireFormat, DataStructure o, DataOutput dataOut, 137 BooleanStream bs) throws IOException { 138 wireFormat.tightMarshalNestedObject2(o, dataOut, bs); 139 } 140 141 protected DataStructure tightUnmarsalCachedObject(OpenWireFormat wireFormat, DataInput dataIn, 142 BooleanStream bs) throws IOException { 143 if (wireFormat.isCacheEnabled()) { 144 if (bs.readBoolean()) { 145 short index = dataIn.readShort(); 146 DataStructure object = wireFormat.tightUnmarshalNestedObject(dataIn, bs); 147 wireFormat.setInUnmarshallCache(index, object); 148 return object; 149 } else { 150 short index = dataIn.readShort(); 151 return wireFormat.getFromUnmarshallCache(index); 152 } 153 } else { 154 return wireFormat.tightUnmarshalNestedObject(dataIn, bs); 155 } 156 } 157 158 protected int tightMarshalCachedObject1(OpenWireFormat wireFormat, DataStructure o, BooleanStream bs) 159 throws IOException { 160 if (wireFormat.isCacheEnabled()) { 161 Short index = wireFormat.getMarshallCacheIndex(o); 162 bs.writeBoolean(index == null); 163 if (index == null) { 164 int rc = wireFormat.tightMarshalNestedObject1(o, bs); 165 wireFormat.addToMarshallCache(o); 166 return 2 + rc; 167 } else { 168 return 2; 169 } 170 } else { 171 return wireFormat.tightMarshalNestedObject1(o, bs); 172 } 173 } 174 175 protected void tightMarshalCachedObject2(OpenWireFormat wireFormat, DataStructure o, DataOutput dataOut, 176 BooleanStream bs) throws IOException { 177 if (wireFormat.isCacheEnabled()) { 178 Short index = wireFormat.getMarshallCacheIndex(o); 179 if (bs.readBoolean()) { 180 dataOut.writeShort(index.shortValue()); 181 wireFormat.tightMarshalNestedObject2(o, dataOut, bs); 182 } else { 183 dataOut.writeShort(index.shortValue()); 184 } 185 } else { 186 wireFormat.tightMarshalNestedObject2(o, dataOut, bs); 187 } 188 } 189 190 protected Throwable tightUnmarsalThrowable(OpenWireFormat wireFormat, DataInput dataIn, BooleanStream bs) 191 throws IOException { 192 if (bs.readBoolean()) { 193 String clazz = tightUnmarshalString(dataIn, bs); 194 String message = tightUnmarshalString(dataIn, bs); 195 Throwable o = createThrowable(clazz, message); 196 if (wireFormat.isStackTraceEnabled()) { 197 if (STACK_TRACE_ELEMENT_CONSTRUCTOR != null) { 198 StackTraceElement ss[] = new StackTraceElement[dataIn.readShort()]; 199 for (int i = 0; i < ss.length; i++) { 200 try { 201 ss[i] = (StackTraceElement)STACK_TRACE_ELEMENT_CONSTRUCTOR 202 .newInstance(new Object[] {convertJmsPackage(tightUnmarshalString(dataIn, bs)), 203 tightUnmarshalString(dataIn, bs), 204 tightUnmarshalString(dataIn, bs), 205 Integer.valueOf(dataIn.readInt())}); 206 } catch (IOException e) { 207 throw e; 208 } catch (Throwable e) { 209 } 210 } 211 o.setStackTrace(ss); 212 } else { 213 short size = dataIn.readShort(); 214 for (int i = 0; i < size; i++) { 215 tightUnmarshalString(dataIn, bs); 216 tightUnmarshalString(dataIn, bs); 217 tightUnmarshalString(dataIn, bs); 218 dataIn.readInt(); 219 } 220 } 221 o.initCause(tightUnmarsalThrowable(wireFormat, dataIn, bs)); 222 223 } 224 return o; 225 } else { 226 return null; 227 } 228 } 229 230 private Throwable createThrowable(String className, String message) { 231 try { 232 className = convertJmsPackage(className); 233 Class clazz = Class.forName(className, false, BaseDataStreamMarshaller.class.getClassLoader()); 234 OpenWireUtil.validateIsThrowable(clazz); 235 Constructor constructor = clazz.getConstructor(new Class[] {String.class}); 236 return (Throwable)constructor.newInstance(new Object[] {message}); 237 } catch (IllegalArgumentException e) { 238 return e; 239 } catch (Throwable e) { 240 return new Throwable(className + ": " + message); 241 } 242 } 243 244 protected int tightMarshalThrowable1(OpenWireFormat wireFormat, Throwable o, BooleanStream bs) 245 throws IOException { 246 if (o == null) { 247 bs.writeBoolean(false); 248 return 0; 249 } else { 250 int rc = 0; 251 bs.writeBoolean(true); 252 rc += tightMarshalString1(o.getClass().getName(), bs); 253 rc += tightMarshalString1(o.getMessage(), bs); 254 if (wireFormat.isStackTraceEnabled()) { 255 rc += 2; 256 StackTraceElement[] stackTrace = o.getStackTrace(); 257 for (int i = 0; i < stackTrace.length; i++) { 258 StackTraceElement element = stackTrace[i]; 259 rc += tightMarshalString1(element.getClassName(), bs); 260 rc += tightMarshalString1(element.getMethodName(), bs); 261 rc += tightMarshalString1(element.getFileName(), bs); 262 rc += 4; 263 } 264 rc += tightMarshalThrowable1(wireFormat, o.getCause(), bs); 265 } 266 return rc; 267 } 268 } 269 270 protected void tightMarshalThrowable2(OpenWireFormat wireFormat, Throwable o, DataOutput dataOut, 271 BooleanStream bs) throws IOException { 272 if (bs.readBoolean()) { 273 tightMarshalString2(o.getClass().getName(), dataOut, bs); 274 tightMarshalString2(o.getMessage(), dataOut, bs); 275 if (wireFormat.isStackTraceEnabled()) { 276 StackTraceElement[] stackTrace = o.getStackTrace(); 277 dataOut.writeShort(stackTrace.length); 278 for (int i = 0; i < stackTrace.length; i++) { 279 StackTraceElement element = stackTrace[i]; 280 tightMarshalString2(element.getClassName(), dataOut, bs); 281 tightMarshalString2(element.getMethodName(), dataOut, bs); 282 tightMarshalString2(element.getFileName(), dataOut, bs); 283 dataOut.writeInt(element.getLineNumber()); 284 } 285 tightMarshalThrowable2(wireFormat, o.getCause(), dataOut, bs); 286 } 287 } 288 } 289 290 @SuppressWarnings("deprecation") 291 protected String tightUnmarshalString(DataInput dataIn, BooleanStream bs) throws IOException { 292 if (bs.readBoolean()) { 293 if (bs.readBoolean()) { 294 int size = dataIn.readShort(); 295 byte data[] = new byte[size]; 296 dataIn.readFully(data); 297 // Yes deprecated, but we know what we are doing. 298 // This allows us to create a String from a ASCII byte array. (no UTF-8 decoding) 299 return new String(data, 0); 300 } else { 301 return dataIn.readUTF(); 302 } 303 } else { 304 return null; 305 } 306 } 307 308 protected int tightMarshalString1(String value, BooleanStream bs) throws IOException { 309 bs.writeBoolean(value != null); 310 if (value != null) { 311 312 int strlen = value.length(); 313 int utflen = 0; 314 char[] charr = new char[strlen]; 315 int c = 0; 316 boolean isOnlyAscii = true; 317 318 value.getChars(0, strlen, charr, 0); 319 320 for (int i = 0; i < strlen; i++) { 321 c = charr[i]; 322 if ((c >= 0x0001) && (c <= 0x007F)) { 323 utflen++; 324 } else if (c > 0x07FF) { 325 utflen += 3; 326 isOnlyAscii = false; 327 } else { 328 isOnlyAscii = false; 329 utflen += 2; 330 } 331 } 332 333 if (utflen >= Short.MAX_VALUE) { 334 throw new IOException("Encountered a String value that is too long to encode."); 335 } 336 bs.writeBoolean(isOnlyAscii); 337 return utflen + 2; 338 339 } else { 340 return 0; 341 } 342 } 343 344 protected void tightMarshalString2(String value, DataOutput dataOut, BooleanStream bs) throws IOException { 345 if (bs.readBoolean()) { 346 // If we verified it only holds ascii values 347 if (bs.readBoolean()) { 348 dataOut.writeShort(value.length()); 349 dataOut.writeBytes(value); 350 } else { 351 dataOut.writeUTF(value); 352 } 353 } 354 } 355 356 protected int tightMarshalObjectArray1(OpenWireFormat wireFormat, DataStructure[] objects, 357 BooleanStream bs) throws IOException { 358 if (objects != null) { 359 int rc = 0; 360 bs.writeBoolean(true); 361 rc += 2; 362 for (int i = 0; i < objects.length; i++) { 363 rc += tightMarshalNestedObject1(wireFormat, objects[i], bs); 364 } 365 return rc; 366 } else { 367 bs.writeBoolean(false); 368 return 0; 369 } 370 } 371 372 protected void tightMarshalObjectArray2(OpenWireFormat wireFormat, DataStructure[] objects, 373 DataOutput dataOut, BooleanStream bs) throws IOException { 374 if (bs.readBoolean()) { 375 dataOut.writeShort(objects.length); 376 for (int i = 0; i < objects.length; i++) { 377 tightMarshalNestedObject2(wireFormat, objects[i], dataOut, bs); 378 } 379 } 380 } 381 382 protected int tightMarshalConstByteArray1(byte[] data, BooleanStream bs, int i) throws IOException { 383 return i; 384 } 385 386 protected void tightMarshalConstByteArray2(byte[] data, DataOutput dataOut, BooleanStream bs, int i) 387 throws IOException { 388 dataOut.write(data, 0, i); 389 } 390 391 protected byte[] tightUnmarshalConstByteArray(DataInput dataIn, BooleanStream bs, int i) 392 throws IOException { 393 byte data[] = new byte[i]; 394 dataIn.readFully(data); 395 return data; 396 } 397 398 protected int tightMarshalByteArray1(byte[] data, BooleanStream bs) throws IOException { 399 bs.writeBoolean(data != null); 400 if (data != null) { 401 return data.length + 4; 402 } else { 403 return 0; 404 } 405 } 406 407 protected void tightMarshalByteArray2(byte[] data, DataOutput dataOut, BooleanStream bs) 408 throws IOException { 409 if (bs.readBoolean()) { 410 dataOut.writeInt(data.length); 411 dataOut.write(data); 412 } 413 } 414 415 protected byte[] tightUnmarshalByteArray(OpenWireFormat wireFormat, DataInput dataIn, BooleanStream bs) throws IOException { 416 byte rc[] = null; 417 if (bs.readBoolean()) { 418 int size = dataIn.readInt(); 419 OpenWireUtil.validateBufferSize(wireFormat, size); 420 rc = new byte[size]; 421 dataIn.readFully(rc); 422 } 423 return rc; 424 } 425 426 protected int tightMarshalByteSequence1(ByteSequence data, BooleanStream bs) throws IOException { 427 bs.writeBoolean(data != null); 428 if (data != null) { 429 return data.getLength() + 4; 430 } else { 431 return 0; 432 } 433 } 434 435 protected void tightMarshalByteSequence2(ByteSequence data, DataOutput dataOut, BooleanStream bs) 436 throws IOException { 437 if (bs.readBoolean()) { 438 dataOut.writeInt(data.getLength()); 439 dataOut.write(data.getData(), data.getOffset(), data.getLength()); 440 } 441 } 442 443 protected ByteSequence tightUnmarshalByteSequence(OpenWireFormat wireFormat, DataInput dataIn, BooleanStream bs) throws IOException { 444 ByteSequence rc = null; 445 if (bs.readBoolean()) { 446 int size = dataIn.readInt(); 447 OpenWireUtil.validateBufferSize(wireFormat, size); 448 byte[] t = new byte[size]; 449 dataIn.readFully(t); 450 return new ByteSequence(t, 0, size); 451 } 452 return rc; 453 } 454 455 // 456 // The loose marshaling logic 457 // 458 459 public void looseMarshal(OpenWireFormat wireFormat, Object o, DataOutput dataOut) throws IOException { 460 } 461 462 public void looseUnmarshal(OpenWireFormat wireFormat, Object o, DataInput dataIn) throws IOException { 463 } 464 465 public void looseMarshalLong(OpenWireFormat wireFormat, long o, DataOutput dataOut) throws IOException { 466 dataOut.writeLong(o); 467 } 468 469 public long looseUnmarshalLong(OpenWireFormat wireFormat, DataInput dataIn) throws IOException { 470 return dataIn.readLong(); 471 } 472 473 protected DataStructure looseUnmarsalNestedObject(OpenWireFormat wireFormat, DataInput dataIn) 474 throws IOException { 475 return wireFormat.looseUnmarshalNestedObject(dataIn); 476 } 477 478 protected void looseMarshalNestedObject(OpenWireFormat wireFormat, DataStructure o, DataOutput dataOut) 479 throws IOException { 480 wireFormat.looseMarshalNestedObject(o, dataOut); 481 } 482 483 protected DataStructure looseUnmarsalCachedObject(OpenWireFormat wireFormat, DataInput dataIn) 484 throws IOException { 485 if (wireFormat.isCacheEnabled()) { 486 if (dataIn.readBoolean()) { 487 short index = dataIn.readShort(); 488 DataStructure object = wireFormat.looseUnmarshalNestedObject(dataIn); 489 wireFormat.setInUnmarshallCache(index, object); 490 return object; 491 } else { 492 short index = dataIn.readShort(); 493 return wireFormat.getFromUnmarshallCache(index); 494 } 495 } else { 496 return wireFormat.looseUnmarshalNestedObject(dataIn); 497 } 498 } 499 500 protected void looseMarshalCachedObject(OpenWireFormat wireFormat, DataStructure o, DataOutput dataOut) 501 throws IOException { 502 if (wireFormat.isCacheEnabled()) { 503 Short index = wireFormat.getMarshallCacheIndex(o); 504 dataOut.writeBoolean(index == null); 505 if (index == null) { 506 index = wireFormat.addToMarshallCache(o); 507 dataOut.writeShort(index.shortValue()); 508 wireFormat.looseMarshalNestedObject(o, dataOut); 509 } else { 510 dataOut.writeShort(index.shortValue()); 511 } 512 } else { 513 wireFormat.looseMarshalNestedObject(o, dataOut); 514 } 515 } 516 517 protected Throwable looseUnmarsalThrowable(OpenWireFormat wireFormat, DataInput dataIn) 518 throws IOException { 519 if (dataIn.readBoolean()) { 520 String clazz = looseUnmarshalString(dataIn); 521 String message = looseUnmarshalString(dataIn); 522 Throwable o = createThrowable(clazz, message); 523 if (wireFormat.isStackTraceEnabled()) { 524 if (STACK_TRACE_ELEMENT_CONSTRUCTOR != null) { 525 StackTraceElement ss[] = new StackTraceElement[dataIn.readShort()]; 526 for (int i = 0; i < ss.length; i++) { 527 try { 528 ss[i] = (StackTraceElement)STACK_TRACE_ELEMENT_CONSTRUCTOR 529 .newInstance(new Object[] {convertJmsPackage(looseUnmarshalString(dataIn)), 530 looseUnmarshalString(dataIn), 531 looseUnmarshalString(dataIn), 532 Integer.valueOf(dataIn.readInt())}); 533 } catch (IOException e) { 534 throw e; 535 } catch (Throwable e) { 536 } 537 } 538 o.setStackTrace(ss); 539 } else { 540 short size = dataIn.readShort(); 541 for (int i = 0; i < size; i++) { 542 looseUnmarshalString(dataIn); 543 looseUnmarshalString(dataIn); 544 looseUnmarshalString(dataIn); 545 dataIn.readInt(); 546 } 547 } 548 o.initCause(looseUnmarsalThrowable(wireFormat, dataIn)); 549 550 } 551 return o; 552 } else { 553 return null; 554 } 555 } 556 557 protected void looseMarshalThrowable(OpenWireFormat wireFormat, Throwable o, DataOutput dataOut) 558 throws IOException { 559 dataOut.writeBoolean(o != null); 560 if (o != null) { 561 looseMarshalString(o.getClass().getName(), dataOut); 562 looseMarshalString(o.getMessage(), dataOut); 563 if (wireFormat.isStackTraceEnabled()) { 564 StackTraceElement[] stackTrace = o.getStackTrace(); 565 dataOut.writeShort(stackTrace.length); 566 for (int i = 0; i < stackTrace.length; i++) { 567 StackTraceElement element = stackTrace[i]; 568 looseMarshalString(element.getClassName(), dataOut); 569 looseMarshalString(element.getMethodName(), dataOut); 570 looseMarshalString(element.getFileName(), dataOut); 571 dataOut.writeInt(element.getLineNumber()); 572 } 573 looseMarshalThrowable(wireFormat, o.getCause(), dataOut); 574 } 575 } 576 } 577 578 protected String looseUnmarshalString(DataInput dataIn) throws IOException { 579 if (dataIn.readBoolean()) { 580 return dataIn.readUTF(); 581 } else { 582 return null; 583 } 584 } 585 586 protected void looseMarshalString(String value, DataOutput dataOut) throws IOException { 587 dataOut.writeBoolean(value != null); 588 if (value != null) { 589 dataOut.writeUTF(value); 590 } 591 } 592 593 protected void looseMarshalObjectArray(OpenWireFormat wireFormat, DataStructure[] objects, 594 DataOutput dataOut) throws IOException { 595 dataOut.writeBoolean(objects != null); 596 if (objects != null) { 597 dataOut.writeShort(objects.length); 598 for (int i = 0; i < objects.length; i++) { 599 looseMarshalNestedObject(wireFormat, objects[i], dataOut); 600 } 601 } 602 } 603 604 protected void looseMarshalConstByteArray(OpenWireFormat wireFormat, byte[] data, DataOutput dataOut, 605 int i) throws IOException { 606 dataOut.write(data, 0, i); 607 } 608 609 protected byte[] looseUnmarshalConstByteArray(DataInput dataIn, int i) throws IOException { 610 byte data[] = new byte[i]; 611 dataIn.readFully(data); 612 return data; 613 } 614 615 protected void looseMarshalByteArray(OpenWireFormat wireFormat, byte[] data, DataOutput dataOut) 616 throws IOException { 617 dataOut.writeBoolean(data != null); 618 if (data != null) { 619 dataOut.writeInt(data.length); 620 dataOut.write(data); 621 } 622 } 623 624 protected byte[] looseUnmarshalByteArray(OpenWireFormat wireFormat, DataInput dataIn) throws IOException { 625 byte rc[] = null; 626 if (dataIn.readBoolean()) { 627 int size = dataIn.readInt(); 628 OpenWireUtil.validateBufferSize(wireFormat, size); 629 rc = new byte[size]; 630 dataIn.readFully(rc); 631 } 632 return rc; 633 } 634 635 protected void looseMarshalByteSequence(OpenWireFormat wireFormat, ByteSequence data, DataOutput dataOut) 636 throws IOException { 637 dataOut.writeBoolean(data != null); 638 if (data != null) { 639 dataOut.writeInt(data.getLength()); 640 dataOut.write(data.getData(), data.getOffset(), data.getLength()); 641 } 642 } 643 644 protected ByteSequence looseUnmarshalByteSequence(OpenWireFormat wireFormat, DataInput dataIn) throws IOException { 645 ByteSequence rc = null; 646 if (dataIn.readBoolean()) { 647 int size = dataIn.readInt(); 648 OpenWireUtil.validateBufferSize(wireFormat, size); 649 byte[] t = new byte[size]; 650 dataIn.readFully(t); 651 rc = new ByteSequence(t, 0, size); 652 } 653 return rc; 654 } 655}