first cut

This commit is contained in:
Oliver Burn 2001-08-30 16:21:20 +00:00
parent 0e3fe56436
commit 1d21af32b9
5 changed files with 573 additions and 0 deletions

View File

@ -0,0 +1,121 @@
////////////////////////////////////////////////////////////////////////////////
// checkstyle: Checks Java source code for adherence to a set of rules.
// Copyright (C) 2001 Oliver Burn
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
////////////////////////////////////////////////////////////////////////////////
package com.puppycrawl.tools.checkstyle;
import java.util.EventObject;
/**
* Raw event for audit.
* <p>
* <i>
* I'm not very satisfied about the design of this event since there are
* optional methods that will return null in most of the case. This will
* need some work to clean it up especially if we want to introduce
* a more sequential reporting action rather than a packet error
* reporting. This will allow for example to follow the process quickly
* in an interface or a servlet (yep, that's cool to run a check via
* a web interface in a source repository ;-)
* </i>
* @author <a href="stephane.bailliez@wanadoo.fr">Stephane Bailliez</a>
* @see #AuditListener
*/
public class AuditEvent
extends EventObject
{
/** filename event associated with **/
private String mFileName;
/** line event associated with **/
private int mLine;
/** message of event **/
private String mMessage;
/**
* Creates a new instance.
* @param aSource the object that created the event
*/
public AuditEvent(Object aSource)
{
super(aSource);
}
/**
* Creates a new <code>AuditEvent</code> instance.
* @param aSrc source of the event
* @param aFileName file associated with the event
*/
public AuditEvent(Object aSrc, String aFileName)
{
super(aSrc);
mFileName = aFileName;
}
/**
* Creates a new <code>AuditEvent</code> instance.
*
* @param aSrc source of the event
* @param aFileName file associated with the event
* @param aLine line number of message
* @param aMessage the actual message
*/
public AuditEvent(Object aSrc, String aFileName, int aLine, String aMessage)
{
super(aSrc);
mFileName = aFileName;
mLine = aLine;
mMessage = aMessage;
}
/**
* @return the file name currently being audited or null if there is
* no relation to a file.
*/
public String getFileName()
{
return mFileName;
}
/**
* return the line number on the source file where the event occurred.
* This may be 0 if there is no relation to a file content.
* @return an integer representing the line number in the file source code.
*/
public int getLine()
{
return mLine;
}
/**
* return the message associated to the event.
* @return the event message
*/
public String getMessage()
{
return mMessage;
}
/**
* return an Emacs compliant line with the following pattern:
* &lt;file&gt;:&lt;line&gt;: &lt;message&gt;
* @return informative line representing the event.
*/
public String toString()
{
return mFileName + ":" + getLine() + ": " + getMessage();
}
}

View File

@ -0,0 +1,76 @@
////////////////////////////////////////////////////////////////////////////////
// checkstyle: Checks Java source code for adherence to a set of rules.
// Copyright (C) 2001 Oliver Burn
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
////////////////////////////////////////////////////////////////////////////////
package com.puppycrawl.tools.checkstyle;
import java.util.EventListener;
/**
* Listener in charge of receiving events from the Checker.
* Typical events sequence is :
* <pre>
* auditStarted
* (fileStarted
* (addError)*
* (addException)*
* fileFinished )*
* (addException)*
* auditFinished
* </pre>
* @author <a href="stephane.bailliez@wanadoo.fr">Stephane Bailliez</a>
*/
public interface AuditListener
extends EventListener
{
/**
* notify that the audit is about to start
* @param aEvt the event details
*/
void auditStarted(AuditEvent aEvt);
/**
* notify that the audit is finished
* @param aEvt the event details
*/
void auditFinished(AuditEvent aEvt);
/**
* notify that audit is about to start on a specific file
* @param aEvt the event details
*/
void fileStarted(AuditEvent aEvt);
/**
* notify that audit is finished on a specific file
* @param aEvt the event details
*/
void fileFinished(AuditEvent aEvt);
/**
* notify that an audit error was discovered on a specific file
* @param aEvt the event details
*/
void addError(AuditEvent aEvt);
/**
* notify that an exception happened while performing audit
* @param aEvt the event details
* @param aThrowable details of the exception
*/
void addException(AuditEvent aEvt, Throwable aThrowable);
}

View File

@ -0,0 +1,110 @@
////////////////////////////////////////////////////////////////////////////////
// checkstyle: Checks Java source code for adherence to a set of rules.
// Copyright (C) 2001 Oliver Burn
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
////////////////////////////////////////////////////////////////////////////////
package com.puppycrawl.tools.checkstyle;
import java.io.OutputStream;
import java.io.PrintWriter;
/**
* Simple plain logger for text output.
* This is maybe not very suitable for a text output into a file since it
* does not need all 'audit finished' and so on stuff, but it looks good on
* stdout anyway. If there is really a problem this is what XMLLogger is for.
* It gives structure.
*
* @author <a href="mailto:stephane.bailliez@wanadoo.fr">Stephane Bailliez</a>
* @see #XMLLogger
*/
public class DefaultLogger
implements AuditListener, Streamable
{
/** where to log **/
private OutputStream mStream;
/** where to write **/
private PrintWriter mWriter;
/**
* Creates a new <code>DefaultLogger</code> instance.
*/
public DefaultLogger()
{
}
/**
* Creates a new <code>DefaultLogger</code> instance.
* @param aOS where to log
*/
public DefaultLogger(OutputStream aOS)
{
setOutputStream(aOS);
}
/** @see Streamable **/
public void setOutputStream(OutputStream aOS)
{
mWriter = new PrintWriter(aOS);
mStream = aOS;
}
/** @see Streamable **/
public OutputStream getOutputStream()
{
return mStream;
}
/** @see AuditListener **/
public void addError(AuditEvent aEvt)
{
mWriter.println(aEvt);
}
/** @see AuditListener **/
public void addException(AuditEvent aEvt, Throwable aThrowable)
{
synchronized (mWriter) {
mWriter.println("Error auditing " + aEvt.getFileName());
aThrowable.printStackTrace(mWriter);
}
}
/** @see AuditListener **/
public void auditStarted(AuditEvent aEvt)
{
mWriter.println("Starting audit...");
}
/** @see AuditListener **/
public void fileFinished(AuditEvent aEvt)
{
mWriter.println("End audit " + aEvt.getFileName());
}
/** @see AuditListener **/
public void fileStarted(AuditEvent aEvt)
{
mWriter.println("Auditing " + aEvt.getFileName());
}
/** @see AuditListener **/
public void auditFinished(AuditEvent aEvt)
{
mWriter.println("Audit done.");
mWriter.flush();
}
}

View File

@ -0,0 +1,57 @@
////////////////////////////////////////////////////////////////////////////////
// checkstyle: Checks Java source code for adherence to a set of rules.
// Copyright (C) 2001 Oliver Burn
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
////////////////////////////////////////////////////////////////////////////////
package com.puppycrawl.tools.checkstyle;
import java.io.OutputStream;
/**
* Mainly use to give an Audit listener the ability to pass
* an OutputStream without cluttering the original Listener
* interfaces.
* <p>
* This will be used to set the appropriate stream at configuration
* time (ie, a file, stdout or whatever) and the stream will be
* closed once the checker is destroyed.
* <i>
* (We cannot rely on the finalizer to close the file because it can
* takes some time and on Window we cannot delete the generated file
* if there is still a handle on it).
* </i>
* Pay attention to keep the original stream so that getOutputStream
* sends back the setted one (You would me to close stdout or stderr
* right ?)
*
* @author <a href="mailto:stephane.bailliez@wanadoo.fr">Stephane Bailliez</a>
* @see #AuditListener
* @see #CheckStyleTask
* @see #Checker
*/
public interface Streamable
{
/**
* Set a stream to write information to.
* @param aOS the outputstream to be set.
*/
void setOutputStream(OutputStream aOS);
/**
* @return the stream used to write information to.
*/
OutputStream getOutputStream();
}

View File

@ -0,0 +1,209 @@
////////////////////////////////////////////////////////////////////////////////
// checkstyle: Checks Java source code for adherence to a set of rules.
// Copyright (C) 2001 Oliver Burn
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
////////////////////////////////////////////////////////////////////////////////
package com.puppycrawl.tools.checkstyle;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
/**
* Simple XML logger.
* It outputs everything in UTF8 (default XML encoding is UTF8) in case
* we want to localize error messages or simply that filenames are
* localized and takes care about escaping as well.
* @author <a href="mailto:stephane.bailliez@wanadoo.fr">Stephane Bailliez</a>
*/
public class XMLLogger
implements AuditListener, Streamable
{
/** the original wrapped stream */
private OutputStream mStream;
/** helper writer that allows easy encoding and printing */
private PrintWriter mWriter;
/** some known entities to detect */
private final static String[] ENTITIES = {"gt", "amp", "lt", "apos",
"quot"};
/**
* sets the output to a defined stream
* @param aOS the stream to write logs to.
*/
public XMLLogger(OutputStream aOS)
{
setOutputStream(aOS);
}
/** @see Streamable **/
public void setOutputStream(OutputStream aOS)
{
try {
final OutputStreamWriter osw = new OutputStreamWriter(aOS, "UTF8");
mWriter = new PrintWriter(osw);
// keep a handle on the original stream
// for getoutputstream
mStream = aOS;
}
catch (UnsupportedEncodingException e) {
// unlikely to happen...
throw new ExceptionInInitializerError(e);
}
}
/** @see Streamable **/
public OutputStream getOutputStream()
{
return mStream;
}
/** @see AuditListener **/
public void auditStarted(AuditEvent aEvt)
{
mWriter.println("<checkstyle>");
}
/** @see AuditListener **/
public void auditFinished(AuditEvent aEvt)
{
mWriter.println("</checkstyle>");
mWriter.flush();
}
/** @see AuditListener **/
public void fileStarted(AuditEvent aEvt)
{
mWriter.println("<file name=\"" + aEvt.getFileName() + "\">");
}
/** @see AuditListener **/
public void fileFinished(AuditEvent aEvt)
{
mWriter.println("</file>");
}
/** @see AuditListener **/
public void addError(AuditEvent aEvt) {
mWriter.println("<error " +
"line=\"" + aEvt.getLine() + "\" " +
"message=\"" + encode(aEvt.getMessage()) + "\"/>");
}
/** @see AuditListener **/
public void addException(AuditEvent aEvt, Throwable aThrowable)
{
final StringWriter sw = new StringWriter();
final PrintWriter pw = new PrintWriter(sw);
pw.println("<exception>");
pw.println("<![CDATA[");
aThrowable.printStackTrace(pw);
pw.println("]]>");
pw.println("</exception>");
pw.flush();
mWriter.println(encode(sw.toString()));
}
/**
* Escape &lt;, &gt; &amp; &apos; and &quot; as their entities.
* @param aValue the value to escape.
* @return the escaped value if necessary.
*/
public String encode(String aValue)
{
final StringBuffer sb = new StringBuffer();
for (int i = 0; i < aValue.length(); i++) {
char c = aValue.charAt(i);
switch (c) {
case '<':
sb.append("&lt;");
break;
case '>':
sb.append("&gt;");
break;
case '\'':
sb.append("&apos;");
break;
case '\"':
sb.append("&quot;");
break;
case '&':
int nextSemi = aValue.indexOf(";", i);
if ((nextSemi < 0) ||
!isReference(aValue.substring(i, nextSemi + 1)))
{
sb.append("&amp;");
}
else {
sb.append('&');
}
break;
default:
sb.append(c);
break;
}
}
return sb.toString();
}
/**
* @return whether the given argument a character or entity reference
* @param aEnt the possible entity to look for.
*/
public boolean isReference(String aEnt)
{
if (!(aEnt.charAt(0) == '&') || !aEnt.endsWith(";")) {
return false;
}
if (aEnt.charAt(1) == '#') {
if (aEnt.charAt(2) == 'x') {
try {
Integer.parseInt(aEnt.substring(3, aEnt.length() - 1), 16);
return true;
}
catch (NumberFormatException nfe) {
return false;
}
}
else {
try {
Integer.parseInt(aEnt.substring(2, aEnt.length() - 1));
return true;
}
catch (NumberFormatException nfe) {
return false;
}
}
}
final String name = aEnt.substring(1, aEnt.length() - 1);
for (int i = 0; i < ENTITIES.length; i++) {
if (name.equals(ENTITIES[i])) {
return true;
}
}
return false;
}
}