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