001: /******************************************************************************
002: * ResponderLOGCONFIG.java
003: * ****************************************************************************/package org.openlaszlo.servlets.responders;
004:
005: import java.io.*;
006: import java.util.Properties;
007: import javax.servlet.ServletConfig;
008: import javax.servlet.ServletException;
009: import javax.servlet.ServletOutputStream;
010: import javax.servlet.http.HttpServletRequest;
011: import javax.servlet.http.HttpServletResponse;
012: import org.openlaszlo.utils.FileUtils;
013: import org.openlaszlo.utils.StringUtils;
014: import org.openlaszlo.server.ConfigDir;
015: import org.openlaszlo.server.LPS;
016:
017: import org.xml.sax.*;
018: import org.apache.log4j.*;
019: import org.apache.log4j.xml.*;
020: import org.w3c.dom.*;
021: import javax.xml.parsers.*;
022: import javax.servlet.http.HttpServlet;
023:
024: public final class ResponderLOGCONFIG extends ResponderAdmin {
025: private static HttpServlet mServlet = null;
026: private static boolean mIsInitialized = false;
027: private static DocumentBuilder mBuilder = null;
028: private static Document mDocument = null;
029: private static boolean mSaveConfig = false;
030: private static File mLogFile = null;
031: /** Servlet who we're logging on behalf of */
032: private static HttpServlet servlet = null;
033:
034: private static class SaveConfigException extends IOException {
035: public SaveConfigException() {
036: super ();
037: }
038:
039: public SaveConfigException(String s) {
040: super (s);
041: }
042: }
043:
044: public static File getLogFile() {
045: return mLogFile;
046: }
047:
048: synchronized protected void respondAdmin(HttpServletRequest req,
049: HttpServletResponse res) throws IOException {
050: res.setContentType("text/xml");
051:
052: String reread = req.getParameter("reread");
053: String xml = req.getParameter("xml");
054: String save = req.getParameter("save");
055:
056: mSaveConfig = (save != null && save.equals("1"));
057:
058: try {
059: if (xml != null) {
060: configure(xml);
061: } else if (reread != null && reread.equals("1")) {
062: configure(mServlet);
063: }
064: } catch (ParserConfigurationException e) {
065: respondWithException(res, e);
066: return;
067: } catch (SAXException e) {
068: respondWithException(res, e);
069: return;
070: } catch (SaveConfigException e) {
071: respondWithException(res, e);
072: return;
073: }
074:
075: if (mDocument == null) {
076: respondWithErrorXML(res,
077: /* (non-Javadoc)
078: * @i18n.test
079: * @org-mes="LPS log not configured"
080: */
081: org.openlaszlo.i18n.LaszloMessages.getMessage(
082: ResponderLOGCONFIG.class.getName(), "051018-93"));
083: return;
084: }
085:
086: printNode(new PrintStream(res.getOutputStream()), mDocument, "");
087: }
088:
089: /**
090: * Configure log4j with xml configuration file. Also sets the servlet we're logging for.
091: * @param servlet servlet to log configured info. Pass null if you don't want loginfo.
092: */
093: synchronized public static void configure(HttpServlet servlet)
094: throws IOException, SecurityException,
095: ParserConfigurationException, SAXException {
096:
097: if (mBuilder == null)
098: mBuilder = DocumentBuilderFactory.newInstance()
099: .newDocumentBuilder();
100: String logfile = null;
101: String configFile = getConfigurationFile();
102: if (configFile != null) {
103: String uri = "file:///" + configFile;
104: logfile = configure(mBuilder.parse(uri), null);
105: } else {
106: configFile = LPS.getConfigDirectory() + File.separator
107: + "lps.xml";
108: logfile = configureWithLPSConfig(configFile);
109: }
110:
111: if (servlet != null) {
112: mServlet = servlet;
113: }
114:
115: if (mServlet != null) {
116: servlet.log(
117: /* (non-Javadoc)
118: * @i18n.test
119: * @org-mes="Detailed LPS log is at " + p[0]
120: */
121: org.openlaszlo.i18n.LaszloMessages.getMessage(
122: ResponderLOGCONFIG.class.getName(), "051018-133",
123: new Object[] { logfile }));
124: servlet.log(
125: /* (non-Javadoc)
126: * @i18n.test
127: * @org-mes="LPS log configured with " + p[0]
128: */
129: org.openlaszlo.i18n.LaszloMessages.getMessage(
130: ResponderLOGCONFIG.class.getName(), "051018-141",
131: new Object[] { configFile }));
132: }
133: }
134:
135: /**
136: * Configure using lps.xml
137: */
138: synchronized public static String configureWithLPSConfig(
139: String lpsConfigFile) throws SAXException, IOException {
140:
141: String logfile = null;
142: String uri = "file:///" + lpsConfigFile;
143: Document doc = mBuilder.parse(uri);
144: NodeList nl = doc.getElementsByTagName("log4j:configuration");
145:
146: if (0 < nl.getLength()) {
147: Document tmpdoc = mBuilder.newDocument();
148: Node node = tmpdoc.importNode(nl.item(0), true);
149: tmpdoc.appendChild(node);
150: logfile = configure(tmpdoc, null);
151: }
152:
153: return logfile;
154: }
155:
156: /**
157: * Configure log4j with xml.
158: */
159: synchronized public static void configure(String xml)
160: throws IOException, SecurityException,
161: ParserConfigurationException, SAXException {
162: if (mBuilder == null)
163: mBuilder = DocumentBuilderFactory.newInstance()
164: .newDocumentBuilder();
165: configure(mBuilder
166: .parse(new InputSource(new StringReader(xml))), null);
167: }
168:
169: /**
170: * Configure log4j with DOM. Create lps.log, if File param has not be
171: * configured.
172: */
173: synchronized private static String configure(Document doc,
174: String replaceFileName) throws IOException,
175: SecurityException {
176: String logFileName = null;
177:
178: Element root = doc.getDocumentElement();
179: NodeList appenderList = root.getElementsByTagName("appender");
180: for (int i = 0; i < appenderList.getLength(); i++) {
181:
182: Element appender = (Element) appenderList.item(i);
183: String appenderName = appender.getAttribute("name");
184: if (appenderName.equals("lps")) {
185: NodeList paramList = appender
186: .getElementsByTagName("param");
187: for (int j = 0; j < paramList.getLength(); j++) {
188:
189: // Look for File param in lps appender.
190: Element param = (Element) paramList.item(j);
191: String paramName = param.getAttribute("name");
192: if (paramName.equals("File")) {
193: if (replaceFileName != null) {
194: replaceFileName = StringUtils.replace(
195: replaceFileName, '\\', "/");
196: param
197: .setAttribute("value",
198: replaceFileName);
199: }
200: logFileName = param.getAttribute("value");
201: break;
202: }
203: }
204:
205: // Create lps.log file iff File param does not exist. Also,
206: // replace File option if replaceFileName is passed in.
207: if (logFileName == null) {
208:
209: logFileName = LPS.getWorkDirectory()
210: + File.separator + "logs" + File.separator
211: + "lps.log";
212:
213: // Seems as if we have to escape back-slashes in log4j.xml
214: // strings.
215: logFileName = StringUtils.replace(logFileName,
216: '\\', "/");
217: try {
218: Element p = doc.createElement("param");
219: p.setAttribute("name", "File");
220: p.setAttribute("value", logFileName);
221:
222: // param must come after errorHandler, if it exists. See
223: // log4j.dtd for more info.
224: NodeList nodes = appender.getChildNodes();
225: for (int k = 0; k < nodes.getLength(); k++) {
226: Node n = nodes.item(k);
227: if (n.getNodeType() == Node.ELEMENT_NODE) {
228: Element e = (Element) n;
229: if (e.getTagName().equals(
230: "errorHandler"))
231: n = e.getNextSibling();
232: appender.insertBefore(p, n);
233: break;
234: }
235: }
236: } catch (DOMException e) {
237: Logger.getLogger(ResponderLOGCONFIG.class)
238: .debug("DOMException: ", e);
239: logFileName = null;
240: }
241: }
242:
243: if (!logFileName.equals("")) {
244: // Sanity check for logfile as configured
245: mLogFile = new File(logFileName);
246: File logFileDir = mLogFile.getParentFile();
247: if (logFileDir != null)
248: logFileDir.mkdirs();
249: mLogFile.createNewFile();
250: }
251: break;
252: }
253: }
254:
255: DOMConfigurator.configure(root);
256: mDocument = doc;
257:
258: if (servlet != null) {
259: servlet.log(
260: /* (non-Javadoc)
261: * @i18n.test
262: * @org-mes="LPS log file is now " + p[0]
263: */
264: org.openlaszlo.i18n.LaszloMessages.getMessage(
265: ResponderLOGCONFIG.class.getName(), "051018-274",
266: new Object[] { logFileName }));
267: }
268:
269: try {
270: if (mSaveConfig) {
271: String configDir = LPS.getConfigDirectory();
272: FileOutputStream out = new FileOutputStream(new File(
273: configDir + File.separator + "log4j.xml"));
274: printNode(new PrintStream(out), mDocument, "");
275: out.close();
276: }
277: } catch (IOException e) {
278: throw new SaveConfigException(
279: /* (non-Javadoc)
280: * @i18n.test
281: * @org-mes="server configured but could not write out configuration."
282: */
283: org.openlaszlo.i18n.LaszloMessages.getMessage(
284: ResponderLOGCONFIG.class.getName(), "051018-293"));
285: }
286:
287: return logFileName;
288: }
289:
290: /**
291: * Prety much ripped from:
292: *
293: * http://www-106.ibm.com/developerworks/java/library/x-jaxp/TestDOMParsing.java
294: */
295: synchronized private static void printNode(PrintStream out,
296: Node node, String indent) throws IOException {
297: switch (node.getNodeType()) {
298: case Node.DOCUMENT_NODE:
299: // recurse on each child
300: NodeList nodes = node.getChildNodes();
301: if (nodes != null) {
302: for (int i = 0; i < nodes.getLength(); i++) {
303: printNode(out, nodes.item(i), "");
304: }
305: }
306: break;
307:
308: case Node.ELEMENT_NODE:
309: String name = node.getNodeName();
310: out.print(indent + "<" + name);
311: NamedNodeMap attributes = node.getAttributes();
312: for (int i = 0; i < attributes.getLength(); i++) {
313: Node current = attributes.item(i);
314: out.print(" " + current.getNodeName() + "=\""
315: + current.getNodeValue() + "\"");
316: }
317: out.print(">\n\n");
318:
319: // recurse on each child
320: NodeList children = node.getChildNodes();
321: if (children != null) {
322: for (int i = 0; i < children.getLength(); i++) {
323: printNode(out, children.item(i), indent + " ");
324: }
325: }
326:
327: out.print(indent + "</" + name + ">\n\n");
328: break;
329:
330: case Node.COMMENT_NODE:
331: case Node.TEXT_NODE:
332: break;
333: }
334: }
335:
336: /**
337: * Clear the log file.
338: * @param status clear log status. Log can be cleared, but state can be bad
339: * if log file can't be reset.
340: */
341: synchronized public static boolean clearLog(String[] status) {
342: String path = mLogFile.getAbsolutePath();
343: boolean cleared = false;
344:
345: try {
346: // Let go of log handle
347: configure(mDocument, "");
348: } catch (Exception e) {
349: if (status != null)
350: status[0] = "can't reconfigure log";
351: Logger.getLogger(ResponderLOGCONFIG.class).info(
352: "can't reconfigure log");
353: return cleared;
354: }
355:
356: try {
357: cleared = new File(path).delete();
358: } catch (SecurityException e) {
359: Logger.getLogger(ResponderLOGCONFIG.class).info(
360: "can't clear log: ", e);
361: }
362:
363: try {
364: // Reset log handle
365: configure(mDocument, path);
366: } catch (Exception e) {
367: if (status != null)
368: status[0] = "can't reset log";
369: Logger.getLogger(ResponderLOGCONFIG.class).info(
370: "can't reset log");
371: }
372:
373: return cleared;
374: }
375:
376: /**
377: * Find log4j.xml configuration file.
378: */
379: private static String getConfigurationFile()
380: throws FileNotFoundException {
381: String configDir = LPS.getConfigDirectory();
382: String filename = configDir + File.separator + "log4j.xml";
383: if (!new File(filename).isFile()) {
384: filename = null;
385: }
386: return filename;
387: }
388:
389: public int getMimeType() {
390: return MIME_TYPE_XML;
391: }
392: }
|