1
2
3
4
5
6
7
8
9
10
11
12
13 package com.eviware.soapui.impl.wsdl.support;
14
15 import java.io.File;
16 import java.net.URI;
17 import java.net.URL;
18 import java.util.ArrayList;
19 import java.util.Arrays;
20 import java.util.List;
21
22 import javax.xml.namespace.QName;
23
24 import org.apache.log4j.Logger;
25 import org.apache.xmlbeans.SchemaTypeLoader;
26 import org.apache.xmlbeans.SimpleValue;
27 import org.apache.xmlbeans.XmlBeans;
28 import org.apache.xmlbeans.XmlCursor;
29 import org.apache.xmlbeans.XmlObject;
30 import org.apache.xmlbeans.XmlOptions;
31 import org.w3c.dom.Element;
32 import org.w3c.dom.Node;
33
34 import com.eviware.soapui.SoapUI;
35
36 /***
37 * XML-Schema related tools
38 *
39 * @author Ole.Matzura
40 */
41
42 public class SchemaUtils
43 {
44 private final static Logger log = Logger.getLogger( SchemaUtils.class );
45
46 public static SchemaTypeLoader loadSchemaTypes(String wsdlUrl) throws Exception
47 {
48 log.info( "Loading schema types from [" + wsdlUrl + "]");
49 SchemaTypeLoader schemaTypes = loadSchemaTypes( getSchemas( wsdlUrl ));
50 return schemaTypes;
51 }
52
53 public static SchemaTypeLoader loadSchemaTypes(List<XmlObject> schemas) throws Exception
54 {
55 XmlOptions options = new XmlOptions();
56 options.setCompileNoValidation();
57 options.setCompileNoPvrRule();
58 options.setCompileDownloadUrls();
59 options.setCompileNoUpaRule();
60
61 ArrayList errorList = new ArrayList();
62 options.setErrorListener( errorList );
63
64 schemas.add( XmlObject.Factory.parse( SoapUI.class.getResource("/soapEncoding.xsd") ));
65
66 try
67 {
68 return XmlBeans.loadXsd(
69 schemas.toArray(new XmlObject[schemas.size()]), options);
70 }
71 catch (Exception e)
72 {
73 for( int c = 0; c < errorList.size(); c++ )
74 {
75 System.out.println( errorList.get( c ) );
76 }
77 throw e;
78 }
79 }
80
81 public static List<XmlObject> getSchemas( String wsdlUrl ) throws Exception
82 {
83 log.info( "loading schema types from " + wsdlUrl );
84 XmlOptions options = new XmlOptions();
85 options.setCompileNoValidation();
86 options.setCompileDownloadUrls();
87 options.setCompileNoUpaRule();
88 options.setSaveUseOpenFrag();
89 options.setSaveSyntheticDocumentElement( new QName( "http://www.w3.org/2001/XMLSchema", "schema" ));
90
91 XmlObject xmlObject = XmlObject.Factory.parse(new URL(wsdlUrl),options);
92
93 XmlObject[] schemas = xmlObject
94 .selectPath("declare namespace s='http://www.w3.org/2001/XMLSchema' .//s:schema");
95
96 for (int i = 0; i < schemas.length; i++)
97 {
98 XmlCursor xmlCursor = schemas[i].newCursor();
99 String xmlText = xmlCursor.getObject().xmlText( options );
100 schemas[i] = XmlObject.Factory.parse(xmlText, options);
101
102 schemas[i].documentProperties().setSourceName(wsdlUrl);
103 if( wsdlUrl.startsWith( "file:"))
104 fixRelativeFileImports( schemas[i] );
105 }
106
107 List<XmlObject> result = new ArrayList<XmlObject>( Arrays.asList( schemas ));
108
109 XmlObject [] imports = xmlObject.selectPath("declare namespace s='http://schemas.xmlsoap.org/wsdl/' .//s:import");
110 for (int i = 0; i < imports.length; i++)
111 {
112 String location = ((Element)imports[i].getDomNode()).getAttribute( "location" );
113 if( location != null )
114 {
115 if( location.indexOf( "://") > 0 )
116 {
117 result.addAll( getSchemas( location ));
118 }
119 else
120 {
121 result.addAll( getSchemas( joinRelativeUrl( wsdlUrl, location ) ));
122 }
123 }
124 }
125
126 return result;
127 }
128
129 public static List<String> getDefinitionUrls( String wsdlUrl ) throws Exception
130 {
131 List<String> result = new ArrayList<String>();
132 result.add( wsdlUrl );
133
134 XmlOptions options = new XmlOptions();
135 options.setCompileNoValidation();
136 options.setCompileDownloadUrls();
137 options.setCompileNoUpaRule();
138 options.setSaveUseOpenFrag();
139 options.setSaveSyntheticDocumentElement( new QName( "http://www.w3.org/2001/XMLSchema", "schema" ));
140
141 XmlObject xmlObject = XmlObject.Factory.parse(new URL(wsdlUrl),options);
142
143 XmlObject [] wsdlImports = xmlObject.selectPath("declare namespace s='http://schemas.xmlsoap.org/wsdl/' .//s:import");
144 for (int i = 0; i < wsdlImports.length; i++)
145 {
146 String location = wsdlImports[i].getDomNode().getAttributes().getNamedItem( "location" ).getNodeValue();
147 if( location != null )
148 {
149 if( location.indexOf( "://") > 0 )
150 {
151 result.addAll( getDefinitionUrls( location ));
152 }
153 else
154 {
155 result.addAll( getDefinitionUrls( joinRelativeUrl( wsdlUrl, location ) ));
156 }
157 }
158 }
159
160 XmlObject[] schemaImports = xmlObject.selectPath("declare namespace s='http://www.w3.org/2001/XMLSchema' .//s:import/@schemaLocation");
161 for (int i = 0; i < schemaImports.length; i++)
162 {
163 String location = ((SimpleValue)schemaImports[i]).getStringValue();
164 if( location != null )
165 {
166 if( location.indexOf( "://") > 0 )
167 {
168 result.addAll( getDefinitionUrls( location ));
169 }
170 else
171 {
172 result.addAll( getDefinitionUrls( joinRelativeUrl( wsdlUrl, location )));
173 }
174 }
175 }
176
177 XmlObject[] schemaIncludes = xmlObject.selectPath("declare namespace s='http://www.w3.org/2001/XMLSchema' .//s:include/@schemaLocation");
178 for (int i = 0; i < schemaIncludes.length; i++)
179 {
180 String location = ((SimpleValue)schemaIncludes[i]).getStringValue();
181 if( location != null )
182 {
183 if( location.indexOf( "://") > 0 )
184 {
185 result.addAll( getDefinitionUrls( location ));
186 }
187 else
188 {
189 result.addAll( getDefinitionUrls( joinRelativeUrl( wsdlUrl, location )));
190 }
191 }
192 }
193
194 return result;
195 }
196
197 public static String joinRelativeUrl( String root, String url )
198 {
199 int ix = root.startsWith("file:") ? root.lastIndexOf( File.separatorChar ) : root.lastIndexOf( '/' );
200 return root.substring( 0, ix+1 ) + url;
201 }
202
203 /***
204 * Fixes relative xsd imports in the specified schema. The schemaLocation of an
205 * xsd import must be an URI which is not the case if the loaded
206 * wsdl is loaded with the "file" schema (ie from the file system) and an import is relative.
207 */
208
209 private static void fixRelativeFileImports(XmlObject xmlObject) throws Exception
210 {
211 XmlObject[] imports = xmlObject
212 .selectPath("declare namespace s='http://www.w3.org/2001/XMLSchema' .//s:import");
213
214 if( imports.length == 0 ) return;
215
216 String source = xmlObject.documentProperties().getSourceName();
217 int ix = source.lastIndexOf( File.separatorChar );
218 if( ix != -1 )
219 source = source.substring( 0, ix+1 );
220
221 for( int c = 0; c < imports.length; c++ )
222 {
223 Node locationNode = imports[c].getDomNode().getAttributes().getNamedItem( "schemaLocation" );
224 if( locationNode != null )
225 {
226 String location = locationNode.getNodeValue();
227 if( location != null )
228 {
229 URI uri = new URI( location );
230 if( !uri.isAbsolute() )
231 {
232 locationNode.setNodeValue( source + location );
233 }
234 }
235 }
236 }
237 }
238 }