1 23 package com.sun.enterprise.server.logging; 24 25 import java.io.*; 26 import java.util.Date ; 27 import java.util.LinkedList ; 28 import java.util.ArrayList ; 29 import java.text.MessageFormat ; 30 import java.text.DateFormat ; 31 import java.text.SimpleDateFormat ; 32 import java.text.FieldPosition ; 33 import java.util.logging.StreamHandler ; 34 import java.util.logging.LogRecord ; 35 import java.util.logging.Level ; 36 import java.util.logging.ErrorManager ; 37 import java.util.logging.Formatter ; 38 39 import javax.management.ObjectName ; 40 import javax.management.MBeanServer ; 41 42 import com.sun.enterprise.util.StringUtils; 43 import com.sun.enterprise.server.ApplicationServer; 44 import com.sun.enterprise.server.ServerContext; 45 46 import com.sun.enterprise.server.logging.stats.ErrorStatistics; 47 import com.sun.enterprise.server.logging.logviewer.backend.LogFilter; 48 import com.sun.enterprise.server.logging.logviewer.backend.LogFile; 49 50 import com.sun.enterprise.config.serverbeans.LogService; 51 52 import java.util.HashMap ; 54 import java.util.logging.Logger ; 55 import java.util.Vector ; 56 57 65 public class FileandSyslogHandler extends StreamHandler { 66 private MeteredStream meter; 69 70 private final AMXLoggingHook mAMXLoggingHook; 71 72 private Date date = new Date ( ); 73 private static final String LOGS_DIR = "logs"; 74 private String logFileName = "server.log"; 75 76 private String absoluteFileName = null; 77 78 private static boolean isInitialized = false; 79 80 private LogMBean logMBean; 81 82 private LogService logService = null; 83 84 private static final int WARNING = Level.WARNING.intValue(); 85 86 private static final int SEVERE = Level.SEVERE.intValue(); 87 88 private static final String INSTANCE_ROOT_PROPERTY = 89 "com.sun.aas.instanceRoot"; 90 91 private static final String LOGGING_MAX_HISTORY_FILES = "com.sun.enterprise.server.logging.max_history_files"; 92 93 private static final int MINIMUM_FILE_ROTATION_VALUE = 500000; 95 96 private int limitForFileRotation = 0; 98 99 private Object fileUpdateLock = new Object ( ); 100 101 private boolean rotationInProgress = false; 102 103 private static final FileandSyslogHandler thisInstance = 104 new FileandSyslogHandler( ); 105 106 private LinkedList pendingLogRecordList = new LinkedList (); 107 108 private static boolean rotationRequested = false; 116 117 public static synchronized FileandSyslogHandler getInstance( ) { 118 return thisInstance; 119 } 120 121 private static final String LOG_ROTATE_DATE_FORMAT = 122 "yyyy-MM-dd'T'HH-mm-ss"; 123 124 private static final SimpleDateFormat logRotateDateFormatter = 125 new SimpleDateFormat ( LOG_ROTATE_DATE_FORMAT ); 126 127 private static Vector _recentErrors = new Vector (); 133 134 private static final int MAX_RECENT_ERRORS = 4; 135 136 public synchronized static Vector getRecentErrorMessages() { 137 return _recentErrors; 138 } 139 140 public synchronized static void clearRecentErrorMessages() { 141 _recentErrors = new Vector (); 142 } 143 144 private synchronized static void addRecentErrorMessage(String error) { 145 if (_recentErrors.size() < MAX_RECENT_ERRORS) { 146 _recentErrors.add(error); 147 } else { 148 _recentErrors.removeElementAt(0); 149 _recentErrors.add(MAX_RECENT_ERRORS - 1, error); 150 } 151 } 152 153 157 void changeFileName( String fileName ) { 158 if( fileName.trim().equals( absoluteFileName ) ) { 161 return; 162 } 163 synchronized( this ) { 164 super.flush( ); 165 super.close(); 166 try { 167 openFile( fileName ); 168 LogFilter.setLogFile( new LogFile( fileName ) ); 170 absoluteFileName = fileName; 171 } catch( IOException ix ) { 172 new ErrorManager ().error( 173 "FATAL ERROR: COULD NOT OPEN LOG FILE. " + 174 "Please Check to make sure that the directory for " + 175 "Logfile exists. Currently reverting back to use the " + 176 " default server.log", ix, ErrorManager.OPEN_FAILURE ); 177 try { 178 openFile( absoluteFileName ); 180 } catch( Exception e ) { 181 new ErrorManager ().error( 182 "FATAL ERROR: COULD NOT RE-OPEN SERVER LOG FILE. ", e, 183 ErrorManager.OPEN_FAILURE ); 184 } 185 } 186 } 187 } 188 189 192 String getAbsoluteLogFileName( ) { 193 return absoluteFileName; 194 } 195 196 199 synchronized void setLimitForRotation( int rotationLimitInBytes ) { 200 if ((rotationLimitInBytes == 0) || 201 (rotationLimitInBytes >= MINIMUM_FILE_ROTATION_VALUE )) { 202 limitForFileRotation = rotationLimitInBytes; 203 } 204 } 205 206 207 208 private class MeteredStream extends OutputStream { 213 OutputStream out; 214 long written; 215 216 MeteredStream(OutputStream out, long written) { 217 this.out = out; 218 this.written = written; 219 } 220 221 public void write(int b) throws IOException { 222 out.write(b); 223 written++; 224 } 225 226 public void write(byte buff[]) throws IOException { 227 out.write(buff); 228 written += buff.length; 229 } 230 231 public void write(byte buff[], int off, int len) throws IOException { 232 out.write(buff,off,len); 233 written += len; 234 } 235 236 public void flush() throws IOException { 237 out.flush(); 238 } 239 240 public void close() throws IOException { 241 out.close(); 242 } 243 } 244 245 246 250 protected FileandSyslogHandler( ) { 251 mAMXLoggingHook = createAMXLoggingHook(); 252 try { 253 setFormatter( new UniformLogFormatter( ) ); 254 } catch( Exception e ) { 255 new ErrorManager ().error( 256 "FATAL ERROR: COULD NOT INSTANTIATE FILE AND SYSLOG HANDLER", 257 e, ErrorManager.GENERIC_FAILURE ); 258 } 259 } 260 261 262 263 266 public String createFileName( ) { 267 ServerContext sc = ApplicationServer.getServerContext(); 268 String instDir = ""; 269 if (sc != null) { 270 instDir = sc.getInstanceEnvironment().getInstancesRoot(); 271 } else { 272 instDir = System.getProperty( INSTANCE_ROOT_PROPERTY ); 273 } 274 String [] names = {instDir, LOGS_DIR, getLogFileName() }; 275 return StringUtils.makeFilePath(names, false); 277 } 278 279 283 private void openFile( String fileName ) throws IOException { 284 File file = new File( fileName ); 285 FileOutputStream fout = new FileOutputStream( fileName, true ); 286 BufferedOutputStream bout = new BufferedOutputStream( fout ); 287 meter = new MeteredStream( bout, file.length() ); 288 setOutputStream( meter ); 289 } 290 291 294 void requestRotation( ) { 295 synchronized( this ) { 296 rotationRequested = true; 297 } 298 } 299 300 308 public void cleanUpHistoryLogFiles() { 309 String nStr = System.getProperty(LOGGING_MAX_HISTORY_FILES); 310 if (nStr==null) return; 311 312 int maxHistryFiles = 10; 313 if (!"".equals(nStr)) { 314 try { 315 maxHistryFiles = Integer.parseInt(nStr); 316 } catch (NumberFormatException e) {}; 317 } 318 if (maxHistryFiles<0) return; 319 320 File dir = new File(absoluteFileName).getParentFile(); 321 if (dir==null) return; 322 323 File[] fset = dir.listFiles(); 324 ArrayList candidates = new ArrayList (); 325 for (int i=0; fset!=null && i<fset.length; i++) { 326 if ( !logFileName.equals(fset[i].getName()) && 327 fset[i].isFile() && 328 fset[i].getName().startsWith(logFileName) ) { 329 candidates.add(fset[i].getAbsolutePath() ); 330 } 331 } 332 if (candidates.size() <= maxHistryFiles) return; 333 334 Object [] pathes = candidates.toArray(); 335 java.util.Arrays.sort(pathes); 336 try { 337 for (int i=0; i<pathes.length-maxHistryFiles; i++) { 338 new File((String )pathes[i]).delete(); 339 } 340 } catch (Exception e) { 341 new ErrorManager ().error("FATAL ERROR: COULD NOT DELETE LOG FILE..", 342 e, ErrorManager.GENERIC_FAILURE ); 343 } 344 } 345 346 347 351 private void rotate( ) { 352 final FileandSyslogHandler thisInstance = this; 353 java.security.AccessController.doPrivileged( 354 new java.security.PrivilegedAction () { 355 public Object run( ) { 356 thisInstance.flush( ); 357 thisInstance.close(); 358 StringBuffer renamedFileName = null; 359 try { 360 File oldFile = new File( absoluteFileName ); 361 renamedFileName = 362 new StringBuffer ( absoluteFileName + "_" ); 363 logRotateDateFormatter.format( 364 new Date (), renamedFileName, 365 new FieldPosition ( 0 ) ); 366 File rotatedFile = new File( 367 renamedFileName.toString() ); 368 boolean renameSuccess = oldFile.renameTo( rotatedFile ); 369 if( !renameSuccess ) { 370 planBLogRotate(absoluteFileName, 376 renamedFileName.toString( ) ); 377 String freshServerLogFileName = createFileName( ); 378 FileOutputStream fo = 382 new FileOutputStream( freshServerLogFileName ); 383 fo.close( ); 384 } 385 openFile( createFileName( ) ); 386 LogFilter.setLogFile( new LogFile( absoluteFileName) ); 387 LogRotationTimer.getInstance( ).restartTimer( ); 391 392 cleanUpHistoryLogFiles(); 393 } catch( IOException ix ) { 394 new ErrorManager ().error( 395 "FATAL ERROR: COULD NOT OPEN LOG FILE..", ix, 396 ErrorManager.OPEN_FAILURE ); 397 } 398 return null; 399 } 400 } 401 ); 402 } 403 404 405 411 private void planBLogRotate( String originalFileName, 412 String renamedFileName ) 413 { 414 FileOutputStream fo = null; 415 FileInputStream fi = null; 416 try { 417 fo = new FileOutputStream( renamedFileName ); 418 fi = new FileInputStream( originalFileName ); 419 420 int BUF_SIZE = 4096; 421 422 byte[] buffer = new byte[BUF_SIZE]; 423 int i = -1; 424 do { 425 i = fi.read( buffer ); 426 if( i == -1 ) { break; } 428 if( i == BUF_SIZE ) { 429 fo.write( buffer ); 430 } else { 431 byte[] tempBuffer = new byte[i]; 436 int j = 0; 437 for( j = 0; j < i; j++ ) { 438 tempBuffer[j] = buffer[j]; 439 } 440 fo.write( tempBuffer ); 441 } 442 } while( true ); 443 } catch( Exception e ) { 444 } finally { 447 try { 448 fo.close( ); 449 fi.close( ); 450 } catch( Exception e ) { } 451 } 452 } 453 454 455 459 public synchronized void publish( LogRecord record ) { 460 if( rotationInProgress ) { 466 pendingLogRecordList.addLast(record); 467 return; 468 } 469 if( meter == null ) { 474 try { 475 absoluteFileName = createFileName( ); 476 openFile( absoluteFileName ); 477 } catch( Exception e ) { 478 throw new RuntimeException ( 479 "Serious Error Couldn't open Log File" + e ); 480 } 481 } 482 super.publish( record ); 483 flush( ); 484 if ( ( rotationRequested ) 485 || ( ( limitForFileRotation > 0 ) 486 && ( meter.written >= limitForFileRotation ) ) ) 487 { 488 rotationInProgress = true; 489 rotate( ); 493 rotationInProgress = false; 494 rotationRequested = false; 495 while (pendingLogRecordList.size() != 0) { 496 publish((LogRecord ) pendingLogRecordList.removeFirst()); 497 } 498 } 499 500 if (mAMXLoggingHook != null) { 501 mAMXLoggingHook.publish( record, getFormatter() ); 502 } 503 504 int level = record.getLevel( ).intValue(); 505 if(( level != WARNING ) && (level != SEVERE)) { 509 return; 510 } 511 512 String logMessage = getFormatter().format(record); 517 addRecentErrorMessage(logMessage); 518 ErrorStatistics.singleton().updateStatistics(record); 520 if( logService == null ) { 521 logService = ServerLogManager.getLogService( ); 522 } 523 if( logService == null ) return; 525 526 if( record.getLevel( ).intValue() == WARNING ) { 529 LogMBean.getInstance().raiseWarningAlarm( record ); 530 } else if( record.getLevel( ).intValue() == SEVERE ) { 531 LogMBean.getInstance().raiseSevereAlarm( record ); 532 } 533 } 534 535 541 protected AMXLoggingHook createAMXLoggingHook() { 542 return new AMXLoggingHook(); 543 } 544 545 protected String getLogFileName() { 546 return logFileName; 547 } 548 } 549 550 | Popular Tags |