aschuma

JAVA :: Classloader Bridge Example

Jul 27th, 2013
179
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 7.42 KB | None | 0 0
  1. package com.example.classloader;
  2.  
  3. import java.lang.reflect.InvocationHandler;
  4. import java.lang.reflect.InvocationTargetException;
  5. import java.lang.reflect.Method;
  6. import java.lang.reflect.Proxy;
  7. import java.net.URL;
  8. import java.net.URLClassLoader;
  9. import java.util.ArrayList;
  10. import java.util.Arrays;
  11. import java.util.Collections;
  12. import java.util.List;
  13. import java.util.concurrent.Callable;
  14. import java.util.concurrent.Semaphore;
  15.  
  16. public class LoaderBridge {
  17.  
  18.    private final static Semaphore LOCK_SEMA = new Semaphore(1, true);
  19.    static List<String> RESOURCES = Collections.unmodifiableList(Arrays.asList("guava-14.0.jar"));
  20.    private volatile ClassLoader loaderOfTheOtherWorld;
  21.  
  22.  
  23.    LoaderBridge() {
  24.    }
  25.  
  26.    static ClassLoader createClassLoader(ClassLoader resourceloader, ClassLoader root, List<String> resources) {
  27.  
  28.       List<URL> urls = new ArrayList<URL>();
  29.       for (String resource : resources) {
  30.  
  31.          final URL urlResource = resourceloader.getResource(resource);
  32.          urls.add(urlResource);
  33.       }
  34.       URLClassLoader urlClassLoader = new URLClassLoader(urls.toArray(new URL[0]), root);
  35.  
  36.       return urlClassLoader;
  37.    }
  38.  
  39.    static <T> T callWithLoader(ClassLoader loader, Callable<T> callable) throws Exception {
  40.  
  41.       ClassLoader current = Thread.currentThread().getContextClassLoader();
  42.       Thread.currentThread().setContextClassLoader(loader);
  43.       try {
  44.          return callable.call();
  45.       } finally {
  46.          Thread.currentThread().setContextClassLoader(current);
  47.       }
  48.    }
  49.  
  50.    public GuavaListsProxy createGuavaListsProxy() {
  51.  
  52.       final InvocationHandler invocationHandler = new BridgeInvocationHandler(getClassLoader(), "com.google.common.collect.Lists", false);
  53.       GuavaListsProxy proxy = (GuavaListsProxy) Proxy.newProxyInstance(this.getClass().getClassLoader(), new Class[]{GuavaListsProxy.class}, invocationHandler);
  54.  
  55.       return proxy;
  56.    }
  57.  
  58.    ClassLoader getClassLoader() {
  59.  
  60.       LOCK_SEMA.acquireUninterruptibly();
  61.       try {
  62.          if (loaderOfTheOtherWorld == null) {
  63.             loaderOfTheOtherWorld = createClassLoader(this.getClass().getClassLoader(), ClassLoader.getSystemClassLoader(), RESOURCES);
  64.          }
  65.          return loaderOfTheOtherWorld;
  66.       } finally {
  67.          LOCK_SEMA.release();
  68.       }
  69.    }
  70.  
  71.    public static interface GuavaListsProxy {
  72.       public <E> List<E> newArrayList(E... e);
  73.       public <E> ArrayList<E> newArrayListWithExpectedSize(int estimatedSize);
  74.    }
  75.  
  76.    private static class BridgeInvocationHandler implements InvocationHandler {
  77.  
  78.       private final ClassLoader clazzLoader;
  79.       private final Class delegateClazz;
  80.       private final Object target;
  81.  
  82.       BridgeInvocationHandler(final ClassLoader clazzLoader, String clazzName, boolean newInstance) {
  83.          this.clazzLoader = clazzLoader;
  84.          try {
  85.             delegateClazz = clazzLoader.loadClass(clazzName);
  86.             target = newInstance ? delegateClazz.newInstance() : null;
  87.          } catch (Exception e) {
  88.             throw new RuntimeException(e);
  89.          }
  90.       }
  91.  
  92.       ;
  93.  
  94.       @Override
  95.       public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable {
  96.          return callWithLoader(clazzLoader, new Callable<Object>() {
  97.             @Override
  98.             public Object call() throws Exception {
  99.                try {
  100.                   Method m = delegateClazz.getMethod(method.getName(), method.getParameterTypes());
  101.                   return m.invoke(target, args);
  102.                } catch (InvocationTargetException ite) {
  103.                   if (ite.getTargetException() instanceof RuntimeException) {
  104.                      throw (RuntimeException) ite.getTargetException();
  105.                   } else if (ite.getTargetException() instanceof Error) {
  106.                      throw (Error) ite.getTargetException();
  107.                   } else {
  108.                      throw new RuntimeException(ite.getTargetException());
  109.                   }
  110.                }
  111.             }
  112.          });
  113.       }
  114.    }
  115. }
  116.  
  117.  
  118.  
  119. -------------------
  120.  
  121. package com.example.classloader;
  122.  
  123.  
  124. import org.junit.runner.RunWith;
  125. import org.mockito.runners.MockitoJUnitRunner;
  126.  
  127. import org.junit.Before;
  128. import org.junit.Test;
  129.  
  130. import static org.junit.Assert.*;
  131.  
  132. import java.net.URL;
  133. import java.util.List;
  134.  
  135.  
  136. // @RunWith(MockitoJUnitRunner.class)
  137. public class LoaderBridgeTest {
  138.  
  139.    LoaderBridge bridge = null;
  140.  
  141.    @Before
  142.    public void setup() {
  143.       bridge = new LoaderBridge();
  144.    }
  145.  
  146.    @Test
  147.    public void testUrlSystemClassLoader() throws Exception {
  148.  
  149.       // given
  150.       ClassLoader urlClassLoader = bridge.createClassLoader(this.getClass().getClassLoader(), ClassLoader.getSystemClassLoader());
  151.  
  152.       // when
  153.       URL url = guavaClassURL(urlClassLoader);
  154.  
  155.       // then
  156.       assertNotNull(url);
  157.    }
  158.  
  159.    @Test
  160.    public void testUrlSystemClassLoaderParent() throws Exception {
  161.  
  162.       // given
  163.       ClassLoader urlClassLoader = bridge.createClassLoader(this.getClass().getClassLoader(), ClassLoader.getSystemClassLoader().getParent());
  164.  
  165.       // when
  166.       URL url = guavaClassURL(urlClassLoader);
  167.  
  168.       // then
  169.       assertNotNull(url);
  170.    }
  171.  
  172.  
  173.    @Test
  174.    public void testThreadLocalClassLoader() {
  175.  
  176.       // given
  177.       ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
  178.  
  179.       // when
  180.       URL url = guavaClassURL(classLoader);
  181.  
  182.       // then
  183.       assertNull(url);
  184.    }
  185.  
  186.    @Test
  187.    public void testLocalClassLoader() {
  188.  
  189.       // given
  190.       ClassLoader classLoader = LoaderBridge.class.getClassLoader();
  191.  
  192.       // when
  193.       URL url = guavaClassURL(classLoader);
  194.  
  195.       // then
  196.       assertNull(url);
  197.    }
  198.  
  199.    @Test
  200.    public void testNewClassLoader() throws Exception {
  201.  
  202.       // given
  203.       ClassLoader urlClassLoader = bridge.getClassLoader();
  204.  
  205.       // when
  206.       URL url = guavaClassURL(urlClassLoader);
  207.  
  208.       // then
  209.       assertNotNull(url);
  210.    }
  211.  
  212.    private URL guavaClassURL( ClassLoader classLoader ) {
  213.       return classLoader.getResource("com/google/common/collect/Lists.class");
  214.    }
  215.  
  216.    @Test
  217.    public void testProxyGuavaProxy() {
  218.  
  219.       // given
  220.  
  221.       // when
  222.       final LoaderBridge.GuavaListsProxy guavaListsProxy = bridge.createGuavaListsProxy();
  223.  
  224.       // then
  225.       assertNotNull( guavaListsProxy);
  226.    }
  227.  
  228.  
  229.    @Test
  230.    public void testProxyGuavaProxyCall1() {
  231.  
  232.       // given
  233.       final LoaderBridge.GuavaListsProxy guavaListsProxy = bridge.createGuavaListsProxy();
  234.  
  235.       // when
  236.       final List<String> strings = guavaListsProxy.newArrayList("1", "2", "3");
  237.  
  238.       // then
  239.       assertNotNull(strings);
  240.       assertArrayEquals("ARRAY", new String[] { "1", "2", "3" }, strings.toArray() );
  241.    }
  242.  
  243.    @Test
  244.    public void testProxyGuavaProxyCall2() {
  245.  
  246.       // given
  247.       final LoaderBridge.GuavaListsProxy guavaListsProxy = bridge.createGuavaListsProxy();
  248.  
  249.       // when
  250.       final List<String> strings = guavaListsProxy.newArrayListWithExpectedSize(1);
  251.  
  252.       // then
  253.       assertNotNull(strings);
  254.       assertTrue(strings.isEmpty());
  255.    }
  256.  
  257.    @Test( expected= IllegalArgumentException.class)
  258.    public void testProxyGuavaProxyCall2ExceptionPropagation() {
  259.  
  260.       // given
  261.       final LoaderBridge.GuavaListsProxy guavaListsProxy = bridge.createGuavaListsProxy();
  262.  
  263.       // when
  264.  
  265.       // then
  266.       List<String> strings = guavaListsProxy.newArrayListWithExpectedSize(-1);
  267.    }
  268. }
Advertisement
Add Comment
Please, Sign In to add comment