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

📄 pluginarchiver.java

📁 java插件系统源码
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
                    if (!result.contains(uid)) {
                        entry = zipStrm.getNextEntry();
                        continue;
                    }
                    count++;
                } else {
                    int p = name.indexOf('/');
                    if ((p == -1) || (p == 0)
                            || !result.contains(name.substring(0, p))) {
                        entry = zipStrm.getNextEntry();
                        continue;
                    }
                }
                unpackEntry(zipStrm, entry, destFolder);
                entry = zipStrm.getNextEntry();
            }
        } finally {
            zipStrm.close();
        }
        if (result.size() != count) {
            throw new IOException("invalid plug-ins number (" + count //$NON-NLS-1$
                    + ") found in the archive, expected number according to " //$NON-NLS-1$
                    + "the archive descriptor is " + result.size()); //$NON-NLS-1$
        }
        return result;
    }
    
    /**
     * Extracts all plug-ins from the given archive file.
     * <br>
     * <b>Note:</b>
     * <br>
     * {@link ObjectFactory#createRegistry() Standard plug-in registry}
     * implementation will be used internally to read plug-in manifests.
     * @param archiveFile plug-in archive file
     * @param destFolder target folder
     * @return collection of UID's of all un-packed plug-ins
     * @throws IOException if an I/O error has occurred
     * @throws ClassNotFoundException if descriptor can't be read
     * @throws ManifestProcessingException if manifest can't be registered
     *         (optional behavior)
     * 
     * @see ObjectFactory#createRegistry()
     */
    public static Collection unpack(final URL archiveFile,
            final File destFolder) throws ManifestProcessingException,
            IOException, ClassNotFoundException {
        return unpack(archiveFile, ObjectFactory.newInstance().createRegistry(),
                destFolder);
    }
    
    /**
     * Extracts plug-ins from the given archive file according to given filter.
     * <br>
     * <b>Note:</b>
     * <br>
     * {@link ObjectFactory#createRegistry() Standard plug-in registry}
     * implementation will be used internally to read plug-in manifests.
     * @param archiveFile plug-in archive file
     * @param destFolder target folder
     * @param filter filter to be used when un-packing plug-ins
     * @return collection of UID's of all un-packed plug-ins
     * @throws IOException if an I/O error has occurred
     * @throws ClassNotFoundException if descriptor can't be read
     * @throws ManifestProcessingException if manifest can't be registered
     *         (optional behavior)
     */
    public static Collection unpack(final URL archiveFile,
            final File destFolder, final Filter filter)
            throws ManifestProcessingException, IOException,
            ClassNotFoundException {
        return unpack(archiveFile, ObjectFactory.newInstance().createRegistry(),
                destFolder, filter);
    }
    
    private static void unpackEntry(final ZipInputStream zipStrm,
            final ZipEntry entry, final File destFolder) throws IOException {
        String name = entry.getName();
        if (name.endsWith("/")) { //$NON-NLS-1$
            File folder = new File(destFolder.getCanonicalPath() + "/" + name); //$NON-NLS-1$
            if (!folder.exists() && !folder.mkdirs()) {
                throw new IOException("can't create folder " + folder); //$NON-NLS-1$
            }
            folder.setLastModified(entry.getTime());
            return;
        }
        File file = new File(destFolder.getCanonicalPath() + "/" + name); //$NON-NLS-1$
        File folder = file.getParentFile();
        if (!folder.exists() && !folder.mkdirs()) {
            throw new IOException("can't create folder " + folder); //$NON-NLS-1$
        }
        OutputStream strm = new BufferedOutputStream(
                new FileOutputStream(file, false));
        try {
            IoUtil.copyStream(zipStrm, strm, 1024);
        } finally {
            strm.close();
        }
        file.setLastModified(entry.getTime());
    }

    /**
     * Reads meta-information from plug-ins archive file and registers found
     * plug-in manifest data with given registry for future analysis.
     * @param archiveFile plug-in archive file
     * @param registry plug-in registry where to register discovered manifests
     *                 for archived plug-ins
     * @return collection of UID's of all registered plug-ins
     * @throws IOException if an I/O error has occurred
     * @throws ClassNotFoundException if descriptor can't be read
     * @throws ManifestProcessingException if manifest can't be registered
     *         (optional behavior)
     * 
     * @see #readDescriptor(URL, PluginRegistry, PluginArchiver.Filter)
     */
    public static Collection readDescriptor(final URL archiveFile,
            final PluginRegistry registry)
            throws IOException, ClassNotFoundException,
            ManifestProcessingException {
        return readDescriptor(archiveFile, registry, new Filter() {
            public boolean accept(final String id, final Version version,
                    final boolean isFragment) {
                return true;
            }
        });
    }

    /**
     * Reads meta-information from plug-ins archive file and registers found
     * plug-in manifest data with given registry for future analysis.
     * <br>
     * <b>Note:</b>
     * <br>
     * In the current implementation all plug-in manifests are extracted to
     * temporary local storage and deleted immediately after their registration
     * with plug-in registry. So manifest URL's are actually point to "fake"
     * locations and main purpose of this method is to allow you to analyze
     * plug-ins archive without needing to download and unpack it.
     * @param archiveFile plug-in archive file
     * @param registry plug-in registry where to register discovered manifests
     *                 for archived plug-ins
     * @param filter filter to be used when un-packing plug-ins
     * @return collection of UID's of all registered plug-ins
     * @throws IOException if an I/O error has occurred
     * @throws ClassNotFoundException if descriptor can't be read
     * @throws ManifestProcessingException if manifest can't be registered
     *         (optional behavior)
     */
    public static Collection readDescriptor(final URL archiveFile,
            final PluginRegistry registry, final Filter filter)
            throws IOException, ClassNotFoundException,
            ManifestProcessingException {
        ZipInputStream zipStrm = new ZipInputStream(new BufferedInputStream(
                archiveFile.openStream()));
        try {
            ZipEntry entry = zipStrm.getNextEntry();
            //NB: we are expecting that descriptor is in the first ZIP entry
            if (entry == null) {
                throw new IOException(
                        "invalid plug-ins archive, no entries found"); //$NON-NLS-1$
            }
            if (!DESCRIPTOR_ENTRY_NAME.equals(entry.getName())) {
                throw new IOException("invalid plug-ins archive " + archiveFile //$NON-NLS-1$
                        + ", entry " + DESCRIPTOR_ENTRY_NAME //$NON-NLS-1$
                        + " not found as first ZIP entry in the archive file"); //$NON-NLS-1$
            }
            ObjectInputStream strm = new ObjectInputStream(zipStrm);
            return readDescriptor(strm, registry, Util.getTempFolder(), filter);
        } finally {
            zipStrm.close();
        }
    }
    
    private static Set writeDescripor(final PluginRegistry registry,
            final Filter filter, final ObjectOutputStream strm)
            throws IOException {
        Map result = new HashMap();
        for (Iterator it = registry.getPluginDescriptors().iterator();
                it.hasNext();) {
            PluginDescriptor descr = (PluginDescriptor) it.next();
            if (!filter.accept(descr.getId(), descr.getVersion(), false)) {
                continue;
            }
            result.put(descr.getUniqueId(),
                    new ArchiveDescriptorEntry(descr.getId(),
                            descr.getVersion(), false,
                            Util.readUrlContent(descr.getLocation())));
        }
        for (Iterator it = registry.getPluginFragments().iterator();
                it.hasNext();) {
            PluginFragment fragment = (PluginFragment) it.next();
            if (!filter.accept(fragment.getId(), fragment.getVersion(), true)) {
                continue;
            }
            result.put(fragment.getUniqueId(),
                    new ArchiveDescriptorEntry(fragment.getId(),
                            fragment.getVersion(), true,
                            Util.readUrlContent(fragment.getLocation())));
        }
        strm.writeObject(result.values().toArray(
                new ArchiveDescriptorEntry[result.size()]));
        return result.keySet();
    }
    
    private static Set readDescriptor(final ObjectInputStream strm,
            final PluginRegistry registry, final File tempFolder,
            final Filter filter) throws IOException, ClassNotFoundException,
            ManifestProcessingException {
        ArchiveDescriptorEntry[] data =
            (ArchiveDescriptorEntry[]) strm.readObject();
        // For simplicity we'll store manifests to a temporary files rather than
        // create special URL's and provide special URL handler for them.
        // More powerful approach will be possibly implemented in the future.
        Set urls = new HashSet();
        Set files = new HashSet();
        for (int i = 0; i < data.length; i++) {
            if (!filter.accept(data[i].getId(), data[i].getVersion(),
                    data[i].isFragment())) {
                continue;
            }
            File file = File.createTempFile("manifest.", null, tempFolder); //$NON-NLS-1$
            file.deleteOnExit();
            OutputStream fileStrm = new BufferedOutputStream(
                    new FileOutputStream(file, false));
            try {
                fileStrm.write(data[i].getData());
            } finally {
                fileStrm.close();
            }
            files.add(file);
            urls.add(IoUtil.file2url(file));
        }
        Set result = new HashSet();
        try {
            for (Iterator it = registry.register((URL[]) urls.toArray(
                    new URL[urls.size()])).values().iterator(); it.hasNext();) {
                Object obj = it.next();
                if (obj instanceof PluginDescriptor) {
                    result.add(((PluginDescriptor) obj).getUniqueId());
                } else if (obj instanceof PluginFragment) {
                    result.add(((PluginFragment) obj).getUniqueId());
                } else {
                    //NB: ignore all other elements
                }
            }
        } finally {
            for (Iterator it = files.iterator(); it.hasNext();) {
                ((File) it.next()).delete();
            }
        }
        return result;
    }
    
    private PluginArchiver() {
        // no-op
    }
    
    /**
     * Callback interface to filter plug-ins being processed.
     * @version $Id: PluginArchiver.java,v 1.1 2006/08/26 15:14:09 ddimon Exp $
     */
    public static interface Filter {
        /**
         * @param id plug-in or plug-in fragment identifier
         * @param version plug-in or plug-in fragment version
         * @param isFragment <code>true</code> if given identity data
         *                   corresponds to plug-in fragment
         * @return <code>true</code> if plug-in or plug-in fragment with given
         *         identity should be taken into account
         */
        boolean accept(String id, Version version, boolean isFragment);
    }
    
    private static class ArchiveDescriptorEntry implements Serializable {
        private static final long serialVersionUID = 8749937247555974932L;
        
        private final String id;
        private final Version version;
        private final boolean isFragment;
        private final byte[] data;
        
        protected ArchiveDescriptorEntry(final String anId,
                final Version aVersion, final boolean fragment,
                final byte[] aData) {
            id = anId;
            version = aVersion;
            isFragment = fragment;
            data = aData;
        }

        protected String getId() {
            return id;
        }

        protected Version getVersion() {
            return version;
        }
        
        protected boolean isFragment() {
            return isFragment;
        }

        protected byte[] getData() {
            return data;
        }
    }
}

⌨️ 快捷键说明

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