View Javadoc

1   /*
2    *  soapUI, copyright (C) 2004-2009 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;
14  
15  import java.io.File;
16  import java.io.FileInputStream;
17  import java.io.IOException;
18  import java.io.InputStream;
19  import java.util.ArrayList;
20  import java.util.Arrays;
21  import java.util.Collection;
22  import java.util.HashMap;
23  import java.util.HashSet;
24  import java.util.List;
25  import java.util.Map;
26  import java.util.Properties;
27  import java.util.Set;
28  
29  import javax.xml.namespace.QName;
30  
31  import org.apache.xmlbeans.XmlString;
32  
33  import com.eviware.soapui.SoapUI;
34  import com.eviware.soapui.config.PropertiesTypeConfig;
35  import com.eviware.soapui.config.PropertyConfig;
36  import com.eviware.soapui.impl.wsdl.MutableTestPropertyHolder;
37  import com.eviware.soapui.impl.wsdl.support.wsdl.UrlWsdlLoader;
38  import com.eviware.soapui.model.ModelItem;
39  import com.eviware.soapui.model.propertyexpansion.PropertyExpansion;
40  import com.eviware.soapui.model.support.TestPropertyUtils;
41  import com.eviware.soapui.model.testsuite.RenameableTestProperty;
42  import com.eviware.soapui.model.testsuite.TestProperty;
43  import com.eviware.soapui.model.testsuite.TestPropertyListener;
44  import com.eviware.soapui.support.StringUtils;
45  
46  public class XmlBeansPropertiesTestPropertyHolder implements MutableTestPropertyHolder, Map<String, TestProperty>
47  {
48  	private PropertiesTypeConfig config;
49  	private List<PropertiesStepProperty> properties = new ArrayList<PropertiesStepProperty>();
50  	private Map<String, PropertiesStepProperty> propertyMap = new HashMap<String, PropertiesStepProperty>();
51  	private Set<TestPropertyListener> listeners = new HashSet<TestPropertyListener>();
52  	private ModelItem modelItem;
53  	private Properties overrideProperties;
54  	private String propertiesLabel = "Test Properties";
55  
56  	public XmlBeansPropertiesTestPropertyHolder( ModelItem modelItem, PropertiesTypeConfig config )
57  	{
58  		this.modelItem = modelItem;
59  		this.config = config;
60  
61  		for( int c = 0; c < config.sizeOfPropertyArray(); c++ )
62  		{
63  			PropertyConfig propertyConfig = config.getPropertyArray( c );
64  			if( StringUtils.hasContent( propertyConfig.getName()))
65  			{
66  				addProperty( propertyConfig, false );		
67  			}
68  			else
69  			{
70  				config.removeProperty( c );
71  				c--;
72  			}
73  		}
74  	}
75  
76  	protected PropertiesStepProperty addProperty( PropertyConfig propertyConfig, boolean notify )
77  	{
78  		PropertiesStepProperty propertiesStepProperty = new PropertiesStepProperty( propertyConfig );
79  		properties.add( propertiesStepProperty );
80  		propertyMap.put( propertiesStepProperty.getName().toUpperCase(), propertiesStepProperty );
81  
82  		if( notify )
83  		{
84  			firePropertyAdded( propertiesStepProperty.getName() );
85  		}
86  
87  		return propertiesStepProperty;
88  	}
89  
90  	private void firePropertyAdded( String name )
91  	{
92  		TestPropertyListener[] listenersArray = listeners.toArray( new TestPropertyListener[listeners.size()] );
93  		for( TestPropertyListener listener : listenersArray )
94  		{
95  			listener.propertyAdded( name );
96  		}
97  	}
98  
99  	private void firePropertyRemoved( String name )
100 	{
101 		TestPropertyListener[] listenersArray = listeners.toArray( new TestPropertyListener[listeners.size()] );
102 		for( TestPropertyListener listener : listenersArray )
103 		{
104 			listener.propertyRemoved( name );
105 		}
106 	}
107 
108 	private void firePropertyMoved( String name, int oldIndex, int newIndex )
109 	{
110 		TestPropertyListener[] listenersArray = listeners.toArray( new TestPropertyListener[listeners.size()] );
111 		for( TestPropertyListener listener : listenersArray )
112 		{
113 			listener.propertyMoved( name, oldIndex, newIndex );
114 		}
115 	}
116 
117 	private void firePropertyRenamed( String oldName, String newName )
118 	{
119 		TestPropertyListener[] listenersArray = listeners.toArray( new TestPropertyListener[listeners.size()] );
120 		for( TestPropertyListener listener : listenersArray )
121 		{
122 			listener.propertyRenamed( oldName, newName );
123 		}
124 	}
125 
126 	private void firePropertyValueChanged( String name, String oldValue, String newValue )
127 	{
128 		TestPropertyListener[] listenersArray = listeners.toArray( new TestPropertyListener[listeners.size()] );
129 		for( TestPropertyListener listener : listenersArray )
130 		{
131 			listener.propertyValueChanged( name, oldValue, newValue );
132 		}
133 	}
134 
135 	public TestProperty addProperty( String name )
136 	{
137 		PropertyConfig propertyConfig = config.addNewProperty();
138 		propertyConfig.setName( name );
139 		return addProperty( propertyConfig, true );
140 	}
141 
142 	public void addTestPropertyListener( TestPropertyListener listener )
143 	{
144 		listeners.add( listener );
145 	}
146 
147 	public PropertiesStepProperty getProperty( String name )
148 	{
149 		return propertyMap.get( name.toUpperCase() );
150 	}
151 
152 	public String[] getPropertyNames()
153 	{
154 		String[] result = new String[properties.size()];
155 		for( int c = 0; c < properties.size(); c++ )
156 			result[c] = properties.get( c ).getName();
157 
158 		return result;
159 	}
160 
161 	public List<TestProperty> getPropertyList()
162 	{
163 		List<TestProperty> result = new ArrayList<TestProperty>();
164 
165 		for( TestProperty property : properties )
166 			result.add( property );
167 
168 		return result;
169 	}
170 
171 	public String getPropertyValue( String name )
172 	{
173 		TestProperty property = getProperty( name );
174 		return property == null ? null : property.getValue();
175 	}
176 
177 	public TestProperty removeProperty( String propertyName )
178 	{
179 		TestProperty property = getProperty( propertyName );
180 		if( property != null )
181 		{
182 			int ix = properties.indexOf( property );
183 			propertyMap.remove( propertyName.toUpperCase() );
184 			properties.remove( ix );
185 			config.removeProperty( ix );
186 
187 			firePropertyRemoved( propertyName );
188 			return property;
189 		}
190 
191 		return null;
192 	}
193 
194 	public void removeTestPropertyListener( TestPropertyListener listener )
195 	{
196 		listeners.remove( listener );
197 	}
198 
199 	public void setPropertyValue( String name, String value )
200 	{
201 		PropertiesStepProperty property = getProperty( name );
202 		if( property != null )
203 			property.setValue( value );
204 		else
205 			addProperty( name ).setValue( value );
206 	}
207 
208 	public void resetPropertiesConfig( PropertiesTypeConfig config )
209 	{
210 		this.config = config;
211 
212 		for( int c = 0; c < config.sizeOfPropertyArray(); c++ )
213 		{
214 			properties.get( c ).setConfig( config.getPropertyArray( c ) );
215 		}
216 	}
217 
218 	public boolean renameProperty( String name, String newName )
219 	{
220 		if( getProperty( newName ) != null )
221 			return false;
222 
223 		PropertiesStepProperty property = getProperty( name );
224 		if( property == null )
225 			return false;
226 
227 		property.setName( newName );
228 		return true;
229 	}
230 
231 	/***
232 	 * Internal property class
233 	 * 
234 	 * @author ole
235 	 */
236 
237 	public class PropertiesStepProperty implements RenameableTestProperty
238 	{
239 		private PropertyConfig propertyConfig;
240 
241 		public PropertiesStepProperty( PropertyConfig propertyConfig )
242 		{
243 			this.propertyConfig = propertyConfig;
244 		}
245 
246 		public void setConfig( PropertyConfig propertyConfig )
247 		{
248 			this.propertyConfig = propertyConfig;
249 		}
250 
251 		public String getName()
252 		{
253 			return propertyConfig.getName();
254 		}
255 
256 		public void setName( String name )
257 		{
258 			String oldName = getName();
259 			propertyConfig.setName( name );
260 
261 			propertyMap.remove( oldName.toUpperCase() );
262 			propertyMap.put( name.toUpperCase(), this );
263 
264 			firePropertyRenamed( oldName, name );
265 		}
266 
267 		public String getDescription()
268 		{
269 			return null;
270 		}
271 
272 		public String getValue()
273 		{
274 			if( overrideProperties != null && overrideProperties.containsKey( getName() ) )
275 				return overrideProperties.getProperty( getName() );
276 
277 			return propertyConfig.getValue();
278 		}
279 
280 		public void setValue( String value )
281 		{
282 			String oldValue = getValue();
283 			propertyConfig.setValue( value );
284 
285 			if( overrideProperties != null && overrideProperties.containsKey( getName() ) )
286 			{
287 				overrideProperties.remove( getName() );
288 				if( overrideProperties.isEmpty() )
289 					overrideProperties = null;
290 			}
291 
292 			firePropertyValueChanged( getName(), oldValue, value );
293 		}
294 
295 		public boolean isReadOnly()
296 		{
297 			return false;
298 		}
299 
300 		public QName getType()
301 		{
302 			return XmlString.type.getName();
303 		}
304 
305 		public ModelItem getModelItem()
306 		{
307 			return modelItem;
308 		}
309 
310 		public String getDefaultValue()
311 		{
312 			return null;
313 		}
314 	}
315 
316 	public int saveTo( String fileName ) throws IOException
317 	{
318 		return TestPropertyUtils.saveTo( this, fileName );
319 	}
320 
321 	public int getPropertyCount()
322 	{
323 		return properties.size();
324 	}
325 
326 	public TestProperty getPropertyAt( int index )
327 	{
328 		return properties.get( index );
329 	}
330 
331 	public Map<String, TestProperty> getProperties()
332 	{
333 		Map<String, TestProperty> result = new HashMap<String, TestProperty>();
334 		for( TestProperty property : propertyMap.values() )
335 		{
336 			result.put( property.getName(), property );
337 		}
338 
339 		return result;
340 	}
341 
342 	public boolean hasProperty( String name )
343 	{
344 		return propertyMap.containsKey( name.toUpperCase() );
345 	}
346 
347 	public int addPropertiesFromFile( String propFile )
348 	{
349 		if( !StringUtils.hasContent( propFile ) )
350 			return 0;
351 
352 		try
353 		{
354 			InputStream input = null;
355 
356 			File file = new File( propFile );
357 			if( file.exists() )
358 			{
359 				input = new FileInputStream( file );
360 			}
361 			else if( propFile.toLowerCase().startsWith( "http://" ) || propFile.toLowerCase().startsWith( "https://" ) )
362 			{
363 				UrlWsdlLoader loader = new UrlWsdlLoader( propFile, getModelItem() );
364 				loader.setUseWorker( false );
365 				input = loader.load();
366 			}
367 
368 			if( input != null )
369 			{
370 				if( overrideProperties == null )
371 					overrideProperties = new Properties();
372 
373 				int sz = overrideProperties.size();
374 				overrideProperties.load( input );
375 
376 				for( Object key : overrideProperties.keySet() )
377 				{
378 					String name = key.toString();
379 					if( !hasProperty( name ) )
380 						addProperty( name );
381 				}
382 
383 				return overrideProperties.size() - sz;
384 			}
385 		}
386 		catch( Exception e )
387 		{
388 			SoapUI.logError( e );
389 		}
390 
391 		return 0;
392 	}
393 
394 	public ModelItem getModelItem()
395 	{
396 		return modelItem;
397 	}
398 
399 	public PropertyExpansion[] getPropertyExpansions()
400 	{
401 		List<PropertyExpansion> result = new ArrayList<PropertyExpansion>();
402 
403 		return result.toArray( new PropertyExpansion[result.size()] );
404 	}
405 
406 	public void moveProperty( String propertyName, int targetIndex )
407 	{
408 		PropertiesStepProperty property = getProperty( propertyName );
409 		int ix = properties.indexOf( property );
410 
411 		if( ix == targetIndex )
412 			return;
413 
414 		if( targetIndex < 0 )
415 			targetIndex = 0;
416 
417 		String value = property.getValue();
418 		config.removeProperty( ix );
419 
420 		PropertyConfig propertyConfig = null;
421 
422 		if( targetIndex < properties.size() )
423 		{
424 			properties.add( targetIndex, properties.remove( ix ) );
425 			propertyConfig = config.insertNewProperty( targetIndex );
426 		}
427 		else
428 		{
429 			properties.add( properties.remove( ix ) );
430 			propertyConfig = config.addNewProperty();
431 		}
432 
433 		propertyConfig.setName( propertyName );
434 		propertyConfig.setValue( value );
435 
436 		resetPropertiesConfig( config );
437 
438 		if( targetIndex > properties.size() )
439 			targetIndex = properties.size();
440 
441 		firePropertyMoved( propertyName, ix, targetIndex );
442 	}
443 
444 	public void clear()
445 	{
446 		while( size() > 0 )
447 			removeProperty( getPropertyAt( 0 ).getName() );
448 	}
449 
450 	public boolean containsKey( Object key )
451 	{
452 		return hasProperty( ( String )key );
453 	}
454 
455 	public boolean containsValue( Object value )
456 	{
457 		return propertyMap.containsValue( value );
458 	}
459 
460 	public Set<java.util.Map.Entry<String, TestProperty>> entrySet()
461 	{
462 		HashSet<java.util.Map.Entry<String, TestProperty>> result = new HashSet<Entry<String, TestProperty>>();
463 
464 		for( TestProperty p : propertyMap.values() )
465 		{
466 			// This does not compile on JDK 1.5:
467 			// result.add( new java.util.HashMap.SimpleEntry<String,
468 			// TestProperty>(p.getName(), p));
469 			result.add( new HashMapEntry<String, TestProperty>( p.getName(), p ) );
470 		}
471 
472 		return result;
473 	}
474 
475 	private static class HashMapEntry<K, V> implements java.util.Map.Entry<K, V>
476 	{
477 		private K key;
478 		private V value;
479 
480 		public HashMapEntry( K key, V value )
481 		{
482 			this.key = key;
483 			this.value = value;
484 		}
485 
486 		public K getKey()
487 		{
488 			return key;
489 		}
490 
491 		public V getValue()
492 		{
493 			return value;
494 		}
495 
496 		public V setValue( V value )
497 		{
498 			throw new UnsupportedOperationException();
499 		}
500 	}
501 
502 	public TestProperty get( Object key )
503 	{
504 		return getProperty( ( String )key );
505 	}
506 
507 	public boolean isEmpty()
508 	{
509 		return propertyMap.isEmpty();
510 	}
511 
512 	public Set<String> keySet()
513 	{
514 		return new HashSet<String>( Arrays.asList( getPropertyNames() ) );
515 	}
516 
517 	public TestProperty put( String key, TestProperty value )
518 	{
519 		TestProperty result = addProperty( key );
520 		result.setValue( value.getValue() );
521 		return result;
522 	}
523 
524 	public void putAll( Map<? extends String, ? extends TestProperty> m )
525 	{
526 		for( TestProperty p : m.values() )
527 		{
528 			addProperty( p.getName() ).setValue( p.getValue() );
529 		}
530 	}
531 
532 	public TestProperty remove( Object key )
533 	{
534 		return removeProperty( ( String )key );
535 	}
536 
537 	public int size()
538 	{
539 		return propertyMap.size();
540 	}
541 
542 	public Collection<TestProperty> values()
543 	{
544 		ArrayList<TestProperty> result = new ArrayList<TestProperty>();
545 		result.addAll( propertyMap.values() );
546 		return result;
547 	}
548 
549 	public String getPropertiesLabel()
550 	{
551 		return propertiesLabel;
552 	}
553 
554 	public void setPropertiesLabel( String propertiesLabel )
555 	{
556 		this.propertiesLabel = propertiesLabel;
557 	}
558 }