/** * */ package de.saumya.mojo.ruby.script; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import org.codehaus.classworlds.ClassRealm; import org.codehaus.classworlds.DuplicateRealmException; import org.codehaus.classworlds.NoSuchRealmException; import de.saumya.mojo.ruby.Logger; import de.saumya.mojo.ruby.ScriptUtils; public class ScriptFactory { public static List<String> NO_CLASSPATH = Collections.emptyList(); final Arguments switches = new Arguments(); final Arguments jvmArgs = new Arguments(); private final Map<String, String> env = new HashMap<String, String>(); final File jrubyStdlibJar; final Logger logger; final ClassRealm classRealm; final File jrubyJar; final List<String> classpathElements; final boolean fork; final Launcher launcher; public ScriptFactory(final Logger logger, final ClassRealm classRealm, final File jrubyJar, final List<String> classpathElements, final boolean fork) throws ScriptException, IOException { this(logger, classRealm, jrubyJar, jrubyJar, classpathElements, fork); } public ScriptFactory(final Logger logger, final ClassRealm classRealm, final File jrubyJar, File stdlibJar, final List<String> classpathElements, final boolean fork) throws ScriptException, IOException { this.logger = logger; this.jrubyStdlibJar = stdlibJar; this.jrubyJar = jrubyJar; if(this.jrubyJar != null){ this.logger.debug("script uses jruby jar:" + this.jrubyJar.getAbsolutePath()); } this.classpathElements = classpathElements == null ? NO_CLASSPATH : Collections.unmodifiableList(classpathElements); this.fork = fork; if (classRealm != null && jrubyJar != null) { this.classRealm = getOrCreateClassRealm(classRealm, jrubyJar); } else { this.classRealm = classRealm; } if (fork) { this.launcher = new AntLauncher(logger, this); } else { this.launcher = new EmbeddedLauncher(logger, this); } } private static synchronized ClassRealm getOrCreateClassRealm(final ClassRealm classRealm, final File jrubyJar) throws MalformedURLException, ScriptException { ClassRealm jruby; try { jruby = classRealm.getWorld().getRealm("jruby"); } catch (final NoSuchRealmException e) { try { jruby = classRealm.getWorld().newRealm("jruby"); if(jrubyJar != null){ jruby.addConstituent(jrubyJar.toURI().toURL()); } } catch (final DuplicateRealmException ee) { throw new ScriptException("could not setup classrealm for jruby", ee); } } return jruby; } public Script newScriptFromSearchPath(final String scriptName) throws IOException { return new Script(this, scriptName, true); } public Script newScriptFromJRubyJar(final String scriptName) throws IOException { try { // the first part only works on jruby-complete.jar URL url = new URL("jar:file:" + this.jrubyStdlibJar.getAbsolutePath() + "!/META-INF/jruby.home/bin/" + scriptName); url.openConnection().getContent(); return new Script(this, url); } catch (Exception e) { try { // fallback on classloader return newScriptFromResource("META-INF/jruby.home/bin/" + scriptName); } catch (FileNotFoundException ee) { // find jruby-home String base = "."; if ( this.env.containsKey( "JRUBY_HOME" ) ) { base = this.env.get( "JRUBY_HOME" ); } else if ( System.getProperty( "jruby.home" ) != null ) { base = System.getProperty( "jruby.home" ); } else { for( String arg : this.jvmArgs.list ){ if (arg.startsWith("-Djruby.home=")){ base = arg.substring("-Djruby.home=".length()); break; } } } File f = new File( base, new File( "bin", scriptName ).getPath() ); if ( f.exists() ){ return new Script(this, f); } else { throw ee; } } } } public Script newScriptFromResource(final String scriptName) throws IOException { URL url = this.classRealm != null ? this.classRealm.getClassLoader() .getResource(scriptName) : null; if (url == null) { url = ScriptUtils.getScriptFromResource(scriptName); } if (url.getProtocol().equals("file")) { return new Script(this, url.getPath(), false); } else { return new Script(this, url); } } public Script newArguments() { return new Script(this); } public Script newScript(final String script) throws IOException { return new Script(this, script); } public Script newScript(final File file) { return new Script(this, file); } public void addJvmArgs(final String args) { this.jvmArgs.parseAndAdd(args); } public void addSwitch(final String name) { this.switches.add(name); } public void addSwitch(final String name, final String value) { this.switches.add(name, value); } public void addSwitches(final String switches) { this.switches.parseAndAdd(switches); } public void addEnv(final String name, final File value) { if (value != null) { this.env.put(name, value.getAbsolutePath()); } else { this.env.put(name, null); } } public Map<String, String> environment(){ return env; } public void addEnv(final String name, final String value) { this.env.put(name, value); } public void addEnvs(final String environmentVars) { for (final String var : environmentVars.split("\\s+")) { final int index = var.indexOf("="); if (index > -1) { this.env.put(var.substring(0, index), var.substring(index + 1)); } } } @Override public String toString() { // TODO final StringBuilder buf = new StringBuilder(getClass().getName()); // for (final String arg : this.switches) { // buf.append(arg).append(" "); // } return buf.toString().trim(); } }