PropertyParser.java

biz/hammurapi/config/PropertyParser.java

Violations

Inspector Message Severity Location
Java Inspector 048 Copyrights information should be present in each file. 1
Java Inspector 070-A Cyclomatic complexity is too high: 18, maximum allowed is 12 2 157:5
Java Inspector 073 [java.lang.StringBuffer] In Java 5 use StringBuilder instead of StringBuffer if access is single-threaded, e.g. StringBuffer is used as a local variable . 2 164:9
Java Inspector 089 Undocumented field 2 37:5
Java Inspector 089 Undocumented field 2 38:9
Java Inspector 089 Undocumented field 2 39:9
Java Inspector 089 Undocumented method 2 56:25
Java Inspector 089 Undocumented parameter context 2 70:5
Java Inspector 089 Javadoc contains tag for non-existent parameter properties 2 70:5
Java Inspector 089 Undocumented parameter tokenFirstOpeningChar 2 84:5
Java Inspector 089 Undocumented parameter tokenSecondOpeningChar 2 84:5
Java Inspector 089 Undocumented parameter tokenClosingChar 2 84:5
Java Inspector 089 Undocumented method 2 86:25
Java Inspector 089 Undocumented parameter context 2 103:5
Java Inspector 089 Undocumented parameter tokenFirstOpeningChar 2 103:5
Java Inspector 089 Undocumented parameter tokenSecondOpeningChar 2 103:5
Java Inspector 089 Undocumented parameter tokenClosingChar 2 103:5
Java Inspector 089 Javadoc contains tag for non-existent parameter properties 2 103:5
Java Inspector 089 Undocumented parameter key 2 121:5
Java Inspector 089 Method return value is not documented 2 121:5
Java Inspector 089 Undocumented parameter str 2 131:5
Java Inspector 089 Method return value is not documented 2 131:5
Java Inspector 003 do, while, if, and for statements need a brace enclosed block 3 179:30
Java Inspector 003 do, while, if, and for statements need a brace enclosed block 3 181:35
Java Inspector 003 do, while, if, and for statements need a brace enclosed block 3 185:30
Java Inspector 003 do, while, if, and for statements need a brace enclosed block 3 200:37
Java Inspector 003 do, while, if, and for statements need a brace enclosed block 3 202:37
Java Inspector 003 do, while, if, and for statements need a brace enclosed block 3 211:23
Java Inspector 025 Avoid hardwired numeric literals. Allowed literals: [1, -1, 0] 3 185:31
Java Inspector 025 Avoid hardwired numeric literals. Allowed literals: [1, -1, 0] 3 192:22
Java Inspector 025 Avoid hardwired numeric literals. Allowed literals: [1, -1, 0] 3 210:20
Java Inspector 026 Avoid hardwired string literals. Allowed literals: [] 3 72:48
Java Inspector 026 Avoid hardwired string literals. Allowed literals: [] 3 105:48
Java Inspector 026 Avoid hardwired string literals. Allowed literals: [] 3 149:57
Java Inspector 026 Avoid hardwired string literals. Allowed literals: [] 3 206:53
Java Inspector 051 It is good practice to call in any case super() in a constructor. 3 54:5
Java Inspector 051 It is good practice to call in any case super() in a constructor. 3 70:5
Java Inspector 051 It is good practice to call in any case super() in a constructor. 3 84:5
Java Inspector 051 It is good practice to call in any case super() in a constructor. 3 103:5

Source code

1/*
2 * hgcommons 9
3 * Hammurapi Group Common Library
4 * Copyright (C) 2003 Hammurapi Group
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 * URL: http://www.hammurapi.biz/hammurapi-biz/ef/xmenu/hammurapi-group/products/products/hgcommons/index.html
21 * e-Mail: support@hammurapi.biz
22 */
23package biz.hammurapi.config;
24
25import java.util.HashSet;
26import java.util.Set;
27import java.util.StringTokenizer;
28
29/**
30 * Expands property value entries like ${myProperty} to property values.
31 * Nested properties are supportd, i.e. if myProperty value contains ${someOtherPropery}
32 * then it will also be expanded. ${ escaping is not supported.
33 * @author Pavel Vlasov
34 * @version $Revision: 1.3 $
35 */
36public class PropertyParser {
37 public static final String TOKEN_CLOSING_CHAR = "}";
38 public static final String TOKEN_SECOND_OPENING_CHAR = "{";
39 public static final String TOKEN_FIRST_OPENING_CHAR = "$";
40
41 private String tokenClosingChar = TOKEN_CLOSING_CHAR;
42 private String tokenSecondOpeningChar = TOKEN_SECOND_OPENING_CHAR;
43 private String tokenFirstOpeningChar = TOKEN_FIRST_OPENING_CHAR;
44
45 private Context context;
46 private boolean useNameAsDefault;
47
48 /**
49 * Creates a new instance of PropertyParser with system
50 * properties.
51 * @param useNameAsDefault If true then property name will be used
52 * as property default value.
53 */
54 public PropertyParser(boolean useNameAsDefault) {
55 context=new Context() {
56 public Object get(String name) {
57 return System.getProperty(name);
58 }
59 };
60
61 this.useNameAsDefault=useNameAsDefault;
62 }
63
64 /**
65 * Creates a new instance of PropertyParser
66 * @param properties Properties
67 * @param useNameAsDefault If true then property name will be used
68 * as property default value.
69 */
70 public PropertyParser(Context context, boolean useNameAsDefault) {
71 if (context==null) {
72 throw new NullPointerException("Context is null");
73 }
74 this.context=context;
75 this.useNameAsDefault=useNameAsDefault;
76 }
77
78 /**
79 * Creates a new instance of PropertyParser with system
80 * properties.
81 * @param useNameAsDefault If true then property name will be used
82 * as property default value.
83 */
84 public PropertyParser(boolean useNameAsDefault, char tokenFirstOpeningChar, char tokenSecondOpeningChar, char tokenClosingChar) {
85 context=new Context() {
86 public Object get(String name) {
87 return System.getProperty(name);
88 }
89 };
90
91 this.useNameAsDefault=useNameAsDefault;
92 this.tokenClosingChar=String.valueOf(tokenClosingChar);
93 this.tokenFirstOpeningChar=String.valueOf(tokenFirstOpeningChar);
94 this.tokenSecondOpeningChar=String.valueOf(tokenSecondOpeningChar);
95 }
96
97 /**
98 * Creates a new instance of PropertyParser
99 * @param properties Properties
100 * @param useNameAsDefault If true then property name will be used
101 * as property default value.
102 */
103 public PropertyParser(Context context, boolean useNameAsDefault, char tokenFirstOpeningChar, char tokenSecondOpeningChar, char tokenClosingChar) {
104 if (context==null) {
105 throw new NullPointerException("Context is null");
106 }
107 this.context=context;
108 this.useNameAsDefault=useNameAsDefault;
109 this.tokenClosingChar=String.valueOf(tokenClosingChar);
110 this.tokenFirstOpeningChar=String.valueOf(tokenFirstOpeningChar);
111 this.tokenSecondOpeningChar=String.valueOf(tokenSecondOpeningChar);
112 }
113
114
115 /**
116 * Property parsing.
117 * Replaces string ${<property name>} with property value.
118 * If property value contains ${<other property name>} it
119 * will be parsed.
120 */
121 public String getParsedProperty(String key) {
122 return getParsedProperty(key, new HashSet());
123 }
124
125 /**
126 * Parses a string by replacing occurences of ${<property name>}
127 * with property values.
128 * If property value contains ${<other property name>} it
129 * will be parsed.
130 */
131 public String parse(String str) {
132 return parse(str, null);
133 }
134
135 private String getParsedProperty(String key, Set stack) {
136 Object o=context.get(key);
137 String pr;
138 if (o==null) {
139 if (useNameAsDefault) {
140 pr=key;
141 } else {
142 return null;
143 }
144 } else {
145 pr=o.toString();
146 }
147
148 if (stack.contains(key)) {
149 throw new RuntimeConfigurationException("Circular reference in property substitution, property: "+key);
150 }
151
152 stack.add(key);
153
154 return parse(pr, stack);
155 }
156
157 private String parse(String str, Set stack) {
158 if (str==null) {
159 return null;
160 }
161
162 StringTokenizer st=new StringTokenizer(str,tokenFirstOpeningChar+tokenSecondOpeningChar+tokenClosingChar,true);
163
164 StringBuffer ret=new StringBuffer();
165 /**
166 * Parser state:
167 * 0: Text
168 * 1: $
169 * 2: ${
170 */
171 int state=0;
172
173 String propName=null;
174 while (st.hasMoreTokens()) {
175 String tkn=st.nextToken();
176 switch (state) {
177 case 0:
178 if (tokenFirstOpeningChar.equals(tkn))
179 state=1;
180 else
181 ret.append(tkn);
182 break;
183 case 1:
184 if (tokenSecondOpeningChar.equals(tkn))
185 state=2;
186 else {
187 state=0;
188 ret.append(tokenFirstOpeningChar);
189 ret.append(tkn);
190 }
191 break;
192 case 2:
193 if (tokenClosingChar.equals(tkn)) {
194 String propVal=getParsedProperty(propName, stack==null ? new HashSet() : stack);
195 ret.append(propVal==null ? tokenFirstOpeningChar+tokenSecondOpeningChar+propName+tokenClosingChar : propVal);
196 propName=null;
197 state=0;
198 } else {
199 if (propName==null)
200 propName=tkn;
201 else
202 propName+=tkn;
203 }
204 break;
205 default:
206 throw new IllegalStateException("Illegal parser state: "+state);
207 }
208 }
209
210 if (state==2)
211 ret.append(tokenFirstOpeningChar+tokenSecondOpeningChar+propName);
212
213 return ret.toString();
214 }
215}
216