com.bertramlabs.plugins.jruby.IsolatedScriptingContainer Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jruby-container Show documentation
Show all versions of jruby-container Show documentation
Provides an isolated Jruby Execution Container that can fetch gems to run from rubygems in an isolated folder.
The newest version!
/*
* Copyright 2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.bertramlabs.plugins.jruby;
import org.jruby.embed.ScriptingContainer;
import org.jruby.embed.PathType;
import org.jruby.embed.LocalContextScope;
import org.jruby.embed.LocalVariableBehavior;
import java.util.HashMap;
import java.util.Set;
import java.io.File;
import java.io.IOException;
import java.util.Map;
import java.util.ArrayList;
/**
* An extension of JRuby's ScriptingContainer that allows the container to run in an isolated gem directory.
* Essentially, provides gemset capabilities to the Jruby runtime in a folder `.jruby-container`
*
* @author David Estes
*/
public class IsolatedScriptingContainer extends org.jruby.embed.ScriptingContainer {
private String name;
private String containerPath;
private File gemDir;
/**
* Constructs an IsolatedScriptingContainer for use.
* @param name The name of the container. Used to isolate gems in a gemset
*/
public IsolatedScriptingContainer(String name) throws IOException {
super();
this.name = name;
this.initializeEnvironment();
}
/**
* Constructs an IsolatedScriptingContainer for use.
* @param name The name of the container. Used to isolate gems in a gemset
* @param behavior
*/
public IsolatedScriptingContainer(String name, LocalVariableBehavior behavior) throws IOException {
super(behavior);
this.name = name;
this.initializeEnvironment();
}
/**
* Constructs an IsolatedScriptingContainer for use.
* @param name The name of the container. Used to isolate gems in a gemset
* @param scope
*/
public IsolatedScriptingContainer(String name, LocalContextScope scope) throws IOException {
super(scope);
this.name = name;
this.initializeEnvironment();
}
/**
* Constructs an IsolatedScriptingContainer for use.
* @param name The name of the container. Used to isolate gems in a gemset
* @param scope
* @param behavior
*/
public IsolatedScriptingContainer(String name, LocalContextScope scope, LocalVariableBehavior behavior) throws IOException {
super(scope,behavior);
this.name = name;
this.initializeEnvironment();
}
/**
* Initializes the environment variables pointing to the container path given by the global config
*/
public void initializeEnvironment() throws IOException {
initializeEnvironment(JrubyContainerConfig.getContainerPath());
}
public String getContainerPath() {
return this.containerPath;
}
/**
* Initializes the environment allowing a custom container path to be specified
* @param containerPath The path to the folder in which the gemsets should be stored. If the directory does not exist, it will be created.
*
*/
public void initializeEnvironment(String containerPath) throws IOException {
if(containerPath == null) {
HashMap environmentMap = new HashMap();
environmentMap.put("GEM_HOME", null);
environmentMap.put("CLASSPATH", "");
this.setEnvironment(environmentMap);
return;
}
this.containerPath = containerPath;
File containerDir = new File(containerPath, this.name);
if(!containerDir.exists()) {
containerDir.mkdirs();
}
gemDir = new File(containerDir.getCanonicalPath(), "gems");
if(!gemDir.exists()) {
gemDir.mkdirs();
}
HashMap environmentMap = new HashMap();
environmentMap.put("GEM_HOME", gemDir.getCanonicalPath());
environmentMap.put("CLASSPATH", "");
//TODO: Do we need to actually do this or keep it at META-INF/jruby.home
// this.setHomeDirectory(containerDir.getCanonicalPath());
this.setEnvironment(environmentMap);
}
/**
* Installs gems from rubygems into the containerPath.
* @param gemList Map of gems to install with the key being the gem name and the value being the version (leave blank if you dont want to scope to a specific version)
*/
public Boolean installGemDependencies(Map gemList) throws IOException {
Set gemSet = gemList.keySet();
ArrayList argList = new ArrayList();
for(String gemName : gemSet) {
String gemVersion = gemList.get(gemName);
if(!isGemInstalled(gemName,gemVersion)) {
if(gemVersion != null && gemVersion.length() > 0) {
argList.add(gemName + ":" + gemVersion);
} else {
argList.add(gemName);
}
}
}
if(argList.size() == 0) {
return true;
}
argList.add(0,"install");
IsolatedScriptingContainer gemInstall = new IsolatedScriptingContainer(name);
// gemInstall.setCompileMode(org.jruby.RubyInstanceConfig.CompileMode.OFF);
gemInstall.put("ARGV", argList.toArray(new String[argList.size()]));
gemInstall.initializeEnvironment(containerPath);
gemInstall.runScriptlet(PathType.CLASSPATH, "META-INF/jruby.home/bin/jgem");
gemInstall.terminate();
return true;
}
/**
* Executes a bin script in the GEM_HOME from this container
* @param path - Binary name of script to be executed
* @param argv - Arguments that you wish to pass to this runtime script.
*/
public Object runBinScript(String path, String[] argv) throws IOException {
String binPath = new File(gemDir.getCanonicalPath(),"bin").getCanonicalPath();
String binExec = new File(binPath,path).getCanonicalPath();
this.put("ARGV", argv);
return this.runScriptlet(PathType.ABSOLUTE, binExec);
}
/**
* Detects if a gem is installed in the current container or not.
* @param gemName - The Name of the gem we are looking for
* @param version - The specific version, if left blank we ignore.
*/
public Boolean isGemInstalled(String gemName, String version) throws IOException {
File specifications = new File(gemDir.getCanonicalPath(),"specifications");
if(!specifications.exists()) {
return false;
}
for(File spec : specifications.listFiles()) {
String name = spec.getName();
String nameWithoutExtension = name.replace("-java.gemspec","").replace(".gemspec","");
int splitPosition = nameWithoutExtension.lastIndexOf('-');
String specGemName = nameWithoutExtension.substring(0,splitPosition);
String specVersion = nameWithoutExtension.substring(splitPosition+1);
if(gemName.equals(specGemName)) {
if(version == null || version.length() == 0 || version.equals(specVersion)) {
return true;
}
}
}
return false;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy