1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 package ifc.beans;
29 
30 import java.util.Vector;
31 
32 import lib.MultiMethodTest;
33 import util.ValueChanger;
34 import util.utils;
35 
36 import com.sun.star.beans.Property;
37 import com.sun.star.beans.PropertyAttribute;
38 import com.sun.star.beans.PropertyChangeEvent;
39 import com.sun.star.beans.XPropertyChangeListener;
40 import com.sun.star.beans.XPropertySet;
41 import com.sun.star.beans.XPropertySetInfo;
42 import com.sun.star.beans.XVetoableChangeListener;
43 import com.sun.star.lang.EventObject;
44 
45 /**
46 * Testing <code>com.sun.star.beans.XPropertySet</code>
47 * interface methods :
48 * <ul>
49 *  <li><code>getPropertySetInfo()</code></li>
50 *  <li><code>setPropertyValue()</code></li>
51 *  <li><code>getPropertyValue()</code></li>
52 *  <li><code>addPropertyChangeListener()</code></li>
53 *  <li><code>removePropertyChangeListener()</code></li>
54 *  <li><code>addVetoableChangeListener()</code></li>
55 *  <li><code>removeVetoableChangeListener()</code></li>
56 * </ul>
57 * @see com.sun.star.beans.XPropertySet
58 */
59 public class _XPropertySet extends MultiMethodTest {
60 
61     public XPropertySet oObj = null;
62 
63     /**
64     * Flag that indicates change listener was called.
65     */
66     private boolean propertyChanged = false;
67 
68     /**
69     * Listener that must be called on bound property changing.
70     */
71     public class MyChangeListener implements XPropertyChangeListener {
72          /**
73          * Just set <code>propertyChanged</code> flag to true.
74          */
75          public void propertyChange(PropertyChangeEvent e) {
76             propertyChanged = true;
77          }
78          public void disposing (EventObject obj) {}
79     };
80 
81     private final XPropertyChangeListener PClistener = new MyChangeListener();
82 
83     /**
84     * Flag that indicates veto listener was called.
85     */
86     private boolean vetoableChanged = false;
87 
88     /**
89     * Listener that must be called on constrained property changing.
90     */
91     public class MyVetoListener implements XVetoableChangeListener {
92          /**
93          * Just set <code>vetoableChanged</code> flag to true.
94          */
95          public void vetoableChange(PropertyChangeEvent e) {
96             vetoableChanged = true;
97          }
98          public void disposing (EventObject obj) {}
99     };
100 
101     private final XVetoableChangeListener VClistener = new MyVetoListener();
102 
103     /**
104     * Structure that collects the properties of different types to test :
105     * Constrained, Bound and Normal.
106     */
107     private final class PropsToTest {
108         Vector< String > constrained = new Vector< String >();
109         Vector< String > bound = new Vector< String >();
110         Vector< String > normal = new Vector< String >();
111     }
112 
113     private final PropsToTest PTT = new PropsToTest();
114 
115     /**
116     * Tests method <code>getPropertySetInfo</code>. After test completed
117     * call {@link #getPropsToTest} method to retrieve different kinds
118     * of properties to test then. <p>
119     * Has OK status if not null <code>XPropertySetInfo</code>
120     * object returned.<p>
121     * Since <code>getPropertySetInfo</code> is optional, it may return null,
122     * if it is not implemented. This method uses then an object relation
123     * <code>PTT</code> (Properties To Test) to determine available properties.
124     * All tests for services without <code>getPropertySetInfo</code> must
125     * provide this object relation.
126     */
127     public void _getPropertySetInfo() {
128 
129         XPropertySetInfo propertySetInfo = oObj.getPropertySetInfo();
130 
131         if (propertySetInfo == null) {
132             log.println("getPropertySetInfo() method returned null");
133             tRes.tested("getPropertySetInfo()", true) ;
134             String[] ptt = (String[]) tEnv.getObjRelation("PTT");
135             PTT.normal.clear();
136             PTT.bound.clear();
137             PTT.constrained.clear();
138             PTT.normal.add( ptt[0] );
139             PTT.bound.add( ptt[1] );
140             PTT.constrained.add( ptt[2] );
141         } else {
142             tRes.tested("getPropertySetInfo()", true );
143             getPropsToTest(propertySetInfo);
144         }
145 
146         return;
147 
148     } // end of getPropertySetInfo()
149 
150     /**
151     * Tests change listener which added for bound properties.
152     * Adds listener to bound property (if it exists), then changes
153     * its value and check if listener was called. <p>
154     * Method tests to be successfully completed before :
155     * <ul>
156     *  <li> <code>getPropertySetInfo</code> : in this method test
157     *    one of bound properties is retrieved. </li>
158     * </ul> <p>
159     * Has OK status if NO bound properties exist or if listener
160     * was successfully called.
161     */
162     public void _addPropertyChangeListener() {
163 
164         requiredMethod("getPropertySetInfo()");
165 
166         int count = PTT.bound.size();
167         if ( count==0 || PTT.bound.get(0).equals("none") ) {
168             log.println("*** No bound properties found ***");
169             tRes.tested("addPropertyChangeListener()", true) ;
170         } else {
171             boolean error = false;
172             for (int i = 0; i < count; i++) {
173                 String propertyName = PTT.bound.get(i);
174                 propertyChanged = false;
175                 try {
176                     oObj.addPropertyChangeListener(propertyName,PClistener);
177                     Object gValue = oObj.getPropertyValue(propertyName);
178                     log.println("Check bound property: " + propertyName );
179                     oObj.setPropertyValue(propertyName,
180                         ValueChanger.changePValue(gValue));
181                 } catch (com.sun.star.beans.PropertyVetoException e) {
182                     log.println("Exception occured while trying to change "+
183                         "property '"+ propertyName+"'");
184                     e.printStackTrace(log);
185                 } catch (com.sun.star.lang.IllegalArgumentException e) {
186                     log.println("Exception occured while trying to change "+
187                         "property '"+ propertyName+"'");
188                     e.printStackTrace(log);
189                 } catch (com.sun.star.beans.UnknownPropertyException e) {
190                     log.println("Exception occured while trying to change "+
191                         "property '"+ propertyName+"'");
192                     e.printStackTrace(log);
193                 } catch (com.sun.star.lang.WrappedTargetException e) {
194                     log.println("Exception occured while trying to change "+
195                         "property '"+ propertyName+"'");
196                     e.printStackTrace(log);
197                 } // end of try-catch
198                 error = error || !propertyChanged;
199                 if (!propertyChanged) {
200                     log.println("propertyChangeListener wasn't called for '"+
201                         propertyName+"'");
202                 }
203             }
204             tRes.tested("addPropertyChangeListener()", !error);
205         }
206 
207         return;
208 
209     } // end of addPropertyChangeListener()
210 
211     /**
212     * Tests vetoable listener which added for constrained properties.
213     * Adds listener to constrained property (if it exists), then changes
214     * its value and check if listener was called. <p>
215     * Method tests to be successfully completed before :
216     * <ul>
217     *  <li> <code>getPropertySetInfo</code> : in this method test
218     *    one of constrained properties is retrieved. </li>
219     * </ul> <p>
220     * Has OK status if NO constrained properties exist or if listener
221     * was successfully called.
222     */
223     public void _addVetoableChangeListener() {
224 
225         requiredMethod("getPropertySetInfo()");
226 
227         int count = PTT.constrained.size();
228         if ( count==0 || PTT.constrained.get(0).equals("none") ) {
229             log.println("*** No constrained properties found ***");
230             tRes.tested("addVetoableChangeListener()", true) ;
231         } else {
232             boolean error = false;
233             for (int i = 0; i < count; i++) {
234                 String propertyName = PTT.constrained.get(i);
235                 vetoableChanged = false;
236                 try {
237                     oObj.addVetoableChangeListener(propertyName,VClistener);
238                     Object gValue = oObj.getPropertyValue(propertyName);
239                     oObj.setPropertyValue(propertyName,
240                         ValueChanger.changePValue(gValue));
241                 } catch (com.sun.star.beans.PropertyVetoException e) {
242                     log.println("Exception occured while trying to change "+
243                         "property '"+ propertyName+"'");
244                     e.printStackTrace(log);
245                 } catch (com.sun.star.lang.IllegalArgumentException e) {
246                     log.println("Exception occured while trying to change "+
247                         "property '"+ propertyName+"'");
248                     e.printStackTrace(log);
249                 } catch (com.sun.star.beans.UnknownPropertyException e) {
250                     log.println("Exception occured while trying to change "+
251                         "property '"+ propertyName+"'");
252                     e.printStackTrace(log);
253                 } catch (com.sun.star.lang.WrappedTargetException e) {
254                     log.println("Exception occured while trying to change "+
255                         "property '"+ propertyName+"'");
256                     e.printStackTrace(log);
257                 } // end of try-catch
258                 error = error || !vetoableChanged;
259                 if (!vetoableChanged) {
260                     log.println("vetoableChangeListener wasn't called for '"+
261                         propertyName+"'");
262                 }
263             }
264             tRes.tested("addVetoableChangeListener()",!error);
265         }
266 
267         return;
268 
269     } // end of addVetoableChangeListener()
270 
271 
272     /**
273     * Tests <code>setPropertyValue</code> method.
274     * Stores value before call, and compares it with value after
275     * call. <p>
276     * Method tests to be successfully completed before :
277     * <ul>
278     *  <li> <code>getPropertySetInfo</code> : in this method test
279     *    one of normal properties is retrieved. </li>
280     * </ul> <p>
281     * Has OK status if NO normal properties exist or if value before
282     * method call is not equal to value after.
283     */
284     public void _setPropertyValue() {
285 
286         requiredMethod("getPropertySetInfo()");
287 
288         Object gValue = null;
289         Object sValue = null;
290 
291         int count = PTT.normal.size();
292         if ( count==0 || PTT.normal.get(0).equals("none") ) {
293             log.println("*** No changeable properties found ***");
294             tRes.tested("setPropertyValue()", true) ;
295         } else {
296             boolean error = false;
297             for (int i = 0; i < count; i++) {
298                 String propertyName = PTT.normal.get(i);
299                 try {
300                     log.println("try to change value of property '" + propertyName + "'" );
301                     gValue = oObj.getPropertyValue(propertyName);
302                     sValue = ValueChanger.changePValue(gValue);
303                     oObj.setPropertyValue(propertyName, sValue);
304                     sValue = oObj.getPropertyValue(propertyName);
305                 } catch (com.sun.star.beans.PropertyVetoException e) {
306                     log.println("Exception occured while trying to change "+
307                         "property '"+ propertyName+"'");
308                     e.printStackTrace(log);
309                 } catch (com.sun.star.lang.IllegalArgumentException e) {
310                     log.println("Exception occured while trying to change "+
311                         "property '"+ propertyName+"'");
312                     e.printStackTrace(log);
313                 } catch (com.sun.star.beans.UnknownPropertyException e) {
314                     log.println("Exception occured while trying to change "+
315                         "property '"+ propertyName+"'");
316                     e.printStackTrace(log);
317                 } catch (com.sun.star.lang.WrappedTargetException e) {
318                     log.println("Exception occured while trying to change "+
319                         "property '"+ propertyName+"'");
320                     e.printStackTrace(log);
321                 } // end of try-catch
322                 if( gValue.equals(sValue) )
323                 {
324                     log.println("setting property '"+ propertyName+"' failed");
325                     error = true;
326                 }
327             }
328             tRes.tested("setPropertyValue()",!error);
329         } //endif
330 
331         return;
332 
333     } // end of setPropertyValue()
334 
335     /**
336     * Tests <code>getPropertyValue</code> method for the given property.
337     * Returns true if no exceptions occured
338     */
339     private boolean getSinglePropertyValue( String propertyName )
340     {
341         boolean runOk = false;
342         try {
343             oObj.getPropertyValue(propertyName);
344             runOk = true;
345         } catch (com.sun.star.beans.UnknownPropertyException e) {
346             log.println("Exception occured while trying to get property '"+
347                  propertyName+"'");
348             e.printStackTrace(log);
349         } catch (com.sun.star.lang.WrappedTargetException e) {
350             log.println("Exception occured while trying to get property '"+
351                 propertyName+"'");
352             e.printStackTrace(log);
353         }
354         return runOk;
355     }
356 
357     /**
358     * Tests <code>getPropertyValue</code> method.
359     * Just call this method and checks for no exceptions <p>
360     * Method tests to be successfully completed before :
361     * <ul>
362     *  <li> <code>getPropertySetInfo</code> : in this method test
363     *    one of normal properties is retrieved. </li>
364     * </ul> <p>
365     * Has OK status if NO normal properties exist or if no
366     * exceptions were thrown.
367     */
368     public void _getPropertyValue() {
369 
370         requiredMethod("getPropertySetInfo()");
371 
372         int count = PTT.normal.size();
373         if ( count==0 || PTT.normal.get(0).equals("none") ) {
374             Property[] properties = oObj.getPropertySetInfo().getProperties();
375             if( properties.length > 0 ) {
376                 String propertyName = properties[0].Name;
377                 log.println("All properties are Read Only");
378                 log.println("Using: "+propertyName);
379                 tRes.tested("getPropertyValue()", getSinglePropertyValue( propertyName ) );
380             }
381             else {
382                 log.println("*** No properties found ***");
383                 tRes.tested("getPropertyValue()", true) ;
384             }
385         } else {
386             boolean error = false;
387             for (int i = 0; i < count; i++) {
388                 String propertyName = PTT.normal.get(i);
389                 boolean runOk = getSinglePropertyValue( propertyName );
390                 if( !runOk )
391                 {
392                     error = true;
393                     log.println("getPropertyValue() failed for property '"+propertyName+"'");
394                 }
395             }
396             tRes.tested("getPropertyValue()", !error) ;
397         }
398 
399         return;
400     }
401 
402     /**
403     * Tests <code>removePropertyChangeListener</code> method.
404     * Removes change listener, then changes bound property value
405     * and checks if the listener was NOT called.
406     * Method tests to be successfully completed before :
407     * <ul>
408     *  <li> <code>addPropertyChangeListener</code> : here listener
409     *   was added. </li>
410     * </ul> <p>
411     * Has OK status if NO bound properties exist or if listener
412     * was not called and no exceptions arose.
413     */
414     public void _removePropertyChangeListener() {
415 
416         requiredMethod("addPropertyChangeListener()");
417 
418         int count = PTT.bound.size();
419         if ( count==0 || PTT.bound.get(0).equals("none") ) {
420             log.println("*** No bound properties found ***");
421             tRes.tested("removePropertyChangeListener()", true) ;
422         } else {
423 
424             //remove all listeners first
425             for (int i = 0; i < count; i++) {
426                 String propertyName = PTT.bound.get(i);
427                 try {
428                     oObj.removePropertyChangeListener(propertyName,PClistener);
429                 } catch (Exception e) {
430                     log.println("Exception occured while removing change listener from"+
431                         "property '"+ propertyName+"'");
432                     e.printStackTrace(log);
433                 }
434             }
435 
436             boolean error = false;
437             for (int i = 0; i < count; i++) {
438                 String propertyName = PTT.bound.get(i);
439                 try {
440                     propertyChanged = false;
441                     oObj.addPropertyChangeListener(propertyName,PClistener);
442                     oObj.removePropertyChangeListener(propertyName,PClistener);
443                     Object gValue = oObj.getPropertyValue(propertyName);
444                     oObj.setPropertyValue(propertyName,
445                         ValueChanger.changePValue(gValue));
446                 } catch (com.sun.star.beans.PropertyVetoException e) {
447                     log.println("Exception occured while trying to change "+
448                         "property '"+ propertyName+"'");
449                     e.printStackTrace(log);
450                 } catch (com.sun.star.lang.IllegalArgumentException e) {
451                     log.println("Exception occured while trying to change "+
452                         "property '"+ propertyName+"'");
453                     e.printStackTrace(log);
454                 } catch (com.sun.star.beans.UnknownPropertyException e) {
455                     log.println("Exception occured while trying to change "+
456                         "property '"+ propertyName+"'");
457                     e.printStackTrace(log);
458                 } catch (com.sun.star.lang.WrappedTargetException e) {
459                     log.println("Exception occured while trying to change "+
460                         "property '"+ propertyName+"'");
461                     e.printStackTrace(log);
462                 } // end of try-catch
463 
464                 error = error || propertyChanged;
465                 if (propertyChanged) {
466                     log.println("propertyChangeListener was called after removing"+
467                         " for '"+propertyName+"'");
468                 }
469             }
470             tRes.tested("removePropertyChangeListener()",!error);
471         }
472 
473         return;
474 
475     } // end of removePropertyChangeListener()
476 
477 
478     /**
479     * Tests <code>removeVetoableChangeListener</code> method.
480     * Removes vetoable listener, then changes constrained property value
481     * and checks if the listener was NOT called.
482     * Method tests to be successfully completed before :
483     * <ul>
484     *  <li> <code>addPropertyChangeListener</code> : here vetoable listener
485     *   was added. </li>
486     * </ul> <p>
487     * Has OK status if NO constrained properties exist or if listener
488     * was NOT called and no exceptions arose.
489     */
490     public void _removeVetoableChangeListener() {
491 
492         requiredMethod("addVetoableChangeListener()");
493 
494         int count = PTT.constrained.size();
495         if ( count==0 || PTT.constrained.get(0).equals("none") ) {
496             log.println("*** No constrained properties found ***");
497             tRes.tested("removeVetoableChangeListener()", true) ;
498         } else {
499 
500             //remove all listeners first
501             for (int i = 0; i < count; i++) {
502                 String propertyName = PTT.constrained.get(i);
503                 try {
504                     oObj.removeVetoableChangeListener(propertyName,VClistener);
505                 } catch (Exception e) {
506                     log.println("Exception occured while removing veto listener from"+
507                         "property '"+ propertyName+"'");
508                     e.printStackTrace(log);
509                 }
510             }
511 
512             boolean error = false;
513             for (int i = 0; i < count; i++) {
514                 String propertyName = PTT.constrained.get(i);
515                 vetoableChanged = false;
516                 try {
517                     oObj.addVetoableChangeListener(propertyName,VClistener);
518                     oObj.removeVetoableChangeListener(propertyName,VClistener);
519                     Object gValue = oObj.getPropertyValue(propertyName);
520                     oObj.setPropertyValue(propertyName,
521                         ValueChanger.changePValue(gValue));
522                 } catch (com.sun.star.beans.PropertyVetoException e) {
523                     log.println("Exception occured while trying to change "+
524                         "property '"+ propertyName+"'");
525                     e.printStackTrace(log);
526                 } catch (com.sun.star.lang.IllegalArgumentException e) {
527                     log.println("Exception occured while trying to change "+
528                         "property '"+ propertyName+"'");
529                     e.printStackTrace(log);
530                 } catch (com.sun.star.beans.UnknownPropertyException e) {
531                     log.println("Exception occured while trying to change "+
532                         "property '"+ propertyName+"'");
533                     e.printStackTrace(log);
534                 } catch (com.sun.star.lang.WrappedTargetException e) {
535                     log.println("Exception occured while trying to change "+
536                         "property '"+ propertyName+"'");
537                     e.printStackTrace(log);
538                 } // end of try-catch
539                 error = error || vetoableChanged;
540                 if (vetoableChanged) {
541                     log.println("vetoableChangeListener was called after "+
542                         "removing for '"+propertyName+"'");
543                 }
544             }
545             tRes.tested("removeVetoableChangeListener()",!error);
546         }
547 
548         return;
549 
550     } // end of removeVetoableChangeListener()
551 
552     /**
553     * Gets the properties being tested. Searches and stores by one
554     * property of each kind (Bound, Vetoable, Normal).
555     */
556     public void getPropsToTest(XPropertySetInfo xPSI) {
557 
558         Property[] properties = xPSI.getProperties();
559         // some properties should not be changed in a unspecific way
560         String[] skip = {"PrinterName", "CharRelief", "IsLayerMode"};
561 
562         for (int i = 0; i < properties.length; i++) {
563 
564             Property property = properties[i];
565             String name = property.Name;
566 
567             boolean cont = false;
568             for (int j = 0; j < skip.length; j++) {
569                 if (name.equals(skip[j])){
570                     log.println("skipping '" + name + "'");
571                     cont = true;
572                 }
573             }
574 
575             if (cont) continue;
576 
577             if (name.equals(oObj))
578             log.println("Checking '"+name+"'");
579             boolean isWritable = ((property.Attributes &
580                 PropertyAttribute.READONLY) == 0);
581             boolean isNotNull = ((property.Attributes &
582                 PropertyAttribute.MAYBEVOID) == 0);
583             boolean isBound = ((property.Attributes &
584                 PropertyAttribute.BOUND) != 0);
585             boolean isConstr = ((property.Attributes &
586                 PropertyAttribute.CONSTRAINED) != 0);
587             boolean canChange = false;
588 
589             if ( !isWritable ) log.println("Property '"+name+"' is READONLY");
590 
591             if (name.endsWith("URL")) isWritable = false;
592             if (name.startsWith("Fill")) isWritable = false;
593             if (name.startsWith("Font")) isWritable = false;
594             if (name.startsWith("IsNumbering")) isWritable = false;
595             if (name.startsWith("LayerName")) isWritable = false;
596             if (name.startsWith("Line")) isWritable = false;
597             if (name.startsWith("TextWriting")) isWritable = false;
598 
599             //if (name.equals("xinterfaceA") || name.equals("xtypeproviderA")
600             //|| name.equals("arAnyA")) isWritable=false;
601 
602             if ( isWritable && isNotNull ) canChange = isChangeable(name);
603 
604             if ( isWritable && isNotNull && isBound && canChange) {
605                 PTT.bound.add(name);
606             }
607 
608             if ( isWritable && isNotNull && isConstr && canChange) {
609                 PTT.constrained.add(name);
610             }
611 
612             if ( isWritable && isNotNull && canChange) {
613                 PTT.normal.add(name);
614             }
615 
616 
617         } // endfor
618     }
619 
620     public boolean isChangeable(String name) {
621         boolean hasChanged = false;
622         try {
623             Object getProp = oObj.getPropertyValue(name);
624             log.println("Getting: "+getProp);
625             if (name.equals("xinterfaceA")) {
626                 System.out.println("drin");
627             }
628 
629             Object setValue = null;
630             if (getProp != null) {
631                 if (!utils.isVoid(getProp))
632                     setValue = ValueChanger.changePValue(getProp);
633                 else log.println("Property '"+name+
634                     "' is void but MAYBEVOID isn't set");
635             } else log.println("Property '"+name+"'is null and can't be changed");
636             if (name.equals("LineStyle")) setValue = null;
637             if (setValue != null) {
638                 log.println("Setting to :"+setValue);
639                 oObj.setPropertyValue(name, setValue);
640                 hasChanged = (! getProp.equals(oObj.getPropertyValue(name)));
641             } else log.println("Couldn't change Property '"+name+"'");
642         } catch (com.sun.star.beans.PropertyVetoException e) {
643             log.println("'" + name + "' throws exception '" + e + "'");
644             e.printStackTrace(log);
645         } catch (com.sun.star.lang.IllegalArgumentException e) {
646             log.println("'" + name + "' throws exception '" + e + "'");
647             e.printStackTrace(log);
648         } catch (com.sun.star.beans.UnknownPropertyException e) {
649             log.println("'" + name + "' throws exception '" + e + "'");
650             e.printStackTrace(log);
651         } catch (com.sun.star.lang.WrappedTargetException e) {
652             log.println("'" + name + "' throws exception '" + e + "'");
653             e.printStackTrace(log);
654         } catch (com.sun.star.uno.RuntimeException e) {
655             log.println("'" + name + "' throws exception '" + e + "'");
656             e.printStackTrace(log);
657         } catch (java.lang.ArrayIndexOutOfBoundsException e) {
658             log.println("'" + name + "' throws exception '" + e + "'");
659             e.printStackTrace(log);
660         }
661 
662         return hasChanged;
663     }
664 
665     /**
666     * Forces environment recreation.
667     */
668     protected void after() {
669         disposeEnvironment();
670     }
671 
672 
673 }  // finish class _XPropertySet
674 
675