Class: Java::ObjectInputStream
- Inherits:
-
Object
- Object
- Java::ObjectInputStream
- Includes:
- ObjectStream
- Defined in:
- lib/javaobs.rb
Overview
The Ruby version of the Java ObjectInputStream. Creates a Ruby proxy class for each Java Class.
Constant Summary
Constants included from ObjectStream
Java::ObjectStream::PRIM_ARRAY, Java::ObjectStream::PRIM_BOOL, Java::ObjectStream::PRIM_BYTE, Java::ObjectStream::PRIM_CHAR, Java::ObjectStream::PRIM_DOUBLE, Java::ObjectStream::PRIM_FLOAT, Java::ObjectStream::PRIM_INT, Java::ObjectStream::PRIM_LONG, Java::ObjectStream::PRIM_OBJECT, Java::ObjectStream::PRIM_SHORT, Java::ObjectStream::SC_BLOCKDATA, Java::ObjectStream::SC_EXTERNALIZABLE, Java::ObjectStream::SC_SERIALIZABLE, Java::ObjectStream::SC_WRITE_METHOD, Java::ObjectStream::STREAM_MAGIC, Java::ObjectStream::STREAM_VERSION, Java::ObjectStream::TC_ARRAY, Java::ObjectStream::TC_BLOCKDATA, Java::ObjectStream::TC_BLOCKDATALONG, Java::ObjectStream::TC_CLASS, Java::ObjectStream::TC_CLASSDESC, Java::ObjectStream::TC_ENDBLOCKDATA, Java::ObjectStream::TC_EXCEPTION, Java::ObjectStream::TC_LONGSTRING, Java::ObjectStream::TC_NULL, Java::ObjectStream::TC_OBJECT, Java::ObjectStream::TC_PROXYCLASSDESC, Java::ObjectStream::TC_REFERENCE, Java::ObjectStream::TC_RESET, Java::ObjectStream::TC_STRING
Instance Method Summary collapse
-
#defaultReadObject(object) ⇒ Object
Cover method for java method.
-
#initialize(str) ⇒ ObjectInputStream
constructor
Initialize from a stream.
-
#readArray(klass) ⇒ Object
Read an array of objects.
-
#readBlockData ⇒ Object
Read a Java block of data with a size and then the following data.
-
#readBlockEnd ⇒ Object
Read the block end tag.
-
#readBlockStart ⇒ Object
Read the block data beginning tag and return the size.
- #readBool ⇒ Object
- #readByte ⇒ Object
-
#readClassAnnotation ⇒ Object
Read the class annotation.
-
#readClassData(klass, object = nil) ⇒ Object
Read class data and recursively read parent classes.
-
#readClassDesc ⇒ Object
Read the Java class description and create a Ruby class to proxy it in this name-space.
- #readDouble ⇒ Object
-
#readFields(klass) ⇒ Object
Read all the fields from the stream and add them to the class.
- #readFloat ⇒ Object
- #readInt ⇒ Object
- #readLong ⇒ Object
-
#readObject ⇒ Object
Read an object from the stream.
-
#readObjectFields(klass, object) ⇒ Object
Reads the object fields from the stream.
-
#readObjects ⇒ Object
Read all objects in the stream.
- #readShort ⇒ Object
- #readString ⇒ Object
-
#readType(type, arrayType = nil, field = nil) ⇒ Object
Read a primitive data type.
- #readUID ⇒ Object
- #readUShort ⇒ Object
-
#rubyClassFor(name, super_name) ⇒ Object
Gets or creates a corresponding Ruby class for the Java class.
Constructor Details
#initialize(str) ⇒ ObjectInputStream
Initialize from a stream.
483 484 485 486 487 488 489 490 491 492 |
# File 'lib/javaobs.rb', line 483 def initialize(str) @str = str magic = readUShort streamVersion = readShort @objects = [] raise "Bad stream #{magic.to_s(16)}:#{streamVersion.to_s(16)}" if magic != STREAM_MAGIC || streamVersion != STREAM_VERSION end |
Instance Method Details
#defaultReadObject(object) ⇒ Object
Cover method for java method.
414 415 416 |
# File 'lib/javaobs.rb', line 414 def defaultReadObject(object) readObjectFields(object.class.javaClass, object) end |
#readArray(klass) ⇒ Object
Read an array of objects.
368 369 370 371 372 373 374 375 376 |
# File 'lib/javaobs.rb', line 368 def readArray(klass) size = readInt a = klass.rubyClass.new type = klass.arrayType 1.upto(size) do a << readType(type) end a end |
#readBlockData ⇒ Object
Read a Java block of data with a size and then the following data.
265 266 267 268 269 270 |
# File 'lib/javaobs.rb', line 265 def readBlockData size = readBlockStart data = @str.read(size) readBlockEnd data end |
#readBlockEnd ⇒ Object
Read the block end tag. Validate it is correct or raise a SerializationError.
259 260 261 262 |
# File 'lib/javaobs.rb', line 259 def readBlockEnd byte = readByte raise SerializationError, "Unexpected byte #{byte}" unless byte == TC_ENDBLOCKDATA end |
#readBlockStart ⇒ Object
Read the block data beginning tag and return the size. We can have a long or short block of data.
242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 |
# File 'lib/javaobs.rb', line 242 def readBlockStart byte = readByte size = nil case byte when TC_BLOCKDATA size = readByte when TC_BLOCKDATALONG size = readInt else raise SerializationError, "Expecting TC_BLOCKDATA, got #{'0x%X' % byte}" unless byte == TC_BLOCKDATA end size end |
#readBool ⇒ Object
236 |
# File 'lib/javaobs.rb', line 236 def readBool; @str.read(1)[0] != 0; end |
#readByte ⇒ Object
229 |
# File 'lib/javaobs.rb', line 229 def readByte; @str.read(1)[0]; end |
#readClassAnnotation ⇒ Object
Read the class annotation. We do not currently handle annotations.
290 291 292 293 |
# File 'lib/javaobs.rb', line 290 def readClassAnnotation ebd = readByte raise SerializationError, "We do not handle annotations!" unless ebd == TC_ENDBLOCKDATA end |
#readClassData(klass, object = nil) ⇒ Object
Read class data and recursively read parent classes. If the class is externalizable then we call the _readJavaData method to ‘ perform the custom serialization. See Java::Util::Hash and Java::Util::Date for an example.
430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 |
# File 'lib/javaobs.rb', line 430 def readClassData(klass, object = nil) if object == nil object = klass.rubyClass.new() @objects << object end readClassData(klass.superClass, object) if (klass.superClass) if klass.flags == SC_SERIALIZABLE readObjectFields(klass, object) else object._readJavaData(self) end object end |
#readClassDesc ⇒ Object
Read the Java class description and create a Ruby class to proxy it in this name-space. Added special handling for the Date class.
324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 |
# File 'lib/javaobs.rb', line 324 def readClassDesc name = readString uid = readUID flags = readByte klass = JavaClass.new(name, uid, flags) @objects << klass readFields(klass) readClassAnnotation klass.superClass = readObject # Create Ruby object representing class if name =~ /^[A-Z.]+/i # Create the class within the correct module. rclass = rubyClassFor(name, klass.superClass.to_s) unless rclass.methods.index('javaClass') rclass.class_eval "extend JavaObject" end rclass.class_eval "@javaClass = klass" vars = klass.fields.map do |f| ':' + f.name end rclass.class_eval "attr_accessor #{vars.join(',')}" klass.rubyClass = rclass else # Arrays newName = 'JavaArray' + klass.name[1..klass.name.length] unless Java.constants.index(newName) rclass = Java.module_eval "#{newName} = Class.new(JavaArray)" else rclass = Java.const_get(newName) end rclass.class_eval "@javaClass = klass" klass.rubyClass = rclass end klass end |
#readDouble ⇒ Object
233 |
# File 'lib/javaobs.rb', line 233 def readDouble; @str.read(8).unpack("G")[0]; end |
#readFields(klass) ⇒ Object
Read all the fields from the stream and add them to the class.
274 275 276 277 278 279 280 281 282 283 284 285 286 287 |
# File 'lib/javaobs.rb', line 274 def readFields(klass) fieldCount = readShort 1.upto(fieldCount) do type = readByte name = readString field = JavaField.new(name, type) # Check for array and object types if type == PRIM_OBJECT || type == PRIM_ARRAY field.subtype = readObject end klass.addField(field) end end |
#readFloat ⇒ Object
234 |
# File 'lib/javaobs.rb', line 234 def readFloat; @str.read(4).unpack("g")[0]; end |
#readInt ⇒ Object
232 |
# File 'lib/javaobs.rb', line 232 def readInt; @str.read(4).unpack("i")[0]; end |
#readLong ⇒ Object
238 |
# File 'lib/javaobs.rb', line 238 def readLong; @str.read(8).unpack("Q").first; end |
#readObject ⇒ Object
Read an object from the stream.
448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 |
# File 'lib/javaobs.rb', line 448 def readObject object = nil byte = readByte case byte when TC_OBJECT klass = readObject object = readClassData(klass) when TC_REFERENCE readShort object = @objects[readShort] when TC_ARRAY klass = readObject object = readArray(klass) @objects << object when TC_STRING object = readString @objects << object when TC_CLASSDESC object = readClassDesc when TC_NULL object = nil else raise SerializationError, "Unexpected byte #{byte} at #{@str.pos}" end object end |
#readObjectFields(klass, object) ⇒ Object
Reads the object fields from the stream.
419 420 421 422 423 424 |
# File 'lib/javaobs.rb', line 419 def readObjectFields(klass, object) klass.fields.each do |f| v = readType(f.type, f.subtype, f) object.send((f.name + '=').intern, v) end end |
#readObjects ⇒ Object
Read all objects in the stream. Calls readObject until the stream eof is reached.
496 497 498 499 500 501 502 |
# File 'lib/javaobs.rb', line 496 def readObjects objs = [] until (@str.eof) objs << readObject end objs end |
#readShort ⇒ Object
231 |
# File 'lib/javaobs.rb', line 231 def readShort; @str.read(2).unpack("s")[0]; end |
#readString ⇒ Object
235 |
# File 'lib/javaobs.rb', line 235 def readString; @str.read(readShort); end |
#readType(type, arrayType = nil, field = nil) ⇒ Object
Read a primitive data type.
379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 |
# File 'lib/javaobs.rb', line 379 def readType(type, arrayType = nil, field = nil) case type when PRIM_BYTE readByte when PRIM_CHAR readByte when PRIM_DOUBLE readDouble when PRIM_FLOAT readFloat when PRIM_INT readInt when PRIM_LONG readLong when PRIM_SHORT readShort when PRIM_BOOL readBool when PRIM_OBJECT, PRIM_ARRAY readObject else raise SerializationError, "Unknown type #{type}" end end |
#readUID ⇒ Object
237 |
# File 'lib/javaobs.rb', line 237 def readUID; @str.read(8); end |
#readUShort ⇒ Object
230 |
# File 'lib/javaobs.rb', line 230 def readUShort; @str.read(2).unpack("n")[0]; end |
#rubyClassFor(name, super_name) ⇒ Object
Gets or creates a corresponding Ruby class for the Java class. This will drop leading com or java and transform the rest of the dotted names to modules.
298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 |
# File 'lib/javaobs.rb', line 298 def rubyClassFor(name, super_name) context = name.split('.') f, = context context.shift if f == 'java' or f == 'com' context.map! { |n| n.capitalize! if n !~ /^[A-Z]/o; n } kname = context.pop mod = Java context.each do |m| unless mod.constants.include?(m) mod = mod.module_eval "#{m} = Module.new" else mod = mod.const_get(m) end end unless mod.constants.include?(kname) rclass = mod.module_eval "#{kname} = Class.new(#{super_name})" else rclass = mod.const_get(kname) end rclass end |