From e3fe104e7d5ec184aac36128aed2d217cb655dfc Mon Sep 17 00:00:00 2001 From: Florian Frank Date: Wed, 22 Sep 2010 22:21:02 +0200 Subject: started to build jruby extension with Rakefile --- java/src/json/ext/RuntimeInfo.java | 119 +++++++++++++++++++++++++++++++++++++ 1 file changed, 119 insertions(+) create mode 100644 java/src/json/ext/RuntimeInfo.java (limited to 'java/src/json/ext/RuntimeInfo.java') diff --git a/java/src/json/ext/RuntimeInfo.java b/java/src/json/ext/RuntimeInfo.java new file mode 100644 index 0000000..f446afe --- /dev/null +++ b/java/src/json/ext/RuntimeInfo.java @@ -0,0 +1,119 @@ +/* + * This code is copyrighted work by Daniel Luz . + * + * Distributed under the Ruby and GPLv2 licenses; see COPYING and GPL files + * for details. + */ +package json.ext; + +import java.lang.ref.WeakReference; +import java.util.HashMap; +import java.util.Map; +import java.util.WeakHashMap; +import org.jruby.Ruby; +import org.jruby.RubyClass; +import org.jruby.RubyEncoding; +import org.jruby.RubyModule; +import org.jruby.runtime.ThreadContext; +import org.jruby.runtime.builtin.IRubyObject; + + +final class RuntimeInfo { + // since the vast majority of cases runs just one runtime, + // we optimize for that + private static WeakReference runtime1 = new WeakReference(null); + private static RuntimeInfo info1; + // store remaining runtimes here (does not include runtime1) + private static Map runtimes; + + // these fields are filled by the service loaders + /** JSON */ + RubyModule jsonModule; + /** JSON::Ext::Generator::GeneratorMethods::String::Extend */ + RubyModule stringExtendModule; + /** JSON::Ext::Generator::State */ + RubyClass generatorStateClass; + /** JSON::SAFE_STATE_PROTOTYPE */ + GeneratorState safeStatePrototype; + + final RubyEncoding utf8; + final RubyEncoding ascii8bit; + // other encodings + private final Map encodings; + + private RuntimeInfo(Ruby runtime) { + RubyClass encodingClass = runtime.getEncoding(); + if (encodingClass == null) { // 1.8 mode + utf8 = ascii8bit = null; + encodings = null; + } else { + ThreadContext context = runtime.getCurrentContext(); + + utf8 = (RubyEncoding)RubyEncoding.find(context, + encodingClass, runtime.newString("utf-8")); + ascii8bit = (RubyEncoding)RubyEncoding.find(context, + encodingClass, runtime.newString("ascii-8bit")); + encodings = new HashMap(); + } + } + + static RuntimeInfo initRuntime(Ruby runtime) { + synchronized (RuntimeInfo.class) { + if (runtime1.get() == runtime) { + return info1; + } else if (runtime1.get() == null) { + runtime1 = new WeakReference(runtime); + info1 = new RuntimeInfo(runtime); + return info1; + } else { + if (runtimes == null) { + runtimes = new WeakHashMap(1); + } + RuntimeInfo cache = runtimes.get(runtime); + if (cache == null) { + cache = new RuntimeInfo(runtime); + runtimes.put(runtime, cache); + } + return cache; + } + } + } + + public static RuntimeInfo forRuntime(Ruby runtime) { + synchronized (RuntimeInfo.class) { + if (runtime1.get() == runtime) return info1; + RuntimeInfo cache = null; + if (runtimes != null) cache = runtimes.get(runtime); + assert cache != null : "Runtime given has not initialized JSON::Ext"; + return cache; + } + } + + public boolean encodingsSupported() { + return utf8 != null; + } + + public RubyEncoding getEncoding(ThreadContext context, String name) { + synchronized (encodings) { + RubyEncoding encoding = encodings.get(name); + if (encoding == null) { + Ruby runtime = context.getRuntime(); + encoding = (RubyEncoding)RubyEncoding.find(context, + runtime.getEncoding(), runtime.newString(name)); + encodings.put(name, encoding); + } + return encoding; + } + } + + public GeneratorState getSafeStatePrototype(ThreadContext context) { + if (safeStatePrototype == null) { + IRubyObject value = jsonModule.getConstant("SAFE_STATE_PROTOTYPE"); + if (!(value instanceof GeneratorState)) { + throw context.getRuntime().newTypeError(value, generatorStateClass); + } + safeStatePrototype = (GeneratorState)value; + } + return safeStatePrototype; + } +} -- cgit v1.2.1