1 package com.puppycrawl.tools.checkstyle.checks.coding; 20 21 import antlr.collections.AST; 22 import com.puppycrawl.tools.checkstyle.api.Check; 23 import com.puppycrawl.tools.checkstyle.api.DetailAST; 24 import com.puppycrawl.tools.checkstyle.api.FullIdent; 25 import com.puppycrawl.tools.checkstyle.api.TokenTypes; 26 import com.puppycrawl.tools.checkstyle.api.Utils; 27 import java.util.HashSet ; 28 import java.util.Iterator ; 29 import java.util.Set ; 30 import java.util.StringTokenizer ; 31 32 63 public class IllegalInstantiationCheck 64 extends Check 65 { 66 67 private final Set mIllegalClasses = new HashSet (); 68 69 70 private String mPkgName; 71 72 73 private final Set mImports = new HashSet (); 74 75 76 private final Set mClassNames = new HashSet (); 77 78 79 private final Set mInstantiations = new HashSet (); 80 81 82 public int[] getDefaultTokens() 83 { 84 return new int[] { 85 TokenTypes.IMPORT, 86 TokenTypes.LITERAL_NEW, 87 TokenTypes.PACKAGE_DEF, 88 TokenTypes.CLASS_DEF, 89 }; 90 } 91 92 97 public int[] getAcceptableTokens() 98 { 99 return new int[] {}; 100 } 101 102 103 public int[] getRequiredTokens() 104 { 105 return new int[] { 106 TokenTypes.IMPORT, 107 TokenTypes.LITERAL_NEW, 108 TokenTypes.PACKAGE_DEF, 109 }; 110 } 111 112 113 public void beginTree(DetailAST aRootAST) 114 { 115 super.beginTree(aRootAST); 116 mPkgName = null; 117 mImports.clear(); 118 mInstantiations.clear(); 119 mClassNames.clear(); 120 } 121 122 123 public void visitToken(DetailAST aAST) 124 { 125 switch (aAST.getType()) { 126 case TokenTypes.LITERAL_NEW: 127 processLiteralNew(aAST); 128 break; 129 case TokenTypes.PACKAGE_DEF: 130 processPackageDef(aAST); 131 break; 132 case TokenTypes.IMPORT: 133 processImport(aAST); 134 break; 135 case TokenTypes.CLASS_DEF: 136 processClassDef(aAST); 137 break; 138 default: 139 throw new IllegalArgumentException ("Unknown type " + aAST); 140 } 141 } 142 143 146 public void finishTree(DetailAST aRootAST) 147 { 148 for (final Iterator it = mInstantiations.iterator(); it.hasNext();) { 149 final DetailAST literalNewAST = (DetailAST) it.next(); 150 postprocessLiteralNew(literalNewAST); 151 } 152 } 153 154 160 private void processClassDef(DetailAST aAST) 161 { 162 final DetailAST identToken = aAST.findFirstToken(TokenTypes.IDENT); 163 final String className = identToken.getText(); 164 mClassNames.add(className); 165 } 166 167 171 private void processImport(DetailAST aAST) 172 { 173 final FullIdent name = FullIdent.createFullIdentBelow(aAST); 174 if (name != null) { 175 mImports.add(name); 178 } 179 } 180 181 185 private void processPackageDef(DetailAST aAST) 186 { 187 final DetailAST packageNameAST = aAST.getLastChild() 188 .getPreviousSibling(); 189 final FullIdent packageIdent = 190 FullIdent.createFullIdent(packageNameAST); 191 mPkgName = packageIdent.getText(); 192 } 193 194 198 private void processLiteralNew(DetailAST aAST) 199 { 200 mInstantiations.add(aAST); 201 } 202 203 208 private void postprocessLiteralNew(DetailAST aAST) 209 { 210 final DetailAST typeNameAST = (DetailAST) aAST.getFirstChild(); 211 final AST nameSibling = typeNameAST.getNextSibling(); 212 if ((nameSibling != null) 213 && (nameSibling.getType() == TokenTypes.ARRAY_DECLARATOR)) 214 { 215 return; 217 } 218 219 final FullIdent typeIdent = FullIdent.createFullIdent(typeNameAST); 220 final String typeName = typeIdent.getText(); 221 final int lineNo = aAST.getLineNo(); 222 final int colNo = aAST.getColumnNo(); 223 final String fqClassName = getIllegalInstantiation(typeName); 224 if (fqClassName != null) { 225 log(lineNo, colNo, "instantiation.avoid", fqClassName); 226 } 227 } 228 229 235 private String getIllegalInstantiation(String aClassName) 236 { 237 final String javaLang = "java.lang."; 238 239 if (mIllegalClasses.contains(aClassName)) { 240 return aClassName; 241 } 242 243 final int clsNameLen = aClassName.length(); 244 final int pkgNameLen = (mPkgName == null) ? 0 : mPkgName.length(); 245 246 final Iterator illIter = mIllegalClasses.iterator(); 247 while (illIter.hasNext()) { 248 final String illegal = (String ) illIter.next(); 249 final int illegalLen = illegal.length(); 250 251 if (((illegalLen - javaLang.length()) == clsNameLen) 253 && illegal.endsWith(aClassName) 254 && illegal.startsWith(javaLang)) 255 { 256 262 final boolean isSameFile = mClassNames.contains(aClassName); 263 264 boolean isSamePackage = false; 265 try { 266 final ClassLoader classLoader = getClassLoader(); 267 if (classLoader != null) { 268 final String fqName = mPkgName + "." + aClassName; 269 classLoader.loadClass(fqName); 270 isSamePackage = true; 272 } 273 } 274 catch (final ClassNotFoundException ex) { 275 isSamePackage = false; 277 } 278 279 if (!(isSameFile || isSamePackage)) { 280 return illegal; 281 } 282 } 283 284 286 289 if ((mPkgName != null) 292 && (clsNameLen == illegalLen - pkgNameLen - 1) 293 && (illegal.charAt(pkgNameLen) == '.') 294 && illegal.endsWith(aClassName) 295 && illegal.startsWith(mPkgName)) 296 { 297 return illegal; 298 } 299 final Iterator importIter = mImports.iterator(); 301 while (importIter.hasNext()) { 302 final FullIdent importLineText = (FullIdent) importIter.next(); 303 final String importArg = importLineText.getText(); 304 if (importArg.endsWith(".*")) { 305 final String fqClass = 306 importArg.substring(0, importArg.length() - 1) 307 + aClassName; 308 if (mIllegalClasses.contains(fqClass)) { 311 return fqClass; 312 } 313 } 314 else { 315 if (Utils.baseClassname(importArg).equals(aClassName) 316 && mIllegalClasses.contains(importArg)) 317 { 318 return importArg; 319 } 320 } 321 } 322 } 323 return null; 324 } 325 326 330 public void setClasses(String aClassNames) 331 { 332 mIllegalClasses.clear(); 333 final StringTokenizer tok = new StringTokenizer (aClassNames, ","); 334 while (tok.hasMoreTokens()) { 335 mIllegalClasses.add(tok.nextToken()); 336 } 337 } 338 } 339 | Popular Tags |