1
2
3
4
5
6
7
8
9
10
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 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 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 }