View Javadoc

1   /*
2    *  soapUI, copyright (C) 2004-2010 eviware.com 
3    *
4    *  soapUI is free software; you can redistribute it and/or modify it under the 
5    *  terms of version 2.1 of the GNU Lesser General Public License as published by 
6    *  the Free Software Foundation.
7    *
8    *  soapUI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without 
9    *  even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
10   *  See the GNU Lesser General Public License for more details at gnu.org.
11   */
12  
13  package com.eviware.soapui.impl.wsdl.support.xsd;
14  
15  import java.io.File;
16  import java.io.IOException;
17  import java.net.MalformedURLException;
18  import java.net.URL;
19  import java.util.ArrayList;
20  import java.util.Collection;
21  import java.util.HashMap;
22  import java.util.HashSet;
23  import java.util.LinkedHashMap;
24  import java.util.List;
25  import java.util.Map;
26  import java.util.Set;
27  
28  import javax.xml.namespace.QName;
29  
30  import org.apache.log4j.Logger;
31  import org.apache.xmlbeans.SchemaAnnotation;
32  import org.apache.xmlbeans.SchemaField;
33  import org.apache.xmlbeans.SchemaLocalElement;
34  import org.apache.xmlbeans.SchemaType;
35  import org.apache.xmlbeans.SchemaTypeSystem;
36  import org.apache.xmlbeans.SimpleValue;
37  import org.apache.xmlbeans.XmlAnySimpleType;
38  import org.apache.xmlbeans.XmlBase64Binary;
39  import org.apache.xmlbeans.XmlBeans;
40  import org.apache.xmlbeans.XmlCursor;
41  import org.apache.xmlbeans.XmlException;
42  import org.apache.xmlbeans.XmlHexBinary;
43  import org.apache.xmlbeans.XmlObject;
44  import org.apache.xmlbeans.XmlOptions;
45  import org.w3c.dom.Attr;
46  import org.w3c.dom.Document;
47  import org.w3c.dom.Element;
48  import org.w3c.dom.NamedNodeMap;
49  import org.w3c.dom.Node;
50  
51  import com.eviware.soapui.SoapUI;
52  import com.eviware.soapui.SoapUIExtensionClassLoader;
53  import com.eviware.soapui.SoapUIExtensionClassLoader.SoapUIClassLoaderState;
54  import com.eviware.soapui.impl.wsdl.support.Constants;
55  import com.eviware.soapui.model.settings.SettingsListener;
56  import com.eviware.soapui.settings.WsdlSettings;
57  import com.eviware.soapui.support.StringUtils;
58  import com.eviware.soapui.support.Tools;
59  
60  /***
61   * XML-Schema related tools
62   * 
63   * @author Ole.Matzura
64   */
65  
66  public class SchemaUtils
67  {
68  	private final static Logger log = Logger.getLogger( SchemaUtils.class );
69  	private static Map<String, XmlObject> defaultSchemas = new HashMap<String, XmlObject>();
70  
71  	static
72  	{
73  		initDefaultSchemas();
74  
75  		SoapUI.getSettings().addSettingsListener( new SettingsListener()
76  		{
77  
78  			public void settingChanged( String name, String newValue, String oldValue )
79  			{
80  				if( name.equals( WsdlSettings.SCHEMA_DIRECTORY ) )
81  				{
82  					log.info( "Reloading default schemas.." );
83  					initDefaultSchemas();
84  				}
85  			}
86  
87  			@Override
88  			public void settingsReloaded()
89  			{
90  				// TODO Auto-generated method stub
91  
92  			}
93  		} );
94  	}
95  
96  	public static void initDefaultSchemas()
97  	{
98  		SoapUIClassLoaderState state = SoapUIExtensionClassLoader.ensure();
99  
100 		try
101 		{
102 			defaultSchemas.clear();
103 
104 			String root = "/com/eviware/soapui/resources/xsds";
105 
106 			loadDefaultSchema( SoapUI.class.getResource( root + "/xop.xsd" ) );
107 			loadDefaultSchema( SoapUI.class.getResource( root + "/XMLSchema.xsd" ) );
108 			loadDefaultSchema( SoapUI.class.getResource( root + "/xml.xsd" ) );
109 			loadDefaultSchema( SoapUI.class.getResource( root + "/swaref.xsd" ) );
110 			loadDefaultSchema( SoapUI.class.getResource( root + "/xmime200505.xsd" ) );
111 			loadDefaultSchema( SoapUI.class.getResource( root + "/xmime200411.xsd" ) );
112 			loadDefaultSchema( SoapUI.class.getResource( root + "/soapEnvelope.xsd" ) );
113 			loadDefaultSchema( SoapUI.class.getResource( root + "/soapEncoding.xsd" ) );
114 			loadDefaultSchema( SoapUI.class.getResource( root + "/soapEnvelope12.xsd" ) );
115 			loadDefaultSchema( SoapUI.class.getResource( root + "/soapEncoding12.xsd" ) );
116 
117 			String schemaDirectory = SoapUI.getSettings().getString( WsdlSettings.SCHEMA_DIRECTORY, null );
118 			if( StringUtils.hasContent( schemaDirectory ) )
119 				loadSchemaDirectory( schemaDirectory );
120 		}
121 		catch( Exception e )
122 		{
123 			SoapUI.logError( e );
124 		}
125 		finally
126 		{
127 			state.restore();
128 		}
129 	}
130 
131 	private static void loadSchemaDirectory( String schemaDirectory ) throws IOException, MalformedURLException
132 	{
133 		File dir = new File( schemaDirectory );
134 		if( dir.exists() && dir.isDirectory() )
135 		{
136 			String[] xsdFiles = dir.list();
137 			int cnt = 0;
138 
139 			if( xsdFiles != null && xsdFiles.length > 0 )
140 			{
141 				for( int c = 0; c < xsdFiles.length; c++ )
142 				{
143 					try
144 					{
145 						String xsdFile = xsdFiles[c];
146 						if( xsdFile.endsWith( ".xsd" ) )
147 						{
148 							String filename = schemaDirectory + File.separator + xsdFile;
149 							loadDefaultSchema( new URL( "file:" + filename ) );
150 							cnt++ ;
151 						}
152 					}
153 					catch( Throwable e )
154 					{
155 						SoapUI.logError( e );
156 					}
157 				}
158 			}
159 
160 			if( cnt == 0 )
161 				log.warn( "Missing schema files in  schemaDirectory [" + schemaDirectory + "]" );
162 		}
163 		else
164 			log.warn( "Failed to open schemaDirectory [" + schemaDirectory + "]" );
165 	}
166 
167 	private static void loadDefaultSchema( URL url ) throws Exception
168 	{
169 		XmlObject xmlObject = XmlObject.Factory.parse( url );
170 		if( !( ( Document )xmlObject.getDomNode() ).getDocumentElement().getNamespaceURI().equals( Constants.XSD_NS ) )
171 			return;
172 
173 		String targetNamespace = getTargetNamespace( xmlObject );
174 
175 		if( defaultSchemas.containsKey( targetNamespace ) )
176 			log.warn( "Overriding schema for targetNamespace " + targetNamespace );
177 
178 		defaultSchemas.put( targetNamespace, xmlObject );
179 
180 		log.info( "Added default schema from " + url.getPath() + " with targetNamespace " + targetNamespace );
181 	}
182 
183 	public static SchemaTypeSystem loadSchemaTypes( String wsdlUrl, SchemaLoader loader ) throws SchemaException
184 	{
185 		SoapUIClassLoaderState state = SoapUIExtensionClassLoader.ensure();
186 
187 		try
188 		{
189 			log.info( "Loading schema types from [" + wsdlUrl + "]" );
190 			ArrayList<XmlObject> schemas = new ArrayList<XmlObject>( getSchemas( wsdlUrl, loader ).values() );
191 
192 			return buildSchemaTypes( schemas );
193 		}
194 		catch( Exception e )
195 		{
196 			SoapUI.logError( e );
197 			throw new SchemaException( "Error loading schema types", e );
198 		}
199 		finally
200 		{
201 			state.restore();
202 		}
203 	}
204 
205 	public static SchemaTypeSystem buildSchemaTypes( List<XmlObject> schemas ) throws SchemaException
206 	{
207 		XmlOptions options = new XmlOptions();
208 		options.setCompileNoValidation();
209 		options.setCompileNoPvrRule();
210 		options.setCompileDownloadUrls();
211 		options.setCompileNoUpaRule();
212 		options.setValidateTreatLaxAsSkip();
213 
214 		for( int c = 0; c < schemas.size(); c++ )
215 		{
216 			XmlObject xmlObject = schemas.get( c );
217 			if( xmlObject == null
218 					|| !( ( Document )xmlObject.getDomNode() ).getDocumentElement().getNamespaceURI().equals(
219 							Constants.XSD_NS ) )
220 			{
221 				schemas.remove( c );
222 				c-- ;
223 			}
224 		}
225 
226 		boolean strictSchemaTypes = SoapUI.getSettings().getBoolean( WsdlSettings.STRICT_SCHEMA_TYPES );
227 		if( !strictSchemaTypes )
228 		{
229 			Set<String> mdefNamespaces = new HashSet<String>();
230 
231 			for( XmlObject xObj : schemas )
232 			{
233 				mdefNamespaces.add( getTargetNamespace( xObj ) );
234 			}
235 
236 			options.setCompileMdefNamespaces( mdefNamespaces );
237 		}
238 
239 		ArrayList<?> errorList = new ArrayList<Object>();
240 		options.setErrorListener( errorList );
241 
242 		XmlCursor cursor = null;
243 
244 		try
245 		{
246 			// remove imports
247 			for( int c = 0; c < schemas.size(); c++ )
248 			{
249 				XmlObject s = schemas.get( c );
250 
251 				Map<?, ?> map = new HashMap<String, String>();
252 				cursor = s.newCursor();
253 				cursor.toStartDoc();
254 				if( toNextContainer( cursor ) )
255 					cursor.getAllNamespaces( map );
256 				else
257 					log.warn( "Can not get namespaces for " + s );
258 
259 				String tns = getTargetNamespace( s );
260 
261 				// log.info( "schema for [" + tns + "] contained [" + map.toString()
262 				// + "] namespaces" );
263 
264 				if( strictSchemaTypes && defaultSchemas.containsKey( tns ) )
265 				{
266 					schemas.remove( c );
267 					c-- ;
268 				}
269 				else
270 				{
271 					removeImports( s );
272 				}
273 
274 				cursor.dispose();
275 				cursor = null;
276 			}
277 
278 			// schemas.add( soapVersion.getSoapEncodingSchema());
279 			// schemas.add( soapVersion.getSoapEnvelopeSchema());
280 			schemas.addAll( defaultSchemas.values() );
281 
282 			SchemaTypeSystem sts = XmlBeans.compileXsd( schemas.toArray( new XmlObject[schemas.size()] ), XmlBeans
283 					.getBuiltinTypeSystem(), options );
284 
285 			return sts;
286 			// return XmlBeans.typeLoaderUnion(new SchemaTypeLoader[] { sts,
287 			// XmlBeans.getBuiltinTypeSystem() });
288 		}
289 		catch( Exception e )
290 		{
291 			SoapUI.logError( e );
292 			throw new SchemaException( e, errorList );
293 		}
294 		finally
295 		{
296 			for( int c = 0; c < errorList.size(); c++ )
297 			{
298 				log.warn( "Error: " + errorList.get( c ) );
299 			}
300 
301 			if( cursor != null )
302 				cursor.dispose();
303 		}
304 	}
305 
306 	public static boolean toNextContainer( XmlCursor cursor )
307 	{
308 		while( !cursor.isContainer() && !cursor.isEnddoc() )
309 			cursor.toNextToken();
310 
311 		return cursor.isContainer();
312 	}
313 
314 	public static String getTargetNamespace( XmlObject s )
315 	{
316 		return ( ( Document )s.getDomNode() ).getDocumentElement().getAttribute( "targetNamespace" );
317 	}
318 
319 	public static Map<String, XmlObject> getSchemas( String wsdlUrl, SchemaLoader loader ) throws SchemaException
320 	{
321 		Map<String, XmlObject> result = new HashMap<String, XmlObject>();
322 		getSchemas( wsdlUrl, result, loader, null /* , false */);
323 		return result;
324 	}
325 
326 	/***
327 	 * Returns a map mapping urls to corresponding XmlSchema XmlObjects for the
328 	 * specified wsdlUrl
329 	 */
330 
331 	public static void getSchemas( String wsdlUrl, Map<String, XmlObject> existing, SchemaLoader loader, String tns )
332 			throws SchemaException
333 	{
334 		if( existing.containsKey( wsdlUrl ) )
335 			return;
336 
337 		// if( add )
338 		// existing.put( wsdlUrl, null );
339 
340 		log.info( "Getting schema " + wsdlUrl );
341 
342 		ArrayList<?> errorList = new ArrayList<Object>();
343 
344 		Map<String, XmlObject> result = new HashMap<String, XmlObject>();
345 
346 		boolean common = false;
347 
348 		try
349 		{
350 			XmlOptions options = new XmlOptions();
351 			options.setCompileNoValidation();
352 			options.setSaveUseOpenFrag();
353 			options.setErrorListener( errorList );
354 			options.setSaveSyntheticDocumentElement( new QName( Constants.XSD_NS, "schema" ) );
355 
356 			XmlObject xmlObject = loader.loadXmlObject( wsdlUrl, options );
357 			if( xmlObject == null )
358 				throw new Exception( "Failed to load schema from [" + wsdlUrl + "]" );
359 
360 			Document dom = ( Document )xmlObject.getDomNode();
361 			Node domNode = dom.getDocumentElement();
362 
363 			// is this an xml schema?
364 			if( domNode.getLocalName().equals( "schema" ) && Constants.XSD_NS.equals( domNode.getNamespaceURI() ) )
365 			{
366 				// set targetNamespace (this happens if we are following an include
367 				// statement)
368 				if( tns != null )
369 				{
370 					Element elm = ( ( Element )domNode );
371 					if( !elm.hasAttribute( "targetNamespace" ) )
372 					{
373 						common = true;
374 						elm.setAttribute( "targetNamespace", tns );
375 					}
376 
377 					// check for namespace prefix for targetNamespace
378 					NamedNodeMap attributes = elm.getAttributes();
379 					int c = 0;
380 					for( ; c < attributes.getLength(); c++ )
381 					{
382 						Node item = attributes.item( c );
383 						if( item.getNodeName().equals( "xmlns" ) )
384 							break;
385 
386 						if( item.getNodeValue().equals( tns ) && item.getNodeName().startsWith( "xmlns" ) )
387 							break;
388 					}
389 
390 					if( c == attributes.getLength() )
391 						elm.setAttribute( "xmlns", tns );
392 				}
393 
394 				if( common && !existing.containsKey( wsdlUrl + "@" + tns ) )
395 					result.put( wsdlUrl + "@" + tns, xmlObject );
396 				else
397 					result.put( wsdlUrl, xmlObject );
398 			}
399 			else
400 			{
401 				existing.put( wsdlUrl, null );
402 
403 				XmlObject[] schemas = xmlObject.selectPath( "declare namespace s='" + Constants.XSD_NS + "' .//s:schema" );
404 
405 				for( int i = 0; i < schemas.length; i++ )
406 				{
407 					XmlCursor xmlCursor = schemas[i].newCursor();
408 					String xmlText = xmlCursor.getObject().xmlText( options );
409 					schemas[i] = XmlObject.Factory.parse( xmlText, options );
410 					schemas[i].documentProperties().setSourceName( wsdlUrl );
411 
412 					result.put( wsdlUrl + "@" + ( i + 1 ), schemas[i] );
413 				}
414 
415 				XmlObject[] wsdlImports = xmlObject.selectPath( "declare namespace s='" + Constants.WSDL11_NS
416 						+ "' .//s:import/@location" );
417 				for( int i = 0; i < wsdlImports.length; i++ )
418 				{
419 					String location = ( ( SimpleValue )wsdlImports[i] ).getStringValue();
420 					if( location != null )
421 					{
422 						if( !location.startsWith( "file:" ) && location.indexOf( "://" ) == -1 )
423 							location = Tools.joinRelativeUrl( wsdlUrl, location );
424 
425 						getSchemas( location, existing, loader, null );
426 					}
427 				}
428 
429 				XmlObject[] wadl10Imports = xmlObject.selectPath( "declare namespace s='" + Constants.WADL10_NS
430 						+ "' .//s:grammars/s:include/@href" );
431 				for( int i = 0; i < wadl10Imports.length; i++ )
432 				{
433 					String location = ( ( SimpleValue )wadl10Imports[i] ).getStringValue();
434 					if( location != null )
435 					{
436 						if( !location.startsWith( "file:" ) && location.indexOf( "://" ) == -1 )
437 							location = Tools.joinRelativeUrl( wsdlUrl, location );
438 
439 						getSchemas( location, existing, loader, null );
440 					}
441 				}
442 
443 				XmlObject[] wadlImports = xmlObject.selectPath( "declare namespace s='" + Constants.WADL11_NS
444 						+ "' .//s:grammars/s:include/@href" );
445 				for( int i = 0; i < wadlImports.length; i++ )
446 				{
447 					String location = ( ( SimpleValue )wadlImports[i] ).getStringValue();
448 					if( location != null )
449 					{
450 						if( !location.startsWith( "file:" ) && location.indexOf( "://" ) == -1 )
451 							location = Tools.joinRelativeUrl( wsdlUrl, location );
452 
453 						getSchemas( location, existing, loader, null );
454 					}
455 				}
456 
457 			}
458 
459 			existing.putAll( result );
460 
461 			XmlObject[] schemas = result.values().toArray( new XmlObject[result.size()] );
462 
463 			for( int c = 0; c < schemas.length; c++ )
464 			{
465 				xmlObject = schemas[c];
466 
467 				XmlObject[] schemaImports = xmlObject.selectPath( "declare namespace s='" + Constants.XSD_NS
468 						+ "' .//s:import/@schemaLocation" );
469 				for( int i = 0; i < schemaImports.length; i++ )
470 				{
471 					String location = ( ( SimpleValue )schemaImports[i] ).getStringValue();
472 					Element elm = ( ( Attr )schemaImports[i].getDomNode() ).getOwnerElement();
473 
474 					if( location != null && !defaultSchemas.containsKey( elm.getAttribute( "namespace" ) ) )
475 					{
476 						if( !location.startsWith( "file:" ) && location.indexOf( "://" ) == -1 )
477 							location = Tools.joinRelativeUrl( wsdlUrl, location );
478 
479 						getSchemas( location, existing, loader, null );
480 					}
481 				}
482 
483 				XmlObject[] schemaIncludes = xmlObject.selectPath( "declare namespace s='" + Constants.XSD_NS
484 						+ "' .//s:include/@schemaLocation" );
485 				for( int i = 0; i < schemaIncludes.length; i++ )
486 				{
487 					String location = ( ( SimpleValue )schemaIncludes[i] ).getStringValue();
488 					if( location != null )
489 					{
490 						String targetNS = getTargetNamespace( xmlObject );
491 
492 						if( !location.startsWith( "file:" ) && location.indexOf( "://" ) == -1 )
493 							location = Tools.joinRelativeUrl( wsdlUrl, location );
494 
495 						getSchemas( location, existing, loader, targetNS );
496 					}
497 				}
498 			}
499 		}
500 		catch( Exception e )
501 		{
502 			SoapUI.logError( e );
503 			throw new SchemaException( e, errorList );
504 		}
505 	}
506 
507 	/***
508 	 * Returns a map mapping urls to corresponding XmlObjects for the specified
509 	 * wsdlUrl
510 	 */
511 
512 	public static Map<String, XmlObject> getDefinitionParts( SchemaLoader loader ) throws Exception
513 	{
514 		Map<String, XmlObject> result = new LinkedHashMap<String, XmlObject>();
515 		getDefinitionParts( loader.getBaseURI(), result, loader );
516 		return result;
517 	}
518 
519 	public static void getDefinitionParts( String origWsdlUrl, Map<String, XmlObject> existing, SchemaLoader loader )
520 			throws Exception
521 	{
522 		String wsdlUrl = origWsdlUrl;
523 		if( existing.containsKey( wsdlUrl ) )
524 			return;
525 
526 		XmlObject xmlObject = loader.loadXmlObject( wsdlUrl, null );
527 		existing.put( wsdlUrl, xmlObject );
528 		// wsdlUrl = loader.getBaseURI();
529 
530 		selectDefinitionParts( wsdlUrl, existing, loader, xmlObject, "declare namespace s='" + Constants.WSDL11_NS
531 				+ "' .//s:import/@location" );
532 		selectDefinitionParts( wsdlUrl, existing, loader, xmlObject, "declare namespace s='" + Constants.WADL10_NS
533 				+ "' .//s:grammars/s:include/@href" );
534 		selectDefinitionParts( wsdlUrl, existing, loader, xmlObject, "declare namespace s='" + Constants.WADL11_NS
535 				+ "' .//s:grammars/s:include/@href" );
536 		selectDefinitionParts( wsdlUrl, existing, loader, xmlObject, "declare namespace s='" + Constants.XSD_NS
537 				+ "' .//s:import/@schemaLocation" );
538 		selectDefinitionParts( wsdlUrl, existing, loader, xmlObject, "declare namespace s='" + Constants.XSD_NS
539 				+ "' .//s:include/@schemaLocation" );
540 	}
541 
542 	private static void selectDefinitionParts( String wsdlUrl, Map<String, XmlObject> existing, SchemaLoader loader,
543 			XmlObject xmlObject, String path ) throws Exception
544 	{
545 		XmlObject[] wsdlImports = xmlObject.selectPath( path );
546 		for( int i = 0; i < wsdlImports.length; i++ )
547 		{
548 			String location = ( ( SimpleValue )wsdlImports[i] ).getStringValue();
549 			if( location != null )
550 			{
551 				if( StringUtils.hasContent( location ) )
552 				{
553 					if( !location.startsWith( "file:" ) && location.indexOf( "://" ) == -1 )
554 						location = Tools.joinRelativeUrl( wsdlUrl, location );
555 
556 					getDefinitionParts( location, existing, loader );
557 				}
558 				else
559 				{
560 					Node domNode = ( ( Attr )wsdlImports[i].getDomNode() ).getOwnerElement();
561 					domNode.getParentNode().removeChild( domNode );
562 				}
563 			}
564 		}
565 	}
566 
567 	/***
568 	 * Extracts namespaces - used in tool integrations for mapping..
569 	 */
570 
571 	public static Collection<String> extractNamespaces( SchemaTypeSystem schemaTypes, boolean removeDefault )
572 	{
573 		Set<String> namespaces = new HashSet<String>();
574 		SchemaType[] globalTypes = schemaTypes.globalTypes();
575 		for( int c = 0; c < globalTypes.length; c++ )
576 		{
577 			namespaces.add( globalTypes[c].getName().getNamespaceURI() );
578 		}
579 
580 		if( removeDefault )
581 		{
582 			namespaces.removeAll( defaultSchemas.keySet() );
583 			namespaces.remove( Constants.SOAP11_ENVELOPE_NS );
584 			namespaces.remove( Constants.SOAP_ENCODING_NS );
585 		}
586 
587 		return namespaces;
588 	}
589 
590 	/***
591 	 * Used when creating a TypeSystem from a complete collection of
592 	 * SchemaDocuments so that referenced types are not downloaded (again)
593 	 */
594 
595 	public static void removeImports( XmlObject xmlObject ) throws XmlException
596 	{
597 		XmlObject[] imports = xmlObject.selectPath( "declare namespace s='" + Constants.XSD_NS + "' .//s:import" );
598 
599 		for( int c = 0; c < imports.length; c++ )
600 		{
601 			XmlCursor cursor = imports[c].newCursor();
602 			cursor.removeXml();
603 			cursor.dispose();
604 		}
605 
606 		XmlObject[] includes = xmlObject.selectPath( "declare namespace s='" + Constants.XSD_NS + "' .//s:include" );
607 
608 		for( int c = 0; c < includes.length; c++ )
609 		{
610 			XmlCursor cursor = includes[c].newCursor();
611 			cursor.removeXml();
612 			cursor.dispose();
613 		}
614 	}
615 
616 	public static boolean isInstanceOf( SchemaType schemaType, SchemaType baseType )
617 	{
618 		if( schemaType == null )
619 			return false;
620 		return schemaType.equals( baseType ) ? true : isInstanceOf( schemaType.getBaseType(), baseType );
621 	}
622 
623 	public static boolean isBinaryType( SchemaType schemaType )
624 	{
625 		return isInstanceOf( schemaType, XmlHexBinary.type ) || isInstanceOf( schemaType, XmlBase64Binary.type );
626 	}
627 
628 	public static String getDocumentation( SchemaType schemaType )
629 	{
630 		String result = null;
631 		String xsPrefix = null;
632 
633 		SchemaField containerField = schemaType.getContainerField();
634 
635 		if( containerField instanceof SchemaLocalElement )
636 		{
637 			SchemaAnnotation annotation = ( ( SchemaLocalElement )containerField ).getAnnotation();
638 			if( annotation != null )
639 			{
640 				XmlObject[] userInformation = annotation.getUserInformation();
641 				if( userInformation != null && userInformation.length > 0 )
642 				{
643 					XmlObject xmlObject = userInformation[0];
644 					XmlCursor cursor = xmlObject.newCursor();
645 					xsPrefix = cursor.prefixForNamespace( "http://www.w3.org/2001/XMLSchema" );
646 					cursor.dispose();
647 
648 					result = xmlObject.xmlText(); // XmlUtils.getElementText( (
649 					// Element )
650 					// userInformation[0].getDomNode());
651 				}
652 			}
653 		}
654 
655 		if( result == null && schemaType != null && schemaType.getAnnotation() != null )
656 		{
657 			XmlObject[] userInformation = schemaType.getAnnotation().getUserInformation();
658 			if( userInformation != null && userInformation.length > 0 && userInformation[0] != null )
659 			{
660 				XmlObject xmlObject = userInformation[0];
661 				XmlCursor cursor = xmlObject.newCursor();
662 				xsPrefix = cursor.prefixForNamespace( "http://www.w3.org/2001/XMLSchema" );
663 				cursor.dispose();
664 				result = xmlObject.xmlText(); // = XmlUtils.getElementText( (
665 				// Element )
666 				// userInformation[0].getDomNode());
667 			}
668 		}
669 
670 		if( result != null )
671 		{
672 			result = result.trim();
673 			if( result.startsWith( "<" ) && result.endsWith( ">" ) )
674 			{
675 				int ix = result.indexOf( '>' );
676 				if( ix > 0 )
677 				{
678 					result = result.substring( ix + 1 );
679 				}
680 
681 				ix = result.lastIndexOf( '<' );
682 				if( ix >= 0 )
683 				{
684 					result = result.substring( 0, ix );
685 				}
686 			}
687 
688 			if( xsPrefix == null || xsPrefix.length() == 0 )
689 				xsPrefix = "xs:";
690 			else
691 				xsPrefix += ":";
692 
693 			// result = result.trim().replaceAll( "<" + xsPrefix + "br/>", "\n"
694 			// ).trim();
695 			result = result.trim().replaceAll( xsPrefix, "" ).trim();
696 
697 			result = StringUtils.toHtml( result );
698 		}
699 
700 		return result;
701 	}
702 
703 	public static String[] getEnumerationValues( SchemaType schemaType, boolean addNull )
704 	{
705 		if( schemaType != null )
706 		{
707 			XmlAnySimpleType[] enumerationValues = schemaType.getEnumerationValues();
708 			if( enumerationValues != null && enumerationValues.length > 0 )
709 			{
710 				if( addNull )
711 				{
712 					String[] values = new String[enumerationValues.length + 1];
713 					values[0] = null;
714 
715 					for( int c = 1; c < values.length; c++ )
716 						values[c] = enumerationValues[c - 1].getStringValue();
717 
718 					return values;
719 				}
720 				else
721 				{
722 					String[] values = new String[enumerationValues.length];
723 
724 					for( int c = 0; c < values.length; c++ )
725 						values[c] = enumerationValues[c].getStringValue();
726 
727 					return values;
728 				}
729 			}
730 		}
731 
732 		return new String[0];
733 	}
734 
735 	public static Collection<? extends QName> getExcludedTypes()
736 	{
737 		String excluded = SoapUI.getSettings().getString( WsdlSettings.EXCLUDED_TYPES, null );
738 		return SettingUtils.string2QNames( excluded );
739 	}
740 
741 	public static boolean isAnyType( SchemaType schemaType )
742 	{
743 		return schemaType.getBuiltinTypeCode() == SchemaType.BTC_ANY_TYPE
744 				|| ( schemaType.getBaseType() != null && schemaType.getBaseType().getBuiltinTypeCode() == SchemaType.BTC_ANY_TYPE );
745 	}
746 }