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 package helper;
23 
24 import com.sun.star.uno.*;
25 import com.sun.star.lang.*;
26 import com.sun.star.container.*;
27 import com.sun.star.beans.*;
28 import com.sun.star.util.*;
29 
30 /**
31  * This <CODE>ConfigHelper</CODE> makes it possible to access the
32  * configuration and change their content.<P>
33  * <P>
34  * Example: <P>
35  * Listing of the <CODE>Configuration</CODE> Views.xcu:<P>
36  * &lt;oor:component-data xmlns:oor=&quot;http://openoffice.org/2001/registry&quot; xmlns:xs=&quot;http://www.w3.org/2001/XMLSchema&quot; oor:name=&quot;Views&quot; oor:package=&quot;org.openoffice.Office&quot;&gt;<p>
37  *   &lt;node oor:name=&quot;Windows&quot;&gt;<P>
38  *       <&lt;node oor:name=&quot;SplitWindow0&quot; oor:op=&quot;replace&quot;&gt;<P>
39  *           &lt;prop oor:name=&quot;Visible&quot; oor:type=&quot;xs:boolean&quot;&gt;<P>
40  *                &lt;value&gt;false&lt;/value&gt;<P>
41  *           &lt;/prop&gt;<P>
42  *           &lt;prop oor:name=&quot;WindowState&quot; oor:type=&quot;xs:string&quot;&gt;<P>
43  *               &lt;value/&gt;<P>
44  *           &lt;/prop&gt;<P>
45  *            &lt;node oor:name=&quot;UserData&quot;&gt;<P>
46  *               &lt;prop oor:name=&quot;UserItem&quot; oor:op=&quot;replace&quot;
47  *                oor:type=&quot;xs:string&quot;&gt;<P>
48  *                   &lt;value&gt;V1,2,0&lt;/value&gt;<P>
49  *               &lt;/prop&gt;<P>
50  *           &lt;/node&gt;<P>
51  *        &lt;/node&gt;<P>
52  *  &lt;/node&gt;<P>
53  * <P>
54  * <CODE>Definition</CODE><P>
55  * <ul>
56  *    <li><CODE>&lt;node oor:name=&quot;Windows&quot;&gt;</CODE>
57  *        represents a <CODE>Set</CODE> and is a <CODE>XNameContainer</CODE></LI>
58  *    <li><CODE>&lt;node oor:name=&quot;SplitWindow0&quot;&gt;</CODE>
59  *        represents a <CODE>Group</CODE> and is a <CODE>XNameReplace</CODE></LI>
60  *    <li><CODE>&lt;prop oor:name=&quot;Visible&quot;&gt;</CODE>
61  *        represents a pr<CODE></CODE>operty of the group</li>
62  *    <li><CODE>&lt;node oor:name=&quot;UserData&quot;&gt;</CODE>
63  *        represents a <CODE>extensible group</CODE> and is a <CODE>XNameContainer</CODE></LI>
64  *    <li><CODE>&lt;prop oor:name=&quot;UserItem&quot;&gt;</CODE>
65  *        represents a <CODE>property</CODE> of the extensible group</LI>
66  * </UL>
67  * We assume in the following examples the existence of:<P>
68  * <CODE>ConfigHelper aConfig = new ConfigHelper(xMSF, "org.openoffice.Office.Views", false);</CODE>
69  * <ul>
70  *    <li>If you like to insert a new <CODE>Group</CODE> into the <CODE>Set</CODE> "Windows":<p>
71  *        <CODE>XNameReplace xMyGroup = aConfig.getOrInsertGroup("Windows", "myGroup");</CODE><P>
72  *        The method <CODE>getOrInsertGroup()</CODE> uses the
73  *        <CODE>XSingleServiceFactory</CODE> to create the skeleton of a new group.
74  *
75  *    </li>
76  *    <li>If you like to change the property "WindowState" of "myGroup"
77  *        of the Set "Windows"<p>
78  *        <CODE>aConfig.updateGroupProperty(
79  *          "Windows","myGroup", "WindowState", "952,180,244,349;1;0,0,0,0;");</CODE>
80  *    </li>
81  *    <li>If you like to change the property "myProp" of the extensible group
82  *        "myExtGroup" which is an extensible group of "my2ndGroup" of the
83  *        Set "Windows":<p>
84  *        <CODE>aConfig.insertOrUpdateExtensibleGroupProperty(
85  *              "Windows", "my2ndGroup", "myExtGroup", "myProp","TheValue");</CODE>
86  *    </li>
87  * </ul>
88  */
89 public class ConfigHelper
90 {
91     private XMultiServiceFactory m_xSMGR = null;
92     private XHierarchicalNameAccess m_xConfig = null;
93 
94     //-----------------------------------------------
95     public ConfigHelper(XMultiServiceFactory xSMGR       ,
96                         String               sConfigPath ,
97                         boolean              bReadOnly   )
98         throws com.sun.star.uno.Exception
99     {
100         m_xSMGR = xSMGR;
101 
102         XMultiServiceFactory xConfigRoot = (XMultiServiceFactory)
103                         UnoRuntime.queryInterface(
104                         XMultiServiceFactory.class,
105                         m_xSMGR.createInstance(
106                         "com.sun.star.configuration.ConfigurationProvider"));
107 
108         PropertyValue[] lParams = new PropertyValue[1];
109         lParams[0] = new PropertyValue();
110         lParams[0].Name  = "nodepath";
111         lParams[0].Value = sConfigPath;
112 
113         Object aConfig;
114         if (bReadOnly)
115             aConfig = xConfigRoot.createInstanceWithArguments(
116                             "com.sun.star.configuration.ConfigurationAccess",
117                             lParams);
118         else
119             aConfig = xConfigRoot.createInstanceWithArguments(
120                             "com.sun.star.configuration.ConfigurationUpdateAccess",
121                             lParams);
122 
123         m_xConfig = (XHierarchicalNameAccess)UnoRuntime.queryInterface(
124                             XHierarchicalNameAccess.class,
125                             aConfig);
126 
127         if (m_xConfig == null)
128             throw new com.sun.star.uno.Exception("Could not open configuration \""+sConfigPath+"\"");
129     }
130 
131     //-----------------------------------------------
132     public Object readRelativeKey(String sRelPath,
133                                   String sKey    )
134         throws com.sun.star.container.NoSuchElementException
135     {
136         try
137         {
138             XPropertySet xPath = (XPropertySet)UnoRuntime.queryInterface(
139                                     XPropertySet.class,
140                                     m_xConfig.getByHierarchicalName(sRelPath));
141             return xPath.getPropertyValue(sKey);
142         }
143         catch(com.sun.star.uno.Exception ex)
144         {
145             throw new com.sun.star.container.NoSuchElementException(ex.getMessage());
146         }
147     }
148 
149     //-----------------------------------------------
150     public void writeRelativeKey(String sRelPath,
151                                  String sKey    ,
152                                  Object aValue  )
153         throws com.sun.star.container.NoSuchElementException
154     {
155         try
156         {
157             XPropertySet xPath = (XPropertySet)UnoRuntime.queryInterface(
158                                     XPropertySet.class,
159                                     m_xConfig.getByHierarchicalName(sRelPath));
160             xPath.setPropertyValue(sKey, aValue);
161         }
162         catch(com.sun.star.uno.Exception ex)
163         {
164             throw new com.sun.star.container.NoSuchElementException(ex.getMessage());
165         }
166     }
167 
168     //-----------------------------------------------
169     /**
170      * Updates the configuration.<p>
171      * This must be called after you have changed the configuration
172      * else you changes will be lost.
173      */
174     public void flush()
175     {
176         try
177         {
178             XChangesBatch xBatch = (XChangesBatch)UnoRuntime.queryInterface(
179                                         XChangesBatch.class,
180                                         m_xConfig);
181             xBatch.commitChanges();
182         }
183         catch(com.sun.star.uno.Exception ex)
184         {}
185     }
186 
187     //-----------------------------------------------
188     public static Object readDirectKey(XMultiServiceFactory xSMGR      ,
189                                        String               sConfigFile,
190                                        String               sRelPath   ,
191                                        String               sKey       )
192         throws com.sun.star.uno.Exception
193     {
194         ConfigHelper aConfig = new ConfigHelper(xSMGR, sConfigFile, true);
195         return aConfig.readRelativeKey(sRelPath, sKey);
196     }
197 
198     //-----------------------------------------------
199     public static void writeDirectKey(XMultiServiceFactory xSMGR      ,
200                                       String               sConfigFile,
201                                       String               sRelPath   ,
202                                       String               sKey       ,
203                                       Object               aValue     )
204         throws com.sun.star.uno.Exception
205     {
206         ConfigHelper aConfig = new ConfigHelper(xSMGR, sConfigFile, false);
207         aConfig.writeRelativeKey(sRelPath, sKey, aValue);
208         aConfig.flush();
209     }
210 
211 
212     /**
213      * Insert a structured node (group) in a name container (set)
214      * or else update it and retrun the <CODE>XNameReplace</CODE> of it.<P>
215      * The <CODE>XSingleServiceFacttory</CODE> of the <CODE>set</CODE> will be used
216      * to create a new group. This group is specific to its set and
217      * creates defined entries.
218      * @return The [inserted] group of the set
219      * @param groupName The name of the goup which should be returned
220      * @param setName The name of the set
221      * @throws com.sun.star.uno.Exception throws
222      *         <CODE>com.sun.star.uno.Exeception</CODE> on any error.
223      */
224     public XNameReplace getOrInsertGroup(String setName, String groupName)
225         throws  com.sun.star.uno.Exception
226 
227     {
228         XNameContainer xSetCont = this.getSet(setName);
229 
230         XNameReplace xChildAccess = null;
231 
232         try {
233             Object xChild=xSetCont.getByName(groupName);
234             xChildAccess = (XNameReplace) UnoRuntime.queryInterface(
235                             XNameReplace.class,xSetCont);
236         } catch(com.sun.star.container.NoSuchElementException e) {
237              // proceed with inserting
238         }
239 
240         if (xChildAccess == null)  {
241             XSingleServiceFactory xChildfactory = (XSingleServiceFactory)
242                 UnoRuntime.queryInterface(XSingleServiceFactory.class,xSetCont);
243 
244             Object xNewChild = xChildfactory.createInstance();
245 
246             xSetCont.insertByName(groupName, xNewChild);
247 
248             xChildAccess = (XNameReplace)
249                 UnoRuntime.queryInterface(XNameContainer.class,xNewChild);
250        }
251 
252         return xChildAccess;
253     }
254 
255      /**
256      * Update a property of a group container of a set container
257      * @param setName the name of the <CODE>set</CODE> which contains the <CODE>group</CODE>
258      * @param groupName the name of the <CODE>group</CODE> which property should be changed
259      * @param propName the name of the property which should be changed
260      * @param propValue the value the property should get
261      * @throws com.sun.star.uno.Exception throws <CODE>com.sun.star.uno.Exeception</CODE> on any error.
262      */
263     public void updateGroupProperty(String setName,
264                                     String groupName,
265                                     String propName,
266                                     Object propValue)
267         throws  com.sun.star.uno.Exception
268     {
269         XNameContainer xSetCont = this.getSet(setName);
270 
271         XPropertySet xProp = null;
272         try {
273         xProp = (XPropertySet)UnoRuntime.queryInterface(
274                                     XPropertySet.class,
275                                     xSetCont.getByName(groupName));
276         } catch (com.sun.star.container.NoSuchElementException e){
277             throw new com.sun.star.uno.Exception(
278                 "could not get group '" + groupName +
279                "' from set '"+ setName +"':\n" + e.toString());
280         }
281         try{
282             xProp.setPropertyValue(propName, propValue);
283         } catch (com.sun.star.uno.Exception e) {
284              throw new com.sun.star.uno.Exception(
285                 "could not set property '" + propName +
286                 "' from group '"+ groupName +
287                 "' from set '"+ setName +"':\n" + e.toString());
288         }
289     }
290 
291 
292     /**
293      * Insert a property in an extensible group container or else update it
294      * @param setName the name of the <CODE>set</CODE> which contains the <CODE>group</CODE>
295      * @param group The name of the <CODE>group</CODE> which conatins the <CODE>extensible group</CODE>.
296      * @param extGroup The name of the <CODE>extensible group</CODE> which
297      *                  [should] contain the property
298      * @param propName The name of the property.
299      * @param propValue The value of the property.
300      * @throws com.sun.star.uno.Exception throws <CODE>com.sun.star.uno.Exeception</CODE> on any error.
301      */
302     public void insertOrUpdateExtensibleGroupProperty(
303                     String setName,
304                     String group,
305                     String extGroup,
306                     String propName,
307                     Object propValue)
308         throws  com.sun.star.uno.Exception
309     {
310         XNameContainer xSetCont = this.getSet(setName);
311 
312         XNameReplace xGroupAccess = null;
313         XNameContainer xExtGroupCont = null;
314 
315         try {
316             Object xGroup=xSetCont.getByName(group);
317             xGroupAccess = (XNameReplace) UnoRuntime.queryInterface(
318                             XNameReplace.class,xGroup);
319         } catch(com.sun.star.container.NoSuchElementException e) {
320              throw new com.sun.star.uno.Exception(
321                 "could not get group '" + group +
322                 "' from set '"+ setName +"':\n" + e.toString());
323         }
324 
325         try {
326             Object xGroup=xGroupAccess.getByName(extGroup);
327             xExtGroupCont = (XNameContainer) UnoRuntime.queryInterface(
328                             XNameContainer.class,xGroup);
329         } catch(com.sun.star.container.NoSuchElementException e) {
330              throw new com.sun.star.uno.Exception(
331                 "could not get extensilbe group '"+extGroup+
332                 "' from group '"+ group +
333                 "' from set '"+ setName +"':\n" + e.toString());
334         }
335 
336         try {
337             xExtGroupCont.insertByName(propName, propValue);
338         }
339         catch(com.sun.star.container.ElementExistException e) {
340             xExtGroupCont .replaceByName(propName, propValue);
341         }
342 
343     }
344 
345 
346     /**
347      * Returns a <CODE>XNameContainer</CODE> of the <CODE>Set</CODE>
348      * of the <CODE>Configuration</CODE>
349      * @param setName the name of the Set which should be returned
350      * @throws com.sun.star.uno.Exception on any error
351      * @return A XNameContainer of the Set
352      */
353     public XNameContainer getSet(String setName)
354         throws com.sun.star.uno.Exception
355     {
356         XNameReplace xCont = (XNameReplace)
357                     UnoRuntime.queryInterface(XNameReplace.class, m_xConfig);
358 
359         Object oSet = xCont.getByName(setName);
360 
361         if (oSet == null)
362              throw new com.sun.star.uno.Exception(
363                 "could not get set '" + setName + ": null");
364 
365         return (XNameContainer) UnoRuntime.queryInterface(
366                                                 XNameContainer.class, oSet);
367 
368     }
369 }
370