001: /*
002: * soapUI, copyright (C) 2004-2007 eviware.com
003: *
004: * soapUI is free software; you can redistribute it and/or modify it under the
005: * terms of version 2.1 of the GNU Lesser General Public License as published by
006: * the Free Software Foundation.
007: *
008: * soapUI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
009: * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
010: * See the GNU Lesser General Public License for more details at gnu.org.
011: */
012:
013: package com.eviware.soapui.impl.wsdl.support.wsdl;
014:
015: import java.util.ArrayList;
016: import java.util.Collection;
017: import java.util.HashMap;
018: import java.util.HashSet;
019: import java.util.List;
020: import java.util.Map;
021: import java.util.Set;
022:
023: import javax.wsdl.Definition;
024: import javax.wsdl.factory.WSDLFactory;
025: import javax.wsdl.xml.WSDLReader;
026: import javax.xml.namespace.QName;
027:
028: import org.apache.log4j.Logger;
029: import org.apache.xmlbeans.SchemaType;
030: import org.apache.xmlbeans.SchemaTypeLoader;
031: import org.apache.xmlbeans.SchemaTypeSystem;
032: import org.apache.xmlbeans.XmlObject;
033: import org.apache.xmlbeans.XmlOptions;
034:
035: import com.eviware.soapui.SoapUI;
036: import com.eviware.soapui.config.DefinitionCacheConfig;
037: import com.eviware.soapui.config.DefintionPartConfig;
038: import com.eviware.soapui.impl.wsdl.WsdlInterface;
039: import com.eviware.soapui.impl.wsdl.support.soap.SoapVersion;
040: import com.eviware.soapui.impl.wsdl.support.xsd.SchemaException;
041: import com.eviware.soapui.impl.wsdl.support.xsd.SchemaUtils;
042: import com.eviware.soapui.support.NullProgressDialog;
043: import com.eviware.soapui.support.UISupport;
044: import com.eviware.x.dialogs.Worker;
045: import com.eviware.x.dialogs.XProgressDialog;
046: import com.eviware.x.dialogs.XProgressMonitor;
047:
048: /**
049: * Holder for WSDL4J Definitions and related SchemaTypeLoader types
050: *
051: * @author Ole.Matzura
052: */
053:
054: public class WsdlContext {
055: private String url;
056: private Definition definition;
057: private SchemaTypeLoader schemaTypes;
058: private boolean loaded;
059: private SchemaException schemaException;
060:
061: private final static Logger log = Logger
062: .getLogger(WsdlContext.class);
063: private SoapVersion soapVersion;
064: private DefinitionCacheConfig cache;
065: private WsdlLoader currentLoader;
066: private final WsdlInterface iface;
067: private WSDLFactory factory;
068: private WSDLReader wsdlReader;
069:
070: public WsdlContext(String url, SoapVersion soapVersion,
071: DefinitionCacheConfig cache, WsdlInterface iface) {
072: this .url = url;
073: this .soapVersion = soapVersion;
074: this .cache = cache;
075: this .iface = iface;
076: }
077:
078: public DefinitionCacheConfig getCacheConfig() {
079: return cache;
080: }
081:
082: public Definition getDefinition() throws Exception {
083: loadIfNecessary();
084: return definition;
085: }
086:
087: public boolean isLoaded() {
088: return loaded;
089: }
090:
091: public synchronized boolean loadIfNecessary() throws Exception {
092: return loadIfNecessary(false);
093: }
094:
095: public synchronized boolean loadIfNecessary(boolean silent)
096: throws Exception {
097: if (!loaded)
098: load(silent);
099:
100: return loaded;
101: }
102:
103: public synchronized void setDefinition(String url,
104: DefinitionCacheConfig cache) {
105: this .url = url;
106: this .cache = null;
107: loaded = false;
108: }
109:
110: public synchronized boolean load() throws Exception {
111: return load(null, false);
112: }
113:
114: public synchronized boolean load(boolean silent) throws Exception {
115: return load(null, silent);
116: }
117:
118: public synchronized boolean load(WsdlLoader wsdlLoader)
119: throws Exception {
120: return load(wsdlLoader, false);
121: }
122:
123: public synchronized boolean load(WsdlLoader wsdlLoader,
124: boolean silent) throws Exception {
125: if (loaded)
126: return true;
127:
128: XProgressDialog progressDialog;
129: if (silent || url.startsWith("file:")) {
130: progressDialog = new NullProgressDialog();
131: } else {
132: progressDialog = UISupport.getDialogs()
133: .createProgressDialog("Loading WSDL", 3,
134: "Loading definition..", true);
135: }
136:
137: Loader loader = new Loader(wsdlLoader);
138: progressDialog.run(loader);
139:
140: // Get the value. It is the responsibility of the progressDialog to
141: // wait for the other thread to finish.
142: if (loader.hasError()) {
143: if (loader.getError() instanceof SchemaException) {
144: schemaException = (SchemaException) loader.getError();
145: ArrayList errorList = schemaException.getErrorList();
146:
147: if (errorList != null) {
148: log.error("Error loading schema types from " + url
149: + ", see log for details");
150: for (int c = 0; c < errorList.size(); c++) {
151: log.error(errorList.get(c).toString());
152: }
153: }
154:
155: UISupport
156: .showErrorMessage("Error loading schema types from "
157: + url + ", see log for details");
158: } else
159: throw loader.getError();
160: } else
161: loaded = true;
162:
163: return loaded;
164: }
165:
166: public SchemaTypeLoader getSchemaTypeLoader() throws Exception {
167: loadIfNecessary();
168: return schemaTypes;
169: }
170:
171: public SchemaException getSchemaException() {
172: return schemaException;
173: }
174:
175: private class Loader extends Worker.WorkerAdapter {
176: private Exception error;
177: private WsdlLoader wsdlLoader;
178:
179: public Loader(WsdlLoader wsdlLoader) {
180: super ();
181: this .wsdlLoader = wsdlLoader;
182: }
183:
184: private WsdlLoader getWsdlLoader() {
185: if (wsdlLoader != null) {
186: return wsdlLoader;
187: } else {
188: return new UrlWsdlLoader(url);
189: }
190: }
191:
192: public boolean hasError() {
193: return error != null;
194: }
195:
196: public Object construct(XProgressMonitor monitor) {
197: try {
198: if (!validateCache(cache)) {
199: monitor
200: .setProgress(1,
201: "Caching definition from url ["
202: + url + "]");
203:
204: currentLoader = getWsdlLoader();
205: cache = iface == null ? WsdlLoader
206: .cacheWsdl(currentLoader) : iface
207: .cacheDefinition(currentLoader);
208:
209: if (currentLoader.isAborted())
210: throw new Exception("Loading of WSDL from ["
211: + url + "] was aborted");
212: }
213:
214: monitor.setProgress(1, "Loading definition from "
215: + (cache == null ? "url" : "cache"));
216:
217: log.debug("Loading definition from "
218: + (cache == null ? "url" : "cache"));
219: loadDefinitions(cache == null ? getWsdlLoader()
220: : new CachedWsdlLoader(cache));
221: return null;
222: } catch (Exception e) {
223: log.error("Loading of definition failed for [" + url
224: + "]; " + e);
225: SoapUI.logError(e);
226: this .error = e;
227: return e;
228: } finally {
229: currentLoader = null;
230: }
231: }
232:
233: public Exception getError() {
234: return error;
235: }
236:
237: public boolean onCancel() {
238: if (currentLoader == null)
239: return false;
240:
241: return currentLoader.abort();
242: }
243: }
244:
245: private void loadDefinitions(WsdlLoader loader) throws Exception {
246: currentLoader = loader;
247:
248: if (factory == null) {
249: factory = WSDLFactory.newInstance();
250: wsdlReader = factory.newWSDLReader();
251: wsdlReader.setFeature("javax.wsdl.verbose", true);
252: wsdlReader.setFeature("javax.wsdl.importDocuments", true);
253: }
254:
255: definition = wsdlReader.readWSDL(loader);
256: log.debug("Loaded definition: "
257: + (definition != null ? "ok" : "null"));
258:
259: if (!currentLoader.isAborted())
260: schemaTypes = SchemaUtils.loadSchemaTypes(url, soapVersion,
261: loader);
262: else
263: throw new Exception("Loading of WSDL from [" + url
264: + "] was aborted");
265: }
266:
267: public boolean validateCache(DefinitionCacheConfig cache) {
268: if (cache == null)
269: return false;
270:
271: if (cache.getRootPart() == null)
272: return false;
273:
274: if (cache.sizeOfPartArray() == 0)
275: return false;
276:
277: return true;
278: }
279:
280: public SchemaTypeSystem getSchemaTypeSystem() throws Exception {
281: if (!loaded)
282: load();
283:
284: if (schemaTypes == null)
285: return null;
286:
287: return schemaTypes.findElement(soapVersion.getEnvelopeQName())
288: .getTypeSystem();
289: }
290:
291: public boolean hasSchemaTypes() throws Exception {
292: loadIfNecessary();
293: return schemaTypes != null;
294: }
295:
296: public SchemaType findType(QName typeName) throws Exception {
297: loadIfNecessary();
298: return schemaTypes == null ? null : schemaTypes
299: .findType(typeName);
300: }
301:
302: public String getUrl() {
303: return url;
304: }
305:
306: public Collection<String> getDefinedNamespaces() throws Exception {
307: loadIfNecessary();
308: Set<String> namespaces = new HashSet<String>();
309:
310: if (schemaTypes != null) {
311: namespaces.addAll(SchemaUtils
312: .extractNamespaces(getSchemaTypeSystem()));
313:
314: namespaces.remove("http://www.w3.org/2005/05/xmlmime");
315: namespaces.remove("http://ws-i.org/profiles/basic/1.1/xsd");
316: namespaces.remove("http://www.w3.org/2004/08/xop/include");
317: }
318:
319: if (definition != null)
320: namespaces.add(definition.getTargetNamespace());
321:
322: return namespaces;
323: }
324:
325: public SoapVersion getSoapVersion() {
326: return soapVersion;
327: }
328:
329: public void setSoapVersion(SoapVersion soapVersion) {
330: this .soapVersion = soapVersion;
331: }
332:
333: public Map<String, XmlObject> getDefinitionParts() throws Exception {
334: Map<String, XmlObject> result = new HashMap<String, XmlObject>();
335:
336: if (cache == null)
337: return SchemaUtils
338: .getDefinitionParts(new UrlWsdlLoader(url));
339:
340: List<DefintionPartConfig> partList = cache.getPartList();
341: for (DefintionPartConfig part : partList) {
342: String str = part.getContent().toString();
343: result.put(part.getUrl(), XmlObject.Factory.parse(str,
344: new XmlOptions().setLoadLineNumbers()));
345: }
346:
347: return result;
348: }
349:
350: public void setDefinitionCache(DefinitionCacheConfig definitionCache) {
351: this.cache = definitionCache;
352: }
353: }
|