diff --git a/src/checkstyle/com/puppycrawl/tools/checkstyle/AuditEvent.java b/src/checkstyle/com/puppycrawl/tools/checkstyle/AuditEvent.java new file mode 100644 index 000000000..bd784108b --- /dev/null +++ b/src/checkstyle/com/puppycrawl/tools/checkstyle/AuditEvent.java @@ -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. + *

+ * + * 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 ;-) + * + * @author Stephane Bailliez + * @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 AuditEvent 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 AuditEvent 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: + * <file>:<line>: <message> + * @return informative line representing the event. + */ + public String toString() + { + return mFileName + ":" + getLine() + ": " + getMessage(); + } +} diff --git a/src/checkstyle/com/puppycrawl/tools/checkstyle/AuditListener.java b/src/checkstyle/com/puppycrawl/tools/checkstyle/AuditListener.java new file mode 100644 index 000000000..68c792f38 --- /dev/null +++ b/src/checkstyle/com/puppycrawl/tools/checkstyle/AuditListener.java @@ -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 : + *

+ * auditStarted
+ *   (fileStarted
+ *     (addError)*
+ *     (addException)*
+ *   fileFinished )*
+ *   (addException)*
+ * auditFinished
+ * 
+ * @author Stephane Bailliez + */ +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); +} diff --git a/src/checkstyle/com/puppycrawl/tools/checkstyle/DefaultLogger.java b/src/checkstyle/com/puppycrawl/tools/checkstyle/DefaultLogger.java new file mode 100644 index 000000000..e2f892097 --- /dev/null +++ b/src/checkstyle/com/puppycrawl/tools/checkstyle/DefaultLogger.java @@ -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 Stephane Bailliez + * @see #XMLLogger + */ +public class DefaultLogger + implements AuditListener, Streamable +{ + /** where to log **/ + private OutputStream mStream; + /** where to write **/ + private PrintWriter mWriter; + + /** + * Creates a new DefaultLogger instance. + */ + public DefaultLogger() + { + } + + /** + * Creates a new DefaultLogger 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(); + } +} diff --git a/src/checkstyle/com/puppycrawl/tools/checkstyle/Streamable.java b/src/checkstyle/com/puppycrawl/tools/checkstyle/Streamable.java new file mode 100644 index 000000000..e9d78eb98 --- /dev/null +++ b/src/checkstyle/com/puppycrawl/tools/checkstyle/Streamable.java @@ -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. + *

+ * 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. + * + * (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). + * + * 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 Stephane Bailliez + * @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(); +} diff --git a/src/checkstyle/com/puppycrawl/tools/checkstyle/XMLLogger.java b/src/checkstyle/com/puppycrawl/tools/checkstyle/XMLLogger.java new file mode 100644 index 000000000..e14e840e7 --- /dev/null +++ b/src/checkstyle/com/puppycrawl/tools/checkstyle/XMLLogger.java @@ -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 Stephane Bailliez + */ +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(""); + } + + /** @see AuditListener **/ + public void auditFinished(AuditEvent aEvt) + { + mWriter.println(""); + mWriter.flush(); + } + + /** @see AuditListener **/ + public void fileStarted(AuditEvent aEvt) + { + mWriter.println(""); + } + + /** @see AuditListener **/ + public void fileFinished(AuditEvent aEvt) + { + mWriter.println(""); + } + + /** @see AuditListener **/ + public void addError(AuditEvent aEvt) { + mWriter.println(""); + } + + /** @see AuditListener **/ + public void addException(AuditEvent aEvt, Throwable aThrowable) + { + final StringWriter sw = new StringWriter(); + final PrintWriter pw = new PrintWriter(sw); + pw.println(""); + pw.println(""); + pw.println(""); + pw.flush(); + mWriter.println(encode(sw.toString())); + } + + /** + * Escape <, > & ' and " 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("<"); + break; + case '>': + sb.append(">"); + break; + case '\'': + sb.append("'"); + break; + case '\"': + sb.append("""); + break; + case '&': + int nextSemi = aValue.indexOf(";", i); + if ((nextSemi < 0) || + !isReference(aValue.substring(i, nextSemi + 1))) + { + sb.append("&"); + } + 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; + } +}