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