View Javadoc

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