View Javadoc

1   /*
2    *  soapUI, copyright (C) 2006 eviware.com 
3    *
4    *  soapUI is free software; you can redistribute it and/or modify it under the 
5    *  terms of the GNU Lesser General Public License as published by the Free Software Foundation; 
6    *  either version 2.1 of the License, or (at your option) any later version.
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.wsdl;
14  
15  import java.io.File;
16  import java.io.InputStream;
17  import java.net.MalformedURLException;
18  import java.net.URL;
19  import java.util.HashMap;
20  import java.util.List;
21  import java.util.Map;
22  
23  import org.apache.commons.httpclient.HttpState;
24  import org.apache.xmlbeans.SimpleValue;
25  import org.apache.xmlbeans.XmlObject;
26  import org.apache.xmlbeans.XmlOptions;
27  
28  import com.eviware.soapui.config.DefinitionCacheConfig;
29  import com.eviware.soapui.config.DefintionPartConfig;
30  import com.eviware.soapui.impl.wsdl.support.Constants;
31  import com.eviware.soapui.support.Tools;
32  
33  public class CachedWsdlLoader extends WsdlLoader 
34  {
35  	private HttpState state;
36  	private final DefinitionCacheConfig config;
37  	
38  	public CachedWsdlLoader(DefinitionCacheConfig config)
39  	{
40  		super( config.getRootPart() );
41  		this.config = config;
42  	}
43  
44  	public CachedWsdlLoader(String wsdlUrl) throws Exception
45  	{
46  		this( WsdlLoader.cacheWsdl( new UrlWsdlLoader( wsdlUrl )));
47  	}
48  
49  	public InputStream load( String url ) throws Exception
50  	{
51  		XmlObject xmlObject = loadXmlObject( url, null );
52  		return xmlObject == null ? null : xmlObject.newInputStream();
53  	}
54  
55  	public XmlObject loadXmlObject(String url, XmlOptions options ) throws Exception
56  	{
57  		List<DefintionPartConfig> partList = config.getPartList();
58  		for( DefintionPartConfig part : partList )
59  		{
60  			if( part.getUrl().equalsIgnoreCase( url ))
61  			{
62  				return XmlObject.Factory.parse( part.getContent().toString(), new XmlOptions().setLoadLineNumbers() );
63  			}
64  		}
65  		
66  		return null;
67  	}
68  
69  	public boolean abort()
70  	{
71  		return false;
72  	}
73  	
74  	public boolean isAborted()
75  	{
76  		return false;
77  	}
78  
79  	public String saveDefinition( String folderName ) throws Exception
80  	{
81  		File outFolder = new File( folderName );
82  		if( !outFolder.exists() && !outFolder.mkdirs() )
83  			throw new Exception( "Failed to create directory [" + folderName + "]" );
84  		
85  		Map<String,String> urlToFileMap = new HashMap<String,String>(); 
86  		
87  		setFilenameForUrl( config.getRootPart(), Constants.WSDL11_NS, urlToFileMap );
88  		
89  		List<DefintionPartConfig> partList = config.getPartList();
90  		for( DefintionPartConfig part : partList )
91  		{
92  			setFilenameForUrl( part.getUrl(), part.getType(), urlToFileMap );
93  		}
94  		
95  		for( DefintionPartConfig part : partList )
96  		{
97  			XmlObject obj = XmlObject.Factory.parse( part.getContent().toString() );
98  			replaceImportsAndIncludes( obj, urlToFileMap, part.getUrl() );
99  			obj.save( new File( outFolder, urlToFileMap.get( part.getUrl() )));
100 		}
101 		
102 		return folderName + File.separatorChar + urlToFileMap.get( config.getRootPart() );
103 	}
104 	
105 	private void setFilenameForUrl( String fileUrl, String type, Map<String,String> urlToFileMap ) throws MalformedURLException
106 	{
107 		URL url = new URL( fileUrl );
108 		String path = url.getPath();
109 		
110 		int ix = path.lastIndexOf( '/' );
111 		String fileName = ix == -1 ? path : path.substring( ix+1 );
112 		
113 		ix = fileName.lastIndexOf( '.');
114 		if( ix != -1 )
115 			fileName = fileName.substring( 0 , ix );
116 			
117 		if( type.equals( Constants.WSDL11_NS ))
118 			fileName += ".wsdl";
119 		else if( type.equals( Constants.XSD_NS ))
120 			fileName += ".xsd";
121 		else
122 			fileName += ".xml";
123 		
124 		while( urlToFileMap.containsValue( fileName ))
125 		{
126 			ix = fileName.lastIndexOf( '.');
127 			fileName = fileName.substring( 0, ix ) + "_" + fileName.substring( ix );
128 		}
129 		
130 		urlToFileMap.put( fileUrl, fileName );
131 	}
132 
133 	private void replaceImportsAndIncludes(XmlObject xmlObject, Map<String, String> urlToFileMap, String baseUrl ) throws Exception
134 	{
135 		XmlObject[] wsdlImports = xmlObject
136 			.selectPath("declare namespace s='http://schemas.xmlsoap.org/wsdl/' .//s:import/@location");
137 		
138 		for (int i = 0; i < wsdlImports.length; i++)
139 		{
140 			SimpleValue wsdlImport = ((SimpleValue) wsdlImports[i]);
141 			replaceLocation(urlToFileMap, baseUrl, wsdlImport);
142 		}
143 		
144 		XmlObject[] schemaImports = xmlObject
145 			.selectPath("declare namespace s='http://www.w3.org/2001/XMLSchema' .//s:import/@schemaLocation");
146 
147 		for (int i = 0; i < schemaImports.length; i++)
148 		{
149 			SimpleValue schemaImport = ((SimpleValue) schemaImports[i]);
150 			replaceLocation(urlToFileMap, baseUrl, schemaImport);
151 		}
152 
153 		XmlObject[] schemaIncludes = xmlObject
154 			.selectPath("declare namespace s='http://www.w3.org/2001/XMLSchema' .//s:include/@schemaLocation");
155 		for (int i = 0; i < schemaIncludes.length; i++)
156 		{
157 			SimpleValue schemaInclude = ((SimpleValue) schemaIncludes[i]);
158 			replaceLocation(urlToFileMap, baseUrl, schemaInclude);
159 		}
160 	}
161 
162 	private void replaceLocation(Map<String, String> urlToFileMap, String baseUrl, SimpleValue wsdlImport) throws Exception
163 	{
164 		String location = wsdlImport.getStringValue();
165 		if (location != null)
166 		{
167 			if (location.startsWith("file:")
168 					|| location.indexOf("://") > 0)
169 			{
170 				String newLocation = urlToFileMap.get( location );
171 				if( newLocation != null )
172 					wsdlImport.setStringValue( newLocation);
173 				else
174 					throw new Exception( "Missing local file for [" + newLocation + "]" );
175 			}
176 			else
177 			{
178 				String loc = Tools.joinRelativeUrl(baseUrl, location);
179 				String newLocation = urlToFileMap.get( loc);
180 				if( newLocation != null )
181 					wsdlImport.setStringValue( newLocation);
182 				else
183 					throw new Exception( "Missing local file for [" + loc + "]" );
184 			}
185 		}
186 	}
187 
188 	public void close()
189 	{
190 	}
191 }