001: /*
002: * ====================================================================
003: * JAFFA - Java Application Framework For All
004: *
005: * Copyright (C) 2002 JAFFA Development Group
006: *
007: * This library is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU Lesser General Public
009: * License as published by the Free Software Foundation; either
010: * version 2.1 of the License, or (at your option) any later version.
011: *
012: * This library is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this library; if not, write to the Free Software
019: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
020: *
021: * Redistribution and use of this software and associated documentation ("Software"),
022: * with or without modification, are permitted provided that the following conditions are met:
023: * 1. Redistributions of source code must retain copyright statements and notices.
024: * Redistributions must also contain a copy of this document.
025: * 2. Redistributions in binary form must reproduce the above copyright notice,
026: * this list of conditions and the following disclaimer in the documentation
027: * and/or other materials provided with the distribution.
028: * 3. The name "JAFFA" must not be used to endorse or promote products derived from
029: * this Software without prior written permission. For written permission,
030: * please contact mail to: jaffagroup@yahoo.com.
031: * 4. Products derived from this Software may not be called "JAFFA" nor may "JAFFA"
032: * appear in their names without prior written permission.
033: * 5. Due credit should be given to the JAFFA Project (http://jaffa.sourceforge.net).
034: *
035: * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
036: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
037: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
038: * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
039: * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
040: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
041: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
042: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
043: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
044: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
045: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
046: * SUCH DAMAGE.
047: * ====================================================================
048: */
049:
050: package org.jaffa.config;
051:
052: import javax.servlet.http.HttpServlet;
053: import javax.servlet.ServletException;
054: import javax.servlet.ServletConfig;
055: import java.io.*;
056: import java.util.*;
057: import java.net.URL;
058: import java.net.MalformedURLException;
059: import org.apache.log4j.Logger;
060: import org.apache.log4j.LogManager;
061: import org.apache.log4j.xml.DOMConfigurator;
062: import org.apache.log4j.BasicConfigurator;
063: import org.jaffa.config.Config;
064: import org.jaffa.util.URLHelper;
065: import org.jaffa.presentation.portlet.session.SessionManager;
066:
067: /** This servlet is called by web.xml as part of the startup process.
068: * It is used to initialize the Logging API and to also get a handle on
069: * the base diretory that the web application is deployed in. This can be used as
070: * a reference point for locating resources relative to the deployment of the web app.
071: *
072: * The following optional parameters can be passed to this servlet:
073: *
074: * framework.ApplicationResourcesLocation - The physical path of where the ApplicationResources.properties is.
075: * Example Absolute location : "C:\tomcat\webapps\Tools\WEB-INF\classes\resources\ApplicationResources.properties"
076: * Example Relative to classpath : "resources/ApplicationResources.properties"
077: * NOTE: This value will have to be provided to the Struts ActionServlet as well in web.xml or struts-config.xml
078: *
079: * framework.ApplicationResourcesDefaultLocation - The physical path of where the ApplicationResources.default is.
080: * Example Absolute location : "C:\tomcat\webapps\Tools\WEB-INF\classes\resources\ApplicationResources.default"
081: * Example Relative to classpath : "resources/ApplicationResources.default"
082: *
083: * framework.ApplicationResourcesOverrideLocation - The physical path of where the ApplicationResources.override is.
084: * Example "C:/ApplicationResources.override"
085: * Example Relative to classpath : "resources/ApplicationResources.override"
086: * NOTE: It is recommended that this file will outside the webapp, so that it is not overwritten during product upgrades.
087: *
088: * If the values are provided for the above parameters, this servlet will combine the ApplicationResources.default and ApplicationResources.override files to generate the ApplicationResources.properties file.
089: * Additionally, the servlet will set the appropriate dynamic properties in the org.jaffa.config.Config class.
090: * These parameters control the working of the 'Jaffa.Admin.LabelEditor' component.
091: *
092: */
093: public class InitApp extends HttpServlet {
094:
095: private static Logger log = null;
096:
097: /** This is invoked by the servlet container when the servlet is first loaded.
098: * It first invokes the init method of the super class.
099: * It then initialises the logging API and gets a handle on the webapp which invoked this servlet.
100: * @param cfg the Servlet configuration passed by the container.
101: * @throws ServletException if any error occurs.
102: */
103: public void init(ServletConfig cfg) throws ServletException {
104: // default init
105: super .init(cfg);
106:
107: // custom inits
108: initLog4j();
109: initBaseDir();
110: initGarbageCollectionOfIdleComponents();
111: checkUserGridSettingsUrls();
112: initApplicationResourcesParameters();
113: }
114:
115: /** This is invoked by the servlet container when the servlet is destroyed.
116: * It clears up the settings related to the logging API.
117: * It then invokes the destroy method of the super class.
118: */
119: public void destroy() {
120: // destroy custom stuff
121: destroyGarbageCollectionOfIdleComponents();
122: destroyLog4j();
123:
124: // destroy the default
125: super .destroy();
126: }
127:
128: /** Initialize log4j using the file specified in the 'framework.Log4JConfig' property in the config.properties file.
129: * This will be set to either 'none', 'default' or a classpath-relative file name. If there is no configuration setting
130: * 'default' wil be assumed.
131: *
132: * @see For more information look at the documentation in 'config.properties'
133: */
134: private void initLog4j() {
135: //Read setting from configuration file
136: String fileName = (String) Config.getProperty(
137: Config.PROP_LOG4J_CONFIG, "default");
138:
139: if (fileName.equalsIgnoreCase("none")) {
140: // do nothing.. Assume that log4j would have been initialized by some other container
141: initializeLogField();
142: log
143: .info("Skipped log4j configuration. Should be done by Web/J2EE Server first!");
144: } else if (fileName.equalsIgnoreCase("default")) {
145: defaultLog4j();
146: } else {
147: try {
148: URL u = URLHelper.newExtendedURL(fileName);
149: DOMConfigurator.configureAndWatch(u.getPath());
150: initializeLogField();
151: if (log.isInfoEnabled())
152: log
153: .info("Configured log4j using the configuration file (relative to classpath): "
154: + fileName);
155: } catch (Exception e) {
156: System.err
157: .println("Error in initializing Log4j using the configFile (relative to classpath): "
158: + fileName);
159: e.printStackTrace();
160: defaultLog4j();
161: }
162: }
163: }
164:
165: private void defaultLog4j() {
166: BasicConfigurator.configure();
167: initializeLogField();
168: if (log.isInfoEnabled())
169: log.info("Configured log4j using the Basic Configurator");
170: }
171:
172: private void destroyLog4j() {
173: LogManager.shutdown();
174: }
175:
176: /** Initialize the base directory. This is the physical root of the web application.
177: * This will be used inside the server to get a real path to relative files...
178: */
179: private void initBaseDir() {
180: try {
181: String baseFile = (String) Config.getProperty(
182: Config.PROP_WEB_SERVER_ROOT_FILE, "/index.html");
183: URL u = getServletContext().getResource(baseFile);
184: String base = "";
185: if (u == null) {
186: log.fatal("Base Web File Not Found '" + baseFile
187: + "', Can't Set Web Root");
188: return;
189: } else {
190: // Try to split the file with the OS native seporator
191: int pos = u.toExternalForm()
192: .lastIndexOf(File.separator);
193: // If this didn't suceed, try the URL sperator (/)
194: if (pos == -1 && File.separatorChar != '/')
195: pos = u.toExternalForm().lastIndexOf('/');
196: if (log.isDebugEnabled())
197: log.debug("URL for locating the base is "
198: + u.toExternalForm()
199: + ", drop file after pos " + pos);
200: if (pos >= 1)
201: base = u.toExternalForm().substring(0, pos);
202: }
203: log.info("Web App Base Directory : " + base);
204: Config.setProperty(Config.PROP_WEB_SERVER_ROOT, base);
205: } catch (MalformedURLException e) {
206: log.fatal("Failed to get root for web server files", e);
207: }
208: }
209:
210: private void initializeLogField() {
211: if (log == null)
212: log = Logger.getLogger(InitApp.class);
213: }
214:
215: private void initGarbageCollectionOfIdleComponents() {
216: if (log.isInfoEnabled())
217: log
218: .info("Starting a Thread to Garbage Collect idle components");
219: SessionManager.startGarbageCollectionOfIdleComponents();
220: }
221:
222: private void destroyGarbageCollectionOfIdleComponents() {
223: if (log.isInfoEnabled())
224: log
225: .info("Stopping the Thread to Garbage Collect idle components");
226: SessionManager.stopGarbageCollectionOfIdleComponents();
227: }
228:
229: /** This validate the framework properties - 'framework.widgets.usergrid.user.url' and 'framework.widgets.usergrid.default.url'.
230: * Warnings will be logged, in case invalid values are provided.
231: */
232: private void checkUserGridSettingsUrls() {
233: // check the URL for the default grid settings
234: checkUrlProperty(Config.PROP_DEFAULT_GRID_SETTINGS_URI, true);
235:
236: // check the URL for the user grid settings
237: checkUrlProperty(Config.PROP_USER_GRID_SETTINGS_URI, false);
238:
239: }
240:
241: private void checkUrlProperty(String prop, boolean isDefault) {
242: String propValue = (String) Config.getProperty(prop);
243: if (propValue != null && propValue.length() > 0) {
244: try {
245: URL settingsUrl = URLHelper.newExtendedURL(propValue);
246: File f = new File(settingsUrl.getFile());
247: if (!f.exists())
248: log
249: .warn("The "
250: + (isDefault ? "default" : "")
251: + " User Grid Settings folder doesn't exist- "
252: + f);
253: else if (log.isInfoEnabled())
254: log.info("The " + (isDefault ? "default" : "")
255: + " User Grid Settings folder- " + f);
256: } catch (MalformedURLException e) {
257: log
258: .warn("Bad URL for the "
259: + (isDefault ? "default" : "")
260: + " User Grid Settings folder- "
261: + propValue, e);
262: }
263: }
264: }
265:
266: /** This method will check the values for the optional sevlet parameters - framework.ApplicationResourcesLocation, framework.ApplicationResourcesDefaultLocation and framework.ApplicationResourcesOverrideLocation.
267: * It will set the appropriate dynamic properties in the org.jaffa.config.Config class.
268: * It will then invoke the generateApplicationResources() method to combine the ApplicationResources.default and ApplicationResources.override files into the ApplicationResources.properties file.
269: */
270: private void initApplicationResourcesParameters() {
271: String value = null;
272:
273: value = (String) Config.getProperty(
274: Config.PROP_MESSAGE_RESOURCES_BUNDLE, null);
275: if (value != null && !value.endsWith(".properties"))
276: value += ".properties";
277: value = determineLocation(value);
278: Config.setProperty(Config.PROP_APPLICATION_RESOURCES_LOCATION,
279: value);
280: if (log.isInfoEnabled())
281: log
282: .info("Config.PROP_APPLICATION_RESOURCES_LOCATION set to: "
283: + value);
284:
285: value = determineLocation(getServletConfig().getInitParameter(
286: Config.PROP_APPLICATION_RESOURCES_DEFAULT_LOCATION));
287: Config.setProperty(
288: Config.PROP_APPLICATION_RESOURCES_DEFAULT_LOCATION,
289: value);
290: if (log.isInfoEnabled())
291: log
292: .info("Config.PROP_APPLICATION_RESOURCES_DEFAULT_LOCATION set to: "
293: + value);
294:
295: value = determineLocation(getServletConfig().getInitParameter(
296: Config.PROP_APPLICATION_RESOURCES_OVERRIDE_LOCATION));
297: Config.setProperty(
298: Config.PROP_APPLICATION_RESOURCES_OVERRIDE_LOCATION,
299: value);
300: if (log.isInfoEnabled())
301: log
302: .info("Config.PROP_APPLICATION_RESOURCES_OVERRIDE_LOCATION set to: "
303: + value);
304:
305: try {
306: generateApplicationResources();
307: } catch (IOException e) {
308: log
309: .fatal(
310: "Error in generating ApplicationResources.properties from the Dafault and Override files",
311: e);
312: }
313: }
314:
315: /** This will check the input in the classpath. If not found, it'll then assume to be in the File system.
316: * It will then return the physical location of the file in the filesystem.
317: */
318: private static String determineLocation(String input) {
319: String output = null;
320: if (input != null && input.trim().length() > 0) {
321: try {
322: URL url = URLHelper.newExtendedURL(input);
323: output = url.getPath();
324: } catch (MalformedURLException e) {
325: File f = new File(input);
326: output = f.getPath();
327: }
328: }
329: return output;
330: }
331:
332: /** Combines the ApplicationResources.default and ApplicationResources.override files into the ApplicationResources.properties file.
333: * The locations for the files are obtained from the dynamic properties set in the Config class.
334: * If the locations are not set, then nothing will be done.
335: * @throws IOException if any I/O error occurs.
336: */
337: public static void generateApplicationResources()
338: throws IOException {
339: String applicationResourcesLocation = (String) Config
340: .getProperty(
341: Config.PROP_APPLICATION_RESOURCES_LOCATION,
342: null);
343: String applicationResourcesDefaultLocation = (String) Config
344: .getProperty(
345: Config.PROP_APPLICATION_RESOURCES_DEFAULT_LOCATION,
346: null);
347: String applicationResourcesOverrideLocation = (String) Config
348: .getProperty(
349: Config.PROP_APPLICATION_RESOURCES_OVERRIDE_LOCATION,
350: null);
351:
352: if (applicationResourcesLocation == null
353: || (applicationResourcesDefaultLocation == null && applicationResourcesOverrideLocation == null)) {
354: if (log.isInfoEnabled())
355: log
356: .info("The locations have not been set for ApplicationResources.properties and its default, override file. No new ApplicationResources.properties file generated.");
357: } else {
358: OutputStream applicationResourcesOutputStream = null;
359: InputStream applicationResourcesDefaultInputStream = null;
360: InputStream applicationResourcesOverrideInputStream = null;
361: try {
362: // Load the 2 properties file, such that the Override file overrides the Default file
363: Properties properties = new Properties();
364: if (applicationResourcesDefaultLocation != null) {
365: applicationResourcesDefaultInputStream = new BufferedInputStream(
366: new FileInputStream(
367: applicationResourcesDefaultLocation));
368: properties
369: .load(applicationResourcesDefaultInputStream);
370: }
371: if (applicationResourcesOverrideLocation != null) {
372: File applicationResourcesOverrideFile = new File(
373: applicationResourcesOverrideLocation);
374: if (applicationResourcesOverrideFile.exists()) {
375: applicationResourcesOverrideInputStream = new BufferedInputStream(
376: new FileInputStream(
377: applicationResourcesOverrideLocation));
378: properties
379: .load(applicationResourcesOverrideInputStream);
380: }
381: }
382:
383: // Generate the header String
384: StringBuffer buf = new StringBuffer("Generated ");
385: buf.append(applicationResourcesLocation);
386: buf.append(" from ");
387: if (applicationResourcesDefaultLocation != null)
388: buf.append(applicationResourcesDefaultLocation);
389: if (applicationResourcesDefaultLocation != null
390: && applicationResourcesOverrideLocation != null)
391: buf.append(" and ");
392: if (applicationResourcesOverrideLocation != null)
393: buf.append(applicationResourcesOverrideLocation);
394: String header = buf.toString();
395:
396: // Write out the loaded properties to the ApplicationResources.properties
397: applicationResourcesOutputStream = new BufferedOutputStream(
398: new FileOutputStream(
399: applicationResourcesLocation, false));
400: properties.store(applicationResourcesOutputStream,
401: header);
402: if (log.isInfoEnabled())
403: log.info(header);
404: } finally {
405: if (applicationResourcesOutputStream != null)
406: applicationResourcesOutputStream.close();
407: if (applicationResourcesDefaultInputStream != null)
408: applicationResourcesDefaultInputStream.close();
409: if (applicationResourcesOverrideInputStream != null)
410: applicationResourcesOverrideInputStream.close();
411: }
412: }
413: }
414: }
|