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 018package org.apache.commons.daemon.support; 019 020import java.io.FileInputStream; 021import java.io.FileNotFoundException; 022import java.io.IOException; 023import java.util.ArrayList; 024import java.util.Properties; 025import 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 $Id: DaemonConfiguration.java 1204010 2011-11-19 16:15:23Z ggregory $ 049 * @author Mladen Turk 050 */ 051public 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 * Loads 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 * Gets the configuration property. 159 * 160 * @param name The name of the property to get. 161 * 162 * @throws ParseException if the property is wrongly formatted. 163 */ 164 public String getProperty(String name) 165 throws ParseException 166 { 167 if (name == null) 168 return null; 169 else 170 return expandProperty(configurationProperties.getProperty(PREFIX + name)); 171 } 172 173 /** 174 * Gets the configuration property array. 175 * <p> 176 * Property array is constructed form the lsit of properties 177 * which end with <code>[index]</code> 178 * </p> 179 * <pre> 180 * daemon.arg[0] = argument 1 181 * daemon.arg[1] = argument 2 182 * daemon.arg[2] = argument 3 183 * </pre> 184 * @param name The name of the property array to get. 185 * 186 * @throws ParseException if the property is wrongly formatted. 187 */ 188 public String[] getPropertyArray(String name) 189 throws ParseException 190 { 191 ArrayList list = new ArrayList(); 192 String args; 193 194 // Load daemon.arg[0] ... daemon.arg[n] into the String array. 195 // 196 while ((args = getProperty(name + "[" + list.size() + "]")) != null) { 197 list.add(args); 198 } 199 return (String[])list.toArray(new String[list.size()]); 200 } 201 202} 203