/** * Take the name of a jar file and extract the plugin.xml file, if possible, to a temporary file. * * @param f The jar file to extract from. * @return a temporary file to which the plugin.xml file has been copied. */ public static File unpackPluginXML(File f) { InputStream in = null; OutputStream out = null; try { JarFile jar = new JarFile(f); ZipEntry entry = jar.getEntry(PLUGIN_XML_FILE); if (entry == null) { return null; } File dest = File.createTempFile("jabref_plugin", ".xml"); dest.deleteOnExit(); in = new BufferedInputStream(jar.getInputStream(entry)); out = new BufferedOutputStream(new FileOutputStream(dest)); byte[] buffer = new byte[2048]; for (; ; ) { int nBytes = in.read(buffer); if (nBytes <= 0) break; out.write(buffer, 0, nBytes); } out.flush(); return dest; } catch (IOException ex) { ex.printStackTrace(); return null; } finally { try { if (out != null) out.close(); if (in != null) in.close(); } catch (IOException ex) { ex.printStackTrace(); } } }
/** * This method deletes a plugin file. If deletion fails - typically happens on Windows due to file * locking - the file is scheduled for deletion on the next startup. * * @param f The file to delete. * @return true if deletion was successful, false if scheduled for later. */ public static boolean deletePluginFile(File f) { boolean success = f.delete(); if (success) return true; else { schedulePluginForDeletion(f.getPath()); return false; } }
/** * Build a list of installed plugins. * * @return a list of plugin names and version numbers. */ public static EventList<NameAndVersion> findInstalledPlugins() { EventList<NameAndVersion> plugins = new BasicEventList<NameAndVersion>(); if (!PluginCore.userPluginDir.exists()) return plugins; String[] files = PluginCore.userPluginDir.list( new FilenameFilter() { public boolean accept(File dir, String name) { return name.endsWith(".jar"); } }); HashMap<String, PluginDescriptor> urls = new HashMap<String, PluginDescriptor>(); Collection<PluginDescriptor> descriptors = PluginCore.getManager().getRegistry().getPluginDescriptors(); for (PluginDescriptor desc : descriptors) { if ((desc.getPluginClassName() == null) || !desc.getPluginClassName().equals("net.sf.jabref.plugin.core.JabRefPlugin")) { urls.put(desc.getId(), desc); } } for (String file1 : files) { File file = new File(PluginCore.userPluginDir, file1); String[] nav = getNameAndVersion(file); if (nav != null) { VersionNumber vn = nav[1] != null ? new VersionNumber(nav[1]) : null; NameAndVersion nameAndVersion = new NameAndVersion(nav[0], vn, true, file); for (Iterator<String> it = urls.keySet().iterator(); it.hasNext(); ) { String loc = it.next(); if (loc.contains(nav[0])) { PluginDescriptor desc = urls.get(loc); // System.out.println("Accounted for: "+desc.getId()+" "+desc.getVersion().toString()); if (!PluginCore.getManager().isPluginEnabled(urls.get(loc))) nameAndVersion.setStatus(BAD); else nameAndVersion.setStatus(LOADED); it.remove(); } } plugins.add(nameAndVersion); } } for (String url : urls.keySet()) { PluginDescriptor desc = urls.get(url); File location = new File(desc.getLocation().getFile()); if (location.getPath().contains(PluginCore.userPluginDir.getPath())) continue; // This must be a loaded user dir plugin that's been deleted. // System.out.println("File: "+desc.getLocation().getFile()); NameAndVersion nameAndVersion = new NameAndVersion( desc.getId(), new VersionNumber(desc.getVersion().toString()), false, location); if (!PluginCore.getManager().isPluginEnabled(urls.get(url))) nameAndVersion.setStatus(BAD); else nameAndVersion.setStatus(LOADED); plugins.add(nameAndVersion); } return plugins; }
/** * Delete the given files. Refuses to delete files outside the user plugin directory. This method * throws no errors is the files don't exist or deletion failed. * * @param filenames An array of names of the files to be deleted. */ public static void deletePluginsOnStartup(String[] filenames) { for (String s : filenames) { File f = new File(s); if (f.getParentFile().equals(PluginCore.userPluginDir)) { // if (s.startsWith(PluginCore.userPluginDir.getPath())) { boolean success = f.delete(); } else System.out.println("File outside of user plugin dir: " + s); } }
/** * Look inside a jar file, find the plugin.xml file, and use it to determine the name and version * of the plugin. * * @param f The file to investigate. * @return A string array containing the plugin name in the first element and the version number * in the second, or null if the filename couldn't be interpreted. */ public static String[] getNameAndVersion(File f) { try { File temp = unpackPluginXML(f); if (temp == null) return null; // Couldn't find the plugin.xml file ManifestInfo mi = PluginCore.getManager().getRegistry().readManifestInfo(temp.toURI().toURL()); temp.delete(); return new String[] {mi.getId(), mi.getVersion().toString()}; } catch (MalformedURLException e) { e.printStackTrace(); return null; } catch (ManifestProcessingException e) { return null; // Couldn't make sense of the plugin.xml } }
public static int copyPlugin(JFrame frame, File source, String destFileName) { if (destFileName == null) destFileName = source.getName(); if (!PluginCore.userPluginDir.exists()) { boolean created = PluginCore.userPluginDir.mkdirs(); if (!created) { return UNABLE_TO_CREATE_DIR; } } File destFile = new File(PluginCore.userPluginDir, destFileName); BufferedInputStream in = null; BufferedOutputStream out = null; try { in = new BufferedInputStream(new FileInputStream(source)); out = new BufferedOutputStream(new FileOutputStream(destFile)); byte[] buf = new byte[1024]; int count; while ((count = in.read(buf, 0, buf.length)) > 0) { out.write(buf, 0, count); } } catch (IOException ex) { ex.printStackTrace(); return UNABLE_TO_COPY_FILE; } finally { if (in != null) { try { in.close(); } catch (IOException ignore) { // UNABLE_TO_COPY_FILE; } } if (out != null) { try { out.close(); } catch (IOException ignore) { // UNABLE_TO_COPY_FILE; } } } return SUCCESS; }
public static void installPlugin(JabRefFrame frame, File file, String targetFileName) { String fileName = targetFileName != null ? targetFileName : file.getName(); if (!PluginCore.userPluginDir.exists()) { boolean created = PluginCore.userPluginDir.mkdirs(); if (!created) { JOptionPane.showMessageDialog( frame, Globals.lang("Unable to create plugin directory") + " (" + PluginCore.userPluginDir.getPath() + ").", Globals.lang("Plugin installer"), JOptionPane.ERROR_MESSAGE); return; } } int status = checkInstalledVersion(file); int result; switch (status) { case NO_VERSIONS_INSTALLED: result = copyPlugin(frame, file, fileName); if (result == SUCCESS) JOptionPane.showMessageDialog( frame, Globals.lang( "Plugin installed successfully. You must restart JabRef to load the new plugin."), Globals.lang("Plugin installer"), JOptionPane.INFORMATION_MESSAGE); else { String reason; if (result == UNABLE_TO_COPY_FILE) reason = Globals.lang("Unable to copy file"); else reason = Globals.lang("Unable to create user plugin directory") + " (" + PluginCore.userPluginDir.getPath() + ")."; JOptionPane.showMessageDialog( frame, Globals.lang("Plugin installation failed.") + " " + reason, Globals.lang("Plugin installer"), JOptionPane.ERROR_MESSAGE); } break; case SAME_VERSION_INSTALLED: JOptionPane.showMessageDialog( frame, Globals.lang("The same version of this plugin is already installed."), Globals.lang("Plugin installer"), JOptionPane.INFORMATION_MESSAGE); break; case NEWER_VERSION_INSTALLED: JOptionPane.showMessageDialog( frame, Globals.lang("A newer version of this plugin is already installed."), Globals.lang("Plugin installer"), JOptionPane.INFORMATION_MESSAGE); break; case OLDER_VERSION_INSTALLED: result = copyPlugin(frame, file, fileName); if (result == SUCCESS) { int answer = JOptionPane.showConfirmDialog( frame, Globals.lang( "One or more older versions of this plugin is installed. Delete old versions?"), Globals.lang("Plugin installer"), JOptionPane.YES_NO_OPTION); if (answer == JOptionPane.YES_OPTION) { boolean success = deleteOlderVersions(file); if (success) { JOptionPane.showMessageDialog( frame, Globals.lang("Old versions deleted successfully."), Globals.lang("Plugin installer"), JOptionPane.INFORMATION_MESSAGE); } else { JOptionPane.showMessageDialog( frame, Globals.lang("Old plugin versions will be deleted next time JabRef starts up."), Globals.lang("Plugin installer"), JOptionPane.INFORMATION_MESSAGE); } } } else { String reason; if (result == UNABLE_TO_COPY_FILE) reason = Globals.lang("Unable to copy file"); else reason = Globals.lang("Unable to create user plugin directory") + " (" + PluginCore.userPluginDir.getPath() + ")."; JOptionPane.showMessageDialog( frame, Globals.lang("Plugin installation failed.") + " " + reason, Globals.lang("Plugin installer"), JOptionPane.ERROR_MESSAGE); } break; // case UNKNOWN_VERSION: // JOptionPane.showMessageDialog(frame, Globals.lang("Could not determine version of ")); // break; case UNKNOWN_VERSION: JLabel lab = new JLabel( "<html>" + Globals.lang( "Unable to determine plugin name and " + "version. This may not be a valid JabRef plugin.") + "<br>" + Globals.lang("Install anyway?") + "</html>"); int answer = JOptionPane.showConfirmDialog( frame, lab, Globals.lang("Plugin installer"), JOptionPane.YES_NO_OPTION); if (answer == JOptionPane.YES_OPTION) { result = copyPlugin(frame, file, fileName); if (result == SUCCESS) JOptionPane.showMessageDialog( frame, Globals.lang( "Plugin installed successfully. You must restart JabRef to load the new plugin."), Globals.lang("Plugin installer"), JOptionPane.INFORMATION_MESSAGE); else { String reason; if (result == UNABLE_TO_COPY_FILE) reason = Globals.lang("Unable to copy file"); else reason = Globals.lang("Unable to create user plugin directory") + " (" + PluginCore.userPluginDir.getPath() + ")."; JOptionPane.showMessageDialog( frame, Globals.lang("Plugin installation failed.") + " " + reason, Globals.lang("Plugin installer"), JOptionPane.ERROR_MESSAGE); } } break; } }