/* This file is *not* under GPL or any other public license
* Copyright 2005 Ugo Taddei
*/
package de.latlon.deejump.plugin.manager;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.JarURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.JarOutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import org.apache.log4j.Logger;
import com.vividsolutions.jts.util.Assert;
import com.vividsolutions.jump.I18N;
import com.vividsolutions.jump.task.TaskMonitor;
import com.vividsolutions.jump.util.StringUtil;
import com.vividsolutions.jump.workbench.WorkbenchContext;
import com.vividsolutions.jump.workbench.plugin.Configuration;
import com.vividsolutions.jump.workbench.plugin.PlugInContext;
import com.vividsolutions.jump.workbench.plugin.PlugInManager;
public class ExtensionHelper {
private static Logger LOG = Logger.getLogger( ExtensionHelper.class );
private ExtensionHelper() {
// no, no, never instantiate
}
public static final void install( ExtensionManagerDialog extensionManager, WorkbenchContext workbenchContext,
ExtensionWrapper ext, TaskMonitor monitor) throws Exception {
PlugInManager manager = workbenchContext.getWorkbench().getPlugInManager();
monitor.report( I18N.get("deejump.pluging.manager.ExtensionHelper.Downloading-resources"));
File[] files =
downloadAndSaveResources(
extensionManager.getExtensionSite(),
ext,
manager.getPlugInDirectory());
URLClassLoader classLoader = new URLClassLoader( toURLs( files ) );
monitor.report( I18N.get("deejump.pluging.manager.ExtensionHelper.Loading-classes"));
// list Extension and/or Configuration classes inside the zips/jars
List extensionClasses = new ArrayList( 10 );
for (int i = 0; i < files.length; i++) {
extensionClasses.addAll( classes( new ZipFile( files[i] ),
classLoader ) );
}
List configs = new ArrayList();
for (Iterator iter = extensionClasses.iterator(); iter.hasNext();) {
Class c = (Class)iter.next();
Configuration configuration = (Configuration) c.newInstance();
configs.add( configuration );
}
monitor.report( I18N.get("deejump.pluging.manager.ExtensionHelper.Loading-extensions"));
//finally, load configs/extensions
// this method will call extension.configure(new PlugInContext(context, null, null,
//null, null)); )
loadConfigurations( configs, workbenchContext );
}
public static final void remove( List fileList,
ExtensionWrapper ext, TaskMonitor monitor)
throws Exception {
List resourceList = ext.getResourceList();
for (Iterator iter = fileList.iterator(); iter.hasNext();) {
File file = (File) iter.next();
if (file.isFile()) {
if ( resourceList.contains( file.getName() ) ) {
// System.out.println("will delete: " + file);
monitor.report( I18N.get("deejump.pluging.manager.ExtensionHelper.Deleting-file") + " " + file );
boolean deleted = false;
try {
deleted = file.delete();
} catch (SecurityException e) {
// TODO decide if re-throw here or handle or log??
e.printStackTrace();
}
//TODO throw exc if false.
// hmm no exception thrown?
// file permissions?
// bye bye
System.out.println(I18N.get("deejump.pluging.manager.ExtensionHelper.deleted") + " '" + file+ "': " + deleted);
//???? above hasn't worked, file locked? del on exited didn'T work...
//put file on a list and finish it off?
// inlcude in a plug-in, listener --> workbench.isclosed -> del file!
// file.deleteOnExit();
}
}
}
}
private static File[] downloadAndSaveResources(String extensionSite, ExtensionWrapper ext, File plugInDirectory) {
// TODO pull down resources from ext and save to pluginDir
List fileList = new ArrayList( ext.getResourceList().size() );
for (Iterator iter = ext.getResourceList().iterator(); iter.hasNext();) {
String resourceName = (String) iter.next();
try {
URL resURL = new URL( //+ ext.getCategory() + "/"
"jar:" + extensionSite + resourceName + "!/"
);
JarURLConnection juc = (JarURLConnection)resURL.openConnection();
JarFile jf = juc.getJarFile();
Enumeration enumer = jf.entries();
String resourceFile = plugInDirectory + File.separator + resourceName;
fileList.add( new File(resourceFile) );
FileOutputStream fos = new FileOutputStream( resourceFile );
System.out.println(":vv " + resourceFile);
JarOutputStream jos = new JarOutputStream( fos );
while (enumer.hasMoreElements()) {
JarEntry je = (JarEntry) enumer.nextElement();
jos.putNextEntry( new JarEntry( je ));
InputStream in = jf.getInputStream( je );
int c;
//TODO FIXME use a buffered reader!!!
while( (c=in.read()) >= 0 ) {
jos.write(c);
}
in.close();
}
jos.closeEntry();
jos.close();
fos.close();
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return (File[])fileList.toArray( new File[ fileList.size() ]);
}
private static void saveRemoteResources( String extensionSite, ExtensionWrapper ext ) {
List extList = ext.getResourceList();
for (Iterator iter = extList.iterator(); iter.hasNext();) {
String resource = (String) iter.next();
try {
URL resURL = new URL( extensionSite + "/" + ext.getCategory() + ext.getName());
byte[] bitsAndBytes = null;
DataInputStream dis = new DataInputStream( resURL.openStream() );
dis.readFully( bitsAndBytes );
FileOutputStream fos = new FileOutputStream(
"c:\temp\ttt.jar"
//manager.getPlugInDirectory()+ ext.getName()
);
fos.write( bitsAndBytes );
fos.close();
dis.close();
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
/* shamelessly copied from PlugInManager */
private static URL[] toURLs(File[] files) {
URL[] urls = new URL[files.length];
for (int i = 0; i < files.length; i++) {
try {
System.out.println( "path: " + files[i].getPath() );
urls[i] = new URL("jar:file:" + files[i].getPath() + "!/");
} catch (MalformedURLException e) {
Assert.shouldNeverReachHere(e.toString());
}
}
return urls;
}
/* shamelessly copied from PlugInManager */
private static List classes(ZipFile zipFile, ClassLoader classLoader) {
ArrayList classes = new ArrayList();
for (Enumeration e = zipFile.entries(); e.hasMoreElements();) {
ZipEntry entry = (ZipEntry) e.nextElement();
//Filter by filename; otherwise we'll be loading all the classes,
// which takes
//significantly longer [Jon Aquino]
if (!(entry.getName().endsWith("Extension.class") || entry
.getName().endsWith("Configuration.class"))) {
//Include "Configuration" for backwards compatibility. [Jon
// Aquino]
continue;
}
Class c = toClass(entry, classLoader);
if (c != null) {
classes.add(c);
}
}
return classes;
}
/* shamelessly copied from PlugInManager */
private static Class toClass(ZipEntry entry, ClassLoader classLoader) {
if (entry.isDirectory()) {
return null;
}
if (!entry.getName().endsWith(".class")) {
return null;
}
if (entry.getName().indexOf("$") != -1) {
//I assume it's not necessary to load inner classes explicitly.
// [Jon Aquino]
return null;
}
String className = entry.getName();
className = className.substring(0, className.length()
- ".class".length());
className = StringUtil.replaceAll(className, "/", ".");
Class candidate;
try {
candidate = classLoader.loadClass(className);
} catch (ClassNotFoundException e) {
Assert.shouldNeverReachHere("Class not found: " + className
+ ". Refine class name algorithm.");
return null;
} catch (Throwable t) {
LOG.error("Throwable encountered loading " + className
+ ":");
//e.g. java.lang.VerifyError: class
// org.apache.xml.serialize.XML11Serializer
//overrides final method [Jon Aquino]
t.printStackTrace(System.out);
return null;
}
return candidate;
}
private static void loadConfigurations(List configurations, WorkbenchContext context) throws Exception {
for (Iterator i = configurations.iterator(); i.hasNext();) {
Configuration configuration = (Configuration) i.next();
configuration.configure(new PlugInContext(context, null, null,
null, null));
}
}
}