001//////////////////////////////////////////////////////////////////////////////// 002// checkstyle: Checks Java source code for adherence to a set of rules. 003// Copyright (C) 2001-2014 Oliver Burn 004// 005// This library is free software; you can redistribute it and/or 006// modify it under the terms of the GNU Lesser General Public 007// License as published by the Free Software Foundation; either 008// version 2.1 of the License, or (at your option) any later version. 009// 010// This library is distributed in the hope that it will be useful, 011// but WITHOUT ANY WARRANTY; without even the implied warranty of 012// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 013// Lesser General Public License for more details. 014// 015// You should have received a copy of the GNU Lesser General Public 016// License along with this library; if not, write to the Free Software 017// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 018//////////////////////////////////////////////////////////////////////////////// 019package com.puppycrawl.tools.checkstyle; 020 021import java.io.OutputStream; 022import java.io.PrintWriter; 023 024import com.puppycrawl.tools.checkstyle.api.AuditEvent; 025import com.puppycrawl.tools.checkstyle.api.AuditListener; 026import com.puppycrawl.tools.checkstyle.api.AutomaticBean; 027import com.puppycrawl.tools.checkstyle.api.SeverityLevel; 028 029/** 030 * Simple plain logger for text output. 031 * This is maybe not very suitable for a text output into a file since it 032 * does not need all 'audit finished' and so on stuff, but it looks good on 033 * stdout anyway. If there is really a problem this is what XMLLogger is for. 034 * It gives structure. 035 * 036 * @author <a href="mailto:stephane.bailliez@wanadoo.fr">Stephane Bailliez</a> 037 * @see XMLLogger 038 */ 039public class DefaultLogger 040 extends AutomaticBean 041 implements AuditListener 042{ 043 /** cushion for avoiding StringBuffer.expandCapacity */ 044 private static final int BUFFER_CUSHION = 12; 045 046 /** where to write info messages **/ 047 private final PrintWriter mInfoWriter; 048 /** close info stream after use */ 049 private final boolean mCloseInfo; 050 051 /** where to write error messages **/ 052 private final PrintWriter mErrorWriter; 053 /** close error stream after use */ 054 private final boolean mCloseError; 055 056 /** 057 * Creates a new <code>DefaultLogger</code> instance. 058 * @param aOS where to log infos and errors 059 * @param aCloseStreamsAfterUse if aOS should be closed in auditFinished() 060 */ 061 public DefaultLogger(OutputStream aOS, boolean aCloseStreamsAfterUse) 062 { 063 // no need to close aOS twice 064 this(aOS, aCloseStreamsAfterUse, aOS, false); 065 } 066 067 /** 068 * Creates a new <code>DefaultLogger</code> instance. 069 * 070 * @param aInfoStream the <code>OutputStream</code> for info messages 071 * @param aCloseInfoAfterUse auditFinished should close aInfoStream 072 * @param aErrorStream the <code>OutputStream</code> for error messages 073 * @param aCloseErrorAfterUse auditFinished should close aErrorStream 074 */ 075 public DefaultLogger(OutputStream aInfoStream, 076 boolean aCloseInfoAfterUse, 077 OutputStream aErrorStream, 078 boolean aCloseErrorAfterUse) 079 { 080 mCloseInfo = aCloseInfoAfterUse; 081 mCloseError = aCloseErrorAfterUse; 082 mInfoWriter = new PrintWriter(aInfoStream); 083 mErrorWriter = (aInfoStream == aErrorStream) 084 ? mInfoWriter 085 : new PrintWriter(aErrorStream); 086 } 087 088 /** 089 * Print an Emacs compliant line on the error stream. 090 * If the column number is non zero, then also display it. 091 * @param aEvt {@inheritDoc} 092 * @see AuditListener 093 **/ 094 public void addError(AuditEvent aEvt) 095 { 096 final SeverityLevel severityLevel = aEvt.getSeverityLevel(); 097 if (!SeverityLevel.IGNORE.equals(severityLevel)) { 098 099 final String fileName = aEvt.getFileName(); 100 final String message = aEvt.getMessage(); 101 102 // avoid StringBuffer.expandCapacity 103 final int bufLen = fileName.length() + message.length() 104 + BUFFER_CUSHION; 105 final StringBuffer sb = new StringBuffer(bufLen); 106 107 sb.append(fileName); 108 sb.append(':').append(aEvt.getLine()); 109 if (aEvt.getColumn() > 0) { 110 sb.append(':').append(aEvt.getColumn()); 111 } 112 if (SeverityLevel.WARNING.equals(severityLevel)) { 113 sb.append(": warning"); 114 } 115 sb.append(": ").append(message); 116 mErrorWriter.println(sb.toString()); 117 } 118 } 119 120 /** {@inheritDoc} */ 121 public void addException(AuditEvent aEvt, Throwable aThrowable) 122 { 123 synchronized (mErrorWriter) { 124 mErrorWriter.println("Error auditing " + aEvt.getFileName()); 125 aThrowable.printStackTrace(mErrorWriter); 126 } 127 } 128 129 /** {@inheritDoc} */ 130 public void auditStarted(AuditEvent aEvt) 131 { 132 mInfoWriter.println("Starting audit..."); 133 } 134 135 /** {@inheritDoc} */ 136 public void fileFinished(AuditEvent aEvt) 137 { 138 } 139 140 /** {@inheritDoc} */ 141 public void fileStarted(AuditEvent aEvt) 142 { 143 } 144 145 /** {@inheritDoc} */ 146 public void auditFinished(AuditEvent aEvt) 147 { 148 mInfoWriter.println("Audit done."); 149 closeStreams(); 150 } 151 152 /** 153 * Flushes the output streams and closes them if needed. 154 */ 155 protected void closeStreams() 156 { 157 mInfoWriter.flush(); 158 if (mCloseInfo) { 159 mInfoWriter.close(); 160 } 161 162 mErrorWriter.flush(); 163 if (mCloseError) { 164 mErrorWriter.close(); 165 } 166 } 167}