1
2
3
4
5
6
7
8
9
10
11
12
13 package com.eviware.soapui.impl.support.definition.support;
14
15 import java.util.ArrayList;
16 import java.util.HashMap;
17 import java.util.List;
18 import java.util.Map;
19
20 import org.apache.log4j.Logger;
21 import org.apache.xmlbeans.SchemaTypeLoader;
22 import org.apache.xmlbeans.SchemaTypeSystem;
23
24 import com.eviware.soapui.SoapUI;
25 import com.eviware.soapui.impl.support.AbstractInterface;
26 import com.eviware.soapui.impl.support.DefinitionContext;
27 import com.eviware.soapui.impl.support.definition.DefinitionCache;
28 import com.eviware.soapui.impl.support.definition.DefinitionLoader;
29 import com.eviware.soapui.impl.support.definition.InterfaceDefinition;
30 import com.eviware.soapui.impl.support.definition.InterfaceDefinitionPart;
31 import com.eviware.soapui.impl.wsdl.support.PathUtils;
32 import com.eviware.soapui.impl.wsdl.support.xsd.SchemaException;
33 import com.eviware.soapui.support.UISupport;
34 import com.eviware.x.dialogs.Worker;
35 import com.eviware.x.dialogs.XProgressDialog;
36 import com.eviware.x.dialogs.XProgressMonitor;
37
38 /***
39 * Holder for InterfaceDefinitions and related SchemaTypeLoader types
40 *
41 * @author Ole.Matzura
42 */
43
44 public abstract class AbstractDefinitionContext<T extends AbstractInterface<?>, T2 extends DefinitionLoader, T3 extends AbstractInterfaceDefinition<T>>
45 implements DefinitionContext<T>
46 {
47 private String url;
48 private T3 definition;
49 private boolean loaded;
50 private SchemaException schemaException;
51
52 private final static Logger log = Logger.getLogger( AbstractDefinitionContext.class );
53
54 private T2 currentLoader;
55 private T iface;
56
57 private static Map<String, InterfaceDefinition<?>> definitionCache = new HashMap<String, InterfaceDefinition<?>>();
58 private static Map<String, Integer> urlReferences = new HashMap<String, Integer>();
59
60 public AbstractDefinitionContext( String url, T iface )
61 {
62 this.url = PathUtils.ensureFilePathIsUrl( url );
63 this.iface = iface;
64 }
65
66 public AbstractDefinitionContext( String url )
67 {
68 this( url, null );
69 }
70
71 public T getInterface()
72 {
73 return iface;
74 }
75
76 @SuppressWarnings( "unchecked" )
77 public T3 getInterfaceDefinition() throws Exception
78 {
79 loadIfNecessary();
80 return ( T3 )( definition == null ? definitionCache.get( url ) : definition );
81 }
82
83 public synchronized boolean isLoaded()
84 {
85 return loaded;
86 }
87
88 public synchronized boolean loadIfNecessary() throws Exception
89 {
90 if( !loaded )
91 load();
92 return loaded;
93 }
94
95 public synchronized void setDefinition( String url, boolean updateCache ) throws Exception
96 {
97 if( !url.equals( this.url ) )
98 {
99 this.url = url;
100
101 if( updateCache )
102 {
103 definitionCache.remove( url );
104 loaded = false;
105 load();
106 }
107
108
109 loaded = iface != null && definitionCache.containsKey( url );
110 }
111 }
112
113 public synchronized boolean load() throws Exception
114 {
115 return load( null );
116 }
117
118 public synchronized boolean load( T2 wsdlLoader ) throws Exception
119 {
120
121 if( !loaded && iface != null )
122 {
123
124 loaded = definitionCache.containsKey( url );
125 }
126
127 if( loaded )
128 return true;
129
130
131 XProgressDialog progressDialog = UISupport.getDialogs().createProgressDialog( "Loading Definition", 3,
132 "Loading definition..", true );
133
134 Loader loader = new Loader( wsdlLoader );
135 progressDialog.run( loader );
136
137
138
139 if( loader.hasError() )
140 {
141 if( loader.getError() instanceof SchemaException )
142 {
143 schemaException = ( SchemaException )loader.getError();
144 ArrayList<?> errorList = schemaException.getErrorList();
145
146 log.error( "Error loading schema types from " + url + ", see log for details" );
147
148 if( errorList != null )
149 {
150 for( int c = 0; c < errorList.size(); c++ )
151 {
152 log.error( errorList.get( c ).toString() );
153 }
154 }
155 }
156 else
157 throw new Exception( loader.getError() );
158 }
159 else
160 {
161 loaded = true;
162 }
163
164 return loaded;
165 }
166
167 public SchemaTypeLoader getSchemaTypeLoader() throws Exception
168 {
169 loadIfNecessary();
170 return iface != null && definitionCache.containsKey( url ) ? definitionCache.get( url ).getSchemaTypeLoader() :
171 definition != null ? definition.getSchemaTypeLoader() : null;
172 }
173
174 public SchemaException getSchemaException()
175 {
176 return schemaException;
177 }
178
179 private class Loader extends Worker.WorkerAdapter
180 {
181 private Throwable error;
182 private T2 wsdlLoader;
183
184 public Loader( T2 wsdlLoader )
185 {
186 super();
187 this.wsdlLoader = wsdlLoader;
188 }
189
190 private T2 getDefinitionLoader()
191 {
192 if( wsdlLoader != null )
193 {
194 return wsdlLoader;
195 }
196 else
197 {
198 return createDefinitionLoader( url );
199 }
200 }
201
202 public boolean hasError()
203 {
204 return error != null;
205 }
206
207 public Object construct( XProgressMonitor monitor )
208 {
209 try
210 {
211 DefinitionCache cache = iface == null ? new StandaloneDefinitionCache<T>()
212 : new InterfaceConfigDefinitionCache<T>( iface );
213
214 if( !cache.validate() )
215 {
216 monitor.setProgress( 1, "Caching Definition from url [" + url + "]" );
217
218 currentLoader = getDefinitionLoader();
219 currentLoader.setProgressMonitor( monitor, 2 );
220
221 cache.update( currentLoader );
222
223 if( currentLoader.isAborted() )
224 throw new Exception( "Loading of Definition from [" + url + "] was aborted" );
225 }
226
227 monitor.setProgress( 1, "Loading Definition from " + ( iface == null ? "url" : "cache" ) );
228
229 log.debug( "Loading Definition..." );
230 cacheDefinition( cache );
231 return null;
232 }
233 catch( Throwable e )
234 {
235 log.error( "Loading of definition failed for [" + url + "]; " + e );
236 SoapUI.logError( e );
237 this.error = e;
238 return e;
239 }
240 finally
241 {
242 currentLoader = null;
243 }
244 }
245
246 public Throwable getError()
247 {
248 return error;
249 }
250
251 public boolean onCancel()
252 {
253 if( currentLoader == null )
254 return false;
255
256 return currentLoader.abort();
257 }
258 }
259
260 private void cacheDefinition( DefinitionCache cache ) throws Exception
261 {
262 currentLoader = createDefinitionLoader( cache );
263 currentLoader.setProgressInfo( "Loading Definition" );
264 definition = loadDefinition( currentLoader );
265 definition.setDefinitionCache( cache );
266
267 log.debug( "Loaded Definition: " + ( definition != null ? "ok" : "null" ) );
268
269 if( !currentLoader.isAborted() && iface != null && iface.isDefinitionShareble() )
270 {
271 definitionCache.put( url, definition );
272 if( urlReferences.containsKey( url ) )
273 {
274 urlReferences.put( url, urlReferences.get( url ) + 1 );
275 }
276 else
277 {
278 urlReferences.put( url, 1 );
279 }
280 }
281
282 if( currentLoader.isAborted() )
283 throw new Exception( "Loading of Definition from [" + url + "] was aborted" );
284
285 loaded = true;
286 }
287
288 protected abstract T2 createDefinitionLoader( DefinitionCache definitionCache );
289
290 protected abstract T2 createDefinitionLoader( String url );
291
292 protected abstract T3 loadDefinition( T2 loader ) throws Exception;
293
294 public void release()
295 {
296 if( iface != null && urlReferences.containsKey( url ) )
297 {
298 Integer i = urlReferences.get( url );
299 if( i.intValue() <= 1 )
300 {
301 urlReferences.remove( url );
302 definitionCache.remove( url );
303 }
304 else
305 {
306 urlReferences.put( url, i - 1 );
307 }
308 }
309 }
310
311 public SchemaTypeSystem getSchemaTypeSystem() throws Exception
312 {
313 if( !isLoaded() )
314 load();
315
316 if( !definitionCache.containsKey( url ) )
317 return null;
318
319 return definitionCache.get( url ).getSchemaTypeSystem();
320 }
321
322 public boolean hasSchemaTypes()
323 {
324 try
325 {
326 loadIfNecessary();
327 }
328 catch( Exception e )
329 {
330 SoapUI.logError( e );
331 return false;
332 }
333
334 InterfaceDefinition<?> def = ( definition != null ? definition : definitionCache.get( url ) );
335 return def != null && def.hasSchemaTypes();
336 }
337
338 public String getUrl()
339 {
340 return url;
341 }
342
343 public void setInterface( T iface )
344 {
345 if( this.iface == null && iface != null )
346 {
347 if( definition != null )
348 {
349 if( definition.getDefinitionCache().validate() )
350 {
351 InterfaceConfigDefinitionCache<T> cache = new InterfaceConfigDefinitionCache<T>( iface );
352 try
353 {
354 cache.importCache( definition.getDefinitionCache() );
355 }
356 catch( Exception e )
357 {
358 SoapUI.logError( e );
359 }
360
361 definition.setDefinitionCache( cache );
362 }
363
364 definition.setIface( iface );
365 definitionCache.put( url, definition );
366 }
367 else
368 {
369 loaded = false;
370 }
371 }
372
373 this.iface = iface;
374 }
375
376 public static void uncache( String url )
377 {
378 definitionCache.remove( url );
379 urlReferences.remove( url );
380 }
381
382 public void reload() throws Exception
383 {
384 getDefinitionCache().clear();
385 definitionCache.remove( url );
386 loaded = false;
387 load();
388 }
389
390 public boolean isCached()
391 {
392 return isLoaded() && definition != null && definition.getDefinitionCache() != null;
393 }
394
395 public List<InterfaceDefinitionPart> getDefinitionParts() throws Exception
396 {
397 loadIfNecessary();
398
399 return getInterfaceDefinition().getDefinitionParts();
400 }
401
402 public DefinitionCache getDefinitionCache() throws Exception
403 {
404 loadIfNecessary();
405
406 return getInterfaceDefinition().getDefinitionCache();
407 }
408 }