//////////////////////////////////////////////////////////////////////////////// // checkstyle: Checks Java source code for adherence to a set of rules. // Copyright (C) 2001-2012 Oliver Burn // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // // This library 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 // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA //////////////////////////////////////////////////////////////////////////////// package com.puppycrawl.tools.checkstyle.api; //import com.google.common.collect.Lists; //import com.google.common.collect.Maps; import java.io.Closeable; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.LineNumberReader; import java.io.UnsupportedEncodingException; //import java.util.Map; import java.util.*; import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; //import org.apache.commons.beanutils.ConversionException; //import org.apache.commons.logging.Log; //import org.apache.commons.logging.LogFactory; import java.util.logging.Logger; import Sequenic.T3.SuiteUtils.Inference.Comment; /** * Contains utility methods. * * @author Oliver Burn * @version 1.0 * * WP note: I modify the class to make it more suitable for T3 testing and inference. * * (1) the static variable CREATED_RES is used to persistently maintain seen patterns. This is * not compatible for the concept of tetsing of T3, where sequences should not interfere * with each other. * * (2) the (static) variable EXCEPTION_LOG is costly for inference, probably when it tries to * serialize it. * * So, I make the class non-static based, keeping the variable CREATED_RES as a static * private variable, and reseting it by the constructor. * * The variable EXCEPTION_LOG is commented out, since it is not used in the code anyway. */ public final class Utils { /** Map of all created regular expressions **/ // private static final Map CREATED_RES = Maps.newHashMap(); private static final Map CREATED_RES = new HashMap(); /** Shared instance of logger for exception logging. */ //private static final Log EXCEPTION_LOG = // WP: commenting this out, we are not going to use it //LogFactory.getLog("com.puppycrawl.tools.checkstyle.ExceptionLog"); private final static Comment comment = new Comment(Logger.getLogger(Utils.class.getName())) ; ///CLOVER:OFF /** stop instances being created **/ public /* private */ Utils() { CREATED_RES.clear(); } ///CLOVER:ON /** * Accessor for shared instance of logger which should be * used to log all exceptions occurred during FileSetCheck * work (debug() should be used). * @return shared exception logger. */ /* public static Logger getExceptionLogger() { return EXCEPTION_LOG; } */ /** * Returns whether the specified string contains only whitespace up to the * specified index. * * @param aIndex index to check up to * @param aLine the line to check * @return whether there is only whitespace */ public /* static */ boolean whitespaceBefore(int aIndex, String aLine) { for (int i = 0; i < aIndex; i++) { if (!Character.isWhitespace(aLine.charAt(i))) { comment.with("see something not white").end() ; return false; } } return true; } /** * Returns the length of a string ignoring all trailing whitespace. It is a * pity that there is not a trim() like method that only removed the * trailing whitespace. * @param aLine the string to process * @return the length of the string ignoring all trailing whitespace **/ public /* static */ int lengthMinusTrailingWhitespace(String aLine) { int len = aLine.length(); comment.with("line is empty").If(len == 0); ; for (int i = len - 1; i >= 0; i--) { if (!Character.isWhitespace(aLine.charAt(i))) { comment.with("see something not white").end() ; break; } len--; } return len; } /** * Returns the length of a String prefix with tabs expanded. * Each tab is counted as the number of characters is takes to * jump to the next tab stop. * @param aString the input String * @param aToIdx index in aString (exclusive) where the calculation stops * @param aTabWidth the distance between tab stop position. * @return the length of aString.substring(0, aToIdx) with tabs expanded. */ public /* static */ int lengthExpandedTabs(String aString, int aToIdx, int aTabWidth) { int len = 0; final char[] chars = aString.toCharArray(); comment.with("string is empty").If(chars.length == 0); ; for (int idx = 0; idx < aToIdx; idx++) { if (chars[idx] == '\t') { len = (len / aTabWidth + 1) * aTabWidth; } else { len++; } } return len; } /** * This is a factory method to return an Pattern object for the specified * regular expression. It calls {@link #getPattern(String, int)} with the * compile flags defaults to 0. * @return an Pattern object for the supplied pattern * @param aPattern the regular expression pattern * @throws PatternSyntaxException an invalid pattern was supplied **/ public /* static */ Pattern getPattern(String aPattern) throws PatternSyntaxException { return getPattern(aPattern, 0); } /** * This is a factory method to return an Pattern object for the specified * regular expression and compile flags. *

* This method is not MT safe, but neither are the returned Pattern objects. * @return an Pattern object for the supplied pattern * @param aPattern the regular expression pattern * @param aCompileFlags the compilation flags * @throws PatternSyntaxException an invalid pattern was supplied **/ public /* static */ Pattern getPattern(String aPattern, int aCompileFlags) throws PatternSyntaxException { final String key = aPattern + ":flags-" + aCompileFlags; Pattern retVal = CREATED_RES.get(key); if (retVal == null) { retVal = Pattern.compile(aPattern, aCompileFlags); CREATED_RES.put(key, retVal); } return retVal; } /** * Loads the contents of a file in a String array. * @return the lines in the file * @param aFileName the name of the file to load * @throws IOException error occurred * @deprecated consider using {@link FileText} instead **/ @Deprecated public /* static */ String[] getLines(String aFileName) throws IOException { return getLines( aFileName, System.getProperty("file.encoding", "UTF-8")); } /** * Loads the contents of a file in a String array using * the named charset. * @return the lines in the file * @param aFileName the name of the file to load * @param aCharsetName the name of a supported charset * @throws IOException error occurred * @deprecated consider using {@link FileText} instead **/ @Deprecated public /* static */ String[] getLines(String aFileName, String aCharsetName) throws IOException { //final List lines = Lists.newArrayList(); final List lines = new ArrayList(); final FileInputStream fr = new FileInputStream(aFileName); LineNumberReader lnr = null; try { lnr = new LineNumberReader(new InputStreamReader(fr, aCharsetName)); } catch (final UnsupportedEncodingException ex) { comment.with("File's encoding not supported").end() ; final String message = "unsupported charset: " + ex.getMessage(); throw new UnsupportedEncodingException(message); } try { while (true) { final String l = lnr.readLine(); if (l == null) { break; } lines.add(l); } } finally { comment.with("got no lines").If(lines.size() == 0); ; closeQuietly(lnr); } return lines.toArray(new String[lines.size()]); } /** * Helper method to create a regular expression. * @param aPattern the pattern to match * @return a created regexp object * @throws ConversionException if unable to create Pattern object. **/ public /* static */ Pattern createPattern(String aPattern) throws ConversionException { Pattern retVal = null; try { return getPattern(aPattern); } catch (final PatternSyntaxException e) { comment.with("Pattern does not have the right syntax").end() ; throw new ConversionException(); } //return retVal; } /** * @return the base class name from a fully qualified name * @param aType the fully qualified name. Cannot be null */ public /* static */ String baseClassname(String aType) { final int i = aType.lastIndexOf("."); return (i == -1) ? aType : aType.substring(i + 1); } /** * Create a stripped down version of a filename. * @param aBasedir the prefix to strip off the original filename * @param aFileName the original filename * @return the filename where an initial prefix of basedir is stripped */ public /* static */ String getStrippedFileName( final String aBasedir, final String aFileName) { final String stripped; if ((aBasedir == null) || !aFileName.startsWith(aBasedir)) { stripped = aFileName; } else { // making the assumption that there is text after basedir final int skipSep = aBasedir.endsWith(File.separator) ? 0 : 1; stripped = aFileName.substring(aBasedir.length() + skipSep); } return stripped; } /** * Closes the supplied {@link Closeable} object ignoring an * {@link IOException} if it is thrown. Honestly, what are you going to * do if you cannot close a file. * @param aShutting the object to be closed. */ public /* static */ void closeQuietly(Closeable aShutting) { if (null != aShutting) { comment.with("File not null").end() ; try { aShutting.close(); } catch (IOException e) { comment.with("File cannot be closed!").end() ; ; // ignore } } } }