1*cdf0e10cSrcweir /*************************************************************************
2*cdf0e10cSrcweir  *
3*cdf0e10cSrcweir  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4*cdf0e10cSrcweir  *
5*cdf0e10cSrcweir  * Copyright 2000, 2010 Oracle and/or its affiliates.
6*cdf0e10cSrcweir  *
7*cdf0e10cSrcweir  * OpenOffice.org - a multi-platform office productivity suite
8*cdf0e10cSrcweir  *
9*cdf0e10cSrcweir  * This file is part of OpenOffice.org.
10*cdf0e10cSrcweir  *
11*cdf0e10cSrcweir  * OpenOffice.org is free software: you can redistribute it and/or modify
12*cdf0e10cSrcweir  * it under the terms of the GNU Lesser General Public License version 3
13*cdf0e10cSrcweir  * only, as published by the Free Software Foundation.
14*cdf0e10cSrcweir  *
15*cdf0e10cSrcweir  * OpenOffice.org is distributed in the hope that it will be useful,
16*cdf0e10cSrcweir  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17*cdf0e10cSrcweir  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18*cdf0e10cSrcweir  * GNU Lesser General Public License version 3 for more details
19*cdf0e10cSrcweir  * (a copy is included in the LICENSE file that accompanied this code).
20*cdf0e10cSrcweir  *
21*cdf0e10cSrcweir  * You should have received a copy of the GNU Lesser General Public License
22*cdf0e10cSrcweir  * version 3 along with OpenOffice.org.  If not, see
23*cdf0e10cSrcweir  * <http://www.openoffice.org/license.html>
24*cdf0e10cSrcweir  * for a copy of the LGPLv3 License.
25*cdf0e10cSrcweir  *
26*cdf0e10cSrcweir  ************************************************************************/
27*cdf0e10cSrcweir 
28*cdf0e10cSrcweir package ifc.beans;
29*cdf0e10cSrcweir 
30*cdf0e10cSrcweir import java.io.PrintWriter;
31*cdf0e10cSrcweir import java.util.HashSet;
32*cdf0e10cSrcweir import java.util.Set;
33*cdf0e10cSrcweir import java.util.StringTokenizer;
34*cdf0e10cSrcweir 
35*cdf0e10cSrcweir import lib.MultiMethodTest;
36*cdf0e10cSrcweir import lib.Status;
37*cdf0e10cSrcweir import util.ValueChanger;
38*cdf0e10cSrcweir 
39*cdf0e10cSrcweir import com.sun.star.beans.Property;
40*cdf0e10cSrcweir import com.sun.star.beans.PropertyAttribute;
41*cdf0e10cSrcweir import com.sun.star.beans.PropertyChangeEvent;
42*cdf0e10cSrcweir import com.sun.star.beans.XMultiPropertySet;
43*cdf0e10cSrcweir import com.sun.star.beans.XPropertiesChangeListener;
44*cdf0e10cSrcweir import com.sun.star.beans.XPropertySetInfo;
45*cdf0e10cSrcweir import com.sun.star.lang.EventObject;
46*cdf0e10cSrcweir 
47*cdf0e10cSrcweir 
48*cdf0e10cSrcweir /**
49*cdf0e10cSrcweir * Testing <code>com.sun.star.beans.XMultiPropertySet</code>
50*cdf0e10cSrcweir * interface methods :
51*cdf0e10cSrcweir * <ul>
52*cdf0e10cSrcweir *  <li><code> getPropertySetInfo()</code></li>
53*cdf0e10cSrcweir *  <li><code> setPropertyValues()</code></li>
54*cdf0e10cSrcweir *  <li><code> getPropertyValues()</code></li>
55*cdf0e10cSrcweir *  <li><code> addPropertiesChangeListener()</code></li>
56*cdf0e10cSrcweir *  <li><code> removePropertiesChangeListener()</code></li>
57*cdf0e10cSrcweir *  <li><code> firePropertiesChangeEvent()</code></li>
58*cdf0e10cSrcweir * </ul> <p>
59*cdf0e10cSrcweir *
60*cdf0e10cSrcweir * Required relations :
61*cdf0e10cSrcweir * <ul>
62*cdf0e10cSrcweir *  <li> <code>'XMultiPropertySet.ExcludeProps'</code>
63*cdf0e10cSrcweir *    <b>(optional) </b> : java.util.Set.
64*cdf0e10cSrcweir *    Has property names which must be skipped from testing in
65*cdf0e10cSrcweir *    some reasons (for example property accepts restricted set
66*cdf0e10cSrcweir *    of values).
67*cdf0e10cSrcweir *  </li>
68*cdf0e10cSrcweir * <ul> <p>
69*cdf0e10cSrcweir *
70*cdf0e10cSrcweir * Test is <b> NOT </b> multithread compilant. <p>
71*cdf0e10cSrcweir * After test completion object environment has to be recreated.
72*cdf0e10cSrcweir * @see com.sun.star.beans.XMultiPropertySet
73*cdf0e10cSrcweir */
74*cdf0e10cSrcweir public class _XMultiPropertySet extends MultiMethodTest {
75*cdf0e10cSrcweir 
76*cdf0e10cSrcweir     public XMultiPropertySet oObj = null;
77*cdf0e10cSrcweir 
78*cdf0e10cSrcweir     private boolean propertiesChanged = false;
79*cdf0e10cSrcweir     private XPropertySetInfo propertySetInfo = null;
80*cdf0e10cSrcweir     private String [] testPropsNames = null;
81*cdf0e10cSrcweir     private int testPropsAmount = 0;
82*cdf0e10cSrcweir     private PrintWriter _log = null;
83*cdf0e10cSrcweir 
84*cdf0e10cSrcweir     private Object[] values = null;
85*cdf0e10cSrcweir 
86*cdf0e10cSrcweir     private Set exclProps = null;
87*cdf0e10cSrcweir 
88*cdf0e10cSrcweir     /**
89*cdf0e10cSrcweir     * Initializes some fields.
90*cdf0e10cSrcweir     */
91*cdf0e10cSrcweir     public void before() {
92*cdf0e10cSrcweir         _log = log;
93*cdf0e10cSrcweir 
94*cdf0e10cSrcweir         exclProps = (Set) tEnv.getObjRelation("XMultiPropertySet.ExcludeProps");
95*cdf0e10cSrcweir         if (exclProps == null) exclProps = new HashSet(0);
96*cdf0e10cSrcweir     }
97*cdf0e10cSrcweir 
98*cdf0e10cSrcweir     /**
99*cdf0e10cSrcweir     * Listener implementation which sets a flag when
100*cdf0e10cSrcweir     * listener was called.
101*cdf0e10cSrcweir     */
102*cdf0e10cSrcweir     public class MyChangeListener implements XPropertiesChangeListener {
103*cdf0e10cSrcweir          public void propertiesChange(PropertyChangeEvent[] e) {
104*cdf0e10cSrcweir              //_log.println("Listener was called");
105*cdf0e10cSrcweir              propertiesChanged = true;
106*cdf0e10cSrcweir          }
107*cdf0e10cSrcweir          public void disposing (EventObject obj) {}
108*cdf0e10cSrcweir     };
109*cdf0e10cSrcweir 
110*cdf0e10cSrcweir     private XPropertiesChangeListener PClistener =
111*cdf0e10cSrcweir         new MyChangeListener();
112*cdf0e10cSrcweir 
113*cdf0e10cSrcweir     /**
114*cdf0e10cSrcweir     * Test calls the method and checks return value.
115*cdf0e10cSrcweir     * <code>PropertySetInfo</code> object is stored<p>
116*cdf0e10cSrcweir     * Has <b> OK </b> status if the method returns not null value
117*cdf0e10cSrcweir     * and no exceptions were thrown. <p>
118*cdf0e10cSrcweir     */
119*cdf0e10cSrcweir     public void _getPropertySetInfo() {
120*cdf0e10cSrcweir         boolean bResult = true;
121*cdf0e10cSrcweir         propertySetInfo = oObj.getPropertySetInfo();
122*cdf0e10cSrcweir 
123*cdf0e10cSrcweir         if (propertySetInfo == null) {
124*cdf0e10cSrcweir             log.println("getPropertySetInfo() method returned null");
125*cdf0e10cSrcweir             bResult = false;
126*cdf0e10cSrcweir         }
127*cdf0e10cSrcweir 
128*cdf0e10cSrcweir         tRes.tested("getPropertySetInfo()", bResult) ;
129*cdf0e10cSrcweir     }
130*cdf0e10cSrcweir 
131*cdf0e10cSrcweir 
132*cdf0e10cSrcweir     /**
133*cdf0e10cSrcweir     * Test collects all property names and retrieves their values,
134*cdf0e10cSrcweir     * then checks the value returned. Finally it also collects
135*cdf0e10cSrcweir     * bound properties for other methods tests.<p>
136*cdf0e10cSrcweir     * Has <b> OK </b> status if the method  returns non null value
137*cdf0e10cSrcweir     * and no exceptions were thrown. <p>
138*cdf0e10cSrcweir     * The following method tests are to be completed successfully before :
139*cdf0e10cSrcweir     * <ul>
140*cdf0e10cSrcweir     *  <li> <code> getPropertySetInfo() </code> : to have a list
141*cdf0e10cSrcweir     *   of properties.</li>
142*cdf0e10cSrcweir     * </ul>
143*cdf0e10cSrcweir     */
144*cdf0e10cSrcweir     public void _getPropertyValues() {
145*cdf0e10cSrcweir         requiredMethod("getPropertySetInfo()");
146*cdf0e10cSrcweir         boolean bResult = true;
147*cdf0e10cSrcweir 
148*cdf0e10cSrcweir         Property[] properties = propertySetInfo.getProperties();
149*cdf0e10cSrcweir         String[] allnames = new String[properties.length];
150*cdf0e10cSrcweir         for (int i = 0; i < properties.length; i++) {
151*cdf0e10cSrcweir             allnames[i] = properties[i].Name;
152*cdf0e10cSrcweir         }
153*cdf0e10cSrcweir 
154*cdf0e10cSrcweir         values = oObj.getPropertyValues(allnames);
155*cdf0e10cSrcweir 
156*cdf0e10cSrcweir         bResult &= values!=null;
157*cdf0e10cSrcweir         tRes.tested("getPropertyValues()", bResult) ;
158*cdf0e10cSrcweir 
159*cdf0e10cSrcweir         getPropsToTest(properties);
160*cdf0e10cSrcweir     }
161*cdf0e10cSrcweir 
162*cdf0e10cSrcweir     /**
163*cdf0e10cSrcweir     * Test adds listener for all bound properties then each property
164*cdf0e10cSrcweir     * is changed and listener call . <p>
165*cdf0e10cSrcweir     * Has <b> OK </b> status if on each property change the listener was
166*cdf0e10cSrcweir     * called and no exceptions were thrown. <p>
167*cdf0e10cSrcweir     * The following method tests are to be completed successfully before :
168*cdf0e10cSrcweir     * <ul>
169*cdf0e10cSrcweir     *  <li> <code> getPropertyValues() </code> : to collect bound
170*cdf0e10cSrcweir     *   properties.</li>
171*cdf0e10cSrcweir     * </ul>
172*cdf0e10cSrcweir     */
173*cdf0e10cSrcweir     public void _addPropertiesChangeListener() {
174*cdf0e10cSrcweir 
175*cdf0e10cSrcweir         requiredMethod("getPropertyValues()");
176*cdf0e10cSrcweir 
177*cdf0e10cSrcweir         boolean result  = true ;
178*cdf0e10cSrcweir         // Creating listener
179*cdf0e10cSrcweir         oObj.addPropertiesChangeListener(testPropsNames, PClistener);
180*cdf0e10cSrcweir 
181*cdf0e10cSrcweir         if ((testPropsAmount==1) && (testPropsNames[0].equals("none"))) {
182*cdf0e10cSrcweir             testPropsAmount = 0;
183*cdf0e10cSrcweir         }
184*cdf0e10cSrcweir 
185*cdf0e10cSrcweir 
186*cdf0e10cSrcweir         // Change one of the property to be sure, that this event was cauched.
187*cdf0e10cSrcweir         //Random rnd = new Random();
188*cdf0e10cSrcweir         //int idx = rnd.nextInt(testPropsAmount);
189*cdf0e10cSrcweir         for (int i=0; i<testPropsAmount;i++) {
190*cdf0e10cSrcweir             log.print("Trying to change property " + testPropsNames[i]);
191*cdf0e10cSrcweir             try {
192*cdf0e10cSrcweir                 Object[] gValues = oObj.getPropertyValues(testPropsNames);
193*cdf0e10cSrcweir                 Object newValue = ValueChanger.changePValue(gValues[i]);
194*cdf0e10cSrcweir                 gValues[i] = newValue;
195*cdf0e10cSrcweir                 propertiesChanged = false;
196*cdf0e10cSrcweir                 oObj.setPropertyValues(testPropsNames, gValues);
197*cdf0e10cSrcweir                 waitAMoment() ;
198*cdf0e10cSrcweir                 result &= propertiesChanged ;
199*cdf0e10cSrcweir                 log.println(" ... done");
200*cdf0e10cSrcweir             } catch (com.sun.star.beans.PropertyVetoException e) {
201*cdf0e10cSrcweir                 log.println("Exception occured while trying to change "+
202*cdf0e10cSrcweir                     "property '"+testPropsNames[i] + "' :" + e);
203*cdf0e10cSrcweir                 e.printStackTrace(log);
204*cdf0e10cSrcweir             } catch (com.sun.star.lang.IllegalArgumentException e) {
205*cdf0e10cSrcweir                 log.println("Exception occured while trying to change "+
206*cdf0e10cSrcweir                     "property '"+testPropsNames[i] + "' :" + e);
207*cdf0e10cSrcweir                 e.printStackTrace(log);
208*cdf0e10cSrcweir             } catch (com.sun.star.lang.WrappedTargetException e) {
209*cdf0e10cSrcweir                 log.println("Exception occured while trying to change "+
210*cdf0e10cSrcweir                     "property '"+testPropsNames[i] + "' :" + e);
211*cdf0e10cSrcweir                 e.printStackTrace(log);
212*cdf0e10cSrcweir             } // end of try-catch
213*cdf0e10cSrcweir         }
214*cdf0e10cSrcweir         if (testPropsAmount == 0) {
215*cdf0e10cSrcweir             log.println("all properties are read only");
216*cdf0e10cSrcweir             tRes.tested("addPropertiesChangeListener()", Status.skipped(true));
217*cdf0e10cSrcweir         } else {
218*cdf0e10cSrcweir             tRes.tested("addPropertiesChangeListener()", propertiesChanged);
219*cdf0e10cSrcweir         }
220*cdf0e10cSrcweir     }
221*cdf0e10cSrcweir 
222*cdf0e10cSrcweir     /**
223*cdf0e10cSrcweir     * Calls method and check if listener was called. <p>
224*cdf0e10cSrcweir     * Has <b> OK </b> status if the listener was
225*cdf0e10cSrcweir     * called and no exceptions were thrown. <p>
226*cdf0e10cSrcweir     * The following method tests are to be completed successfully before :
227*cdf0e10cSrcweir     * <ul>
228*cdf0e10cSrcweir     *  <li> <code> addPropertiesChangeListener() </code> : listener to
229*cdf0e10cSrcweir     *    be added.</li>
230*cdf0e10cSrcweir     * </ul>
231*cdf0e10cSrcweir     */
232*cdf0e10cSrcweir     public void _firePropertiesChangeEvent() {
233*cdf0e10cSrcweir         requiredMethod("addPropertiesChangeListener()");
234*cdf0e10cSrcweir         propertiesChanged = false ;
235*cdf0e10cSrcweir 
236*cdf0e10cSrcweir         oObj.firePropertiesChangeEvent(testPropsNames, PClistener);
237*cdf0e10cSrcweir         waitAMoment() ;
238*cdf0e10cSrcweir 
239*cdf0e10cSrcweir         tRes.tested("firePropertiesChangeEvent()", propertiesChanged);
240*cdf0e10cSrcweir     }
241*cdf0e10cSrcweir 
242*cdf0e10cSrcweir 
243*cdf0e10cSrcweir     /**
244*cdf0e10cSrcweir     * Removes listener added before. <p>
245*cdf0e10cSrcweir     * Has <b> OK </b> status no exceptions were thrown. <p>
246*cdf0e10cSrcweir     * The following method tests are to be completed successfully before :
247*cdf0e10cSrcweir     * <ul>
248*cdf0e10cSrcweir     *  <li> <code> addPropertiesChangeListener() </code> : listener to
249*cdf0e10cSrcweir     *    be added.</li>
250*cdf0e10cSrcweir     * </ul>
251*cdf0e10cSrcweir     */
252*cdf0e10cSrcweir     public void _removePropertiesChangeListener() {
253*cdf0e10cSrcweir         requiredMethod("firePropertiesChangeEvent()");
254*cdf0e10cSrcweir         boolean bResult = true;
255*cdf0e10cSrcweir 
256*cdf0e10cSrcweir         oObj.removePropertiesChangeListener(PClistener);
257*cdf0e10cSrcweir 
258*cdf0e10cSrcweir         tRes.tested("removePropertiesChangeListener()", bResult);
259*cdf0e10cSrcweir     }
260*cdf0e10cSrcweir 
261*cdf0e10cSrcweir 
262*cdf0e10cSrcweir     /**
263*cdf0e10cSrcweir     * Changes all properties, then set them to new values, get them
264*cdf0e10cSrcweir     * and checks if their values were changed properly. <p>
265*cdf0e10cSrcweir     * Has <b> OK </b> status if all properties properly changed
266*cdf0e10cSrcweir     * and no exceptions were thrown. <p>
267*cdf0e10cSrcweir     * The following method tests are to be completed successfully before :
268*cdf0e10cSrcweir     * <ul>
269*cdf0e10cSrcweir     *  <li> <code> getPropertyValues() </code> : to collect bound
270*cdf0e10cSrcweir     *   properties.</li>
271*cdf0e10cSrcweir     * </ul>
272*cdf0e10cSrcweir     */
273*cdf0e10cSrcweir     public void _setPropertyValues() {
274*cdf0e10cSrcweir         requiredMethod("getPropertyValues()");
275*cdf0e10cSrcweir         boolean bResult = true;
276*cdf0e10cSrcweir 
277*cdf0e10cSrcweir         if ((testPropsNames.length==1)&&(testPropsNames[0].equals("none"))) {
278*cdf0e10cSrcweir             log.println("all properties are readOnly");
279*cdf0e10cSrcweir             tRes.tested("setPropertyValues()",Status.skipped(true));
280*cdf0e10cSrcweir             return;
281*cdf0e10cSrcweir         }
282*cdf0e10cSrcweir 
283*cdf0e10cSrcweir         log.println("Changing all properties");
284*cdf0e10cSrcweir         Object[] gValues = oObj.getPropertyValues(testPropsNames);
285*cdf0e10cSrcweir         for (int i=0; i<testPropsAmount;i++) {
286*cdf0e10cSrcweir             Object oldValue = gValues[i];
287*cdf0e10cSrcweir             Object newValue = ValueChanger.changePValue(oldValue);
288*cdf0e10cSrcweir             gValues[i] = newValue;
289*cdf0e10cSrcweir         }
290*cdf0e10cSrcweir 
291*cdf0e10cSrcweir         try {
292*cdf0e10cSrcweir             oObj.setPropertyValues(testPropsNames, gValues);
293*cdf0e10cSrcweir             Object[] newValues = oObj.getPropertyValues(testPropsNames);
294*cdf0e10cSrcweir             for (int i=0; i<testPropsAmount;i++) {
295*cdf0e10cSrcweir                 if (newValues[i].equals(gValues[i])) {
296*cdf0e10cSrcweir                     bResult = true;
297*cdf0e10cSrcweir                 }
298*cdf0e10cSrcweir             }
299*cdf0e10cSrcweir         } catch (com.sun.star.beans.PropertyVetoException e) {
300*cdf0e10cSrcweir             log.println("Exception occured while setting properties");
301*cdf0e10cSrcweir             e.printStackTrace(log);
302*cdf0e10cSrcweir             bResult = false;
303*cdf0e10cSrcweir         } catch (com.sun.star.lang.IllegalArgumentException e) {
304*cdf0e10cSrcweir             log.println("Exception occured while setting properties");
305*cdf0e10cSrcweir             e.printStackTrace(log);
306*cdf0e10cSrcweir             bResult = false;
307*cdf0e10cSrcweir         } catch (com.sun.star.lang.WrappedTargetException e) {
308*cdf0e10cSrcweir             log.println("Exception occured while setting properties");
309*cdf0e10cSrcweir             e.printStackTrace(log);
310*cdf0e10cSrcweir             bResult = false;
311*cdf0e10cSrcweir         } // end of try-catch
312*cdf0e10cSrcweir 
313*cdf0e10cSrcweir         tRes.tested("setPropertyValues()", bResult);
314*cdf0e10cSrcweir     }
315*cdf0e10cSrcweir 
316*cdf0e10cSrcweir     //Get the properties being tested
317*cdf0e10cSrcweir     private void getPropsToTest(Property[] properties) {
318*cdf0e10cSrcweir 
319*cdf0e10cSrcweir         String bound = "";
320*cdf0e10cSrcweir 
321*cdf0e10cSrcweir         for (int i = 0; i < properties.length; i++) {
322*cdf0e10cSrcweir 
323*cdf0e10cSrcweir             Property property = properties[i];
324*cdf0e10cSrcweir             String name = property.Name;
325*cdf0e10cSrcweir             boolean isWritable = ((property.Attributes &
326*cdf0e10cSrcweir                 PropertyAttribute.READONLY) == 0);
327*cdf0e10cSrcweir             boolean isNotNull = ((property.Attributes &
328*cdf0e10cSrcweir                 PropertyAttribute.MAYBEVOID) == 0);
329*cdf0e10cSrcweir             boolean isBound = ((property.Attributes &
330*cdf0e10cSrcweir                 PropertyAttribute.BOUND) != 0);
331*cdf0e10cSrcweir             boolean isExcluded = exclProps.contains(name);
332*cdf0e10cSrcweir 
333*cdf0e10cSrcweir             //exclude UserDefined, because we can't change XNameContainer
334*cdf0e10cSrcweir             if (name.indexOf("UserDefined")>0 || name.indexOf("Device")>0) {
335*cdf0e10cSrcweir                 isWritable=false;
336*cdf0e10cSrcweir             }
337*cdf0e10cSrcweir 
338*cdf0e10cSrcweir             values = oObj.getPropertyValues(new String[]{property.Name});
339*cdf0e10cSrcweir 
340*cdf0e10cSrcweir             boolean isVoid = util.utils.isVoid(values[0]);
341*cdf0e10cSrcweir 
342*cdf0e10cSrcweir             if ( isWritable && isNotNull && isBound && !isExcluded && !isVoid) {
343*cdf0e10cSrcweir                 bound+=name+";";
344*cdf0e10cSrcweir             }
345*cdf0e10cSrcweir 
346*cdf0e10cSrcweir         } // endfor
347*cdf0e10cSrcweir 
348*cdf0e10cSrcweir         //get a array of bound properties
349*cdf0e10cSrcweir         if (bound.equals("")) bound = "none";
350*cdf0e10cSrcweir         StringTokenizer ST=new StringTokenizer(bound,";");
351*cdf0e10cSrcweir         int nr = ST.countTokens();
352*cdf0e10cSrcweir         testPropsNames = new String[nr];
353*cdf0e10cSrcweir         for (int i=0; i<nr; i++) testPropsNames[i] = ST.nextToken();
354*cdf0e10cSrcweir         testPropsAmount = nr;
355*cdf0e10cSrcweir         return;
356*cdf0e10cSrcweir 
357*cdf0e10cSrcweir     }
358*cdf0e10cSrcweir 
359*cdf0e10cSrcweir     /**
360*cdf0e10cSrcweir     * Waits some time for listener to be called.
361*cdf0e10cSrcweir     */
362*cdf0e10cSrcweir     private void waitAMoment() {
363*cdf0e10cSrcweir         try {
364*cdf0e10cSrcweir             Thread.sleep(200) ;
365*cdf0e10cSrcweir         } catch (java.lang.InterruptedException e) {
366*cdf0e10cSrcweir             log.println("!!! Exception while waiting !!!") ;
367*cdf0e10cSrcweir         }
368*cdf0e10cSrcweir     }
369*cdf0e10cSrcweir 
370*cdf0e10cSrcweir     /*
371*cdf0e10cSrcweir     * Does nothing.
372*cdf0e10cSrcweir     */
373*cdf0e10cSrcweir     protected void after() {
374*cdf0e10cSrcweir         disposeEnvironment();
375*cdf0e10cSrcweir     }
376*cdf0e10cSrcweir }
377*cdf0e10cSrcweir 
378*cdf0e10cSrcweir 
379