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
-~----------~----~----~----~------~----~------~--~---

Reply via email to