1 33 package org.jruby; 34 35 import java.io.ByteArrayInputStream ; 36 import java.io.ByteArrayOutputStream ; 37 import java.io.EOFException ; 38 import java.io.IOException ; 39 import java.io.InputStream ; 40 import java.io.OutputStream ; 41 42 import org.jruby.runtime.Block; 43 import org.jruby.runtime.CallbackFactory; 44 import org.jruby.runtime.Constants; 45 import org.jruby.runtime.builtin.IRubyObject; 46 import org.jruby.runtime.marshal.MarshalStream; 47 import org.jruby.runtime.marshal.UnmarshalStream; 48 49 import org.jruby.util.ByteList; 50 51 56 public class RubyMarshal { 57 58 public static RubyModule createMarshalModule(Ruby runtime) { 59 RubyModule module = runtime.defineModule("Marshal"); 60 CallbackFactory callbackFactory = runtime.callbackFactory(RubyMarshal.class); 61 62 module.defineSingletonMethod("dump", callbackFactory.getOptSingletonMethod("dump")); 63 module.defineSingletonMethod("load", callbackFactory.getOptSingletonMethod("load")); 64 module.defineSingletonMethod("restore", callbackFactory.getOptSingletonMethod("load")); 65 module.defineConstant("MAJOR_VERSION", runtime.newFixnum(Constants.MARSHAL_MAJOR)); 66 module.defineConstant("MINOR_VERSION", runtime.newFixnum(Constants.MARSHAL_MINOR)); 67 68 return module; 69 } 70 71 public static IRubyObject dump(IRubyObject recv, IRubyObject[] args, Block unusedBlock) { 72 if (args.length < 1) { 73 throw recv.getRuntime().newArgumentError("wrong # of arguments(at least 1)"); 74 } 75 IRubyObject objectToDump = args[0]; 76 77 RubyIO io = null; 78 int depthLimit = -1; 79 80 if (args.length >= 2) { 81 if (args[1] instanceof RubyIO) { 82 io = (RubyIO) args[1]; 83 } else if (args[1] instanceof RubyFixnum) { 84 depthLimit = (int) ((RubyFixnum) args[1]).getLongValue(); 85 } 86 if (args.length == 3) { 87 depthLimit = (int) ((RubyFixnum) args[2]).getLongValue(); 88 } 89 } 90 91 try { 92 if (io != null) { 93 dumpToStream(objectToDump, io.getOutStream(), depthLimit); 94 return io; 95 } 96 ByteArrayOutputStream stringOutput = new ByteArrayOutputStream (); 97 dumpToStream(objectToDump, stringOutput, depthLimit); 98 return RubyString.newString(recv.getRuntime(), new ByteList(stringOutput.toByteArray(),false)); 99 100 } catch (IOException ioe) { 101 throw recv.getRuntime().newIOErrorFromException(ioe); 102 } 103 104 } 105 106 public static IRubyObject load(IRubyObject recv, IRubyObject[] args, Block unusedBlock) { 107 try { 108 if (args.length < 1) { 109 throw recv.getRuntime().newArgumentError("wrong number of arguments (0 for 1)"); 110 } 111 112 if (args.length > 2) { 113 throw recv.getRuntime().newArgumentError("wrong number of arguments (" + args.length + " for 2)"); 114 } 115 116 IRubyObject in = null; 117 IRubyObject proc = null; 118 119 switch (args.length) { 120 case 2: 121 proc = args[1]; 122 case 1: 123 in = args[0]; 124 } 125 126 InputStream rawInput; 127 if (in instanceof RubyIO) { 128 rawInput = ((RubyIO) in).getInStream(); 129 } else if (in.respondsTo("to_str")) { 130 RubyString inString = (RubyString) in.callMethod(recv.getRuntime().getCurrentContext(), "to_str"); 131 rawInput = new ByteArrayInputStream (inString.getBytes()); 132 } else { 133 throw recv.getRuntime().newTypeError("instance of IO needed"); 134 } 135 136 UnmarshalStream input = new UnmarshalStream(recv.getRuntime(), rawInput, proc); 137 138 return input.unmarshalObject(); 139 140 } catch (EOFException ee) { 141 throw recv.getRuntime().newEOFError(); 142 } catch (IOException ioe) { 143 throw recv.getRuntime().newIOErrorFromException(ioe); 144 } 145 } 146 147 private static void dumpToStream(IRubyObject object, OutputStream rawOutput, int depthLimit) 148 throws IOException 149 { 150 MarshalStream output = new MarshalStream(object.getRuntime(), rawOutput, depthLimit); 151 output.dumpObject(object); 152 } 153 } 154 | Popular Tags |