Author: limpbizkit
Date: Fri Feb 27 18:43:04 2009
New Revision: 873
Added:
trunk/test/com/googlecode/guice/StrictContainerTestSuite.java
trunk/test/com/googlecode/guice/StrictContainerTestSuiteBuilder.java
Modified:
trunk/src/com/google/inject/internal/BytecodeGen.java
trunk/test/com/google/inject/AllTests.java
trunk/test/com/googlecode/guice/BytecodeGenTest.java
Log:
Changing BytecodeGen to be sensitive to restrictions on calls to
ClassLoader.getSystemClassLoader(). This is necessary for some constrained
JVMs.
Modified: trunk/src/com/google/inject/internal/BytecodeGen.java
==============================================================================
--- trunk/src/com/google/inject/internal/BytecodeGen.java (original)
+++ trunk/src/com/google/inject/internal/BytecodeGen.java Fri Feb 27
18:43:04 2009
@@ -16,6 +16,7 @@
package com.google.inject.internal;
+import static com.google.inject.internal.Preconditions.checkNotNull;
import java.lang.reflect.Constructor;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
@@ -103,12 +104,25 @@
/**
* For class loaders, {...@code null}, is always an alias to the
- * {...@link ClassLoader#getSystemClassLoader() system class loader}.
+ * {...@link ClassLoader#getSystemClassLoader() system class loader}. This
method
+ * will not return null.
*/
private static ClassLoader canonicalize(ClassLoader classLoader) {
return classLoader != null
? classLoader
- : ClassLoader.getSystemClassLoader();
+ : checkNotNull(getSystemClassLoaderOrNull(), "Couldn't get a
ClassLoader");
+ }
+
+ /**
+ * Returns the system classloader, or {...@code null} if we don't have
+ * permission.
+ */
+ private static ClassLoader getSystemClassLoaderOrNull() {
+ try {
+ return ClassLoader.getSystemClassLoader();
+ } catch (SecurityException e) {
+ return null;
+ }
}
/**
@@ -122,7 +136,7 @@
delegate = canonicalize(delegate);
// if the application is running in the System classloader, assume we
can run there too
- if (delegate == ClassLoader.getSystemClassLoader()) {
+ if (delegate == getSystemClassLoaderOrNull()) {
return delegate;
}
Modified: trunk/test/com/google/inject/AllTests.java
==============================================================================
--- trunk/test/com/google/inject/AllTests.java (original)
+++ trunk/test/com/google/inject/AllTests.java Fri Feb 27 18:43:04 2009
@@ -99,7 +99,7 @@
// names
suite.addTestSuite(NamesTest.class);
-
+
// tools
// suite.addTestSuite(JmxTest.class); not a testcase
@@ -111,6 +111,7 @@
suite.addTestSuite(IntegrationTest.class);
suite.addTestSuite(MethodInterceptionTest.class);
suite.addTestSuite(com.googlecode.guice.BytecodeGenTest.class);
+ suite.addTest(com.googlecode.guice.StrictContainerTestSuite.suite());
/*end[AOP]*/
return suite;
Modified: trunk/test/com/googlecode/guice/BytecodeGenTest.java
==============================================================================
--- trunk/test/com/googlecode/guice/BytecodeGenTest.java (original)
+++ trunk/test/com/googlecode/guice/BytecodeGenTest.java Fri Feb 27
18:43:04 2009
@@ -42,6 +42,8 @@
*/
public class BytecodeGenTest extends TestCase {
+ private final ClassLoader systemClassLoader =
ClassLoader.getSystemClassLoader();
+
private final Module interceptorModule = new AbstractModule() {
protected void configure() {
bindInterceptor(any(), any(), new MethodInterceptor() {
@@ -188,14 +190,20 @@
}
}).getInstance(ProxyTest.class);
- assertSame(testProxy.getClass().getClassLoader(),
ClassLoader.getSystemClassLoader());
+ // unforunately, the expected classloader depends on which class
loader loaded this test.
+ if (ProxyTest.class.getClassLoader() == systemClassLoader) {
+ assertSame(testProxy.getClass().getClassLoader(), systemClassLoader);
+ } else {
+ assertNotSame(testProxy.getClass().getClassLoader(),
ProxyTest.class.getClassLoader());
+ assertNotSame(testProxy.getClass().getClassLoader(),
systemClassLoader);
+ }
}
public void testProxyClassUnloading() {
Object testObject = Guice.createInjector(interceptorModule, testModule)
.getInstance(proxyTestClass);
assertNotNull(testObject.getClass().getClassLoader());
- assertNotSame(testObject.getClass().getClassLoader(),
ClassLoader.getSystemClassLoader());
+ assertNotSame(testObject.getClass().getClassLoader(),
systemClassLoader);
// take a weak reference to the generated proxy class
Reference<Class<?>> clazzRef = new
WeakReference<Class<?>>(testObject.getClass());
Added: trunk/test/com/googlecode/guice/StrictContainerTestSuite.java
==============================================================================
--- (empty file)
+++ trunk/test/com/googlecode/guice/StrictContainerTestSuite.java Fri Feb
27 18:43:04 2009
@@ -0,0 +1,58 @@
+/**
+ * Copyright (C) 2009 Google Inc.
+ *
+ * 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.googlecode.guice;
+
+import com.google.inject.internal.MapMakerTestSuite;
+import java.io.FilePermission;
+import java.security.Permission;
+import java.util.Arrays;
+import junit.framework.Test;
+
+/**
+ * Runs a subset of our tests in a more secure environment. It loads the
tests in another
+ * classloader, and runs them with a specific security manager. Note that
no security manager is in
+ * place when test instances are constructed.
+ *
+ * @author [email protected] (Jesse Wilson)
+ */
+public class StrictContainerTestSuite {
+
+ public static Test suite() {
+ SecurityManager securityManager = new SecurityManager() {
+ @Override public void checkPermission(Permission permission) {
+ if (permission instanceof FilePermission) {
+ return;
+ }
+
+ if (permission instanceof RuntimePermission
+ && permission.getName().equals("getClassLoader")
+ && Arrays.toString(new
Throwable().getStackTrace()).contains(".getSystemClassLoader(")) {
+ throw new SecurityException("StrictContainerTestSuite forbids
this!");
+ }
+ }
+
+ @Override public void checkPermission(Permission permission, Object
context) {
+ checkPermission(permission);
+ }
+ };
+
+ StrictContainerTestSuiteBuilder builder = new
StrictContainerTestSuiteBuilder(securityManager);
+ builder.add(BytecodeGenTest.class.getName());
+ builder.addSuite(MapMakerTestSuite.class.getName());
+ return builder.build();
+ }
+}
Added: trunk/test/com/googlecode/guice/StrictContainerTestSuiteBuilder.java
==============================================================================
--- (empty file)
+++ trunk/test/com/googlecode/guice/StrictContainerTestSuiteBuilder.java
Fri Feb 27 18:43:04 2009
@@ -0,0 +1,159 @@
+/**
+ * Copyright (C) 2009 Google Inc.
+ *
+ * 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.googlecode.guice;
+
+import java.io.File;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import junit.extensions.TestDecorator;
+import junit.framework.Test;
+import junit.framework.TestResult;
+import junit.framework.TestSuite;
+
+/**
+ * Builds a test suite whose tests are loaded in a private classloader and
run them with a security
+ * manager.
+ *
+ * @author [email protected] (Jesse Wilson)
+ */
+public class StrictContainerTestSuiteBuilder {
+
+ private final ClassLoader classLoader = new NonSystemClassLoader();
+ private final SecurityManager securityManager;
+ private final TestSuite testSuite = new TestSuite("StrictContainer");
+
+ public StrictContainerTestSuiteBuilder(SecurityManager securityManager) {
+ this.securityManager = securityManager;
+ }
+
+ public void add(String testClassName) {
+ try {
+ Class<?> testClass = classLoader.loadClass(testClassName);
+ testSuite.addTest(new SecurityManagedTest(new TestSuite(testClass)));
+ } catch (Exception e) {
+ testSuite.addTest(new SuiteConstructionError(testClassName, e));
+ }
+ }
+
+ public void addSuite(String suiteClassname) {
+ try {
+ Class<?> suiteClass = classLoader.loadClass(suiteClassname);
+ Test testSuite = (Test) suiteClass.getMethod("suite").invoke(null);
+ this.testSuite.addTest(new SecurityManagedTest(testSuite));
+ } catch (Exception e) {
+ testSuite.addTest(new SuiteConstructionError(suiteClassname, e));
+ }
+ }
+
+ public TestSuite build() {
+ return testSuite;
+ }
+
+ /**
+ * A classloader that reloads everything outside of the JDK.
+ */
+ static class NonSystemClassLoader extends URLClassLoader {
+ public NonSystemClassLoader() {
+ super(new URL[0]);
+
+ for (final String element :
System.getProperty("java.class.path").split(File.pathSeparator)) {
+ try {
+ // is it a remote/local URL?
+ addURL(new URL(element));
+ } catch (MalformedURLException e1) {
+ // nope - perhaps it's a filename?
+ try {
+ addURL(new File(element).toURI().toURL());
+ } catch (MalformedURLException e2) {
+ throw new RuntimeException(e1);
+ }
+ }
+ }
+ }
+
+ @Override
+ protected Class<?> loadClass(String name, boolean resolve) throws
ClassNotFoundException {
+ // check our local cache to avoid duplicates
+ synchronized (this) {
+ Class<?> clazz = findLoadedClass(name);
+ if (clazz != null) {
+ return clazz;
+ }
+ }
+
+ if (name.startsWith("java.")
+ || name.startsWith("javax.")
+ || name.startsWith("junit.")
+ || name.startsWith("sun.")
+ || name.startsWith("com.sun.")) {
+ return super.loadClass(name, resolve);
+ }
+
+ Class<?> clazz = findClass(name);
+ if (resolve) {
+ resolveClass(clazz);
+ }
+ return clazz;
+ }
+ }
+
+ /**
+ * A test that sets up and tears down a security manager while it's run.
+ */
+ private class SecurityManagedTest extends TestDecorator {
+ public SecurityManagedTest(Test delegate) {
+ super(delegate);
+ }
+
+ public void run(TestResult testResult) {
+ SecurityManager originalSecurityManager =
System.getSecurityManager();
+ System.setSecurityManager(securityManager);
+ try {
+ basicRun(testResult);
+ } finally {
+ testResult.endTest(this);
+ System.setSecurityManager(originalSecurityManager);
+ }
+ }
+ }
+
+ /**
+ * A simple test that always fails with an exception.
+ */
+ private static class SuiteConstructionError implements Test {
+ private String className;
+ private final Exception cause;
+
+ public SuiteConstructionError(String className, Exception cause) {
+ this.className = className;
+ this.cause = cause;
+ }
+
+ public void run(TestResult testResult) {
+ testResult.addError(this, cause);
+ }
+
+ public int countTestCases() {
+ return 1;
+ }
+
+ @Override public String toString() {
+ return className;
+ }
+ }
+}
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"google-guice-dev" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/google-guice-dev?hl=en
-~----------~----~----~----~------~----~------~--~---