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.support.definition.export;
14  
15  import java.io.File;
16  import java.net.MalformedURLException;
17  import java.net.URL;
18  import java.util.HashMap;
19  import java.util.List;
20  import java.util.Map;
21  
22  import org.apache.xmlbeans.SimpleValue;
23  import org.apache.xmlbeans.XmlObject;
24  
25  import com.eviware.soapui.impl.rest.RestService;
26  import com.eviware.soapui.impl.support.definition.InterfaceDefinition;
27  import com.eviware.soapui.impl.support.definition.InterfaceDefinitionPart;
28  import com.eviware.soapui.impl.wsdl.support.Constants;
29  import com.eviware.soapui.model.iface.Interface;
30  import com.eviware.soapui.support.Tools;
31  import com.eviware.soapui.support.types.StringToStringMap;
32  
33  public abstract class AbstractDefinitionExporter<T extends Interface> implements DefinitionExporter
34  {
35  	private InterfaceDefinition<T> definition;
36  
37  	public AbstractDefinitionExporter( InterfaceDefinition<T> definition )
38  	{
39  		this.definition = definition;
40  	}
41  
42  	public InterfaceDefinition<T> getDefinition()
43  	{
44  		return definition;
45  	}
46  
47  	public void setDefinition( InterfaceDefinition<T> definition )
48  	{
49  		this.definition = definition;
50  	}
51  
52  	public String export( String folderName ) throws Exception
53  	{
54  		if( definition.getDefinitionCache() == null || !definition.getDefinitionCache().validate() )
55  			throw new Exception( "Definition is not cached for export" );
56  
57  		File outFolder = new File( folderName );
58  		if( !outFolder.exists() && !outFolder.mkdirs() )
59  			throw new Exception( "Failed to create directory [" + folderName + "]" );
60  
61  		Map<String, String> urlToFileMap = new HashMap<String, String>();
62  
63  		setFilenameForPart( definition.getDefinitionCache().getRootPart(), urlToFileMap, null );
64  
65  		List<InterfaceDefinitionPart> partList = definition.getDefinitionCache().getDefinitionParts();
66  		for( InterfaceDefinitionPart part : partList )
67  		{
68  			setFilenameForPart( part, urlToFileMap, null );
69  		}
70  
71  		for( InterfaceDefinitionPart part : partList )
72  		{
73  			XmlObject obj = XmlObject.Factory.parse( part.getContent() );
74  			replaceImportsAndIncludes( obj, urlToFileMap, part.getUrl() );
75  			postProcessing( obj, part );
76  			obj.save( new File( outFolder, urlToFileMap.get( part.getUrl() ) ) );
77  		}
78  
79  		return folderName + File.separatorChar
80  				+ urlToFileMap.get( definition.getDefinitionCache().getRootPart().getUrl() );
81  	}
82  
83  	public StringToStringMap createFilesForExport( String urlPrefix ) throws Exception
84  	{
85  		StringToStringMap result = new StringToStringMap();
86  		Map<String, String> urlToFileMap = new HashMap<String, String>();
87  
88  		if( urlPrefix == null )
89  			urlPrefix = "";
90  
91  		setFilenameForPart( definition.getDefinitionCache().getRootPart(), urlToFileMap, urlPrefix );
92  
93  		List<InterfaceDefinitionPart> partList = definition.getDefinitionCache().getDefinitionParts();
94  		for( InterfaceDefinitionPart part : partList )
95  		{
96  			if( !part.isRootPart() )
97  				setFilenameForPart( part, urlToFileMap, urlPrefix );
98  		}
99  
100 		for( InterfaceDefinitionPart part : partList )
101 		{
102 			XmlObject obj = XmlObject.Factory.parse( part.getContent() );
103 			replaceImportsAndIncludes( obj, urlToFileMap, part.getUrl() );
104 			String urlString = urlToFileMap.get( part.getUrl() );
105 			if( urlString.startsWith( urlPrefix ) )
106 				urlString = urlString.substring( urlPrefix.length() );
107 
108 			result.put( urlString, obj.xmlText() );
109 
110 			if( part.isRootPart() )
111 				result.put( "#root#", urlString );
112 		}
113 
114 		return result;
115 	}
116 
117 	protected void postProcessing( XmlObject obj, InterfaceDefinitionPart part )
118 	{
119 	}
120 
121 	private void setFilenameForPart( InterfaceDefinitionPart part, Map<String, String> urlToFileMap, String urlPrefix )
122 			throws MalformedURLException
123 	{
124 
125 		String path = part.getUrl();
126 
127 		try
128 		{
129 			URL url = new URL( path );
130 			path = url.getPath();
131 		}
132 		catch( MalformedURLException e )
133 		{
134 		}
135 
136 		int ix = path.lastIndexOf( '/' );
137 		String fileName = ix == -1 ? path : path.substring( ix + 1 );
138 
139 		ix = fileName.lastIndexOf( '.' );
140 		if( ix != -1 )
141 			fileName = fileName.substring( 0, ix );
142 
143 		String type = part.getType();
144 
145 		if( type.equals( Constants.WSDL11_NS ) )
146 			fileName += ".wsdl";
147 		else if( part.getType().equals( Constants.XSD_NS ) )
148 			fileName += ".xsd";
149 		else if( part.getType().equals( ((RestService)getDefinition().getInterface()).getWadlVersion() ) )
150 			fileName += ".wadl";
151 		else
152 			fileName += ".xml";
153 
154 		if( urlPrefix != null )
155 			fileName = urlPrefix + fileName;
156 
157 		int cnt = 1;
158 		while( urlToFileMap.containsValue( fileName ) )
159 		{
160 			ix = fileName.lastIndexOf( '.' );
161 			fileName = fileName.substring( 0, ix ) + "_" + cnt + fileName.substring( ix );
162 			cnt++ ;
163 		}
164 
165 		urlToFileMap.put( part.getUrl(), fileName );
166 	}
167 
168 	private void replaceImportsAndIncludes( XmlObject xmlObject, Map<String, String> urlToFileMap, String baseUrl )
169 			throws Exception
170 	{
171 		String[] paths = getLocationXPathsToReplace();
172 
173 		for( String path : paths )
174 		{
175 			XmlObject[] locations = xmlObject.selectPath( path );
176 
177 			for( int i = 0; i < locations.length; i++ )
178 			{
179 				SimpleValue wsdlImport = ( ( SimpleValue )locations[i] );
180 				replaceLocation( urlToFileMap, baseUrl, wsdlImport );
181 			}
182 		}
183 	}
184 
185 	protected abstract String[] getLocationXPathsToReplace();
186 
187 	private void replaceLocation( Map<String, String> urlToFileMap, String baseUrl, SimpleValue wsdlImport )
188 			throws Exception
189 	{
190 		String location = wsdlImport.getStringValue();
191 		if( location != null )
192 		{
193 			if( location.startsWith( "file:" ) || location.indexOf( "://" ) > 0 )
194 			{
195 				String newLocation = urlToFileMap.get( location );
196 				if( newLocation != null )
197 					wsdlImport.setStringValue( newLocation );
198 				else
199 					throw new Exception( "Missing local file for [" + newLocation + "]" );
200 			}
201 			else
202 			{
203 				String loc = Tools.joinRelativeUrl( baseUrl, location );
204 				String newLocation = urlToFileMap.get( loc );
205 				if( newLocation != null )
206 					wsdlImport.setStringValue( newLocation );
207 				else
208 					throw new Exception( "Missing local file for [" + loc + "]" );
209 			}
210 		}
211 	}
212 
213 }