1 /**
2 * AUTOHIT 2003
3 * Copyright Erich P Gatejen (c) 1989,1997,2003,2004
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or (at
8 * your option) any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Additional license information can be found in the documentation.
19 * @author Erich P Gatejen
20 */
21 package autohit.common;
22 import autohit.common.channels.Atom;
23 import autohit.common.channels.Controller;
24 import autohit.common.channels.SimpleChannel;
25 import autohit.common.AutohitLogDrain;
26 import autohit.common.channels.Injector;
27 import autohit.common.channels.SimpleInjector;
28 import autohit.common.AutohitLogInjectorWrapper;
29
30 import autohit.common.traps.CommonsLoggerTrap;
31
32 import java.util.Hashtable;
33 import java.util.Enumeration;
34
35 /**
36 * Basic autohit log manager. If anyone orders a die or lets an instance
37 * fall out of scope, it will invalidate all instances (by killing the channel).
38 * Don't do it. You should really only have one of these--ever.
39 * <p>
40 * This will not create a channel controller!
41 * @see autohit.common.channels.Controller
42 *
43 * @author Erich P. Gatejen
44 * @version 1.0
45 * <i>Version History</i>
46 * <code>EPG - Rewrite - 23Apr03</code>
47 *
48 */
49 public class AutohitBasicLogManager {
50
51 //private static Controller myLogController; // we aren't doing this
52 private static SimpleChannel controlChannel;
53 private static SimpleChannel clientChannel;
54 private static AutohitLogDrain controlDrain;
55 private static AutohitLogDrain clientDrain;
56 private static Injector rootInjector;
57 private static AutohitLogInjectorWrapper rootLogger;
58 private static Hashtable clientTable;
59
60 /**
61 * Default constructor. Creates a generic Drain to System.err.
62 */
63 public AutohitBasicLogManager() throws Exception {
64 // make sure we only init once.
65 if (controlDrain != null)
66 return;
67
68 // Create a generic drain and call the other constructor
69 controlDrain = new AutohitLogDrainDefault();
70 controlDrain.init(System.err);
71 clientDrain = new AutohitLogDrainDefault();
72 clientDrain.init(System.err);
73 init(controlDrain, clientDrain);
74 }
75
76 /**
77 * Constructor. Specifies a specific drain. You should call this construcot
78 * only once ever during the life of a JVM.
79 * @param control A control drain
80 * @param client A client drain
81 * @throws Exception which is usually a very bad thing.
82 */
83 public AutohitBasicLogManager(AutohitLogDrain control, AutohitLogDrain client) throws Exception {
84 if (controlDrain != null)
85 throw new Exception("You can only construct with a specific drain once for the life of the JVM.");
86 controlDrain = control;
87 clientDrain = client;
88 init(control, client);
89 }
90
91 /**
92 * Constructor. Specifies a specific drain.
93 * @param control A control drain
94 * @param client A client drain
95 * @see autohit.common.AutohitLogDrain
96 * @throws Exception Which usually means something very bad happened.
97 */
98 private void init(AutohitLogDrain control, AutohitLogDrain client) throws Exception {
99
100 // Create the channels
101 controlChannel = new SimpleChannel();
102 clientChannel = new SimpleChannel();
103
104 // Register Drains
105 controlChannel.register(AutohitProperties.LOGS_CONTROL_DRAIN, control);
106 clientChannel.register(AutohitProperties.LOGS_CLIENT_DRAIN, client);
107
108 // Register the root Injector
109 rootInjector = new SimpleInjector();
110 rootLogger = new AutohitLogInjectorWrapper();
111 rootLogger.init(AutohitProperties.LOGS_ROOT_ID, rootInjector);
112 controlChannel.register(AutohitProperties.LOGS_CONTROL_INJECTOR, rootInjector);
113
114 // Set routing
115 controlChannel.requestLevel(AutohitProperties.LOGS_CONTROL_DRAIN, Atom.P_TOP);
116 controlChannel.requestType(AutohitProperties.LOGS_CONTROL_DRAIN, Atom.TYPE_LOG);
117 clientChannel.requestLevel(AutohitProperties.LOGS_CLIENT_DRAIN, Atom.P_TOP);
118 clientChannel.requestType(AutohitProperties.LOGS_CLIENT_DRAIN, Atom.TYPE_LOG);
119 // for future compatibility
120
121 // Register the channels
122 Controller.register(AutohitProperties.LOGS_CONTROL_STATION, controlChannel);
123 Controller.register(AutohitProperties.LOGS_CLIENT_STATION, clientChannel);
124
125 // Trap any commons loggers
126 // TODO move this to some other channel
127 CommonsLoggerTrap.setTrap(rootLogger);
128
129 // Make Logger cache
130 clientTable = new Hashtable();
131 }
132
133 /**
134 * Get the root logger.
135 * @return a reference to the root AutohitLogInjectorWrapper, which wraps the root injector
136 * @see autohit.common.AutohitLogInjectorWrapper
137 */
138 public AutohitLogInjectorWrapper getRootLogger() {
139 return rootLogger;
140 }
141
142 /**
143 * Get the root injector.
144 * @return a reference to the root Injector
145 * @see autohit.common.AutohitLogInjectorWrapper
146 */
147 public Injector getRootInjector() {
148 return rootInjector;
149 }
150
151 /**
152 * Add an injector to the client channel. It is a very good idea to
153 * discard the logger when you are done.
154 * @param il An injector
155 * @param id A string id for the sender. Technically, it doesn't have to be unique.
156 * @see autohit.common.channels.Injector
157 */
158 public void addClient(Injector il, String id) throws Exception {
159
160 String registerID = AutohitProperties.LOGS_CLIENT_INJECTOR + id;
161
162 // Register it
163 clientChannel.register(registerID, il);
164 clientTable.put(registerID, il);
165 }
166
167 /**
168 * It will discard a client injector
169 * @param id A string id for the sender. Needs to be the same as the one use to register it.
170 */
171 public void discardClient(String id) {
172
173 try {
174
175 // if it is in the cache, use it
176 if (clientTable.containsKey(id)) {
177 clientTable.remove(id);
178 clientChannel.removeInjector(id);
179 }
180
181 } catch (Exception e) { // don't care. null should return
182 }
183 }
184
185 /**
186 * Set pretty formatting on output
187 * @param p Set TRUE for on.
188 */
189 public void pretty(boolean p) {
190 controlDrain.setPrettyFlag(p);
191 clientDrain.setPrettyFlag(p);
192 }
193
194 /**
195 * Set timestamp formatting on output
196 * @param p Set TRUE for on.
197 */
198 public void stampit(boolean p) {
199 controlDrain.setTimestampFlag(p);
200 clientDrain.setTimestampFlag(p);
201 }
202
203 /**
204 * Get primary drain
205 * @return the primary log drain
206 */
207 public AutohitLogDrain getDrain() {
208 return controlDrain;
209 }
210
211 /**
212 * Get client drain
213 * @return the client log drain
214 */
215 public AutohitLogDrain getClientDrain() {
216 return clientDrain;
217 }
218
219 /**
220 * Discard client drain writer. This is a terrible hack.
221 * @param id the id of the drain writer to discard
222 */
223 public void discardDrainWriter(String id) {
224 try {
225 clientDrain.discardWriter(id);
226 } catch (Exception e) {
227 // do nothing
228 }
229 }
230
231 /**
232 * Turn debug logging on. It will turn debugging on for the root logger, but
233 * not any clients! you have to do that yourself.
234 */
235 public void debugOn() {
236 try {
237 rootLogger.debugFlag(true);
238 clientChannel.requestLevel(
239 AutohitProperties.LOGS_CLIENT_DRAIN,
240 Atom.P_TOP);
241 controlChannel.requestLevel(
242 AutohitProperties.LOGS_CONTROL_DRAIN,
243 Atom.P_TOP);
244 } catch (Exception e) {
245 System.out.println(
246 "!! LOGGING system failure. Cannot debugOn() for autohit.*.drain."
247 + e.getMessage());
248 }
249 }
250
251 /**
252 * Turn debug logging off
253 */
254 public void debugOff() {
255 try {
256 rootLogger.debugFlag(false);
257 clientChannel.requestLevel(
258 AutohitProperties.LOGS_CLIENT_DRAIN ,
259 Atom.ROUTINE);
260 controlChannel.requestLevel(
261 AutohitProperties.LOGS_CONTROL_DRAIN ,
262 Atom.ROUTINE);
263 } catch (Exception e) {
264 System.out.println(
265 "!! LOGGING system failure. Cannot debugOff() for autohit.*.drain."
266 + e.getMessage());
267 }
268 }
269
270 /**
271 * Die
272 */
273 public void die() {
274 try {
275
276 // Pull drain and all injectors
277 controlChannel.removeDrain(AutohitProperties.LOGS_CONTROL_DRAIN );
278 controlChannel.removeInjector(AutohitProperties.LOGS_CONTROL_INJECTOR);
279 clientChannel.removeDrain(AutohitProperties.LOGS_CLIENT_DRAIN);
280 try {
281 Object thingthang;
282 for (Enumeration e = clientTable.keys(); e.hasMoreElements();) {
283 thingthang = e.nextElement();
284 clientTable.remove(e);
285 clientChannel.removeInjector((String) thingthang);
286 }
287 } catch (Exception efc) { //dont care
288 }
289
290 // Unregister channel
291 Controller.remove(AutohitProperties.LOGS_CONTROL_STATION);
292 Controller.remove(AutohitProperties.LOGS_CLIENT_STATION);
293
294 } catch (Exception e) { // don't really care - FUBAR
295 }
296 clientChannel = null;
297 controlChannel = null;
298 }
299
300 /*
301 * finalizer
302 * Make sure the log handler is unhooked
303 */
304 protected void finalize() throws Throwable {
305 super.finalize();
306 this.die();
307 }
308
309 }
|