View Javadoc

1   package com.atlassian.plugin.util;
2   
3   import junit.framework.TestCase;
4   
5   import java.io.IOException;
6   import java.io.Serializable;
7   import java.net.URL;
8   import java.net.URLClassLoader;
9   import java.util.*;
10  
11  import static com.google.common.collect.Sets.newHashSet;
12  import static java.util.Arrays.asList;
13  import static java.util.Collections.singletonList;
14  import static org.mockito.Mockito.mock;
15  
16  /**
17   *
18   */
19  public class TestClassUtils extends TestCase
20  {
21      public void testFindAllTypes()
22      {
23          assertEquals(newHashSet(
24                  List.class,
25                  AbstractList.class,
26                  Cloneable.class,
27                  RandomAccess.class,
28                  AbstractCollection.class,
29                  Iterable.class,
30                  Collection.class,
31                  ArrayList.class,
32                  Object.class,
33                  Serializable.class
34          ), ClassUtils.findAllTypes(ArrayList.class));
35      }
36  
37      public void testGetTypeArguments()
38      {
39          assertEquals(asList(String.class), ClassUtils.getTypeArguments(BaseClass.class, Child.class));
40  
41          assertEquals(asList(String.class), ClassUtils.getTypeArguments(BaseClass.class, Baby.class));
42  
43          assertEquals(singletonList(null), ClassUtils.getTypeArguments(BaseClass.class, ForgotType.class));
44      }
45  
46      public void testGetTypeArgumentsDifferentClassloader() throws Exception
47      {
48          ClassLoader cl = Thread.currentThread().getContextClassLoader();
49          try
50          {
51              URL log4jUrl = getClass().getClassLoader().getResource("log4j.properties");
52              URL root = new URL(new URL(log4jUrl.toExternalForm()), ".");
53  
54              URLClassLoader urlCl = new URLClassLoader(new URL[] {root}, new FilteredClassLoader(MySuperClass.class));
55              ClosableClassLoader wrapCl = new ClosableClassLoader(getClass().getClassLoader());
56  
57              Thread.currentThread().setContextClassLoader(null);
58              Class<?> module = ClassUtils.getTypeArguments((Class<Object>) urlCl.loadClass(MySuperClass.class.getName()),
59                      (Class<? extends MySuperClass>) urlCl.loadClass(MySubClass.class.getName())).get(0);
60              assertEquals(MyModule.class.getName(), module.getName());
61  
62              ClassLoader urlCl2 = new URLClassLoader(new URL[] {root}, new FilteredClassLoader(MySuperClass.class));
63              assertTrue(wrapCl.loadClass(MySuperClass.class.getName()) == urlCl2.loadClass(MySuperClass.class.getName()));
64              assertTrue(wrapCl.loadClass(MySubClass.class.getName()) != urlCl2.loadClass(MySubClass.class.getName()));
65              assertTrue(wrapCl.loadClass(MySubClass.class.getName()).getSuperclass() == urlCl2.loadClass(MySubClass.class.getName()).getSuperclass());
66              
67              wrapCl.setClosed(true);
68              //Thread.currentThread().setContextClassLoader(urlCl2);
69              Class<?> module2 = ClassUtils.getTypeArguments((Class<Object>) urlCl2.loadClass(MySuperClass.class.getName()),
70                      (Class<? extends MySuperClass>) urlCl2.loadClass(MySubClass.class.getName())).get(0);
71              assertEquals(MyModule.class.getName(), module2.getName());
72              assertTrue(module != module2);
73              assertTrue(module != MyModule.class);
74              assertTrue(module2 != MyModule.class);
75          }
76          finally
77          {
78              Thread.currentThread().setContextClassLoader(cl);
79          }
80      }
81  
82      public void testGetTypeArgumentsChildNotSubclass()
83      {
84          Class fakeChild = BaseClass.class;
85          try
86          {
87              assertEquals(singletonList(null), ClassUtils.getTypeArguments(Baby.class, (Class<? extends Baby>) fakeChild));
88              fail("Should have failed");
89          }
90          catch (IllegalArgumentException ex)
91          {
92              // this is good
93          }
94      }
95  
96      private static class BaseClass<T> {}
97      private static class Child extends BaseClass<String>{}
98      private static class ForgotType extends BaseClass{}
99  
100     private static class Mom<T> extends BaseClass<T>{}
101     private static class Baby extends Mom<String>{}
102 
103     private static class ClosableClassLoader extends ClassLoader
104     {
105         private final ClassLoader delegate;
106         private volatile boolean closed;
107 
108         public ClosableClassLoader(ClassLoader delegate)
109         {
110             super(null);
111             this.delegate = delegate;
112         }
113 
114         @Override
115         public Class<?> loadClass(String name)
116                 throws ClassNotFoundException
117         {
118             checkClosed();
119             return delegate.loadClass(name);
120         }
121         @Override
122         public Class<?> loadClass(String name, boolean resolve)
123                 throws ClassNotFoundException
124         {
125             checkClosed();
126             return delegate.loadClass(name);
127         }
128 
129         private void checkClosed()
130         {
131             if (closed)
132             {
133                 throw new IllegalStateException("Closed");
134             }
135         }
136 
137         @Override
138         public URL getResource(String name)
139         {
140             checkClosed();
141             return delegate.getResource(name);
142         }
143 
144         @Override
145         public Enumeration<URL> getResources(String name)
146                 throws IOException
147         {
148             checkClosed();
149             return delegate.getResources(name);
150         }
151 
152         public void setClosed(boolean closed)
153         {
154             this.closed = closed;
155         }
156     }
157 
158     private static class FilteredClassLoader extends ClassLoader
159     {
160         private final Collection<Class> classes;
161 
162         public FilteredClassLoader(Class... classes)
163         {
164             super(null);
165             this.classes = asList(classes);
166         }
167 
168         @Override
169         public Class<?> loadClass(String name, boolean resolve)
170                 throws ClassNotFoundException
171         {
172             for (Class cls : classes)
173             {
174                 if (cls.getName().equals(name))
175                 {
176                     return cls;
177                 }
178             }
179             if (name.startsWith("java."))
180             {
181                 return ClassLoader.getSystemClassLoader().loadClass(name);
182             }
183             throw new ClassNotFoundException(name);
184         }
185     }
186 }