⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pluginmanager.java

📁 基于Jabber协议的即时消息服务器
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
     * @param plugin the plugin.
     * @param xpath  the xpath expression.
     * @return the value of the element selected by the xpath expression.
     */
    private String getElementValue(Plugin plugin, String xpath) {
        File pluginDir = pluginDirs.get(plugin);
        if (pluginDir == null) {
            return null;
        }
        try {
            File pluginConfig = new File(pluginDir, "plugin.xml");
            if (pluginConfig.exists()) {
                SAXReader saxReader = new SAXReader();
                saxReader.setEncoding("UTF-8");
                Document pluginXML = saxReader.read(pluginConfig);
                Element element = (Element)pluginXML.selectSingleNode(xpath);
                if (element != null) {
                    return element.getTextTrim();
                }
            }
        }
        catch (Exception e) {
            Log.error(e);
        }
        return null;
    }

    /**
     * An enumberation for plugin license agreement types.
     */
    public enum License {

        /**
         * The plugin is distributed using a commercial license.
         */
        commercial,

        /**
         * The plugin is distributed using the GNU Public License (GPL).
         */
        gpl,

        /**
         * The plugin is distributed using the Apache license.
         */
        apache,

        /**
         * The plugin is for internal use at an organization only and is not re-distributed.
         */
        internal,

        /**
         * The plugin is distributed under another license agreement not covered by
         * one of the other choices. The license agreement should be detailed in the
         * plugin Readme.
         */
        other
    }

    /**
     * A service that monitors the plugin directory for plugins. It periodically
     * checks for new plugin JAR files and extracts them if they haven't already
     * been extracted. Then, any new plugin directories are loaded.
     */
    private class PluginMonitor implements Runnable {

        /**
         * Tracks if the monitor is currently running.
         */
        private boolean running = false;

        public void run() {
            // If the task is already running, return.
            synchronized (this) {
                if (running) {
                    return;
                }
                running = true;
            }
            try {
                running = true;
                // Look for extra plugin directories specified as a system property.
                String pluginDirs = System.getProperty("pluginDirs");
                if (pluginDirs != null) {
                    StringTokenizer st = new StringTokenizer(pluginDirs, ", ");
                    while (st.hasMoreTokens()) {
                        String dir = st.nextToken();
                        if (!devPlugins.contains(dir)) {
                            loadPlugin(new File(dir));
                            devPlugins.add(dir);
                        }
                    }
                }

                File[] jars = pluginDirectory.listFiles(new FileFilter() {
                    public boolean accept(File pathname) {
                        String fileName = pathname.getName().toLowerCase();
                        return (fileName.endsWith(".jar") || fileName.endsWith(".war"));
                    }
                });

                if (jars == null) {
                    return;
                }

                for (File jarFile : jars) {
                    String pluginName = jarFile.getName().substring(0,
                        jarFile.getName().length() - 4).toLowerCase();
                    // See if the JAR has already been exploded.
                    File dir = new File(pluginDirectory, pluginName);
                    // If the JAR hasn't been exploded, do so.
                    if (!dir.exists()) {
                        unzipPlugin(pluginName, jarFile, dir);
                    }
                    // See if the JAR is newer than the directory. If so, the plugin
                    // needs to be unloaded and then reloaded.
                    else if (jarFile.lastModified() > dir.lastModified()) {
                        unloadPlugin(pluginName);
                        // Give the plugin 2 seconds to unload.
                        Thread.sleep(2000);
                        // Ask the system to clean up references.
                        System.gc();
                        int count = 0;
                        while (!deleteDir(dir) && count < 5) {
                            Log.warn("Error unloading plugin " + pluginName + ". " +
                                "Will attempt again momentarily.");
                            Thread.sleep(8000);
                            count++;
                            // Ask the system to clean up references.
                            System.gc();
                        }
                        // If the delete operation was a success, unzip the plugin.
                        if (count != 5) {
                            unzipPlugin(pluginName, jarFile, dir);
                        }
                    }
                }

                File[] dirs = pluginDirectory.listFiles(new FileFilter() {
                    public boolean accept(File pathname) {
                        return pathname.isDirectory();
                    }
                });

                // Sort the list of directories so that the "admin" plugin is always
                // first in the list.
                Arrays.sort(dirs, new Comparator<File>() {
                    public int compare(File file1, File file2) {
                        if (file1.getName().equals("admin")) {
                            return -1;
                        }
                        else if (file2.getName().equals("admin")) {
                            return 1;
                        }
                        else {
                            return file1.compareTo(file2);
                        }
                    }
                });

                // Turn the list of JAR/WAR files into a set so that we can do lookups.
                Set<String> jarSet = new HashSet<String>();
                for (File file : jars) {
                    jarSet.add(file.getName().toLowerCase());
                }

                // See if any currently running plugins need to be unloaded
                // due to the JAR file being deleted (ignore admin plugin).
                // Build a list of plugins to delete first so that the plugins
                // keyset isn't modified as we're iterating through it.
                List<String> toDelete = new ArrayList<String>();
                for (File pluginDir : dirs) {
                    String pluginName = pluginDir.getName();
                    if (pluginName.equals("admin")) {
                        continue;
                    }
                    if (!jarSet.contains(pluginName + ".jar")) {
                        if (!jarSet.contains(pluginName + ".war")) {
                            toDelete.add(pluginName);
                        }
                    }
                }
                for (String pluginName : toDelete) {
                    unloadPlugin(pluginName);
                    System.gc();
                    int count = 0;
                    File dir = new File(pluginDirectory, pluginName);
                    while (!deleteDir(dir) && count < 5) {
                        Log.error("Error unloading plugin " + pluginName + ". " +
                            "Will attempt again momentarily.");
                        Thread.sleep(10000);
                        count++;
                    }
                }

                // Load all plugins that need to be loaded.
                for (File dirFile : dirs) {
                    // If the plugin hasn't already been started, start it.
                    if (dirFile.exists() && !plugins.containsKey(dirFile.getName())) {
                        loadPlugin(dirFile);
                    }
                }
            }
            catch (Throwable e) {
                Log.error(e);
            }
            // Finished running task.
            synchronized (this) {
                running = false;
            }
        }

        /**
         * Unzips a plugin from a JAR file into a directory. If the JAR file
         * isn't a plugin, this method will do nothing.
         *
         * @param pluginName the name of the plugin.
         * @param file the JAR file
         * @param dir the directory to extract the plugin to.
         */
        private void unzipPlugin(String pluginName, File file, File dir) {
            try {
                ZipFile zipFile = new JarFile(file);
                // Ensure that this JAR is a plugin.
                if (zipFile.getEntry("plugin.xml") == null) {
                    return;
                }
                dir.mkdir();
                // Set the date of the JAR file to the newly created folder
                dir.setLastModified(file.lastModified());
                Log.debug("Extracting plugin: " + pluginName);
                for (Enumeration e = zipFile.entries(); e.hasMoreElements();) {
                    JarEntry entry = (JarEntry)e.nextElement();
                    File entryFile = new File(dir, entry.getName());
                    // Ignore any manifest.mf entries.
                    if (entry.getName().toLowerCase().endsWith("manifest.mf")) {
                        continue;
                    }
                    if (!entry.isDirectory()) {
                        entryFile.getParentFile().mkdirs();
                        FileOutputStream out = new FileOutputStream(entryFile);
                        InputStream zin = zipFile.getInputStream(entry);
                        byte[] b = new byte[512];
                        int len;
                        while ((len = zin.read(b)) != -1) {
                            out.write(b, 0, len);
                        }
                        out.flush();
                        out.close();
                        zin.close();
                    }
                }
                zipFile.close();

                // The lib directory of the plugin may contain Pack200 versions of the JAR
                // file. If so, unpack them.
                unpackArchives(new File(dir, "lib"));
            }
            catch (Exception e) {
                Log.error(e);
            }
        }

        /**
         * Converts any pack files in a directory into standard JAR files. Each
         * pack file will be deleted after being converted to a JAR. If no
         * pack files are found, this method does nothing.
         *
         * @param libDir the directory containing pack files.
         */
        private void unpackArchives(File libDir) {
            // Get a list of all packed files in the lib directory.
            File [] packedFiles = libDir.listFiles(new FilenameFilter() {
                public boolean accept(File dir, String name) {
                    return name.endsWith(".pack");
                }
            });

            if (packedFiles == null) {
                // Do nothing since no .pack files were found
                return;
            }

            // Unpack each.
            for (File packedFile : packedFiles) {
                try {
                    String jarName = packedFile.getName().substring(0,
                            packedFile.getName().length() - ".pack".length());
                    // Delete JAR file with same name if it exists (could be due to upgrade
                    // from old Wildfire release).
                    File jarFile = new File(libDir, jarName);
                    if (jarFile.exists()) {
                        jarFile.delete();
                    }

                    InputStream in = new BufferedInputStream(new FileInputStream(packedFile));
                    JarOutputStream out = new JarOutputStream(new BufferedOutputStream(
                            new FileOutputStream(new File(libDir, jarName))));
                    Pack200.Unpacker unpacker = Pack200.newUnpacker();
                    // Call the unpacker
                    unpacker.unpack(in, out);

                    in.close();
                    out.close();
                    packedFile.delete();
                }
                catch (Exception e) {
                    Log.error(e);
                }
            }
        }

        /**
         * Deletes a directory.
         *
         * @param dir the directory to delete.
         * @return true if the directory was deleted.
         */
        private boolean deleteDir(File dir) {
            if (dir.isDirectory()) {
                String[] childDirs = dir.list();
                // Always try to delete JAR files first since that's what will
                // be under contention. We do this by always sorting the lib directory
                // first.
                List<String> children = new ArrayList<String>(Arrays.asList(childDirs));
                Collections.sort(children, new Comparator<String>() {
                    public int compare(String o1, String o2) {
                        if (o1.equals("lib")) {
                            return -1;
                        }
                        if (o2.equals("lib")) {
                            return 1;
                        }
                        else {
                            return o1.compareTo(o2);
                        }
                    }
                });
                for (String file : children) {
                    boolean success = deleteDir(new File(dir, file));
                    if (!success) {
                        Log.debug("Plugin removal: could not delete: " + new File(dir, file));
                        return false;
                    }
                }
            }
            return dir.delete();
        }
    }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -