001/* Look for class files under a directory and return package names. 002 003 Copyright (c) 2006-2015 The Regents of the University of California. 004 All rights reserved. 005 Permission is hereby granted, without written agreement and without 006 license or royalty fees, to use, copy, modify, and distribute this 007 software and its documentation for any purpose, provided that the above 008 copyright notice and the following two paragraphs appear in all copies 009 of this software. 010 011 IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY 012 FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 013 ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF 014 THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF 015 SUCH DAMAGE. 016 017 THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, 018 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 019 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE 020 PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF 021 CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, 022 ENHANCEMENTS, OR MODIFICATIONS. 023 024 PT_COPYRIGHT_VERSION_2 025 COPYRIGHTENDKEY 026 027 */ 028package ptolemy.vergil.actor; 029 030import java.io.File; 031import java.io.FileFilter; 032import java.util.HashSet; 033import java.util.Iterator; 034import java.util.Set; 035 036import ptolemy.util.ExecuteCommands; 037 038/** Look for class files under a directory and return package names. 039 * @author Christopher Brooks 040 * @version $Id$ 041 * @since Ptolemy II 5.2 042 * @Pt.ProposedRating Red (cxh) 043 * @Pt.AcceptedRating Red (cxh) 044 */ 045public class FindPackages { 046 /** Look for class files under a directory and return package names. 047 * Directories that end in adm, CVS and vendors are skipped. 048 * @param ptII The File under which to look for classes. 049 * @param executeCommands The ExecuteCommands object in which to report 050 * status. If null, then print to standard out. 051 * @return A string of space separated package names, relative to 052 * the File named by the ptII argument. 053 */ 054 public static String findPackages(File ptII, 055 ExecuteCommands executeCommands) { 056 StringBuffer results = new StringBuffer(); 057 Set directoriesSeen = new HashSet(); 058 Set classFilesSeen = new HashSet(); 059 String ptIIPath = ptII.getPath().replace('\\', '/'); 060 if (executeCommands == null) { 061 System.out.println("Searching for .class files in " + ptIIPath); 062 } else { 063 executeCommands.stdout("Searching for .class files in " + ptIIPath); 064 } 065 _getDirectories(ptII, directoriesSeen, classFilesSeen); 066 Set packages = new HashSet(); 067 Iterator classFiles = classFilesSeen.iterator(); 068 while (classFiles.hasNext()) { 069 File files[] = (File[]) classFiles.next(); 070 for (File file : files) { 071 String fullPath = file.toString().replace('\\', '/'); 072 String shortPath = fullPath.substring(0, 073 file.toString().length() - 6); 074 if (shortPath.startsWith(ptIIPath)) { 075 shortPath = shortPath.substring(ptIIPath.length() + 1); 076 } 077 shortPath = shortPath.substring(0, shortPath.lastIndexOf('/')); 078 String packageName = shortPath.replace('/', '.'); 079 if (!packages.contains(packageName)) { 080 packages.add(packageName); 081 results.append(" " + packageName); 082 } 083 } 084 } 085 if (executeCommands == null) { 086 System.out.println(results.toString()); 087 } else { 088 executeCommands.stdout(results.toString()); 089 } 090 return results.toString(); 091 } 092 093 /** Print out any packages found under the directory named 094 * by the first argument. 095 * <p>Usage: java -classpath $PTII ptolemy.vergil.actor.FindPackages $PTII 096 * @param args An array of Strings, where the first argument is 097 * a string that names the directory under which we search for packages. 098 */ 099 public static void main(String[] args) { 100 findPackages(new File(args[0]), null); 101 } 102 103 /////////////////////////////////////////////////////////////////// 104 //// private methods //// 105 106 /** Recursively descend the filesystem. 107 * Directories that end in adm, CVS and vendors are skipped. 108 * @param directory The top level directory. 109 * @param directoriesSeen A Set of objects of type File 110 * that name directories that have been seen. 111 */ 112 private static void _getDirectories(File directory, Set directoriesSeen, 113 Set classFilesSeen) { 114 File directories[] = directory.listFiles(new DirectoryFileFilter()); 115 // Coverity Scan: Dereference null value returns. directories could be null. 116 if (directories != null) { 117 for (int i = 0; i < directories.length; i++) { 118 if (!directoriesSeen.contains(directories[i]) 119 && !directories[i].getName().endsWith("adm") 120 && !directories[i].getName().endsWith("CVS") 121 && !directories[i].getName().endsWith("vendors")) { 122 File classFiles[] = directories[i] 123 .listFiles(new ClassFileFilter()); 124 classFilesSeen.add(classFiles); 125 directoriesSeen.add(directories[i]); 126 _getDirectories(directories[i], directoriesSeen, 127 classFilesSeen); 128 } 129 } 130 } 131 } 132 133 /** Filter that returns true if the pathname ends with .class. */ 134 private static class ClassFileFilter implements FileFilter { 135 /** Filter that returns true if the file name ends with .class. 136 * @param pathname The pathname to be checked 137 * @return true if the pathname ends with .class. 138 */ 139 @Override 140 public boolean accept(File pathname) { 141 return pathname.getName().endsWith(".class"); 142 } 143 } 144 145 /** Filter that returns true if the pathname is a directory. */ 146 private static class DirectoryFileFilter implements FileFilter { 147 /** Filter that returns true if the pathname is a directory. 148 * @param pathname The pathname to be checked 149 * @return true if the pathname is a directory. 150 */ 151 @Override 152 public boolean accept(File pathname) { 153 return pathname.isDirectory(); 154 } 155 } 156 157}