package org.Algy.models;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;
import org.Algy.jar.JarClassFile;
import org.Algy.jar.JarObject;
import org.Algy.jar.JarSource;
import org.Algy.jar.JavaDecompiler;
import org.Algy.jar.MetaCommentFile;
import org.Algy.jar.MyJarFile;
import org.apache.commons.io.IOUtils;
public class CachedJarModel {
private MyJarFile jarFile;
// className : JarObject (package sparator is /)
private HashMap<String, JarClassFile> classFiles;
private Set<String> directories;
// className : JarSource (package sparator is /)
private HashMap<String, JarSource> compiledSource;
//className( path - ".class") : comment file
private HashMap<String, MetaCommentFile> comments;
private boolean analyzed = false;
private boolean decompileSourceAtOnce;
private JavaDecompiler decompiler;
public CachedJarModel(File jarFile, JavaDecompiler decompiler, boolean decompileSourceAtOnce) throws IOException
{
if(jarFile != null)
setJar(jarFile);
this.decompileSourceAtOnce = decompileSourceAtOnce;
this.decompiler = decompiler;
}
public void setJar(File jarFile) throws IOException
{
this.jarFile = new MyJarFile(jarFile);
analyzed = false;
}
public void analyzeJar()
{
classFiles = new HashMap<String, JarClassFile>();
compiledSource = new HashMap<String, JarSource>();
comments = new HashMap<String, MetaCommentFile>();
directories = jarFile.getDirectories();
jarFile.collectObjects(new JavaDecompiler());
Iterator<JarObject> iter = jarFile.jarObjects();
while(iter.hasNext())
{
JarObject jarObj = iter.next();
if(jarObj instanceof JarClassFile)
{
JarClassFile jarClassFile =(JarClassFile)jarObj;
classFiles.put(jarClassFile.getClassName(), jarClassFile);
}
else if( jarObj instanceof MetaCommentFile)
{
MetaCommentFile commentFile = (MetaCommentFile)jarObj;
comments.put(commentFile.getClassName(), commentFile);
}
}
if(decompileSourceAtOnce)
{
for (JarClassFile file :classFiles.values())
{
try {
forceCompile(file);
} catch (IOException e) {
e.printStackTrace();
}
}
}
analyzed = true;
}
public JarSource forceCompile(String className) throws NoSuchClassFile, IOException
{
if(!classFiles.containsKey(className))
throw new NoSuchClassFile(className);
return forceCompile(classFiles.get(className));
}
public JarSource forceCompile(JarClassFile classFile) throws IOException
{
JarSource source = new JarSource(classFile, decompiler, false);
compiledSource.put(classFile.getClassName(), source);
return source;
}
public JarSource compile(String className) throws NoSuchClassFile, IOException
{
if(compiledSource.containsKey(className))
return compiledSource.get(className);
return forceCompile(className);
}
public JarSource compile(JarClassFile classFile) throws IOException
{
if(compiledSource.containsKey(classFile.getClassName()))
return compiledSource.get(classFile.getClassName());
return forceCompile(classFile);
}
public void clearSourceData()
{
classFiles.clear();
directories.clear();
compiledSource.clear();
}
public void clearCompiledCache()
{
compiledSource.clear();
}
public void saveAs(File file) throws IOException
{
IOUtils.copy(new FileInputStream(jarFile.getFile()), new FileOutputStream(file));
//and metadata input
}
//safely...
public void safeSave(File file) throws IOException
{
if(jarFile == null)
throw new IOException("No File to save");
String original = file.getPath();
File savingFile = new File(file.getPath() + ".saving");
File oldFile =jarFile.getFile();
InputStream oldFileStream = new FileInputStream(oldFile);
OutputStream savingFileStream = new FileOutputStream(savingFile);
IOUtils.copy(oldFileStream, savingFileStream);
//and metadata input ...
//TODO : metadata input
//if metadata input suceed
oldFileStream.close();
savingFileStream.close();
if(file.exists())
file.delete();
savingFile.renameTo(new File(original));
}
public boolean isAnalyzed() {
return analyzed;
}
public Set<String> getDirectories() {
return directories;
}
public HashMap<String, JarClassFile> getClassFiles() {
return classFiles;
}
public HashMap<String, JarSource> getCompiledSource() {
return compiledSource;
}
public HashMap<String, MetaCommentFile> getComments() {
return comments;
}
public MyJarFile getJarFile() {
return jarFile;
}
}