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(DataInput dataIn, BooleanStream bs) throws IOException { 413 byte rc[] = null; 414 if (bs.readBoolean()) { 415 int size = dataIn.readInt(); 416 rc = new byte[size]; 417 dataIn.readFully(rc); 418 } 419 return rc; 420 } 421 422 protected int tightMarshalByteSequence1(ByteSequence data, BooleanStream bs) throws IOException { 423 bs.writeBoolean(data != null); 424 if (data != null) { 425 return data.getLength() + 4; 426 } else { 427 return 0; 428 } 429 } 430 431 protected void tightMarshalByteSequence2(ByteSequence data, DataOutput dataOut, BooleanStream bs) 432 throws IOException { 433 if (bs.readBoolean()) { 434 dataOut.writeInt(data.getLength()); 435 dataOut.write(data.getData(), data.getOffset(), data.getLength()); 436 } 437 } 438 439 protected ByteSequence tightUnmarshalByteSequence(DataInput dataIn, BooleanStream bs) throws IOException { 440 ByteSequence rc = null; 441 if (bs.readBoolean()) { 442 int size = dataIn.readInt(); 443 byte[] t = new byte[size]; 444 dataIn.readFully(t); 445 return new ByteSequence(t, 0, size); 446 } 447 return rc; 448 } 449 450 // 451 // The loose marshaling logic 452 // 453 454 public void looseMarshal(OpenWireFormat wireFormat, Object o, DataOutput dataOut) throws IOException { 455 } 456 457 public void looseUnmarshal(OpenWireFormat wireFormat, Object o, DataInput dataIn) throws IOException { 458 } 459 460 public void looseMarshalLong(OpenWireFormat wireFormat, long o, DataOutput dataOut) throws IOException { 461 dataOut.writeLong(o); 462 } 463 464 public long looseUnmarshalLong(OpenWireFormat wireFormat, DataInput dataIn) throws IOException { 465 return dataIn.readLong(); 466 } 467 468 protected DataStructure looseUnmarsalNestedObject(OpenWireFormat wireFormat, DataInput dataIn) 469 throws IOException { 470 return wireFormat.looseUnmarshalNestedObject(dataIn); 471 } 472 473 protected void looseMarshalNestedObject(OpenWireFormat wireFormat, DataStructure o, DataOutput dataOut) 474 throws IOException { 475 wireFormat.looseMarshalNestedObject(o, dataOut); 476 } 477 478 protected DataStructure looseUnmarsalCachedObject(OpenWireFormat wireFormat, DataInput dataIn) 479 throws IOException { 480 if (wireFormat.isCacheEnabled()) { 481 if (dataIn.readBoolean()) { 482 short index = dataIn.readShort(); 483 DataStructure object = wireFormat.looseUnmarshalNestedObject(dataIn); 484 wireFormat.setInUnmarshallCache(index, object); 485 return object; 486 } else { 487 short index = dataIn.readShort(); 488 return wireFormat.getFromUnmarshallCache(index); 489 } 490 } else { 491 return wireFormat.looseUnmarshalNestedObject(dataIn); 492 } 493 } 494 495 protected void looseMarshalCachedObject(OpenWireFormat wireFormat, DataStructure o, DataOutput dataOut) 496 throws IOException { 497 if (wireFormat.isCacheEnabled()) { 498 Short index = wireFormat.getMarshallCacheIndex(o); 499 dataOut.writeBoolean(index == null); 500 if (index == null) { 501 index = wireFormat.addToMarshallCache(o); 502 dataOut.writeShort(index.shortValue()); 503 wireFormat.looseMarshalNestedObject(o, dataOut); 504 } else { 505 dataOut.writeShort(index.shortValue()); 506 } 507 } else { 508 wireFormat.looseMarshalNestedObject(o, dataOut); 509 } 510 } 511 512 protected Throwable looseUnmarsalThrowable(OpenWireFormat wireFormat, DataInput dataIn) 513 throws IOException { 514 if (dataIn.readBoolean()) { 515 String clazz = looseUnmarshalString(dataIn); 516 String message = looseUnmarshalString(dataIn); 517 Throwable o = createThrowable(clazz, message); 518 if (wireFormat.isStackTraceEnabled()) { 519 if (STACK_TRACE_ELEMENT_CONSTRUCTOR != null) { 520 StackTraceElement ss[] = new StackTraceElement[dataIn.readShort()]; 521 for (int i = 0; i < ss.length; i++) { 522 try { 523 ss[i] = (StackTraceElement)STACK_TRACE_ELEMENT_CONSTRUCTOR 524 .newInstance(new Object[] {looseUnmarshalString(dataIn), 525 looseUnmarshalString(dataIn), 526 looseUnmarshalString(dataIn), 527 Integer.valueOf(dataIn.readInt())}); 528 } catch (IOException e) { 529 throw e; 530 } catch (Throwable e) { 531 } 532 } 533 o.setStackTrace(ss); 534 } else { 535 short size = dataIn.readShort(); 536 for (int i = 0; i < size; i++) { 537 looseUnmarshalString(dataIn); 538 looseUnmarshalString(dataIn); 539 looseUnmarshalString(dataIn); 540 dataIn.readInt(); 541 } 542 } 543 o.initCause(looseUnmarsalThrowable(wireFormat, dataIn)); 544 545 } 546 return o; 547 } else { 548 return null; 549 } 550 } 551 552 protected void looseMarshalThrowable(OpenWireFormat wireFormat, Throwable o, DataOutput dataOut) 553 throws IOException { 554 dataOut.writeBoolean(o != null); 555 if (o != null) { 556 looseMarshalString(o.getClass().getName(), dataOut); 557 looseMarshalString(o.getMessage(), dataOut); 558 if (wireFormat.isStackTraceEnabled()) { 559 StackTraceElement[] stackTrace = o.getStackTrace(); 560 dataOut.writeShort(stackTrace.length); 561 for (int i = 0; i < stackTrace.length; i++) { 562 StackTraceElement element = stackTrace[i]; 563 looseMarshalString(element.getClassName(), dataOut); 564 looseMarshalString(element.getMethodName(), dataOut); 565 looseMarshalString(element.getFileName(), dataOut); 566 dataOut.writeInt(element.getLineNumber()); 567 } 568 looseMarshalThrowable(wireFormat, o.getCause(), dataOut); 569 } 570 } 571 } 572 573 protected String looseUnmarshalString(DataInput dataIn) throws IOException { 574 if (dataIn.readBoolean()) { 575 return dataIn.readUTF(); 576 } else { 577 return null; 578 } 579 } 580 581 protected void looseMarshalString(String value, DataOutput dataOut) throws IOException { 582 dataOut.writeBoolean(value != null); 583 if (value != null) { 584 dataOut.writeUTF(value); 585 } 586 } 587 588 protected void looseMarshalObjectArray(OpenWireFormat wireFormat, DataStructure[] objects, 589 DataOutput dataOut) throws IOException { 590 dataOut.writeBoolean(objects != null); 591 if (objects != null) { 592 dataOut.writeShort(objects.length); 593 for (int i = 0; i < objects.length; i++) { 594 looseMarshalNestedObject(wireFormat, objects[i], dataOut); 595 } 596 } 597 } 598 599 protected void looseMarshalConstByteArray(OpenWireFormat wireFormat, byte[] data, DataOutput dataOut, 600 int i) throws IOException { 601 dataOut.write(data, 0, i); 602 } 603 604 protected byte[] looseUnmarshalConstByteArray(DataInput dataIn, int i) throws IOException { 605 byte data[] = new byte[i]; 606 dataIn.readFully(data); 607 return data; 608 } 609 610 protected void looseMarshalByteArray(OpenWireFormat wireFormat, byte[] data, DataOutput dataOut) 611 throws IOException { 612 dataOut.writeBoolean(data != null); 613 if (data != null) { 614 dataOut.writeInt(data.length); 615 dataOut.write(data); 616 } 617 } 618 619 protected byte[] looseUnmarshalByteArray(DataInput dataIn) throws IOException { 620 byte rc[] = null; 621 if (dataIn.readBoolean()) { 622 int size = dataIn.readInt(); 623 rc = new byte[size]; 624 dataIn.readFully(rc); 625 } 626 return rc; 627 } 628 629 protected void looseMarshalByteSequence(OpenWireFormat wireFormat, ByteSequence data, DataOutput dataOut) 630 throws IOException { 631 dataOut.writeBoolean(data != null); 632 if (data != null) { 633 dataOut.writeInt(data.getLength()); 634 dataOut.write(data.getData(), data.getOffset(), data.getLength()); 635 } 636 } 637 638 protected ByteSequence looseUnmarshalByteSequence(DataInput dataIn) throws IOException { 639 ByteSequence rc = null; 640 if (dataIn.readBoolean()) { 641 int size = dataIn.readInt(); 642 byte[] t = new byte[size]; 643 dataIn.readFully(t); 644 rc = new ByteSequence(t, 0, size); 645 } 646 return rc; 647 } 648}