/*
* [FindImports.java]
*
* Summary: Scan Java source code for import statements.
*
* Copyright: (c) 2005-2017 Roedy Green, Canadian Mind Products, http://mindprod.com
*
* Licence: This software may be copied and used freely for any purpose but military.
* http://mindprod.com/contact/nonmil.html
*
* Requires: JDK 1.8+
*
* Created with: JetBrains IntelliJ IDEA IDE http://www.jetbrains.com/idea/
*
* Version History:
* 1.0 2005-06-30 loosely based on SeeSort
* 1.1 2006-03-05 reformat with IntelliJ, add Javadoc
*/
package com.mindprod.findimports;
import com.mindprod.commandline.CommandLine;
import com.mindprod.common18.EIO;
import com.mindprod.filter.AllButSVNDirectoriesFilter;
import com.mindprod.filter.ExtensionListFilter;
import com.mindprod.hunkio.HunkIO;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static java.lang.System.*;
/**
* Scan Java source code for import statements.
*
* scans all *.java files in current dir tree for import statements to generate and include file for source and class
* files for the packages referenced. Works only one level deep. Handles zip at package level, unlike Jar which must be
* done at the class level. Works using regex. This may serve as a base for other programs that use regexev to extract
* data from set of files.
*
* @author Roedy Green, Canadian Mind Products
* @version 1.1 2006-03-05 reformat with IntelliJ, add Javadoc
* @since 2005-06-30
*/
public final class FindImports
{
private static final int FIRST_COPYRIGHT_YEAR = 2005;
/**
* undisplayed copyright notice
*/
private static final String EMBEDDED_COPYRIGHT =
"Copyright: (c) 2005-2017 Roedy Green, Canadian Mind Products, http://mindprod.com";
private static final String RELEASE_DATE = "2006-03-06";
/**
* embedded version string.
*/
private static final String VERSION_STRING = "1.1";
// this is the preferred pattern. Finds classname, which we later chop to
// classname
private static final Pattern importPattern = Pattern
.compile( "import\\s+(com\\.mindprod\\.([\\w\\.\\*]++))\\s*\\;" );
/**
* dotted names of imports found in java source, no wildcards! , strippd of leading import and trailing ;, trimmed
*/
private static ArrayList foundImportedPackages;
/**
* Constructor
*/
private FindImports()
{
}
/**
* Remove any duplicates. The first object encountered is kept. Subsequent ones are removed.
*
* @param withDups ArrayList with duplicates. (will be sorted as side effect by natural comparator )
*
* @return list with any duplicates removed and sorted in order by the natural comparator.
*/
private static ArrayList deDupKeepingFirst( ArrayList withDups )
{
Collections.sort( withDups );
int size = withDups.size();
ArrayList result = new ArrayList<>( size );
if ( size <= 1 )
{
if ( size == 1 )
{
result.add( withDups.get( 0 ) );
}
return result;
}
String prev = withDups.get( 0 );
result.add( prev );
for ( int i = 1; i < size; i++ )
{
String o = withDups.get( i );
if ( o.compareTo( prev ) != 0 )
{
result.add( o );
prev = o;
}
}
return result;
}
/**
* compact and tidy one file to fix verbose hrefs.
*
* @param fileBeingProcessed File to scan for imports
*
* @throws IOException if cannot read file.
*/
private static void findImportsInFile( File fileBeingProcessed ) throws IOException
{
String big = HunkIO.readEntireFile( fileBeingProcessed );
// find stuff between import ... ;
out.println( fileBeingProcessed + " " + big.length() );
Matcher m = importPattern.matcher( big );
while ( m.find() )
{
// group 0 import static java.lang.System.err; import static java.lang.System.*; import com.mindprod
// .hunkio.HunkIO;
// group 1 com.mindprod.hunkio.HunkIO
// group 2 hunkio.HunkIO
// we only are interested in group 1, allowing for future multiple
// prefixes.
String importedClassName = m.group( 1 ).trim();
// impuortedClassname will end in .xxxx or .*, chop it off to get
// package name.
int place = importedClassName.lastIndexOf( '.' );
// just ignore, might have been gibberish in a comment. We are
// pretty mindless about parsing.
if ( place < 1 )
{
continue;
}
String packageName = importedClassName.substring( 0, place );
foundImportedPackages.add( packageName );
}
} // end findImportsInFile
/**
* finds imports in java source in current directory.
*
* @param args not used If there is no index for the dir, then use empty.ser
*/
public static void main( String[] args )
{
// global over all wantedFiles.
foundImportedPackages = new ArrayList<>( 500 );
out.println( "Gathering files to process..." );
CommandLine commmandLine = new CommandLine( new String[] { "-s", "." },
new AllButSVNDirectoriesFilter(),
new ExtensionListFilter( "java" ) );
for ( File wantedFile : commmandLine )
{
try
{
findImportsInFile( wantedFile );
}
catch ( FileNotFoundException e )
{
out.println( "Error: "
+ EIO.getCanOrAbsPath( wantedFile )
+ " not found." );
}
catch ( Exception e )
{
err.println();
e.printStackTrace( err );
err.println( " in file " + EIO.getCanOrAbsPath( wantedFile ) );
err.println();
}
} // end for
// foundImportedPackages has our big list of packages.
// sort and dedup
foundImportedPackages = deDupKeepingFirst( foundImportedPackages );
try
{
out.println( "Saving forZipsCore.list" );
PrintWriter emit =
new PrintWriter( new FileWriter( new File(
"forZipsCore.list" ) ) );
for ( String packageName : foundImportedPackages )
{
// generate lines like:
// com\mindprod\hunkio\*.class
// com\mindprod\hunkio\*.java
packageName = packageName.replace( '.', '\\' );
emit.println( packageName + "\\*.class" );
emit.println( packageName + "\\*.java" );
}
emit.close();
}
catch ( IOException e )
{
err.println();
e.printStackTrace( err );
err.println( "trouble generating forZipsCore.list" );
err.println();
}
} // end main
} // end FindImports