groovy.lang.GroovyCodeSource Maven / Gradle / Ivy
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 groovy.lang;
import groovy.security.GroovyCodeSourcePermission;
import groovy.util.CharsetToolkit;
import org.codehaus.groovy.runtime.IOGroovyMethods;
import org.codehaus.groovy.runtime.ResourceGroovyMethods;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.Reader;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.net.URLConnection;
import java.security.AccessController;
import java.security.CodeSource;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.security.cert.Certificate;
/**
* CodeSource wrapper class that allows specific security policies to be associated with a class
* compiled from groovy source.
*
* @author Steve Goetze
* @author Guillaume Laforge
* @author Merlyn Albery-Speyer
*/
public class GroovyCodeSource {
/**
* The codeSource to be given the generated class. This can be used by policy file
* grants to administer security.
*/
private CodeSource codeSource;
/**
* The name given to the generated class
*/
private String name;
/**
* The groovy source to be compiled and turned into a class
*/
private String scriptText;
/**
* The certificates used to sign the items from the codesource
*/
Certificate[] certs;
private boolean cachable;
private File file;
private URL url;
public GroovyCodeSource(String script, String name, String codeBase) {
this.name = name;
this.scriptText = script;
this.codeSource = createCodeSource(codeBase);
this.cachable = true;
}
/**
* Construct a GroovyCodeSource for an inputStream of groovyCode that has an
* unknown provenance -- meaning it didn't come from a File or a URL (e.g. a String).
* The supplied codeBase will be used to construct a File URL that should match up
* with a java Policy entry that determines the grants to be associated with the
* class that will be built from the InputStream.
*
* The permission groovy.security.GroovyCodeSourcePermission will be used to determine if the given codeBase
* may be specified. That is, the current Policy set must have a GroovyCodeSourcePermission that implies
* the codeBase, or an exception will be thrown. This is to prevent callers from hijacking
* existing codeBase policy entries unless explicitly authorized by the user.
*/
public GroovyCodeSource(Reader reader, String name, String codeBase) {
this.name = name;
this.codeSource = createCodeSource(codeBase);
try {
this.scriptText = IOGroovyMethods.getText(reader);
} catch (IOException e) {
throw new RuntimeException("Impossible to read the text content from that reader, for script: " + name + " with codeBase: " + codeBase, e);
}
}
public GroovyCodeSource(final File infile, final String encoding) throws IOException {
// avoid files which confuse us like ones with .. in path
final File file = new File(infile.getCanonicalPath());
if (!file.exists()) {
throw new FileNotFoundException(file.toString() + " (" + file.getAbsolutePath() + ")");
}
if (file.isDirectory()) {
throw new IllegalArgumentException(file.toString() + " (" + file.getAbsolutePath() + ") is a directory not a Groovy source file.");
}
try {
if (!file.canRead())
throw new RuntimeException(file.toString() + " can not be read. Check the read permission of the file \"" + file.toString() + "\" (" + file.getAbsolutePath() + ").");
}
catch (SecurityException e) {
throw e;
}
this.file = file;
this.cachable = true;
//The calls below require access to user.dir - allow here since getName() and getCodeSource() are
//package private and used only by the GroovyClassLoader.
try {
Object[] info = AccessController.doPrivileged(new PrivilegedExceptionAction