All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.picocontainer.script.jruby.JRubyContainerBuilder Maven / Gradle / Ivy

There is a newer version: 2.2
Show newest version
/*****************************************************************************
 * Copyright (C) PicoContainer Organization. All rights reserved.            *
 * ------------------------------------------------------------------------- *
 * The software in this package is published under the terms of the BSD      *
 * style license a copy of which has been included with this distribution in *
 * the LICENSE.txt file.                                                     *
 * Original code by Nick Sieger                                                                          *
 *****************************************************************************/

package org.picocontainer.script.jruby;

import java.io.IOException;
import java.io.Reader;
import java.io.StringWriter;
import java.util.Collections;

import org.jruby.Ruby;
import org.jruby.RubyInstanceConfig;
import org.jruby.exceptions.RaiseException;
import org.jruby.javasupport.JavaEmbedUtils;
import org.jruby.runtime.builtin.IRubyObject;
import org.picocontainer.MutablePicoContainer;
import org.picocontainer.PicoCompositionException;
import org.picocontainer.PicoContainer;
import org.picocontainer.DefaultPicoContainer;
import org.picocontainer.containers.EmptyPicoContainer;
import org.picocontainer.classname.ClassLoadingPicoContainer;
import org.picocontainer.classname.DefaultClassLoadingPicoContainer;
import org.picocontainer.script.LifecycleMode;
import org.picocontainer.script.ScriptedPicoContainerMarkupException;
import org.picocontainer.script.ScriptedContainerBuilder;
import org.picocontainer.behaviors.Caching;

/**
 * The script uses the {@code scriptedcontainer.rb} script to create an instance of
 * {@link PicoContainer}. There are implicit variables named "$parent" and
 * "$assembly_scope".
 * 
 * @author Nick Sieger
 */
public final class JRubyContainerBuilder extends ScriptedContainerBuilder {
	public static final String MARKUP_EXCEPTION_PREFIX = "scriptedbuilder: ";

	private final String script;

	public JRubyContainerBuilder(Reader script, ClassLoader classLoader) {
		this(script,classLoader, LifecycleMode.AUTO_LIFECYCLE);
	}
	
	
	public JRubyContainerBuilder(Reader script, ClassLoader classLoader, LifecycleMode lifecycle) {
		super(script, classLoader, lifecycle);
		this.script = toString(script);
	}

	private String toString(Reader script) {
		int charsRead;
		char[] chars = new char[1024];
		StringWriter writer = new StringWriter();
		try {
			while ((charsRead = script.read(chars)) != -1) {
				writer.write(chars, 0, charsRead);
			}
		} catch (IOException e) {
			throw new RuntimeException("unable to read script from reader", e);
		}
		return writer.toString();
	}

	/**
	 * {@inheritDoc}
	 * 

Latest method of invoking jruby script have been adapted from * JRuby wiki:

* @todo create a way to prevent initialization and shutdown with each script invocation. */ protected PicoContainer createContainerFromScript(PicoContainer parentContainer, Object assemblyScope) { if ( parentContainer == null ){ parentContainer = new DefaultClassLoadingPicoContainer(getClassLoader(), new DefaultPicoContainer(new Caching(), new EmptyPicoContainer())); } if (! (parentContainer instanceof ClassLoadingPicoContainer)) { if (parentContainer instanceof MutablePicoContainer) { parentContainer = new DefaultClassLoadingPicoContainer(getClassLoader(), (MutablePicoContainer)parentContainer); } else { //We want this last because it will never propagate parent behaviors parentContainer = new DefaultClassLoadingPicoContainer(getClassLoader(), new DefaultPicoContainer(new Caching(), parentContainer)); } } RubyInstanceConfig rubyConfig = new RubyInstanceConfig(); rubyConfig.setLoader(this.getClassLoader()); Ruby ruby = JavaEmbedUtils.initialize(Collections.EMPTY_LIST, rubyConfig); ruby.getLoadService().require("org/picocontainer/script/jruby/scriptedbuilder"); ruby.defineReadonlyVariable("$parent", JavaEmbedUtils.javaToRuby(ruby, parentContainer)); ruby.defineReadonlyVariable("$assembly_scope", JavaEmbedUtils.javaToRuby(ruby, assemblyScope)); try { //IRubyObject result = ruby.executeScript(script); IRubyObject result = JavaEmbedUtils.newRuntimeAdapter().eval(ruby, script); return (PicoContainer) JavaEmbedUtils.rubyToJava(ruby, result, PicoContainer.class); } catch (RaiseException re) { if (re.getCause() instanceof ScriptedPicoContainerMarkupException) { throw (ScriptedPicoContainerMarkupException) re.getCause(); } Object errorMessage = JavaEmbedUtils.rubyToJava(ruby, re.getException().message, String.class); if (errorMessage instanceof String) { String message = (String) JavaEmbedUtils.rubyToJava(ruby, re.getException().message, String.class); if (message.startsWith(MARKUP_EXCEPTION_PREFIX)) { throw new ScriptedPicoContainerMarkupException(message.substring(MARKUP_EXCEPTION_PREFIX.length())); } else { throw new PicoCompositionException(message, re); } } else { throw new PicoCompositionException(errorMessage.toString(), re); } } finally { JavaEmbedUtils.terminate(ruby); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy