KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > oddjob > arooa > PropertyHelper


1 /*
2  * This source code is heavily based on source code from the Apache
3  * Ant project. As such the following is included:
4  * ------------------------------------------------------------------
5  *
6  * The Apache Software License, Version 1.1
7  *
8  * Copyright (c) 2000,2002-2003 The Apache Software Foundation. All rights
9  * reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  *
15  * 1. Redistributions of source code must retain the above copyright
16  * notice, this list of conditions and the following disclaimer.
17  *
18  * 2. Redistributions in binary form must reproduce the above copyright
19  * notice, this list of conditions and the following disclaimer in
20  * the documentation and/or other materials provided with the
21  * distribution.
22  *
23  * 3. The end-user documentation included with the redistribution, if
24  * any, must include the following acknowlegement:
25  * "This product includes software developed by the
26  * Apache Software Foundation (http://www.apache.org/)."
27  * Alternately, this acknowlegement may appear in the software itself,
28  * if and wherever such third-party acknowlegements normally appear.
29  *
30  * 4. The names "Ant" and "Apache Software
31  * Foundation" must not be used to endorse or promote products derived
32  * from this software without prior written permission. For written
33  * permission, please contact apache@apache.org.
34  *
35  * 5. Products derived from this software may not be called "Apache"
36  * nor may "Apache" appear in their names without prior written
37  * permission of the Apache Group.
38  *
39  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
40  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
41  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
42  * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
43  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
45  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
46  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
47  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
48  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
49  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
50  * SUCH DAMAGE.
51  * ====================================================================
52  *
53  * This software consists of voluntary contributions made by many
54  * individuals on behalf of the Apache Software Foundation. For more
55  * information on the Apache Software Foundation, please see
56  * <http://www.apache.org/>.
57  */

58
59 package org.oddjob.arooa;
60
61 import java.io.Serializable JavaDoc;
62 import java.util.Enumeration JavaDoc;
63 import java.util.Vector JavaDoc;
64
65 import org.oddjob.arooa.reflect.IntrospectionHelper;
66 import org.oddjob.arooa.reflect.RegistryLookup;
67
68
69 /**
70  * Used for replacing properties in strings.
71  * <p>
72  * Based on an original by <b>Costin Manolache</b>.
73  */

74
75 public class PropertyHelper implements Serializable JavaDoc {
76
77     Vector JavaDoc fragments = new Vector JavaDoc();
78     Vector JavaDoc propertyRefs = new Vector JavaDoc();
79     private final String JavaDoc value;
80     
81     /**
82      * Default constructor.
83      */

84     public PropertyHelper(String JavaDoc value) {
85         this.value = value;
86         if (value == null) {
87             return;
88         }
89         parsePropertyString(value, fragments, propertyRefs);
90     }
91
92     /**
93      * Get the original value ${ and all.
94      *
95      * @return The original value.
96      */

97     public String JavaDoc getValue() {
98         return value;
99     }
100     
101     /**
102      * Replaces <code>${xxx}</code> style constructions in the given value
103      * with the string value of the corresponding data types.
104      *
105      * @param value The string to be scanned for property references.
106      * May be <code>null</code>, in which case this
107      * method returns immediately with no effect.
108      * @param keys Mapping (String to String) of property names to their
109      * values. If <code>null</code>, only project properties will
110      * be used.
111      *
112      * @exception ArooaException if the string contains an opening
113      * <code>${</code> without a closing
114      * <code>}</code>
115      * @return the original string with the properties replaced, or
116      * <code>null</code> if the original string is <code>null</code>.
117      */

118     public Object JavaDoc replaceProperties(RegistryLookup registry, boolean strictSubstitution)
119             throws ArooaException {
120
121         // return an object if there was only one ref and no fragments.
122
if (propertyRefs.size() == 1 && fragments.size() == 1) {
123             String JavaDoc propertyName = (String JavaDoc)propertyRefs.elementAt(0);
124             Object JavaDoc replacement = registry.getProperty(propertyName);
125             if (replacement == null && strictSubstitution) {
126                 throw new NullPointerException JavaDoc("Value must not be null [" + propertyName + "]" );
127             }
128             return replacement;
129         }
130
131         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
132         Enumeration JavaDoc i = fragments.elements();
133         Enumeration JavaDoc j = propertyRefs.elements();
134
135         while (i.hasMoreElements()) {
136             String JavaDoc fragment = (String JavaDoc) i.nextElement();
137             if (fragment == null) {
138                 String JavaDoc propertyName = (String JavaDoc) j.nextElement();
139                 Object JavaDoc possibleProxy = registry.getProperty(propertyName);
140                 Object JavaDoc replacement = IntrospectionHelper.valueFor(possibleProxy,
141                         String JavaDoc.class);
142                 if (replacement == null) {
143                     if (strictSubstitution) {
144                         throw new NullPointerException JavaDoc("Value must not be null [" + propertyName + "] in [" + value + "]" );
145                     }
146                     else {
147                         replacement = "";
148                     }
149                 }
150
151                 fragment = (replacement != null)
152                         ? replacement.toString()
153                         : "${" + propertyName + "}";
154             }
155             sb.append(fragment);
156         }
157
158         return sb.toString();
159     }
160
161     /**
162      * Parses a string containing <code>${xxx}</code> style property
163      * references into two lists. The first list is a collection
164      * of text fragments, while the other is a set of string property names.
165      * <code>null</code> entries in the first list indicate a property
166      * reference from the second list.
167      *
168      * It can be overridden with a more efficient or customized version.
169      *
170      * @param value Text to parse. Must not be <code>null</code>.
171      * @param fragments List to add text fragments to.
172      * Must not be <code>null</code>.
173      * @param propertyRefs List to add property names to.
174      * Must not be <code>null</code>.
175      *
176      * @exception ArooaException if the string contains an opening
177      * <code>${</code> without a closing
178      * <code>}</code>
179      */

180
181     private void parsePropertyString(String JavaDoc value, Vector JavaDoc fragments,
182                                     Vector JavaDoc propertyRefs)
183             throws ArooaException {
184         int prev = 0;
185         int pos;
186         //search for the next instance of $ from the 'prev' position
187
while ((pos = value.indexOf("$", prev)) >= 0) {
188
189             //if there was any text before this, add it as a fragment
190
//TODO, this check could be modified to go if pos>prev;
191
//seems like this current version could stick empty strings
192
//into the list
193
if (pos > 0) {
194                 fragments.addElement(value.substring(prev, pos));
195             }
196             //if we are at the end of the string, we tack on a $
197
//then move past it
198
if (pos == (value.length() - 1)) {
199                 fragments.addElement("$");
200                 prev = pos + 1;
201             } else if (value.charAt(pos + 1) != '{') {
202                 //peek ahead to see if the next char is a property or not
203
//not a property: insert the char as a literal
204
/*
205                 fragments.addElement(value.substring(pos + 1, pos + 2));
206                 prev = pos + 2;
207                 */

208                 if (value.charAt(pos + 1) == '$') {
209                     //backwards compatibility two $ map to one mode
210
fragments.addElement("$");
211                     prev = pos + 2;
212                 } else {
213                     //new behaviour: $X maps to $X for all values of X!='$'
214
fragments.addElement(value.substring(pos, pos + 2));
215                     prev = pos + 2;
216                 }
217
218             } else {
219                 //property found, extract its name or bail on a typo
220
int endName = value.indexOf('}', pos);
221                 if (endName < 0) {
222                     throw new ArooaException("Syntax error in property: "
223                                                  + value);
224                 }
225                 String JavaDoc propertyName = value.substring(pos + 2, endName);
226                 fragments.addElement(null);
227                 propertyRefs.addElement(propertyName);
228                 prev = endName + 1;
229             }
230         }
231         //no more $ signs found
232
//if there is any tail to the file, append it
233
if (prev < value.length()) {
234             fragments.addElement(value.substring(prev));
235         }
236     }
237     
238     /**
239      * Is the property constant. i.e. it doesn't contain any ${} type things.
240      *
241      * @return True if the property is constant.
242      */

243     public boolean isConstant() {
244         
245         return propertyRefs.size() == 0;
246     }
247
248     public String JavaDoc toString() {
249         return value;
250     }
251 }
252
Popular Tags