View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.fulcrum.yaafi.framework.util;
20  
21  import java.util.Map;
22  
23  import org.apache.avalon.framework.configuration.Configuration;
24  import org.apache.avalon.framework.configuration.ConfigurationException;
25  import org.apache.avalon.framework.configuration.DefaultConfiguration;
26  import org.apache.avalon.framework.logger.Logger;
27  
28  /**
29   * Helper class to expand the value and all attributes.
30   *
31   * @author <a href="mailto:siegfried.goeschl@it20one.at">Siegfried Goeschl</a>
32   */
33  public class ConfigurationUtil
34  {
35      /**
36       * Expand place holders found in values or attrbute values with the
37       * content of the given variables. The implementation assumes that
38       * the given configuration can be cast to a DefaultConfiguration
39       * otherwise we can't use any setters.
40       *
41       * @param logger the logger to write diagnostic messages
42       * @param defaultConfiguration the configuration
43       * @param vars the map holding the variables
44       * @throws ConfigurationException parsing the configuration failed
45       */
46      public static void expand(Logger logger, DefaultConfiguration defaultConfiguration, Map<?, ?> vars) throws ConfigurationException
47      {
48          if( vars == null || vars.size() == 0)
49          {
50              return;
51          }
52  
53          // update the value of the configuration element
54  
55          if(defaultConfiguration.getValue(null) != null)
56          {
57              String oldValue = defaultConfiguration.getValue();
58              String newValue = ConfigurationUtil.expand(oldValue, vars);
59              defaultConfiguration.setValue(newValue);
60  
61              if(oldValue.equals(newValue) == false)
62              {
63                  logger.debug("Changed element <"
64                      + defaultConfiguration.getName()
65                      + "> from '"
66                      + oldValue
67                      + "' ==> '"
68                      + newValue
69                      + "'"
70                      );
71              }
72          }
73  
74          // update all attributes
75  
76          String attributeName = null;
77          String[] attributeNames = defaultConfiguration.getAttributeNames();
78  
79          for(int i=0; i<attributeNames.length; i++)
80          {
81              attributeName = attributeNames[i];
82              String oldAttributeValue = defaultConfiguration.getAttribute(attributeName);
83              String newAttributeValue = ConfigurationUtil.expand(oldAttributeValue, vars);
84              defaultConfiguration.setAttribute(attributeName, newAttributeValue);
85  
86              if(oldAttributeValue.equals(newAttributeValue) == false)
87              {
88                  logger.debug("Changed attribute '"
89                      + defaultConfiguration.getName() + "@" + attributeName
90                      + "' from '"
91                      + oldAttributeValue
92                      + "' ==> '"
93                      + newAttributeValue
94                      + "'"
95                      );
96              }
97          }
98  
99          // and now recurse through all children (children are in general a lot of work)
100 
101         Configuration[] children = defaultConfiguration.getChildren();
102 
103         for(int i=0; i<children.length; i++)
104         {
105             ConfigurationUtil.expand(logger, ((DefaultConfiguration) children[i]), vars);
106         }
107     }
108 
109     /**
110      * Perform a series of substitutions. The substitutions
111      * are performed by replacing ${variable} in the target
112      * string with the value of provided by the key "variable"
113      * in the provided hashtable.
114      *
115      * The unexpanded ${variable} is always written to 
116      * the string buffer. 
117      *
118      * @param argStr target string
119      * @param vars name/value pairs used for substitution
120      * @return String target string with replacements.
121      */
122     private static String expand(String argStr, Map<?, ?> vars)
123     {
124     	// ignore failures
125     	boolean isLenient = true;
126     	
127     	StringBuilder argBuf = new StringBuilder();
128         int argStrLength = argStr.length();
129 
130         for (int cIdx = 0 ; cIdx < argStrLength;)
131         {
132             char ch = argStr.charAt(cIdx);
133             char del = ' ';
134 
135             switch (ch)
136             {
137                 case '$':
138                     StringBuilder nameBuf = new StringBuilder();
139                     del = argStr.charAt(cIdx+1);
140                     if( del == '{')
141                     {
142                         cIdx++;
143 
144                         for (++cIdx ; cIdx < argStr.length(); ++cIdx)
145                         {
146                             ch = argStr.charAt(cIdx);
147                             if (ch != '}')
148                                 nameBuf.append(ch);
149                             else
150                                 break;
151                         }
152 
153                         if (nameBuf.length() > 0)
154                         {
155                             Object value = vars.get(nameBuf.toString());
156 
157                             if (value != null)
158                             {
159                                 argBuf.append(value.toString());
160                             }
161                             else
162                             {
163                                 if (!isLenient)
164                                 {
165                                     throw new RuntimeException("No value found for : " + nameBuf );
166                                 }
167                                 else
168                                 {
169                                     argBuf.append("${").append(nameBuf).append("}");
170                                 }
171                             }
172 
173                             del = argStr.charAt(cIdx);
174 
175                             if( del != '}')
176                             {
177                                 throw new RuntimeException("Delimineter not found for : " + nameBuf );
178                             }
179                         }
180 
181                         cIdx++;
182                     }
183                     else
184                     {
185                         argBuf.append(ch);
186                         ++cIdx;
187                     }
188 
189                     break;
190 
191                 default:
192                     argBuf.append(ch);
193                     ++cIdx;
194                     break;
195             }
196         }
197 
198         return argBuf.toString();    	
199     }
200 }