1 40 41 package com.sun.jmx.examples.scandir; 42 43 import static com.sun.jmx.examples.scandir.ScanManager.getNextSeqNumber; 44 import com.sun.jmx.examples.scandir.config.ResultLogConfig; 45 import com.sun.jmx.examples.scandir.config.XmlConfigUtils; 46 import com.sun.jmx.examples.scandir.config.ResultRecord; 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 63 81 public class ResultLogManager extends NotificationBroadcasterSupport 82 implements ResultLogManagerMXBean, MBeanRegistration { 83 84 87 public static final ObjectName RESULT_LOG_MANAGER_NAME = 88 ScanManager.makeSingletonName(ResultLogManagerMXBean.class); 89 90 93 private static final Logger LOG = 94 Logger.getLogger(ResultLogManager.class.getName()); 95 96 private final List <ResultRecord> memoryLog; 99 100 private volatile boolean memCapacityReached = false; 104 105 private volatile int memCapacity; 109 110 private volatile long fileCapacity; 114 115 private volatile File logFile; 118 119 private volatile OutputStream logStream = null; 122 123 private volatile long logCount = 0; 128 129 private volatile ResultLogConfig config; 133 134 139 ResultLogManager() { 140 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 memCapacity = 2048; 163 164 fileCapacity = 0; 166 167 logFile = null; 169 170 config = new ResultLogConfig(); 173 config.setMemoryMaxRecords(memCapacity); 174 config.setLogFileName(getLogFileName(false)); 175 config.setLogFileMaxRecords(fileCapacity); 176 } 177 178 179 199 public ObjectName preRegister(MBeanServer server, ObjectName name) 200 throws Exception { 201 if (name == null) 202 name = RESULT_LOG_MANAGER_NAME; 203 objectName = name; 204 mbeanServer = server; 205 return name; 206 } 207 208 217 public void postRegister(Boolean registrationDone) { 218 } 220 221 228 public void preDeregister() throws Exception { 229 } 231 232 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 252 256 private File createNewLogFile(String basename) throws IOException { 257 return XmlConfigUtils.createNewXmlFile(basename); 258 } 259 260 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 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 public void log(ResultRecord record) 301 throws IOException { 302 if (memCapacity > 0) logToMemory(record); 303 if (logFile != null) logToFile(record); 304 } 305 306 public ResultRecord[] getMemoryLog() { 308 return memoryLog.toArray(new ResultRecord[0]); 309 } 310 311 public int getMemoryLogCapacity() { 313 return memCapacity; 314 } 315 316 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 public void setLogFileCapacity(long maxRecords) 328 throws IOException { 329 synchronized (this) { 330 fileCapacity = maxRecords; 331 config.setLogFileMaxRecords(maxRecords); 332 } 333 checkLogFile(getLogFileName(),fileCapacity,false); 334 } 335 336 public long getLogFileCapacity() { 338 return fileCapacity; 339 } 340 341 public long getLoggedCount() { 343 return logCount; 344 } 345 346 public void newLogFile(String logname, long maxRecord) 348 throws IOException { 349 checkLogFile(logname,maxRecord,true); 350 config.setLogFileName(getLogFileName(false)); 351 config.setLogFileMaxRecords(getLogFileCapacity()); 352 } 353 354 public String getLogFileName() { 356 return getLogFileName(true); 357 } 358 359 public void clearLogs() throws IOException { 361 clearMemoryLog(); 362 clearLogFile(); 363 } 364 365 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 private void clearLogFile() throws IOException { 381 checkLogFile(getLogFileName(),fileCapacity,true); 383 } 384 385 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 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 final OutputStream stream = 417 checkLogFile(basename,maxRecords,false); 418 419 if (stream == null) return; 421 422 synchronized (this) { 423 try { 424 XmlConfigUtils.write(record,stream,true); 425 stream.flush(); 426 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 437 443 public final static String LOG_FILE_CHANGED = 444 "com.sun.jmx.examples.scandir.log.file.switched"; 445 446 451 public final static String MEMORY_LOG_MAX_CAPACITY = 452 "com.sun.jmx.examples.scandir.log.memory.full"; 453 454 459 public final static String MEMORY_LOG_CLEARED = 460 "com.sun.jmx.examples.scandir.log.memory.cleared"; 461 462 470 public MBeanNotificationInfo [] getNotificationInfo() { 471 return new MBeanNotificationInfo [] { 472 new MBeanNotificationInfo (new String [] { 473 LOG_FILE_CHANGED}, 474 Notification .class.getName(), 475 "Emitted when the log file is switched") 476 , 477 new MBeanNotificationInfo (new String [] { 478 MEMORY_LOG_MAX_CAPACITY}, 479 Notification .class.getName(), 480 "Emitted when the memory log capacity is reached") 481 , 482 new MBeanNotificationInfo (new String [] { 483 MEMORY_LOG_CLEARED}, 484 Notification .class.getName(), 485 "Emitted when the memory log is cleared") 486 }; 487 } 488 489 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 void setConfig(ResultLogConfig logConfigBean) throws IOException { 503 if (logConfigBean == null) 504 throw new IllegalArgumentException ("logConfigBean is null"); 505 synchronized (this) { 506 config = logConfigBean; 507 setMemoryLogCapacity(config.getMemoryMaxRecords()); 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)) { 513 newLogFile(config.getLogFileName(), 514 config.getLogFileMaxRecords()); 515 } else { 516 setLogFileCapacity(config.getLogFileMaxRecords()); 517 } 518 } 519 520 ResultLogConfig getConfig() { 524 return config; 525 } 526 527 528 private MBeanServer mbeanServer; 530 private ObjectName objectName; 531 532 533 534 } 535 536 537 | Popular Tags |