001: /*
002: * Copyright 2002-2005 the original author or authors.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package info.jtrac.config;
018:
019: import java.io.File;
020: import java.io.FileInputStream;
021: import java.io.FileOutputStream;
022: import java.io.FilenameFilter;
023: import java.io.InputStream;
024: import java.io.OutputStream;
025: import java.io.PrintWriter;
026: import java.io.Writer;
027: import java.util.Properties;
028: import javax.servlet.ServletContext;
029: import org.springframework.beans.factory.BeanCreationException;
030: import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
031: import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
032: import org.springframework.core.io.ClassPathResource;
033: import org.springframework.core.io.FileSystemResource;
034: import org.springframework.web.context.ServletContextAware;
035:
036: /**
037: * Custom extension of the Spring PropertyPlaceholderConfigurer that
038: * sets up the jtrac.home System property (creates if required) and also creates
039: * a default jtrac.properties file for HSQLDB - useful for those who want
040: * to quickly evaluate JTrac. Just dropping the war into a servlet container
041: * would work without the need to even configure a datasource.
042: *
043: * This class would effectively do nothing if a "jtrac.properties" file exists in jtrac.home
044: *
045: * 1) a "jtrac.home" property is looked for in /WEB-INF/classes/jtrac-init.properties
046: * 2) if not found, then a "jtrac.home" system property is checked for
047: * 3) then a servlet context init-parameter called "jtrac.home" is looked for
048: * 4) last resort, a ".jtrac" folder is created in the "user.home" and used as "jtrac.home"
049: *
050: * Other tasks
051: * - initialize the "test" query for checking idle database connections
052: * - initialize list of available locales based on the properties files available
053: *
054: * Also playing an important role during startup are the following factory beans:
055: * - DataSourceFactoryBean:
056: * * switches between embedded HSQLDB or Apache DBCP (connection pool)
057: * * performs graceful shutdown of database if embedded HSQLDB
058: * - ProviderManagerFactoryBean
059: * * conditionally includes LDAP authentication if requested
060: *
061: * Note that later on during startup, the HibernateJtracDao would check if
062: * database tables exist, and if they dont, would proceed to create them
063: */
064:
065: public class JtracConfigurer extends PropertyPlaceholderConfigurer
066: implements ServletContextAware {
067:
068: private ServletContext servletContext;
069:
070: public void setServletContext(ServletContext servletContext) {
071: this .servletContext = servletContext;
072: }
073:
074: @Override
075: public void postProcessBeanFactory(
076: ConfigurableListableBeanFactory beanFactory) {
077: // do our custom configuration before spring gets a chance to
078: try {
079: configureJtrac();
080: } catch (Exception e) {
081: throw new BeanCreationException("JtracConfigurer failed", e);
082: }
083: super .postProcessBeanFactory(beanFactory);
084: }
085:
086: private void configureJtrac() throws Exception {
087:
088: String jtracHome = null;
089: ClassPathResource jtracInitResource = new ClassPathResource(
090: "jtrac-init.properties");
091: // jtrac-init.properties assumed to exist
092: Properties props = loadProps(jtracInitResource.getFile());
093: logger
094: .info("found 'jtrac-init.properties' on classpath, processing...");
095: jtracHome = props.getProperty("jtrac.home");
096: if (jtracHome != null) {
097: logger
098: .info("'jtrac.home' property initialized from 'jtrac-init.properties' as '"
099: + jtracHome + "'");
100: }
101: //======================================================================
102: FilenameFilter ff = new FilenameFilter() {
103: public boolean accept(File dir, String name) {
104: return name.startsWith("messages_")
105: && name.endsWith(".properties");
106: }
107: };
108: File[] messagePropsFiles = jtracInitResource.getFile()
109: .getParentFile().listFiles(ff);
110: String locales = "en";
111: for (File f : messagePropsFiles) {
112: int endIndex = f.getName().indexOf('.');
113: String localeCode = f.getName().substring(9, endIndex);
114: locales += "," + localeCode;
115: }
116: logger.info("locales available configured are '" + locales
117: + "'");
118: props.setProperty("jtrac.locales", locales);
119: //======================================================================
120: if (jtracHome == null) {
121: logger
122: .info("valid 'jtrac.home' property not available in 'jtrac-init.properties', trying system properties.");
123: jtracHome = System.getProperty("jtrac.home");
124: if (jtracHome != null) {
125: logger
126: .info("'jtrac.home' property initialized from system properties as '"
127: + jtracHome + "'");
128: }
129: }
130: if (jtracHome == null) {
131: logger
132: .info("valid 'jtrac.home' property not available in system properties, trying servlet init paramters.");
133: jtracHome = servletContext.getInitParameter("jtrac.home");
134: if (jtracHome != null) {
135: logger
136: .info("Servlet init parameter 'jtrac.home' exists: '"
137: + jtracHome + "'");
138: }
139: }
140: if (jtracHome == null) {
141: jtracHome = System.getProperty("user.home") + "/.jtrac";
142: logger
143: .warn("Servlet init paramter 'jtrac.home' does not exist. Will use 'user.home' directory '"
144: + jtracHome + "'");
145: }
146: //======================================================================
147: File homeFile = new File(jtracHome);
148: if (!homeFile.exists()) {
149: homeFile.mkdir();
150: logger.info("directory does not exist, created '"
151: + homeFile.getPath() + "'");
152: if (!homeFile.exists()) {
153: String message = "invalid path '"
154: + homeFile.getAbsolutePath()
155: + "', try creating this directory first. Aborting.";
156: logger.error(message);
157: throw new Exception(message);
158: }
159: } else {
160: logger.info("directory already exists: '"
161: + homeFile.getPath() + "'");
162: }
163: props.setProperty("jtrac.home", homeFile.getAbsolutePath());
164: //======================================================================
165: File attachmentsFile = new File(jtracHome + "/attachments");
166: if (!attachmentsFile.exists()) {
167: attachmentsFile.mkdir();
168: logger.info("directory does not exist, created '"
169: + attachmentsFile.getPath() + "'");
170: } else {
171: logger.info("directory already exists: '"
172: + attachmentsFile.getPath() + "'");
173: }
174: File indexesFile = new File(jtracHome + "/indexes");
175: if (!indexesFile.exists()) {
176: indexesFile.mkdir();
177: logger.info("directory does not exist, created '"
178: + indexesFile.getPath() + "'");
179: } else {
180: logger.info("directory already exists: '"
181: + indexesFile.getPath() + "'");
182: }
183: //======================================================================
184: File propsFile = new File(homeFile.getPath()
185: + "/jtrac.properties");
186: if (!propsFile.exists()) {
187: propsFile.createNewFile();
188: logger.info("properties file does not exist, created '"
189: + propsFile.getPath() + "'");
190: OutputStream os = new FileOutputStream(propsFile);
191: Writer out = new PrintWriter(os);
192: try {
193: out.write("database.driver=org.hsqldb.jdbcDriver\n");
194: out
195: .write("database.url=jdbc:hsqldb:file:${jtrac.home}/db/jtrac\n");
196: out.write("database.username=sa\n");
197: out.write("database.password=\n");
198: out
199: .write("hibernate.dialect=org.hibernate.dialect.HSQLDialect\n");
200: out.write("hibernate.show_sql=false\n");
201: } finally {
202: out.close();
203: os.close();
204: }
205: logger.info("HSQLDB will be used. Finished creating '"
206: + propsFile.getPath() + "'");
207: } else {
208: logger.info("'jtrac.properties' file exists: '"
209: + propsFile.getPath() + "'");
210: }
211: //======================================================================
212: String version = "0.0.0";
213: String timestamp = "0000";
214: ClassPathResource versionResource = new ClassPathResource(
215: "jtrac-version.properties");
216: if (versionResource.exists()) {
217: logger
218: .info("found 'jtrac-version.properties' on classpath, processing...");
219: Properties versionProps = loadProps(versionResource
220: .getFile());
221: version = versionProps.getProperty("version");
222: timestamp = versionProps.getProperty("timestamp");
223: } else {
224: logger
225: .info("did not find 'jtrac-version.properties' on classpath");
226: }
227: logger.info("jtrac.version = '" + version + "'");
228: logger.info("jtrac.timestamp = '" + timestamp + "'");
229: props.setProperty("jtrac.version", version);
230: props.setProperty("jtrac.timestamp", timestamp);
231: props.setProperty("database.validationQuery", "SELECT 1");
232: props.setProperty("ldap.url", "");
233: props.setProperty("ldap.activeDirectoryDomain", "");
234: props.setProperty("ldap.searchBase", "");
235: props.setProperty("database.datasource.jndiname", "");
236: // set default properties that can be overridden by user if required
237: setProperties(props);
238: // finally set the property that spring is expecting, manually
239: FileSystemResource fsr = new FileSystemResource(propsFile);
240: setLocation(fsr);
241: }
242:
243: private Properties loadProps(File file) throws Exception {
244: InputStream is = null;
245: Properties props = new Properties();
246: try {
247: is = new FileInputStream(file);
248: props.load(is);
249: } finally {
250: is.close();
251: }
252: return props;
253: }
254:
255: }
|