1   
2   
3   
4   
5   
6   
7   
8   
9   
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  package org.apache.commons.jcs.io;
20  
21  import java.io.IOException;
22  import java.io.InputStream;
23  import java.io.ObjectInputStream;
24  import java.io.ObjectStreamClass;
25  import java.lang.reflect.Proxy;
26  
27  public class ObjectInputStreamClassLoaderAware extends ObjectInputStream {
28      private final ClassLoader classLoader;
29  
30      public ObjectInputStreamClassLoaderAware(final InputStream in, final ClassLoader classLoader) throws IOException {
31          super(in);
32          this.classLoader = classLoader != null ? classLoader : Thread.currentThread().getContextClassLoader();
33      }
34  
35      @Override
36      protected Class<?> resolveClass(final ObjectStreamClass desc) throws ClassNotFoundException {
37          return Class.forName(BlacklistClassResolver.DEFAULT.check(desc.getName()), false, classLoader);
38      }
39  
40      @Override
41      protected Class<?> resolveProxyClass(final String[] interfaces) throws IOException, ClassNotFoundException {
42          final Class<?>[] cinterfaces = new Class[interfaces.length];
43          for (int i = 0; i < interfaces.length; i++) {
44              cinterfaces[i] = Class.forName(interfaces[i], false, classLoader);
45          }
46  
47          try {
48              return Proxy.getProxyClass(classLoader, cinterfaces);
49          } catch (IllegalArgumentException e) {
50              throw new ClassNotFoundException(null, e);
51          }
52      }
53  
54      private static class BlacklistClassResolver {
55          private static final BlacklistClassResolver DEFAULT = new BlacklistClassResolver(
56              toArray(System.getProperty(
57                  "jcs.serialization.class.blacklist",
58                  "org.codehaus.groovy.runtime.,org.apache.commons.collections.functors.,org.apache.xalan")),
59              toArray(System.getProperty("jcs.serialization.class.whitelist")));
60  
61          private final String[] blacklist;
62          private final String[] whitelist;
63  
64          protected BlacklistClassResolver(final String[] blacklist, final String[] whitelist) {
65              this.whitelist = whitelist;
66              this.blacklist = blacklist;
67          }
68  
69          protected boolean isBlacklisted(final String name) {
70              return (whitelist != null && !contains(whitelist, name)) || contains(blacklist, name);
71          }
72  
73          public final String check(final String name) {
74              if (isBlacklisted(name)) {
75                  throw new SecurityException(name + " is not whitelisted as deserialisable, prevented before loading.");
76              }
77              return name;
78          }
79  
80          private static String[] toArray(final String property) {
81              return property == null ? null : property.split(" *, *");
82          }
83  
84          private static boolean contains(final String[] list, String name) {
85              if (list != null) {
86                  for (final String white : list) {
87                      if (name.startsWith(white)) {
88                          return true;
89                      }
90                  }
91              }
92              return false;
93          }
94      }
95  }