001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041:
042: package org.netbeans.modules.tomcat5.util;
043:
044: import java.io.File;
045: import java.io.InputStreamReader;
046: import java.util.Collections;
047: import java.util.HashMap;
048: import java.util.Map;
049: import java.util.WeakHashMap;
050: import java.util.logging.Level;
051: import java.util.logging.Logger;
052: import org.netbeans.modules.tomcat5.TomcatManager;
053: import org.netbeans.modules.tomcat5.TomcatManagerConfig;
054: import org.netbeans.modules.tomcat5.TomcatModule;
055: import org.netbeans.modules.tomcat5.TomcatModuleConfig;
056: import org.openide.NotifyDescriptor;
057: import org.openide.DialogDisplayer;
058: import org.openide.util.NbBundle;
059:
060: /**
061: * <code>LogManager</code> manages all context and shared context logs for one
062: * Tomcat server instace (one <code>TomcatManager</code>).
063: *
064: * @author Stepan Herold
065: */
066: public class LogManager {
067: private ServerLog serverLog;
068: private LogViewer sharedContextLogViewer;
069: private LogViewer juliLogViewer;
070: private Map/*<TomcatModule, TomcatModuleConfig>*/tomcatModuleConfigs = Collections
071: .synchronizedMap(new WeakHashMap());
072: private Map/*<String, LogViewer>*/contextLogViewers = Collections
073: .synchronizedMap(new HashMap());
074: private TomcatManager manager;
075:
076: private Object serverLogLock = new Object();
077: private Object sharedContextLogLock = new Object();
078: private Object juliLogLock = new Object();
079: private Object contextLogLock = new Object();
080:
081: private Boolean juliJarExist;
082:
083: /** Creates a new instance of LogManager */
084: public LogManager(TomcatManager tm) {
085: manager = tm;
086: }
087:
088: // ------- server log (output) ---------------------------------------------
089:
090: /**
091: * Open the server log (output).
092: */
093: public void openServerLog() {
094: final Process process = manager.getTomcatProcess();
095: assert process != null;
096: synchronized (serverLogLock) {
097: if (serverLog != null) {
098: serverLog.takeFocus();
099: return;
100: }
101: serverLog = new ServerLog(manager, manager
102: .getTomcatProperties().getDisplayName(),
103: new InputStreamReader(process.getInputStream()),
104: new InputStreamReader(process.getErrorStream()),
105: true, false);
106: serverLog.start();
107: }
108: //PENDING: currently we copy only Tomcat std & err output. We should
109: // also support copying to Tomcat std input.
110: new Thread() {
111: public void run() {
112: try {
113: process.waitFor();
114: Thread.sleep(2000); // time for server log
115: } catch (InterruptedException e) {
116: } finally {
117: serverLog.interrupt();
118: }
119: }
120: }.start();
121: }
122:
123: /**
124: * Stop the server log thread, if started.
125: */
126: public void closeServerLog() {
127: synchronized (serverLogLock) {
128: if (serverLog != null) {
129: serverLog.interrupt();
130: serverLog = null;
131: }
132: }
133: }
134:
135: /**
136: * Can be the server log (output) displayed?
137: *
138: * @return <code>true</code> if the server log can be displayed, <code>false</code>
139: * otherwise.
140: */
141: public boolean hasServerLog() {
142: return manager.getTomcatProcess() != null;
143: }
144:
145: // ------- end of server log (output) --------------------------------------
146:
147: // ------- shared context log ----------------------------------------------
148:
149: /**
150: * Opens shared context log. Shared context log can be defined in the host or
151: * engine element. Definition in the host element overrides definition in the
152: * engine element.
153: */
154: public void openSharedContextLog() {
155: TomcatManagerConfig tomcatManagerConfig = manager
156: .getTomcatManagerConfig();
157: tomcatManagerConfig.refresh();
158: if (!tomcatManagerConfig.hasLogger()) {
159: return;
160: }
161: LogViewer newSharedContextLog = null;
162: try {
163: TomcatProperties tp = manager.getTomcatProperties();
164: newSharedContextLog = new LogViewer(manager, null,
165: tomcatManagerConfig.loggerClassName(),
166: tomcatManagerConfig.loggerDir(),
167: tomcatManagerConfig.loggerPrefix(),
168: tomcatManagerConfig.loggerSuffix(),
169: tomcatManagerConfig.loggerTimestamp(), false);
170: } catch (UnsupportedLoggerException e) {
171: NotifyDescriptor notDesc = new NotifyDescriptor.Message(
172: NbBundle.getMessage(LogManager.class,
173: "MSG_UnsupportedLogger", e
174: .getLoggerClassName()));
175: DialogDisplayer.getDefault().notify(notDesc);
176: return;
177: } catch (NullPointerException npe) {
178: Logger.getLogger(LogManager.class.getName()).log(
179: Level.INFO, null, npe);
180: }
181:
182: // ensure only one thread will be opened
183: synchronized (sharedContextLogLock) {
184: if (sharedContextLogViewer != null
185: && sharedContextLogViewer.isOpen()
186: && !sharedContextLogViewer
187: .equals(newSharedContextLog)) {
188: sharedContextLogViewer.removeAllLogViewerStopListener();
189: sharedContextLogViewer.close();
190: sharedContextLogViewer = newSharedContextLog;
191: sharedContextLogViewer
192: .addLogViewerStopListener(new LogViewer.LogViewerStopListener() {
193: public void callOnStop() {
194: synchronized (sharedContextLogLock) {
195: sharedContextLogViewer = null;
196: }
197: }
198: });
199: sharedContextLogViewer.start();
200: } else if (sharedContextLogViewer == null
201: || !sharedContextLogViewer.isOpen()) {
202: if (sharedContextLogViewer != null) {
203: sharedContextLogViewer
204: .removeAllLogViewerStopListener();
205: }
206: sharedContextLogViewer = newSharedContextLog;
207: sharedContextLogViewer
208: .addLogViewerStopListener(new LogViewer.LogViewerStopListener() {
209: public void callOnStop() {
210: synchronized (sharedContextLogLock) {
211: sharedContextLogViewer = null;
212: }
213: }
214: });
215: sharedContextLogViewer.start();
216: }
217: sharedContextLogViewer.takeFocus();
218: }
219: }
220:
221: /**
222: * Is shared context log defined for this server?
223: *
224: * @return <code>true</code> shared context log is defined, <code>false</code>
225: * otherwise.
226: */
227: public boolean hasSharedLogger() {
228: TomcatManagerConfig tomcatManagerConfig = manager
229: .getTomcatManagerConfig();
230: tomcatManagerConfig.refresh();
231: return tomcatManagerConfig.hasLogger();
232: }
233:
234: // ------- end of shared context log ---------------------------------------
235:
236: // ------- juli log --------------------------------------------------------
237:
238: public synchronized boolean hasJuliLog() {
239: if (juliJarExist == null) {
240: if (new File(manager.getTomcatProperties()
241: .getCatalinaHome(), "bin/tomcat-juli.jar").exists()) { // NOI18N
242: juliJarExist = Boolean.TRUE;
243: } else {
244: juliJarExist = Boolean.FALSE;
245: }
246: }
247: return juliJarExist.booleanValue();
248: }
249:
250: public void openJuliLog() {
251: // ensure only one thread will be opened
252: synchronized (juliLogLock) {
253: if (juliLogViewer == null || !juliLogViewer.isOpen()) {
254: if (juliLogViewer != null) {
255: juliLogViewer.removeAllLogViewerStopListener();
256: }
257: try {
258: TomcatProperties tp = manager.getTomcatProperties();
259: juliLogViewer = new LogViewer(manager, null, null,
260: null, "localhost.", null, true, false); // NOI18N
261: juliLogViewer.setDisplayName(NbBundle.getMessage(
262: LogManager.class, "TXT_JuliLogDisplayName",
263: tp.getDisplayName()));
264: } catch (UnsupportedLoggerException e) { // should never occur
265: Logger.getLogger(LogManager.class.getName()).log(
266: Level.INFO, null, e);
267: return;
268: } catch (NullPointerException npe) {
269: Logger.getLogger(LogManager.class.getName()).log(
270: Level.INFO, null, npe);
271: return;
272: }
273: juliLogViewer
274: .addLogViewerStopListener(new LogViewer.LogViewerStopListener() {
275: public void callOnStop() {
276: synchronized (juliLogLock) {
277: juliLogViewer = null;
278: }
279: }
280: });
281: juliLogViewer.start();
282: }
283: juliLogViewer.takeFocus();
284: }
285: }
286:
287: // ------- end of juli log -------------------------------------------------
288:
289: // ------- context log -----------------------------------------------------
290:
291: /**
292: * Open a context log for the specified module.
293: *
294: * @param module its context log should be opened.
295: */
296: public void openContextLog(TomcatModule module) {
297: final String moduleID = module.getModuleID();
298: Object o = tomcatModuleConfigs.get(module);
299: TomcatModuleConfig moduleConfig = null;
300: LogViewer contextLog = null;
301: if (o == null) {
302: moduleConfig = new TomcatModuleConfig(module.getDocRoot(),
303: module.getPath(), manager.getTomcatManagerConfig()
304: .serverXmlPath());
305: tomcatModuleConfigs.put(module, moduleConfig);
306: } else {
307: moduleConfig = (TomcatModuleConfig) o;
308: moduleConfig.refresh();
309: }
310: if (!moduleConfig.hasLogger())
311: return;
312: contextLog = (LogViewer) contextLogViewers.get(moduleID);
313: LogViewer newContextLog = null;
314: try {
315: newContextLog = new LogViewer(manager, module.getPath(),
316: moduleConfig.loggerClassName(), moduleConfig
317: .loggerDir(), moduleConfig.loggerPrefix(),
318: moduleConfig.loggerSuffix(), moduleConfig
319: .loggerTimestamp(), false);
320: } catch (UnsupportedLoggerException e) {
321: NotifyDescriptor notDesc = new NotifyDescriptor.Message(
322: NbBundle.getMessage(LogManager.class,
323: "MSG_UnsupportedLogger", e
324: .getLoggerClassName()));
325: DialogDisplayer.getDefault().notify(notDesc);
326: return;
327: } catch (NullPointerException npe) {
328: Logger.getLogger(LogManager.class.getName()).log(
329: Level.INFO, null, npe);
330: }
331:
332: // ensure only one thread will be opened
333: synchronized (contextLogLock) {
334: if (contextLog != null && contextLog.isOpen()
335: && !contextLog.equals(newContextLog)) {
336: contextLog.removeAllLogViewerStopListener();
337: contextLog.close();
338: contextLog = newContextLog;
339: contextLog
340: .addLogViewerStopListener(new LogViewer.LogViewerStopListener() {
341: public void callOnStop() {
342: contextLogViewers.remove(moduleID);
343: }
344: });
345: contextLogViewers.put(moduleID, contextLog);
346: contextLog.start();
347: } else if (contextLog == null || !contextLog.isOpen()) {
348: if (contextLog != null) {
349: contextLog.removeAllLogViewerStopListener();
350: }
351: contextLog = newContextLog;
352: contextLog
353: .addLogViewerStopListener(new LogViewer.LogViewerStopListener() {
354: public void callOnStop() {
355: contextLogViewers.remove(moduleID);
356: }
357: });
358: contextLogViewers.put(moduleID, contextLog);
359: contextLog.start();
360: }
361: }
362: contextLog.takeFocus();
363: }
364:
365: /**
366: * Is context log defined for the specified module.
367: *
368: * @param module which should be examined.
369: * @return <code>true</code> if specified module has a context log defined,
370: * <code>false</code> otherwise.
371: */
372: public boolean hasContextLogger(TomcatModule module) {
373: Object o = tomcatModuleConfigs.get(module);
374: TomcatModuleConfig moduleConfig = null;
375: if (o == null) {
376: moduleConfig = new TomcatModuleConfig(module.getDocRoot(),
377: module.getPath(), manager.getTomcatManagerConfig()
378: .serverXmlPath());
379: tomcatModuleConfigs.put(module, moduleConfig);
380: } else {
381: moduleConfig = (TomcatModuleConfig) o;
382: moduleConfig.refresh();
383: }
384: return moduleConfig.hasLogger();
385: }
386:
387: // ------- end of context log ----------------------------------------------
388: }
|