package com.dragome.commons.compiler.classpath.serverside;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.logging.Logger;
import com.dragome.commons.compiler.classpath.ClasspathEntry;
import com.dragome.commons.compiler.classpath.ClasspathFile;
import com.dragome.commons.compiler.classpath.ClasspathFileFilter;
public class JarClasspathEntry extends AbstractClasspathEntry implements ClasspathEntry
{
private static Logger LOGGER= Logger.getLogger(JarClasspathEntry.class.getName());
private JarFile jarFile;
public JarClasspathEntry(JarFile jarFile)
{
this.jarFile= jarFile;
}
public ClasspathFile getClasspathFileOf(String relativeName)
{
// There is a "bug" that using getJarEntry with "/" fails and "\\" succeed and vice versa. so solution is to loop all class
String tmprelativeName = relativeName.replace("\\", "/");
final Enumeration<JarEntry> entries= jarFile.entries();
while (entries.hasMoreElements())
{
final JarEntry entry= entries.nextElement();
final String entryName= entry.getName().replace("\\", "/"); // force all path to "/" if its using "\\"
if (tmprelativeName.equals(entryName))
return new InsideJarClasspathFile(jarFile, entry, relativeName);
}
return null;
}
private List<String> findClassesInJar(JarFile jarFile)
{
ArrayList<String> result= new ArrayList<String>();
final Enumeration<JarEntry> entries= jarFile.entries();
while (entries.hasMoreElements())
{
try
{
final JarEntry entry= entries.nextElement();
final String entryName= entry.getName();
// if (entryName.endsWith(".class"))
// result.add(entryName.replace('/', File.separatorChar).replace(".class", ""));
result.add(entryName);
}
catch (Exception e)
{
LOGGER.warning("There is an invalid jar entry: " + e.getMessage());
}
}
return result;
}
public List<ClasspathFile> getClasspathFilesFiltering(ClasspathFileFilter classpathFilter)
{
List<ClasspathFile> files= new ArrayList<ClasspathFile>();
List<String> classesInJar= findClassesInJar(jarFile);
for (String file : classesInJar)
{
ClasspathFile classpathFile= getClasspathFileOf(file);
if (classpathFilter == null || classpathFilter.accept(classpathFile))
files.add(classpathFile);
}
return files;
}
public static ClasspathEntry createFromPath(String path)
{
try
{
return new JarClasspathEntry(new JarFile(new File(path), false));
}
catch (IOException e)
{
throw new RuntimeException(e);
}
}
public String toString()
{
return jarFile.getName();
}
public String getName()
{
return jarFile.getName();
}
}