import java.io.*;
import java.util.*;
import java.util.jar.*;
import java.util.zip.*;

import org.apache.oro.text.regex.*;

public class PackageConflicts{

	Map packages = new HashMap();
	Map conflicts = new TreeMap();

	public static void main(String[] args) throws Exception{
		new PackageConflicts().checkConflicts();
	}

	void checkConflicts()throws Exception{
		String cp = System.getProperty("java.class.path",".");
		String ps = System.getProperty("path.separator", ";");
		Vector pathElements = Util.split( new Perl5Matcher(), (new Perl5Compiler()).compile(ps), cp);

		Iterator elems = pathElements.iterator();
		while(elems.hasNext()){
			String pathElement = (String)elems.next();
			if (!pathElement.endsWith(".jar")) continue;

			checkPackages(pathElement);

		}
		reportConflicts();
	}

	void checkPackages(String jarName){
		System.out.println("checking: " + jarName);
		Perl5Matcher matcher = new Perl5Matcher();
		Perl5Pattern pattern = null;
		try {
			pattern = (Perl5Pattern)(new Perl5Compiler()).compile("([a-z0-9/]+/)[a-z0-9_]+\\.class",Perl5Compiler.CASE_INSENSITIVE_MASK );
		}catch(MalformedPatternException mpe){
			mpe.printStackTrace();
			return;
		}
		HashSet checked = new HashSet();
		//Open the jar
		try{
			ZipFile jar = new ZipFile(jarName);
			Enumeration entries = jar.entries();
			while(entries.hasMoreElements()){
				ZipEntry entry = (ZipEntry) entries.nextElement();
				if(!matcher.contains(entry.getName(), pattern)) continue;

				String packageName = matcher.getMatch().group(1);
				//System.out.println("  testing: " + packageName);

				if (checked.contains(packageName)) continue;

				checked.add(packageName);
				if (packages.containsKey(packageName)){
					recordConflict(packageName, jarName);
					continue;
				}
				checkAddPackage(packageName, jarName);
			}
		}catch(IOException ioe){
			ioe.printStackTrace();
		}
	}

	void recordConflict(String packageName, String jarName){
		HashSet definedIns = null;
		if (conflicts.containsKey(packageName)){
			definedIns = (HashSet)conflicts.get(packageName);
		}
		else {
			definedIns = new HashSet();
			conflicts.put(packageName, definedIns);
			definedIns.add(packages.get(packageName));
		}
		//System.out.println("Adding: " + jarName);
		definedIns.add(jarName);

	}

	void checkAddPackage(String packageName, String jarName){
		if(checkIsPackage(packageName)){
			packages.put(packageName, jarName);
		}

	}

	boolean checkIsPackage(String potential){
		if (potential.indexOf("/") != potential.lastIndexOf("/")){
			// System.out.println("found: " + potential);
			return true;
		}
		else return false;
	}



	void reportConflicts(){
		Iterator potentials = conflicts.keySet().iterator();
		while(potentials.hasNext()){
			String packageName = (String)potentials.next();
			Iterator jars = ((HashSet)conflicts.get(packageName)).iterator();
			System.out.println("Package: " + packageName + " defined in: " );
			while(jars.hasNext()){
				System.out.println("  " + jars.next());
			}
			System.out.println("");
		}
	}

}