问题
I have a an object that I'd like to grab the contents of in java. The only problem is that is is currently in ruby.
irb(main):050:0> blah
=> "BAh7ByIeYXV0aGVudGljYXRpb25fc3RyYXRlZ2llczAiCXVzZXJpBg%253D%253D-\
-0cdecf4edfaa5cbe4693c9fb83b204c1256a54a6"
irb(main):049:0> Marshal.load(Base64.decode64(blah))
=> {"authentication_strategies"=>nil, "user"=>1}
I got the base64 portion allright -- so now everything is in bytes. How would i access that 2nd string? I presume something can be done with jruby but I've never used it before and would have no clue where to start.
let me elaborate on my problem here.
1) these are cookies that I'm trying to share between a servlet on tomcat and a merb app on apache
2) I am not going to be storing them in the database. I have thought about using them in memcached but for other reasons I'd like to store them as cookies (yes I'm well aware of the security implications involved)
I am currently looking at jruby's Red Bridge/jruby-embed, however since this is only like 70 bytes I need to look at I think it's ridiculous to call up all that overhead for something so simple.
rather than start up a new question.... code I have right now looks like so:
// using commons
Base64 b64 = new Base64();
byte[] decoded = b64.decode(cookie.getValue().getBytes());
ScriptingContainer container = new ScriptingContainer();
container.runScriptlet("la = Marshal.load(\"" + decoded + "\"); puts la.to_s;");
obviously this isn't going to work cause marshal is going to check the first 2 bytes of decoded and freak out since it doesn't match jruby's major/minor version....hrmss..
回答1:
For a solution not involving JRuby, Why don't you serialize the fields you are interested in yourself? For example, saving them as raw strings into a file or to a relational database?
I realize that this may not exactly answer the question but it may be a possibility that you hadn't previously thought of!
EDIT - feydr has made it clear that he was not talking about serializing object data to a file. I presume therefore that the serialization is for inter-process communication, in which case a binary protocol (or any protocol really) delivered via sockets isa good solution and easy to implement. You could do worse than to have a look at Google protocol buffers (it can even do code generation on the Java side).
回答2:
Ok! This is what I did. Let me re-iterate my whole purpose here was to get a cookie session from merb to a servlet running under tomcat.
import java.io.*;
import java.util.*;
import org.jruby.embed.ScriptingContainer;
import org.apache.commons.codec.binary.Base64;
import javax.servlet.*;
import javax.servlet.http.*;
public class process extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
HttpSession session = request.getSession(true);
PrintWriter out = response.getWriter();
Cookie[] cookies = request.getCookies();
for(int i=0; i<cookies.length; i++) {
Cookie cookie = cookies[i];
// base64 decode, then un-marshall ruby style...
// finally figure out what to do with our session secret key
if(cookie.getName().equals("_session_id")) {
ScriptingContainer container = new ScriptingContainer();
container.setWriter(out);
container.runScriptlet("require 'base64'; puts \"" + cookie.getValue() + "\"; " +
"puts Marshal.load(Base64.decode64(\"" + cookie.getValue() + "\")).to_s; ");
}
}
}
}
Obviously this code can be cleaned up quite a lot -- eg: moving the base64 decoding back to java -- but this will get a cookie from merb. Now I just need to throw the validator in there to make sure this isn't forged.
Thanks for your suggestions everyone!
回答3:
You may also consider using Google protocol buffers which are available for Ruby and Java (as well as C++ and Python).
来源:https://stackoverflow.com/questions/1759371/how-do-i-unmarshal-a-ruby-object-in-java