Crossfire JXClient, Trunk
ResultLogManager.java
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * - Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *
11  * - Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in the
13  * documentation and/or other materials provided with the distribution.
14  *
15  * - Neither the name of Oracle nor the names of its
16  * contributors may be used to endorse or promote products derived
17  * from this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
20  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 /*
33  * This source code is provided to illustrate the usage of a given feature
34  * or technique and has been deliberately simplified. Additional steps
35  * required for a production-quality application, such as security checks,
36  * input validation and proper error handling, might not be present in
37  * this sample code.
38  */
39 
40 
41 package com.sun.jmx.examples.scandir;
42 
43 import static com.sun.jmx.examples.scandir.ScanManager.getNextSeqNumber;
47 import java.io.File;
48 import java.io.FileOutputStream;
49 import java.io.IOException;
50 import java.io.OutputStream;
51 import java.util.Collections;
52 import java.util.LinkedList;
53 import java.util.List;
54 import java.util.logging.Logger;
55 import javax.management.MBeanNotificationInfo;
56 import javax.management.MBeanRegistration;
57 import javax.management.MBeanServer;
58 import javax.management.Notification;
59 import javax.management.NotificationBroadcasterSupport;
60 import javax.management.ObjectName;
61 import javax.xml.bind.JAXBException;
62 
81 public class ResultLogManager extends NotificationBroadcasterSupport
82  implements ResultLogManagerMXBean, MBeanRegistration {
83 
87  public static final ObjectName RESULT_LOG_MANAGER_NAME =
89 
93  private static final Logger LOG =
94  Logger.getLogger(ResultLogManager.class.getName());
95 
96  // The memory log
97  //
98  private final List<ResultRecord> memoryLog;
99 
100  // Whether the memory log capacity was reached. In that case every
101  // new entry triggers the deletion of the eldest one.
102  //
103  private volatile boolean memCapacityReached = false;
104 
105  // The maximum number of record that the memory log can
106  // contain.
107  //
108  private volatile int memCapacity;
109 
110  // The maximum number of record that the ResultLogManager can
111  // log in the log file before creating a new file.
112  //
113  private volatile long fileCapacity;
114 
115  // The current log file.
116  //
117  private volatile File logFile;
118 
119  // The OutputStream of the current log file.
120  //
121  private volatile OutputStream logStream = null;
122 
123  // number of record that this object has logged in the log file
124  // since the log file was created. Creating a new file or clearing
125  // the log file reset this value to '0'
126  //
127  private volatile long logCount = 0;
128 
129  // The ResultLogManager config - modified whenever
130  // ScanManager.applyConfiguration is called.
131  //
132  private volatile ResultLogConfig config;
133 
139  ResultLogManager() {
140  // Instantiate the memory log - override the add() method so that
141  // it removes the head of the list when the maximum capacity is
142  // reached. Note that add() is the only method we will be calling,
143  // otherwise we would have to override all the other flavors
144  // of adding methods. Note also that this implies that the memoryLog
145  // will *always* remain encapsulated in this object and is *never*
146  // handed over (otherwise we wouldn't be able to ensure that
147  // add() is the only method ever called to add a record).
148  //
149  memoryLog =
150  Collections.synchronizedList(new LinkedList<ResultRecord>() {
151  public synchronized boolean add(ResultRecord e) {
152  final int max = getMemoryLogCapacity();
153  while (max > 0 && size() >= max) {
154  memCapacityReached = true;
155  removeFirst();
156  }
157  return super.add(e);
158  }
159  });
160 
161  // default memory capacity
162  memCapacity = 2048;
163 
164  // default file capacity: 0 means infinite ;-)
165  fileCapacity = 0;
166 
167  // by default logging to file is disabled.
168  logFile = null;
169 
170  // Until the ScanManager apply a new configuration, we're going to
171  // work with a default ResultLogConfig object.
172  config = new ResultLogConfig();
176  }
177 
178 
199  public ObjectName preRegister(MBeanServer server, ObjectName name)
200  throws Exception {
201  if (name == null)
203  objectName = name;
204  mbeanServer = server;
205  return name;
206  }
207 
217  public void postRegister(Boolean registrationDone) {
218  // Don't need to do anything here.
219  }
220 
228  public void preDeregister() throws Exception {
229  // Don't need to do anything here.
230  }
231 
237  public void postDeregister() {
238  try {
239  if (logStream != null) {
240  synchronized(this) {
241  logStream.flush();
242  logStream.close();
243  logFile = null;
244  logStream = null;
245  }
246  }
247  } catch (Exception x) {
248  LOG.finest("Failed to close log properly: "+x);
249  }
250  }
251 
256  private File createNewLogFile(String basename) throws IOException {
257  return XmlConfigUtils.createNewXmlFile(basename);
258  }
259 
269  private OutputStream checkLogFile(String basename, long maxRecords,
270  boolean force)
271  throws IOException {
272  final OutputStream newStream;
273  synchronized(this) {
274  if ((force==false) && (logCount < maxRecords))
275  return logStream;
276  final OutputStream oldStream = logStream;
277 
278  // First close the stream. On some platforms you cannot rename
279  // a file that has open streams...
280  //
281  if (oldStream != null) {
282  oldStream.flush();
283  oldStream.close();
284  }
285  final File newFile = (basename==null)?null:createNewLogFile(basename);
286 
287  newStream = (newFile==null)?null:new FileOutputStream(newFile,true);
288  logStream = newStream;
289  logFile = newFile;
290  fileCapacity = maxRecords;
291  logCount = 0;
292  }
293  sendNotification(new Notification(LOG_FILE_CHANGED,objectName,
294  getNextSeqNumber(),
295  basename));
296  return newStream;
297  }
298 
299  // see ResultLogManagerMXBean
300  public void log(ResultRecord record)
301  throws IOException {
302  if (memCapacity > 0) logToMemory(record);
303  if (logFile != null) logToFile(record);
304  }
305 
306  // see ResultLogManagerMXBean
308  return memoryLog.toArray(new ResultRecord[0]);
309  }
310 
311  // see ResultLogManagerMXBean
312  public int getMemoryLogCapacity() {
313  return memCapacity;
314  }
315 
316  // see ResultLogManagerMXBean
317  public void setMemoryLogCapacity(int maxRecords) {
318  synchronized(this) {
319  memCapacity = maxRecords;
320  if (memoryLog.size() < memCapacity)
321  memCapacityReached = false;
322  config.setMemoryMaxRecords(maxRecords);
323  }
324  }
325 
326  // see ResultLogManagerMXBean
327  public void setLogFileCapacity(long maxRecords)
328  throws IOException {
329  synchronized (this) {
330  fileCapacity = maxRecords;
331  config.setLogFileMaxRecords(maxRecords);
332  }
334  }
335 
336  // see ResultLogManagerMXBean
337  public long getLogFileCapacity() {
338  return fileCapacity;
339  }
340 
341  // see ResultLogManagerMXBean
342  public long getLoggedCount() {
343  return logCount;
344  }
345 
346  // see ResultLogManagerMXBean
347  public void newLogFile(String logname, long maxRecord)
348  throws IOException {
349  checkLogFile(logname,maxRecord,true);
352  }
353 
354  // see ResultLogManagerMXBean
355  public String getLogFileName() {
356  return getLogFileName(true);
357  }
358 
359  // see ResultLogManagerMXBean
360  public void clearLogs() throws IOException {
361  clearMemoryLog();
362  clearLogFile();
363  }
364 
365  // Clear the memory log, sends a notification indicating that
366  // the memory log was cleared.
367  //
368  private void clearMemoryLog()throws IOException {
369  synchronized(this) {
370  memoryLog.clear();
371  memCapacityReached = false;
372  }
373  sendNotification(new Notification(MEMORY_LOG_CLEARED,
374  objectName,
375  getNextSeqNumber(),"memory log cleared"));
376  }
377 
378  // Clears the log file.
379  //
380  private void clearLogFile() throws IOException {
381  // simply force the creation of a new log file.
383  }
384 
385  // Log a record to the memory log. Send a notification if the
386  // maximum capacity of the memory log is reached.
387  //
388  private void logToMemory(ResultRecord record) {
389 
390  final boolean before = memCapacityReached;
391  final boolean after;
392  synchronized(this) {
393  memoryLog.add(record);
394  after = memCapacityReached;
395  }
396  if (before==false && after==true)
397  sendNotification(new Notification(MEMORY_LOG_MAX_CAPACITY,
398  objectName,
399  getNextSeqNumber(),"memory log capacity reached"));
400  }
401 
402 
403  // Log a record to the memory log. Send a notification if the
404  // maximum capacity of the memory log is reached.
405  //
406  private void logToFile(ResultRecord record) throws IOException {
407  final String basename;
408  final long maxRecords;
409  synchronized (this) {
410  if (logFile == null) return;
411  basename = getLogFileName(false);
412  maxRecords = fileCapacity;
413  }
414 
415  // Get the stream into which we should log.
416  final OutputStream stream =
417  checkLogFile(basename,maxRecords,false);
418 
419  // logging to file now disabled - too bad.
420  if (stream == null) return;
421 
422  synchronized (this) {
423  try {
424  XmlConfigUtils.write(record,stream,true);
425  stream.flush();
426  // don't increment logCount if we were not logging in logStream.
427  if (stream == logStream) logCount++;
428  } catch (JAXBException x) {
429  final IllegalArgumentException iae =
430  new IllegalArgumentException("bad record",x);
431  LOG.finest("Failed to log record: "+x);
432  throw iae;
433  }
434  }
435  }
436 
443  public final static String LOG_FILE_CHANGED =
444  "com.sun.jmx.examples.scandir.log.file.switched";
445 
451  public final static String MEMORY_LOG_MAX_CAPACITY =
452  "com.sun.jmx.examples.scandir.log.memory.full";
453 
459  public final static String MEMORY_LOG_CLEARED =
460  "com.sun.jmx.examples.scandir.log.memory.cleared";
461 
470  public MBeanNotificationInfo[] getNotificationInfo() {
471  return new MBeanNotificationInfo[] {
472  new MBeanNotificationInfo(new String[] {
474  Notification.class.getName(),
475  "Emitted when the log file is switched")
476  ,
477  new MBeanNotificationInfo(new String[] {
479  Notification.class.getName(),
480  "Emitted when the memory log capacity is reached")
481  ,
482  new MBeanNotificationInfo(new String[] {
484  Notification.class.getName(),
485  "Emitted when the memory log is cleared")
486  };
487  }
488 
489  // Return the name of the log file, or null if logging to file is
490  // disabled.
491  private String getLogFileName(boolean absolute) {
492  synchronized (this) {
493  if (logFile == null) return null;
494  if (absolute) return logFile.getAbsolutePath();
495  return logFile.getPath();
496  }
497  }
498 
499  // This method is be called by the ScanManagerMXBean when a configuration
500  // is applied.
501  //
502  void setConfig(ResultLogConfig logConfigBean) throws IOException {
503  if (logConfigBean == null)
504  throw new IllegalArgumentException("logConfigBean is null");
505  synchronized (this) {
506  config = logConfigBean;
508  }
509  final String filename = config.getLogFileName();
510  final String logname = getLogFileName(false);
511  if ((filename != null && !filename.equals(logname))
512  || (filename == null && logname != null)) {
515  } else {
517  }
518  }
519 
520  // This method is called by the ScanManagerMXBean when
521  // applyCurrentResultLogConfig() is called.
522  //
523  ResultLogConfig getConfig() {
524  return config;
525  }
526 
527 
528  // Set by preRegister().
529  private MBeanServer mbeanServer;
530  private ObjectName objectName;
531 
532 
533 
534 }
com.sun.jmx.examples.scandir.ResultLogManager.MEMORY_LOG_CLEARED
static final String MEMORY_LOG_CLEARED
Definition: ResultLogManager.java:459
com.sun.jmx.examples.scandir.ResultLogManager.getMemoryLogCapacity
int getMemoryLogCapacity()
Definition: ResultLogManager.java:312
com.sun.jmx.examples.scandir.config.ResultLogConfig.setLogFileMaxRecords
void setLogFileMaxRecords(long logFileMaxRecords)
Definition: ResultLogConfig.java:130
com.sun.jmx.examples.scandir.ResultLogManager.LOG_FILE_CHANGED
static final String LOG_FILE_CHANGED
Definition: ResultLogManager.java:443
com.sun.jmx.examples.scandir.ResultLogManager.clearMemoryLog
void clearMemoryLog()
Definition: ResultLogManager.java:368
com.sun.jmx.examples.scandir.ScanManager
Definition: ScanManager.java:103
com.sun.jmx.examples.scandir.ResultLogManager.postRegister
void postRegister(Boolean registrationDone)
Definition: ResultLogManager.java:217
com.sun.jmx.examples.scandir.ResultLogManager.getNotificationInfo
MBeanNotificationInfo[] getNotificationInfo()
Definition: ResultLogManager.java:470
com.sun.jmx.examples.scandir.config
Definition: DirectoryScannerConfig.java:41
com.sun.jmx.examples.scandir.ResultLogManager.preDeregister
void preDeregister()
Definition: ResultLogManager.java:228
com.sun.jmx.examples.scandir.ResultLogManager.getLogFileName
String getLogFileName()
Definition: ResultLogManager.java:355
com.sun.jmx.examples.scandir.ResultLogManager.checkLogFile
OutputStream checkLogFile(String basename, long maxRecords, boolean force)
Definition: ResultLogManager.java:269
com.sun.jmx.examples.scandir.config.ResultRecord
Definition: ResultRecord.java:62
com.sun.jmx.examples.scandir
com.sun.jmx.examples.scandir.ResultLogManager.getLogFileCapacity
long getLogFileCapacity()
Definition: ResultLogManager.java:337
com.sun.jmx.examples.scandir.ResultLogManager.getLogFileName
String getLogFileName(boolean absolute)
Definition: ResultLogManager.java:491
com.sun.jmx.examples.scandir.ResultLogManager.getLoggedCount
long getLoggedCount()
Definition: ResultLogManager.java:342
com.sun.jmx.examples.scandir.ResultLogManager.MEMORY_LOG_MAX_CAPACITY
static final String MEMORY_LOG_MAX_CAPACITY
Definition: ResultLogManager.java:451
com.sun.jmx.examples.scandir.ResultLogManager.getMemoryLog
ResultRecord[] getMemoryLog()
Definition: ResultLogManager.java:307
com.sun.jmx.examples.scandir.ResultLogManager.clearLogFile
void clearLogFile()
Definition: ResultLogManager.java:380
com.sun.jmx.examples.scandir.config.XmlConfigUtils.write
static void write(ScanManagerConfig bean, OutputStream os, boolean fragment)
Definition: XmlConfigUtils.java:256
com.sun.jmx.examples.scandir.ResultLogManager.log
void log(ResultRecord record)
Definition: ResultLogManager.java:300
com.sun.jmx.examples.scandir.config.ResultLogConfig.getLogFileMaxRecords
long getLogFileMaxRecords()
Definition: ResultLogConfig.java:119
com.sun.jmx.examples.scandir.ResultLogManager.fileCapacity
volatile long fileCapacity
Definition: ResultLogManager.java:113
com.sun.jmx.examples.scandir.config.ResultLogConfig.getLogFileName
String getLogFileName()
Definition: ResultLogConfig.java:99
com.sun.jmx.examples
com.sun.jmx.examples.scandir.config.XmlConfigUtils
Definition: XmlConfigUtils.java:62
com.sun.jmx.examples.scandir.ResultLogManager.LOG
static final Logger LOG
Definition: ResultLogManager.java:93
com.sun.jmx.examples.scandir.ScanManager.makeSingletonName
static final ObjectName makeSingletonName(Class clazz)
Definition: ScanManager.java:197
com.sun.jmx.examples.scandir.config.ResultLogConfig.setMemoryMaxRecords
void setMemoryMaxRecords(int memoryMaxRecords)
Definition: ResultLogConfig.java:155
com.sun
com.sun.jmx.examples.scandir.config.ResultLogConfig
Definition: ResultLogConfig.java:60
com.sun.jmx.examples.scandir.ResultLogManagerMXBean
Definition: ResultLogManagerMXBean.java:73
com.sun.jmx.examples.scandir.ResultLogManager.objectName
ObjectName objectName
Definition: ResultLogManager.java:530
com.sun.jmx.examples.scandir.ResultLogManager.preRegister
ObjectName preRegister(MBeanServer server, ObjectName name)
Definition: ResultLogManager.java:199
com.sun.jmx.examples.scandir.config.ResultLogConfig.getMemoryMaxRecords
int getMemoryMaxRecords()
Definition: ResultLogConfig.java:143
com.sun.jmx.examples.scandir.ResultLogManager.createNewLogFile
File createNewLogFile(String basename)
Definition: ResultLogManager.java:256
com.sun.jmx.examples.scandir.ResultLogManager.logToMemory
void logToMemory(ResultRecord record)
Definition: ResultLogManager.java:388
com.sun.jmx.examples.scandir.config.XmlConfigUtils.createNewXmlFile
static File createNewXmlFile(String basename)
Definition: XmlConfigUtils.java:389
com.sun.jmx.examples.scandir.ResultLogManager.logFile
volatile File logFile
Definition: ResultLogManager.java:117
com.sun.jmx.examples.scandir.ResultLogManager.setLogFileCapacity
void setLogFileCapacity(long maxRecords)
Definition: ResultLogManager.java:327
com
com.sun.jmx
com.sun.jmx.examples.scandir.ResultLogManager.logToFile
void logToFile(ResultRecord record)
Definition: ResultLogManager.java:406
com.sun.jmx.examples.scandir.ResultLogManager.config
volatile ResultLogConfig config
Definition: ResultLogManager.java:132
com.sun.jmx.examples.scandir.ResultLogManager.setMemoryLogCapacity
void setMemoryLogCapacity(int maxRecords)
Definition: ResultLogManager.java:317
com.sun.jmx.examples.scandir.ResultLogManager.RESULT_LOG_MANAGER_NAME
static final ObjectName RESULT_LOG_MANAGER_NAME
Definition: ResultLogManager.java:87
com.sun.jmx.examples.scandir.ResultLogManager.mbeanServer
MBeanServer mbeanServer
Definition: ResultLogManager.java:529
com.sun.jmx.examples.scandir.ResultLogManager.memoryLog
final List< ResultRecord > memoryLog
Definition: ResultLogManager.java:98
com.sun.jmx.examples.scandir.ResultLogManager.clearLogs
void clearLogs()
Definition: ResultLogManager.java:360
com.sun.jmx.examples.scandir.ResultLogManager.logCount
volatile long logCount
Definition: ResultLogManager.java:127
com.sun.jmx.examples.scandir.ResultLogManager.memCapacityReached
volatile boolean memCapacityReached
Definition: ResultLogManager.java:103
com.sun.jmx.examples.scandir.config.ResultLogConfig.setLogFileName
void setLogFileName(String logFileName)
Definition: ResultLogConfig.java:108
com.sun.jmx.examples.scandir.ResultLogManager.memCapacity
volatile int memCapacity
Definition: ResultLogManager.java:108
com.sun.jmx.examples.scandir.ResultLogManager
Definition: ResultLogManager.java:81
com.sun.jmx.examples.scandir.ResultLogManager.postDeregister
void postDeregister()
Definition: ResultLogManager.java:237
com.sun.jmx.examples.scandir.ResultLogManager.newLogFile
void newLogFile(String logname, long maxRecord)
Definition: ResultLogManager.java:347
com.sun.jmx.examples.scandir.ResultLogManager.logStream
volatile OutputStream logStream
Definition: ResultLogManager.java:121