1
2
3
4
5
6
7
8
9
10
11
12
13 package com.eviware.soapui;
14
15 import java.io.File;
16 import java.io.IOException;
17 import java.lang.reflect.Method;
18 import java.net.MalformedURLException;
19 import java.net.URL;
20 import java.net.URLClassLoader;
21 import java.util.ArrayList;
22 import java.util.HashMap;
23 import java.util.List;
24 import java.util.Map;
25
26 /***
27 * ClassLoader that loads external jars
28 *
29 * @author Ole
30 */
31
32 public class SoapUIExtensionClassLoader extends URLClassLoader
33 {
34 public SoapUIExtensionClassLoader( URL[] urls, ClassLoader parent )
35 {
36 super( urls, parent );
37 }
38
39 @Override
40 public void addURL( URL url )
41 {
42 super.addURL( url );
43 }
44
45 public void addFile( File file ) throws MalformedURLException
46 {
47 addURL( file.toURI().toURL() );
48 }
49
50 private static Map<ClassLoader, SoapUIClassLoaderState> clStates = new HashMap<ClassLoader, SoapUIClassLoaderState>();
51
52 public static SoapUIClassLoaderState ensure()
53 {
54 ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
55 SoapUIClassLoaderState state = clStates.get( contextClassLoader );
56
57 if( state == null )
58 {
59 ClassLoader cl = contextClassLoader;
60
61 while( cl != null && !( cl instanceof SoapUIExtensionClassLoader ) )
62 {
63 cl = cl.getParent();
64 }
65
66 state = new SoapUIClassLoaderState( cl == null ? contextClassLoader : null );
67 clStates.put( contextClassLoader, state );
68 }
69
70 return state.activate();
71 }
72
73 public static class SoapUIClassLoaderState
74 {
75 private ClassLoader cl;
76
77 private SoapUIClassLoaderState( ClassLoader cl )
78 {
79 this.cl = cl;
80 }
81
82 private SoapUIClassLoaderState activate()
83 {
84 if( cl != null && SoapUI.getSoapUICore() != null )
85 Thread.currentThread().setContextClassLoader( SoapUI.getSoapUICore().getExtensionClassLoader() );
86
87 return this;
88 }
89
90 public void restore()
91 {
92 if( cl != null )
93 Thread.currentThread().setContextClassLoader( cl );
94 }
95 }
96
97 public static SoapUIExtensionClassLoader create( String root, ClassLoader parent ) throws MalformedURLException
98 {
99 String extDir = System.getProperty( "soapui.ext.libraries" );
100
101 File dir = extDir != null ? new File( extDir ) : new File( new File( root ), "ext" );
102 List<URL> urls = new ArrayList<URL>();
103
104 if( dir.exists() && dir.isDirectory() )
105 {
106 File[] files = dir.listFiles();
107 for( File file : files )
108 {
109 if( file.getName().toLowerCase().endsWith( ".jar" ) )
110 {
111 urls.add( file.toURI().toURL() );
112 SoapUI.log.info( "Adding [" + file.getAbsolutePath() + "] to extensions classpath" );
113 }
114 }
115 }
116 else
117 {
118 SoapUI.log.warn( "Missing folder [" + dir.getAbsolutePath() + "] for external libraries" );
119 }
120
121 return new SoapUIExtensionClassLoader( urls.toArray( new URL[urls.size()] ), parent );
122 }
123
124 /***
125 * method used for hermes classloading
126 * @param u
127 * @param classLoader
128 * @throws IOException
129 */
130 public static void addUrlToClassLoader( URL u, ClassLoader classLoader ) throws IOException
131 {
132 try
133 {
134 Method method = classLoader.getClass().getDeclaredMethod( "addURL", new Class[] { java.net.URL.class } );
135 method.setAccessible( true );
136 method.invoke( classLoader, new Object[] { u } );
137
138 SoapUI.log.info( "Added [" + u.toString() + "] to classpath" );
139 }
140 catch( NoSuchMethodException e )
141 {
142 try
143 {
144 Method method = classLoader.getClass().getSuperclass().getDeclaredMethod( "addURL",
145 new Class[] { java.net.URL.class } );
146 method.setAccessible( true );
147 method.invoke( classLoader, new Object[] { u } );
148
149 SoapUI.log.info( "Added [" + u.toString() + "] to classpath" );
150 }
151 catch( NoSuchMethodException ex )
152 {
153 try
154 {
155 Method method = classLoader.getClass().getSuperclass().getSuperclass().getDeclaredMethod( "addURL",
156 new Class[] { java.net.URL.class } );
157 method.setAccessible( true );
158 method.invoke( classLoader, new Object[] { u } );
159
160 SoapUI.log.info( "Added [" + u.toString() + "] to classpath" );
161 }
162 catch( Throwable t )
163 {
164 try
165 {
166 if( classLoader.getParent() != null )
167 {
168 SoapUI.log.info( "Failed to add jar to " + classLoader.getClass().getName() + ", trying parent" );
169 addUrlToClassLoader( u, classLoader.getParent() );
170 }
171 else
172 throw new IOException( "Error, could not add URL to classloader "
173 + classLoader.getClass().getName() );
174 }
175 catch( IOException e3 )
176 {
177 SoapUI.logError( t );
178 throw e3;
179 }
180 }
181 }
182 catch( Throwable t )
183 {
184 SoapUI.logError( t );
185 throw new IOException( "Error, could not add URL to system classloader " + classLoader.getClass().getName() );
186 }
187 }
188 catch( Throwable t )
189 {
190 SoapUI.logError( t );
191 throw new IOException( "Error, could not add URL to system classloader " + classLoader.getClass().getName() );
192 }
193 }
194 }