View Javadoc
1 package net.sourceforge.pmd; 2 3 import net.sourceforge.pmd.swingui.event.ListenerList; 4 import net.sourceforge.pmd.swingui.event.PMDDirectoryRequestEvent; 5 import net.sourceforge.pmd.swingui.event.PMDDirectoryRequestEventListener; 6 import net.sourceforge.pmd.swingui.event.PMDDirectoryReturnedEvent; 7 import net.sourceforge.pmd.swingui.event.RuleSetEvent; 8 import net.sourceforge.pmd.swingui.event.RuleSetEventListener; 9 10 import java.io.File; 11 import java.io.FileInputStream; 12 import java.io.FileNotFoundException; 13 import java.io.FileOutputStream; 14 import java.io.FilenameFilter; 15 import java.io.IOException; 16 import java.text.MessageFormat; 17 import java.util.ArrayList; 18 import java.util.Iterator; 19 import java.util.List; 20 import java.util.Properties; 21 22 23 /*** 24 * Defines and provides access to PMD's directory structure. The user defines the location 25 * of the root PMD directory, e.g., /users/userA/PMD. The PMD directory structure provides 26 * the following: 27 * <ul> 28 * <li>Organization to simplify PMD's access to files.</li> 29 * <li>Eliminates dependence of manually updating the Java classpath.</li> 30 * <li>Permits adding and removing rule sets without updating lists.</li> 31 * </ul> 32 * <pre> 33 * The directory structure and contents are the following: 34 * <code> 35 * PMD 36 * pmd.properties 37 * rulesets 38 * basic.xml 39 * design.xml 40 * import.xml 41 * com 42 * myCompany 43 * pmd 44 * rules 45 * myRule01.class 46 * myRule02.class 47 * myRule03.class 48 * net 49 * sourceforge 50 * pmd 51 * rules 52 * myNewExperimentalRule.class 53 * </code> 54 * </pre> 55 * The <b>PMD</b> directory is the root directory of all PMD files. 56 * <p> 57 * The <b>pmd.properties</b> file contains various information to be defined. 58 * <p> 59 * The <b>rulesets</b> directory contains the rule set files and rule class file directories. 60 * <p> 61 * A <b>rule set file</b> is a XML file that describes the rule set and its rules. This 62 * information is displayed and maintained in the PMD Viewer. The rule class files are called by PMD 63 * to perform the analysis. 64 * <p> 65 * All rule classes, other than the rule classes in pmd.jar, are stored in directory paths 66 * defined by each rule's class name. The Java classpath is appended with the rulesets 67 * directory so that the rule class and any supporting class files may be found. 68 * <p> 69 * <b>NOTE:</b> The user's home directory will contain a PMD directory with a user.preferences 70 * file. An entry in the user's preferences will be the path to the PMD root directory 71 * described above. 72 * 73 * @author Donald A. Leckie 74 * @since September 19, 2002 75 * @version $Revision: 1.13 $, $Date: 2003/03/14 19:03:44 $ 76 */ 77 78 public class PMDDirectory { 79 80 private String m_pmdDirectoryPath; 81 private String m_ruleSetsDirectoryPath; 82 private Properties m_properties; 83 private PMDDirectoryRequestEventHandler m_pmdDirectoryRequestEventHandler; 84 private RuleSetEventHandler m_ruleSetEventHandler; 85 private static PMDDirectory m_pmdDirectoryInstance; 86 87 // Constants 88 private final String PROPERTIES_FILE_NAME = "pmd.properties"; 89 90 /*** 91 ******************************************************************************** 92 * 93 * Creates the information about the PMD directory structure that will be required 94 * for accessing the PMD files. 95 * 96 * @param pathToPMD The full path to the PMD directory, but excludes the PMD directory. 97 */ 98 private PMDDirectory(String pathToPMD) throws PMDException { 99 String classpath; 100 String key; 101 102 m_pmdDirectoryRequestEventHandler = new PMDDirectoryRequestEventHandler(); 103 m_ruleSetEventHandler = new RuleSetEventHandler(); 104 ListenerList.addListener(m_pmdDirectoryRequestEventHandler); 105 ListenerList.addListener(m_ruleSetEventHandler); 106 m_pmdDirectoryPath = pathToPMD + File.separator + "PMD"; 107 m_ruleSetsDirectoryPath = m_pmdDirectoryPath + File.separator + "rulesets"; 108 key = "java.class.path"; 109 classpath = System.getProperty(key); 110 classpath = classpath + ";" + m_ruleSetsDirectoryPath; 111 System.setProperty(key, classpath); 112 loadPropertiesFile(); 113 } 114 115 /*** 116 ******************************************************************************** 117 * 118 * @param pathToPMD The full path to the PMD directory, but excludes the PMD directory. 119 */ 120 public static final void open(String pathToPMD) throws PMDException { 121 m_pmdDirectoryInstance = new PMDDirectory(pathToPMD); 122 } 123 124 /*** 125 ******************************************************************************** 126 * 127 * @return 128 */ 129 public static final PMDDirectory getDirectory() { 130 return m_pmdDirectoryInstance; 131 } 132 133 /*** 134 ******************************************************************************** 135 * 136 * Gets a rule set containing only the rule sets and rules to be included for running 137 * the analysis. 138 * 139 * @return A rule containing only included rules. 140 */ 141 public RuleSet getIncludedRules(int lowestPriorityForAnalysis) throws PMDException { 142 RuleSet includedRules = new RuleSet(); 143 Iterator ruleSetFiles = getRuleSetFiles().iterator(); 144 145 while (ruleSetFiles.hasNext()) { 146 File ruleSetFile = (File) ruleSetFiles.next(); 147 RuleSet ruleSet = getRuleSet(ruleSetFile, true); 148 149 if ((ruleSet != null) && ruleSet.include()) { 150 Iterator allRules = ruleSet.getRules().iterator(); 151 152 while (allRules.hasNext()) { 153 Rule rule = (Rule) allRules.next(); 154 155 if (rule.include()) { 156 if (rule.getPriority() <= lowestPriorityForAnalysis) { 157 includedRules.addRule(rule); 158 } 159 } 160 } 161 } 162 } 163 164 return includedRules; 165 } 166 167 /*** 168 ******************************************************************************** 169 * 170 * Gets the rule set for the given rule set file. All rules in the rule set file 171 * are stored in the rule set regardless of their <i>include</i> state. 172 * 173 * @param ruleSetFile The file of the desired rule set. 174 * 175 * @return A rule set containing all of its rules. 176 * 177 * @throws PMDException 178 */ 179 public RuleSet getRuleSet(File ruleSetFile) throws PMDException { 180 return getRuleSet(ruleSetFile, false); 181 } 182 183 /*** 184 ******************************************************************************** 185 * 186 * Gets the rule set for the given rule set File. All rules in the rule set file 187 * are stored in the rule set according of their <i>include</i> state and the <i>onlyIfIncluded</i> 188 * flag. 189 * 190 * @param ruleSetFile The file of the desired rule set. 191 * 192 * @return A rule set containing all of its rules. 193 * 194 * @throws PMDException 195 */ 196 public RuleSet getRuleSet(File ruleSetFile, boolean onlyIfIncluded) throws PMDException { 197 if (ruleSetFile == null) { 198 String message = "Rule set file parameter is missing."; 199 PMDException exception = new PMDException(message); 200 exception.fillInStackTrace(); 201 throw exception; 202 } 203 204 FileInputStream inputStream = null; 205 RuleSet ruleSet = null; 206 207 try { 208 RuleSetReader reader; 209 inputStream = new FileInputStream(ruleSetFile); 210 reader = new RuleSetReader(); 211 ruleSet = reader.read(inputStream, ruleSetFile.getName(), onlyIfIncluded); 212 } catch (FileNotFoundException exception) { 213 String template = "Rule set \"{0}\" was not found."; 214 String[] args = {ruleSetFile.getPath()}; 215 String message = MessageFormat.format(template, args); 216 PMDException pmdException = new PMDException(message, exception); 217 pmdException.fillInStackTrace(); 218 throw pmdException; 219 } finally { 220 if (inputStream != null) { 221 try { 222 inputStream.close(); 223 } catch (IOException exception) { 224 } 225 } 226 } 227 228 return ruleSet; 229 } 230 231 /*** 232 ******************************************************************************** 233 * 234 * @return 235 */ 236 private List getRuleSetFiles() { 237 List ruleSetFiles = new ArrayList(); 238 File directory = new File(m_ruleSetsDirectoryPath); 239 240 if (directory.exists() == false) { 241 directory.mkdirs(); 242 } 243 244 File[] files = directory.listFiles(new XMLFileNameFilter()); 245 246 for (int n = 0; n < files.length; n++) { 247 ruleSetFiles.add(files[n]); 248 } 249 250 return ruleSetFiles; 251 } 252 253 /*** 254 ******************************************************************************** 255 * 256 * @return 257 */ 258 public List getRegisteredRuleSets() { 259 List ruleSetList = new ArrayList(); 260 261 try { 262 Iterator ruleSets = (new RuleSetFactory()).getRegisteredRuleSets(); 263 264 while (ruleSets.hasNext()) { 265 RuleSet ruleSet; 266 Iterator rules; 267 268 ruleSet = (RuleSet) ruleSets.next(); 269 ruleSet.setInclude(true); 270 rules = ruleSet.getRules().iterator(); 271 272 while (rules.hasNext()) { 273 ((Rule) rules.next()).setInclude(true); 274 } 275 276 ruleSetList.add(ruleSet); 277 } 278 } catch (RuleSetNotFoundException exception) { 279 // This should not happen because the registered rule sets are resources in pmd.jar. 280 System.out.println(exception.getMessage()); 281 } 282 283 return ruleSetList; 284 } 285 286 /*** 287 ******************************************************************************** 288 * 289 * @return 290 */ 291 public List getRuleSets() throws PMDException { 292 List ruleSetList; 293 List ruleSetFilesList = getRuleSetFiles(); 294 295 if (ruleSetFilesList.size() == 0) { 296 ruleSetList = getRegisteredRuleSets(); 297 } else { 298 Iterator ruleSetFiles; 299 300 ruleSetList = new ArrayList(); 301 ruleSetFiles = ruleSetFilesList.iterator(); 302 303 while (ruleSetFiles.hasNext()) { 304 File ruleSetFile = (File) ruleSetFiles.next(); 305 RuleSet ruleSet = getRuleSet(ruleSetFile); 306 307 ruleSetList.add(ruleSet); 308 } 309 } 310 311 return ruleSetList; 312 } 313 314 /*** 315 ******************************************************************************** 316 * 317 * @return 318 */ 319 public String getPMDDirectoryPath() { 320 return m_pmdDirectoryPath; 321 } 322 323 /*** 324 ******************************************************************************** 325 * 326 * @return 327 */ 328 public String getRuleSetsDirectoryPath() { 329 return m_ruleSetsDirectoryPath; 330 } 331 332 /*** 333 ******************************************************************************** 334 * 335 * @param ruleSetList 336 */ 337 protected void saveRuleSets(List ruleSetList) { 338 Iterator ruleSets = ruleSetList.iterator(); 339 340 while (ruleSets.hasNext()) { 341 RuleSet ruleSet = (RuleSet) ruleSets.next(); 342 String ruleSetFileName = ruleSet.getFileName(); 343 String path = m_ruleSetsDirectoryPath + File.separator + ruleSetFileName; 344 File file = new File(path); 345 FileOutputStream outputStream = null; 346 347 if (file.exists()) { 348 file.delete(); 349 } 350 351 try { 352 RuleSetWriter writer; 353 354 outputStream = new FileOutputStream(file); 355 writer = new RuleSetWriter(outputStream); 356 writer.write(ruleSet); 357 } catch (FileNotFoundException exception) { 358 // Should not reach here because the rule set file has been deleted if it 359 // existed and the directories all exist. 360 exception = null; 361 } finally { 362 if (outputStream != null) { 363 try { 364 outputStream.close(); 365 } catch (IOException exception) { 366 exception = null; 367 } 368 } 369 } 370 } 371 } 372 373 /*** 374 ******************************************************************************** 375 * 376 * @param pathToPMD 377 */ 378 private void loadPropertiesFile() throws PMDException { 379 String propertiesFileName; 380 FileInputStream inputStream; 381 382 propertiesFileName = m_pmdDirectoryPath + File.separator + PROPERTIES_FILE_NAME; 383 m_properties = new Properties(); 384 inputStream = null; 385 386 try { 387 File file = new File(propertiesFileName); 388 389 if (file.exists() == false) { 390 File directory = file.getParentFile(); 391 392 directory.mkdirs(); 393 file.createNewFile(); 394 } 395 396 inputStream = new FileInputStream(propertiesFileName); 397 m_properties.load(inputStream); 398 } catch (FileNotFoundException exception) { 399 String template = "Could not find the file \"{0}\"."; 400 String[] args = {propertiesFileName}; 401 String message = MessageFormat.format(template, args); 402 PMDException pmdException = new PMDException(message, exception); 403 pmdException.fillInStackTrace(); 404 throw pmdException; 405 } catch (IOException exception) { 406 String template = "Unable to read the file \"{0}\"."; 407 String[] args = {propertiesFileName}; 408 String message = MessageFormat.format(template, args); 409 PMDException pmdException = new PMDException(message, exception); 410 pmdException.fillInStackTrace(); 411 throw pmdException; 412 } finally { 413 if (inputStream != null) { 414 try { 415 inputStream.close(); 416 } catch (IOException exception) { 417 exception = null; 418 } 419 } 420 } 421 } 422 423 /*** 424 ******************************************************************************** 425 * 426 */ 427 public void savePropertiesFile() throws PMDException { 428 FileOutputStream outputStream = null; 429 String propertiesFileName = m_pmdDirectoryPath + File.separator + PROPERTIES_FILE_NAME; 430 File file = new File(propertiesFileName); 431 if (file.exists()) { 432 file.delete(); 433 } 434 435 try { 436 m_properties.store(outputStream, null); 437 } catch (FileNotFoundException exception) { 438 String template = "Could not find the file \"{0}\"."; 439 String[] args = {propertiesFileName}; 440 String message = MessageFormat.format(template, args); 441 PMDException pmdException = new PMDException(message, exception); 442 pmdException.fillInStackTrace(); 443 throw pmdException; 444 } catch (IOException exception) { 445 String template = "Unable to read the file \"{0}\"."; 446 String[] args = {propertiesFileName}; 447 String message = MessageFormat.format(template, args); 448 PMDException pmdException = new PMDException(message, exception); 449 pmdException.fillInStackTrace(); 450 throw pmdException; 451 } finally { 452 if (outputStream != null) { 453 try { 454 outputStream.close(); 455 } catch (IOException exception) { 456 exception = null; 457 } 458 } 459 } 460 } 461 462 /*** 463 ******************************************************************************* 464 ******************************************************************************* 465 ******************************************************************************* 466 */ 467 private class RuleSetEventHandler implements RuleSetEventListener { 468 469 /*** 470 *************************************************************************** 471 * 472 * @param event 473 */ 474 public void saveRuleSets(RuleSetEvent event) { 475 List ruleSetList = event.getRuleSetList(); 476 PMDDirectory.this.saveRuleSets(ruleSetList); 477 } 478 } 479 480 /*** 481 ******************************************************************************* 482 ******************************************************************************* 483 ******************************************************************************* 484 */ 485 private class PMDDirectoryRequestEventHandler implements PMDDirectoryRequestEventListener { 486 487 /*** 488 *************************************************************************** 489 * 490 * @param event 491 */ 492 public void requestRuleSetPath(PMDDirectoryRequestEvent event) { 493 PMDDirectoryReturnedEvent.notifyReturnedRuleSetPath(this, getRuleSetsDirectoryPath()); 494 } 495 496 /*** 497 *************************************************************************** 498 * 499 * @param event 500 */ 501 public void requestAllRuleSets(PMDDirectoryRequestEvent event) throws PMDException { 502 PMDDirectoryReturnedEvent.notifyReturnedAllRuleSets(this, getRuleSets()); 503 } 504 505 /*** 506 *************************************************************************** 507 * 508 * @param event 509 */ 510 public void requestDefaultRuleSets(PMDDirectoryRequestEvent event) { 511 PMDDirectoryReturnedEvent.notifyReturnedDefaultRuleSets(this, getRegisteredRuleSets()); 512 } 513 514 /*** 515 *************************************************************************** 516 * 517 * @param event 518 */ 519 public void requestIncludedRules(PMDDirectoryRequestEvent event) throws PMDException { 520 int priority = event.getLowestPriorityForAnalysis(); 521 PMDDirectoryReturnedEvent.notifyReturnedIncludedRules(this, getIncludedRules(priority)); 522 } 523 } 524 525 /*** 526 ******************************************************************************* 527 ******************************************************************************* 528 ******************************************************************************* 529 */ 530 private class XMLFileNameFilter implements FilenameFilter { 531 532 /*** 533 *************************************************************************** 534 * 535 * @param directory 536 * @param fileName 537 * 538 * @return 539 */ 540 public boolean accept(File directory, String fileName) { 541 return fileName.toLowerCase().endsWith(".xml"); 542 } 543 } 544 }

This page was automatically generated by Maven