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.v1; 018 019import java.io.DataInput; 020import java.io.DataOutput; 021import java.io.IOException; 022import java.lang.reflect.Constructor; 023 024import org.apache.activemq.command.DataStructure; 025import org.apache.activemq.openwire.BooleanStream; 026import org.apache.activemq.openwire.DataStreamMarshaller; 027import org.apache.activemq.openwire.OpenWireFormat; 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 new Integer(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 Constructor constructor = clazz.getConstructor(new Class[] {String.class}); 232 return (Throwable)constructor.newInstance(new Object[] {message}); 233 } catch (Throwable e) { 234 return new Throwable(className + ": " + message); 235 } 236 } 237 238 protected int tightMarshalThrowable1(OpenWireFormat wireFormat, Throwable o, BooleanStream bs) 239 throws IOException { 240 if (o == null) { 241 bs.writeBoolean(false); 242 return 0; 243 } else { 244 int rc = 0; 245 bs.writeBoolean(true); 246 rc += tightMarshalString1(o.getClass().getName(), bs); 247 rc += tightMarshalString1(o.getMessage(), bs); 248 if (wireFormat.isStackTraceEnabled()) { 249 rc += 2; 250 StackTraceElement[] stackTrace = o.getStackTrace(); 251 for (int i = 0; i < stackTrace.length; i++) { 252 StackTraceElement element = stackTrace[i]; 253 rc += tightMarshalString1(element.getClassName(), bs); 254 rc += tightMarshalString1(element.getMethodName(), bs); 255 rc += tightMarshalString1(element.getFileName(), bs); 256 rc += 4; 257 } 258 rc += tightMarshalThrowable1(wireFormat, o.getCause(), bs); 259 } 260 return rc; 261 } 262 } 263 264 protected void tightMarshalThrowable2(OpenWireFormat wireFormat, Throwable o, DataOutput dataOut, 265 BooleanStream bs) throws IOException { 266 if (bs.readBoolean()) { 267 tightMarshalString2(o.getClass().getName(), dataOut, bs); 268 tightMarshalString2(o.getMessage(), dataOut, bs); 269 if (wireFormat.isStackTraceEnabled()) { 270 StackTraceElement[] stackTrace = o.getStackTrace(); 271 dataOut.writeShort(stackTrace.length); 272 for (int i = 0; i < stackTrace.length; i++) { 273 StackTraceElement element = stackTrace[i]; 274 tightMarshalString2(element.getClassName(), dataOut, bs); 275 tightMarshalString2(element.getMethodName(), dataOut, bs); 276 tightMarshalString2(element.getFileName(), dataOut, bs); 277 dataOut.writeInt(element.getLineNumber()); 278 } 279 tightMarshalThrowable2(wireFormat, o.getCause(), dataOut, bs); 280 } 281 } 282 } 283 284 @SuppressWarnings("deprecation") 285 protected String tightUnmarshalString(DataInput dataIn, BooleanStream bs) throws IOException { 286 if (bs.readBoolean()) { 287 if (bs.readBoolean()) { 288 int size = dataIn.readShort(); 289 byte data[] = new byte[size]; 290 dataIn.readFully(data); 291 // Yes deprecated, but we know what we are doing. 292 // This allows us to create a String from a ASCII byte array. (no UTF-8 decoding) 293 return new String(data, 0); 294 } else { 295 return dataIn.readUTF(); 296 } 297 } else { 298 return null; 299 } 300 } 301 302 protected int tightMarshalString1(String value, BooleanStream bs) throws IOException { 303 bs.writeBoolean(value != null); 304 if (value != null) { 305 306 int strlen = value.length(); 307 int utflen = 0; 308 char[] charr = new char[strlen]; 309 int c = 0; 310 boolean isOnlyAscii = true; 311 312 value.getChars(0, strlen, charr, 0); 313 314 for (int i = 0; i < strlen; i++) { 315 c = charr[i]; 316 if ((c >= 0x0001) && (c <= 0x007F)) { 317 utflen++; 318 } else if (c > 0x07FF) { 319 utflen += 3; 320 isOnlyAscii = false; 321 } else { 322 isOnlyAscii = false; 323 utflen += 2; 324 } 325 } 326 327 if (utflen >= Short.MAX_VALUE) { 328 throw new IOException("Encountered a String value that is too long to encode."); 329 } 330 bs.writeBoolean(isOnlyAscii); 331 return utflen + 2; 332 333 } else { 334 return 0; 335 } 336 } 337 338 protected void tightMarshalString2(String value, DataOutput dataOut, BooleanStream bs) throws IOException { 339 if (bs.readBoolean()) { 340 // If we verified it only holds ascii values 341 if (bs.readBoolean()) { 342 dataOut.writeShort(value.length()); 343 dataOut.writeBytes(value); 344 } else { 345 dataOut.writeUTF(value); 346 } 347 } 348 } 349 350 protected int tightMarshalObjectArray1(OpenWireFormat wireFormat, DataStructure[] objects, 351 BooleanStream bs) throws IOException { 352 if (objects != null) { 353 int rc = 0; 354 bs.writeBoolean(true); 355 rc += 2; 356 for (int i = 0; i < objects.length; i++) { 357 rc += tightMarshalNestedObject1(wireFormat, objects[i], bs); 358 } 359 return rc; 360 } else { 361 bs.writeBoolean(false); 362 return 0; 363 } 364 } 365 366 protected void tightMarshalObjectArray2(OpenWireFormat wireFormat, DataStructure[] objects, 367 DataOutput dataOut, BooleanStream bs) throws IOException { 368 if (bs.readBoolean()) { 369 dataOut.writeShort(objects.length); 370 for (int i = 0; i < objects.length; i++) { 371 tightMarshalNestedObject2(wireFormat, objects[i], dataOut, bs); 372 } 373 } 374 } 375 376 protected int tightMarshalConstByteArray1(byte[] data, BooleanStream bs, int i) throws IOException { 377 return i; 378 } 379 380 protected void tightMarshalConstByteArray2(byte[] data, DataOutput dataOut, BooleanStream bs, int i) 381 throws IOException { 382 dataOut.write(data, 0, i); 383 } 384 385 protected byte[] tightUnmarshalConstByteArray(DataInput dataIn, BooleanStream bs, int i) 386 throws IOException { 387 byte data[] = new byte[i]; 388 dataIn.readFully(data); 389 return data; 390 } 391 392 protected int tightMarshalByteArray1(byte[] data, BooleanStream bs) throws IOException { 393 bs.writeBoolean(data != null); 394 if (data != null) { 395 return data.length + 4; 396 } else { 397 return 0; 398 } 399 } 400 401 protected void tightMarshalByteArray2(byte[] data, DataOutput dataOut, BooleanStream bs) 402 throws IOException { 403 if (bs.readBoolean()) { 404 dataOut.writeInt(data.length); 405 dataOut.write(data); 406 } 407 } 408 409 protected byte[] tightUnmarshalByteArray(DataInput dataIn, BooleanStream bs) throws IOException { 410 byte rc[] = null; 411 if (bs.readBoolean()) { 412 int size = dataIn.readInt(); 413 rc = new byte[size]; 414 dataIn.readFully(rc); 415 } 416 return rc; 417 } 418 419 protected int tightMarshalByteSequence1(ByteSequence data, BooleanStream bs) throws IOException { 420 bs.writeBoolean(data != null); 421 if (data != null) { 422 return data.getLength() + 4; 423 } else { 424 return 0; 425 } 426 } 427 428 protected void tightMarshalByteSequence2(ByteSequence data, DataOutput dataOut, BooleanStream bs) 429 throws IOException { 430 if (bs.readBoolean()) { 431 dataOut.writeInt(data.getLength()); 432 dataOut.write(data.getData(), data.getOffset(), data.getLength()); 433 } 434 } 435 436 protected ByteSequence tightUnmarshalByteSequence(DataInput dataIn, BooleanStream bs) throws IOException { 437 ByteSequence rc = null; 438 if (bs.readBoolean()) { 439 int size = dataIn.readInt(); 440 byte[] t = new byte[size]; 441 dataIn.readFully(t); 442 return new ByteSequence(t, 0, size); 443 } 444 return rc; 445 } 446 447 // 448 // The loose marshaling logic 449 // 450 451 public void looseMarshal(OpenWireFormat wireFormat, Object o, DataOutput dataOut) throws IOException { 452 } 453 454 public void looseUnmarshal(OpenWireFormat wireFormat, Object o, DataInput dataIn) throws IOException { 455 } 456 457 public void looseMarshalLong(OpenWireFormat wireFormat, long o, DataOutput dataOut) throws IOException { 458 dataOut.writeLong(o); 459 } 460 461 public long looseUnmarshalLong(OpenWireFormat wireFormat, DataInput dataIn) throws IOException { 462 return dataIn.readLong(); 463 } 464 465 protected DataStructure looseUnmarsalNestedObject(OpenWireFormat wireFormat, DataInput dataIn) 466 throws IOException { 467 return wireFormat.looseUnmarshalNestedObject(dataIn); 468 } 469 470 protected void looseMarshalNestedObject(OpenWireFormat wireFormat, DataStructure o, DataOutput dataOut) 471 throws IOException { 472 wireFormat.looseMarshalNestedObject(o, dataOut); 473 } 474 475 protected DataStructure looseUnmarsalCachedObject(OpenWireFormat wireFormat, DataInput dataIn) 476 throws IOException { 477 if (wireFormat.isCacheEnabled()) { 478 if (dataIn.readBoolean()) { 479 short index = dataIn.readShort(); 480 DataStructure object = wireFormat.looseUnmarshalNestedObject(dataIn); 481 wireFormat.setInUnmarshallCache(index, object); 482 return object; 483 } else { 484 short index = dataIn.readShort(); 485 return wireFormat.getFromUnmarshallCache(index); 486 } 487 } else { 488 return wireFormat.looseUnmarshalNestedObject(dataIn); 489 } 490 } 491 492 protected void looseMarshalCachedObject(OpenWireFormat wireFormat, DataStructure o, DataOutput dataOut) 493 throws IOException { 494 if (wireFormat.isCacheEnabled()) { 495 Short index = wireFormat.getMarshallCacheIndex(o); 496 dataOut.writeBoolean(index == null); 497 if (index == null) { 498 index = wireFormat.addToMarshallCache(o); 499 dataOut.writeShort(index.shortValue()); 500 wireFormat.looseMarshalNestedObject(o, dataOut); 501 } else { 502 dataOut.writeShort(index.shortValue()); 503 } 504 } else { 505 wireFormat.looseMarshalNestedObject(o, dataOut); 506 } 507 } 508 509 protected Throwable looseUnmarsalThrowable(OpenWireFormat wireFormat, DataInput dataIn) 510 throws IOException { 511 if (dataIn.readBoolean()) { 512 String clazz = looseUnmarshalString(dataIn); 513 String message = looseUnmarshalString(dataIn); 514 Throwable o = createThrowable(clazz, message); 515 if (wireFormat.isStackTraceEnabled()) { 516 if (STACK_TRACE_ELEMENT_CONSTRUCTOR != null) { 517 StackTraceElement ss[] = new StackTraceElement[dataIn.readShort()]; 518 for (int i = 0; i < ss.length; i++) { 519 try { 520 ss[i] = (StackTraceElement)STACK_TRACE_ELEMENT_CONSTRUCTOR 521 .newInstance(new Object[] {looseUnmarshalString(dataIn), 522 looseUnmarshalString(dataIn), 523 looseUnmarshalString(dataIn), 524 new Integer(dataIn.readInt())}); 525 } catch (IOException e) { 526 throw e; 527 } catch (Throwable e) { 528 } 529 } 530 o.setStackTrace(ss); 531 } else { 532 short size = dataIn.readShort(); 533 for (int i = 0; i < size; i++) { 534 looseUnmarshalString(dataIn); 535 looseUnmarshalString(dataIn); 536 looseUnmarshalString(dataIn); 537 dataIn.readInt(); 538 } 539 } 540 o.initCause(looseUnmarsalThrowable(wireFormat, dataIn)); 541 542 } 543 return o; 544 } else { 545 return null; 546 } 547 } 548 549 protected void looseMarshalThrowable(OpenWireFormat wireFormat, Throwable o, DataOutput dataOut) 550 throws IOException { 551 dataOut.writeBoolean(o != null); 552 if (o != null) { 553 looseMarshalString(o.getClass().getName(), dataOut); 554 looseMarshalString(o.getMessage(), dataOut); 555 if (wireFormat.isStackTraceEnabled()) { 556 StackTraceElement[] stackTrace = o.getStackTrace(); 557 dataOut.writeShort(stackTrace.length); 558 for (int i = 0; i < stackTrace.length; i++) { 559 StackTraceElement element = stackTrace[i]; 560 looseMarshalString(element.getClassName(), dataOut); 561 looseMarshalString(element.getMethodName(), dataOut); 562 looseMarshalString(element.getFileName(), dataOut); 563 dataOut.writeInt(element.getLineNumber()); 564 } 565 looseMarshalThrowable(wireFormat, o.getCause(), dataOut); 566 } 567 } 568 } 569 570 protected String looseUnmarshalString(DataInput dataIn) throws IOException { 571 if (dataIn.readBoolean()) { 572 return dataIn.readUTF(); 573 } else { 574 return null; 575 } 576 } 577 578 protected void looseMarshalString(String value, DataOutput dataOut) throws IOException { 579 dataOut.writeBoolean(value != null); 580 if (value != null) { 581 dataOut.writeUTF(value); 582 } 583 } 584 585 protected void looseMarshalObjectArray(OpenWireFormat wireFormat, DataStructure[] objects, 586 DataOutput dataOut) throws IOException { 587 dataOut.writeBoolean(objects != null); 588 if (objects != null) { 589 dataOut.writeShort(objects.length); 590 for (int i = 0; i < objects.length; i++) { 591 looseMarshalNestedObject(wireFormat, objects[i], dataOut); 592 } 593 } 594 } 595 596 protected void looseMarshalConstByteArray(OpenWireFormat wireFormat, byte[] data, DataOutput dataOut, 597 int i) throws IOException { 598 dataOut.write(data, 0, i); 599 } 600 601 protected byte[] looseUnmarshalConstByteArray(DataInput dataIn, int i) throws IOException { 602 byte data[] = new byte[i]; 603 dataIn.readFully(data); 604 return data; 605 } 606 607 protected void looseMarshalByteArray(OpenWireFormat wireFormat, byte[] data, DataOutput dataOut) 608 throws IOException { 609 dataOut.writeBoolean(data != null); 610 if (data != null) { 611 dataOut.writeInt(data.length); 612 dataOut.write(data); 613 } 614 } 615 616 protected byte[] looseUnmarshalByteArray(DataInput dataIn) throws IOException { 617 byte rc[] = null; 618 if (dataIn.readBoolean()) { 619 int size = dataIn.readInt(); 620 rc = new byte[size]; 621 dataIn.readFully(rc); 622 } 623 return rc; 624 } 625 626 protected void looseMarshalByteSequence(OpenWireFormat wireFormat, ByteSequence data, DataOutput dataOut) 627 throws IOException { 628 dataOut.writeBoolean(data != null); 629 if (data != null) { 630 dataOut.writeInt(data.getLength()); 631 dataOut.write(data.getData(), data.getOffset(), data.getLength()); 632 } 633 } 634 635 protected ByteSequence looseUnmarshalByteSequence(DataInput dataIn) throws IOException { 636 ByteSequence rc = null; 637 if (dataIn.readBoolean()) { 638 int size = dataIn.readInt(); 639 byte[] t = new byte[size]; 640 dataIn.readFully(t); 641 rc = new ByteSequence(t, 0, size); 642 } 643 return rc; 644 } 645}