001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017
018 package org.apache.commons.daemon.support;
019
020 import java.io.FileInputStream;
021 import java.io.FileNotFoundException;
022 import java.io.IOException;
023 import java.util.ArrayList;
024 import java.util.Properties;
025 import java.text.ParseException;
026
027 /**
028 * Used by jsvc for Daemon configuration.
029 * <p>
030 * Configuration is read from properties file.
031 * If no properties file is given the <code>daemon.properties</code>
032 * is used from the current directory.
033 * </p>
034 * <p>
035 * The properties file can have property values expanded at runtime
036 * by using System properties or execution environment. The part
037 * of the property value between <code>${</code> and <code>}</code>
038 * will be used as System property or environment key. If found then
039 * the entire <code>${foo}</code> will be replaced by the value of
040 * either system property or environment variable named <code>foo</code>.
041 * </p>
042 * <p>
043 * If no variable is found the <code>${foo}</code> will be passed as is.
044 * In case of <code>$${foo}</code> this will be unescaped and resulting
045 * value will be <code>${foo}</code>.
046 * </p>
047 *
048 * @version 1.0 <i>(SVN $Revision: 925053 $)</i>
049 * @author Mladen Turk
050 */
051 public final class DaemonConfiguration
052 {
053 /**
054 * Default configuration file name.
055 */
056 protected final static String DEFAULT_CONFIG = "daemon.properties";
057 /**
058 * Property prefix
059 */
060 protected final static String PREFIX = "daemon.";
061 private final static String BTOKEN = "${";
062 private final static String ETOKEN = "}";
063
064
065 private final Properties configurationProperties;
066 private final Properties systemProperties;
067
068 /**
069 * Default constructor
070 */
071 public DaemonConfiguration()
072 {
073 configurationProperties = new Properties();
074 systemProperties = System.getProperties();
075 }
076
077 /**
078 * Load the configuration properties file.
079 *
080 * @param fileName The properties file to load.
081 * @return <code>true</code> if the file was loaded.
082 */
083 public boolean load(String fileName)
084 {
085 boolean ok = false;
086 FileInputStream file = null;
087 try {
088 if (fileName == null)
089 fileName = DEFAULT_CONFIG;
090 file = new FileInputStream(fileName);
091 configurationProperties.clear();
092 configurationProperties.load(file);
093 ok = true;
094 }
095 catch (FileNotFoundException ex) {
096 // fileName does not exist
097 }
098 catch (IOException ex) {
099 // Error reading properties file
100 } finally {
101 try {
102 if (file != null)
103 file.close();
104 } catch (IOException ex) {
105 }
106 }
107 return ok;
108 }
109
110 private String expandProperty(String propValue)
111 throws ParseException
112 {
113 StringBuffer expanded;
114 int btoken;
115 int ctoken = 0;
116
117 if (propValue == null)
118 return null;
119 expanded = new StringBuffer();
120 btoken = propValue.indexOf(BTOKEN);
121 while (btoken != -1) {
122 if (btoken > 0 && propValue.charAt(btoken - 1) == BTOKEN.charAt(0)) {
123 // Skip and unquote.
124 expanded.append(propValue.substring(ctoken, btoken));
125 ctoken = btoken + 1;
126 btoken = propValue.indexOf(BTOKEN, btoken + BTOKEN.length());
127 continue;
128 }
129 int etoken = propValue.indexOf(ETOKEN, btoken);
130 if (etoken != -1) {
131 String variable = propValue.substring(btoken + BTOKEN.length(), etoken);
132 String sysvalue = systemProperties.getProperty(variable);
133 if (sysvalue == null) {
134 // Try with the environment if there was no
135 // property by that name.
136 sysvalue = System.getenv(variable); // N.B. Deprecated in Java 1.3/1.4, but re-instated in Java 1.5+
137 }
138 if (sysvalue != null) {
139 String strtoken = propValue.substring(ctoken, btoken);
140 expanded.append(strtoken);
141 expanded.append(sysvalue);
142 ctoken = etoken + ETOKEN.length();
143 }
144 }
145 else {
146 // We have "${" without "}"
147 throw new ParseException("Error while looking for teminating '" +
148 ETOKEN + "'", btoken);
149 }
150 btoken = propValue.indexOf(BTOKEN, etoken + ETOKEN.length());
151 }
152 // Add what's left.
153 expanded.append(propValue.substring(ctoken, propValue.length()));
154 return expanded.toString();
155 }
156
157 /**
158 * Get the configuration property.
159 * @param name The name of the property to get.
160 *
161 * @throws ParseException if the property is wrongly formatted.
162 */
163 public String getProperty(String name)
164 throws ParseException
165 {
166 if (name == null)
167 return null;
168 else
169 return expandProperty(configurationProperties.getProperty(PREFIX + name));
170 }
171
172 /**
173 * Get the configuration property array.
174 * <p>
175 * Property array is constructed form the lsit of properties
176 * which end with <code>[index]</code>
177 * </p>
178 * <pre>
179 * daemon.arg[0] = argument 1
180 * daemon.arg[1] = argument 2
181 * daemon.arg[2] = argument 3
182 * </pre>
183 * @param name The name of the property array to get.
184 *
185 * @throws ParseException if the property is wrongly formatted.
186 */
187 public String[] getPropertyArray(String name)
188 throws ParseException
189 {
190 ArrayList list = new ArrayList();
191 String args;
192
193 // Load daemon.arg[0] ... daemon.arg[n] into the String array.
194 //
195 while ((args = getProperty(name + "[" + list.size() + "]")) != null) {
196 list.add(args);
197 }
198 return (String[])list.toArray(new String[list.size()]);
199 }
200
201 }
202