一、前言
关于项目依赖网络远程jar,这边分享apache的commons-vfs包中的org.apache.commons.vfs.provider.jar.JarURLConnectionImpl的源码继承实现java.net.JarURLConnection,并通过示例代码JarURLConnectionTest说明具体使用例子。
二、示例代码
import java.io.IOException; @b@import java.lang.reflect.Method; @b@import java.net.JarURLConnection; @b@import java.net.MalformedURLException; @b@import java.net.URL; @b@import java.net.URLClassLoader; @b@import java.util.Map.Entry; @b@import java.util.jar.Attributes; @b@import java.util.jar.JarFile; @b@import java.util.jar.Manifest; @b@ @b@public class JarURLConnectionTest{ @b@ @b@ private final static String JAR_URL = "jar:http://www.xwood.net/test/ftpserver-core-1.0.6.jar!/"; @b@ private final static String JAR_FILE_PATH = "http://www.xwood.net/test/ftpserver-core-1.0.6.jar"; @b@ @b@ private static URLClassLoader urlClassLoader; @b@ @b@ @SuppressWarnings("rawtypes")@b@ public static void main(String[] args) throws Exception { @b@ try { @b@ URL FileSysUrl = new URL(JAR_URL); @b@ @b@ // Create a jar URL connection object @b@ JarURLConnection jarURLConnection = (JarURLConnection)FileSysUrl.openConnection(); @b@ // Get the jar file @b@ JarFile jarFile = jarURLConnection.getJarFile(); @b@ // Get jar file name @b@ System.out.println("Jar Name: " + jarFile.getName()); @b@ // When no entry is specified on the URL, the entry name is null @b@ System.out.println("\nJar Entry: " + jarURLConnection.getJarEntry()); @b@ // Get the manifest of the jar @b@ Manifest manifest = jarFile.getManifest(); @b@ // Print the manifest attributes @b@ System.out.println("\nManifest file attributes: "); @b@ for (Entry entry : manifest.getMainAttributes().entrySet()) { @b@ System.out.println(entry.getKey() +": "+ entry.getValue()); @b@ } @b@ System.out.println("\nExternal JAR Execution output: "); @b@ // Get the jar URL which contains target class @b@ URL[] classLoaderUrls = new URL[]{new URL(JAR_FILE_PATH)}; @b@ // Create a classloader and load the entry point class @b@ urlClassLoader = new URLClassLoader(classLoaderUrls); @b@ // Get the main class name (the entry point class) @b@ String mainClassName = manifest.getMainAttributes().getValue(Attributes.Name.MAIN_CLASS); @b@ // Load the target class @b@ Class beanClass = urlClassLoader.loadClass("org.apache.ftpserver.main.Daemon"); @b@ // Get the main method from the loaded class and invoke it @b@ Method method = beanClass.getMethod("main", String[].class); @b@ // init params accordingly @b@ String[] params = null; @b@ // static method doesn't have an instance @b@ method.invoke(null, (Object) params); @b@ } catch (MalformedURLException e) { @b@ e.printStackTrace(); @b@ } catch (IOException e) { @b@ e.printStackTrace(); @b@ } @b@ @b@ } @b@ @b@}
控制台结果
Jar Name: C:\Users\nijun\AppData\Local\Temp\jar_cache5379592952184444941.tmp@b@@b@Jar Entry: null@b@@b@Manifest file attributes: @b@Export-Package: org.apache.ftpserver;uses:="org.apache.ftpserver.ssl,org.slf4j,org.apache.ftpserver.message,org.apache.ftpserver.ftpletcontainer,org.apache.ftpserver.command,org.apache.ftpserver.listener";version="1.0.6",org.apache.ftpserver.command;uses:="org.apache.mina.core.future";version="1.0.6",org.apache.ftpserver.config.spring;uses:="org.springframework.beans.factory.support,org.springframework.util,org.springframework.beans.factory.xml,org.springframework.beans.factory.config,org.w3c.dom,org.apache.ftpserver.command,org.apache.ftpserver.filesystem.nativefs,org.apache.ftpserver.ssl,org.slf4j,org.apache.ftpserver.ipfilter,org.apache.ftpserver,org.apache.ftpserver.listener,org.apache.ftpserver.message,org.springframework.util.xml,org.apache.ftpserver.usermanager";version="1.0.6",org.apache.ftpserver.filesystem.nativefs;uses:="org.slf4j";version="1.0.6",org.apache.ftpserver.ftpletcontainer;version="1.0.6",org.apache.ftpserver.ipfilter;uses:="org.apache.mina.filter.firewall,org.slf4j,org.apache.mina.core.future,org.apache.mina.core.session,org.apache.mina.core.filterchain";version="1.0.6",org.apache.ftpserver.listener;uses:="org.apache.ftpserver.ssl,org.apache.mina.filter.firewall,org.apache.ftpserver,org.apache.ftpserver.ipfilter";version="1.0.6",org.apache.ftpserver.main;uses:="org.apache.ftpserver,org.springframework.context.support,org.slf4j";version="1.0.6",org.apache.ftpserver.message;version="1.0.6",org.apache.ftpserver.ssl;uses:="javax.net.ssl,org.apache.ftpserver,org.slf4j";version="1.0.6",org.apache.ftpserver.usermanager;uses:="javax.sql,org.apache.ftpserver";version="1.0.6"@b@Implementation-Title: Apache FtpServer Core@b@Implementation-Version: 1.0.6@b@Specification-Vendor: The Apache Software Foundation@b@Built-By: niklas@b@Manifest-Version: 1.0@b@Tool: Bnd-1.15.0@b@Bundle-Name: Apache FtpServer Core@b@Created-By: Apache Maven Bundle Plugin@b@Bundle-Vendor: The Apache Software Foundation@b@Implementation-Vendor: The Apache Software Foundation@b@Implementation-Vendor-Id: org.apache.ftpserver@b@Build-Jdk: 1.6.0_24@b@Bundle-Version: 1.0.6@b@Bnd-LastModified: 1309182429270@b@Specification-Title: Apache FtpServer Core@b@Bundle-ManifestVersion: 2@b@Bundle-Description: The Apache Software Foundation provides support for the Apache community of open-source software projects. The Apache projects are characterized by a collaborative, consensus based development process, an open and pragmatic software license, and a desire to create high quality software that leads the way in its field. We consider ourselves not simply a group of projects sharing a server, but rather a community of developers and users.@b@Bundle-License: http://www.apache.org/licenses/LICENSE-2.0@b@Specification-Version: 1.0.6@b@Import-Package: javax.net.ssl,javax.sql,org.apache.ftpserver.ipfilter;version="[1.0,2)",org.apache.mina.core.buffer;version="[2.0,3)",org.apache.mina.core.filterchain;version="[2.0,3)",org.apache.mina.core.future;version="[2.0,3)",org.apache.mina.core.service;version="[2.0,3)",org.apache.mina.core.session;version="[2.0,3)",org.apache.mina.core.write;version="[2.0,3)",org.apache.mina.filter.codec;version="[2.0,3)",org.apache.mina.filter.codec.textline;version="[2.0,3)",org.apache.mina.filter.executor;version="[2.0,3)",org.apache.mina.filter.firewall;version="[2.0,3)",org.apache.mina.filter.logging;version="[2.0,3)",org.apache.mina.filter.ssl;version="[2.0,3)",org.apache.mina.transport.socket;version="[2.0,3)",org.apache.mina.transport.socket.nio;version="[2.0,3)",org.slf4j;version="[1.5,2)",org.springframework.beans.factory.config;resolution:=optional;version="2.5",org.springframework.beans.factory.support;resolution:=optional;version="2.5",org.springframework.beans.factory.xml;resolution:=optional;version="2.5",org.springframework.context.support;resolution:=optional;version="2.5",org.springframework.util;resolution:=optional;version="2.5",org.springframework.util.xml;resolution:=optional;version="2.5",org.w3c.dom@b@Bundle-SymbolicName: ftpserver-core@b@Bundle-DocURL: http://www.apache.org/@b@@b@External JAR Execution output:
三、源码说明
package org.apache.commons.vfs.provider.jar;@b@@b@import java.io.IOException;@b@import java.io.InputStream;@b@import java.io.OutputStream;@b@import java.net.JarURLConnection;@b@import java.net.MalformedURLException;@b@import java.net.URL;@b@import java.security.cert.Certificate;@b@import java.util.jar.Attributes;@b@import java.util.jar.JarEntry;@b@import java.util.jar.JarFile;@b@import java.util.jar.Manifest;@b@import org.apache.commons.vfs.FileContent;@b@import org.apache.commons.vfs.FileName;@b@import org.apache.commons.vfs.FileSystemException;@b@@b@public class JarURLConnectionImpl extends JarURLConnection@b@{@b@ private static final String HACK_URL = "jar:http://somehost/somejar.jar!/";@b@ private FileContent content;@b@ private URL parentURL;@b@ private JarFileObject file;@b@ private String entryName;@b@@b@ public JarURLConnectionImpl(JarFileObject file, FileContent content)@b@ throws MalformedURLException, FileSystemException@b@ {@b@ super(new URL("jar:http://somehost/somejar.jar!/"));@b@@b@ this.url = file.getURL();@b@ this.content = content;@b@ this.parentURL = file.getURL();@b@ this.entryName = file.getName().getPath();@b@ this.file = file;@b@ }@b@@b@ public URL getJarFileURL()@b@ {@b@ return this.parentURL;@b@ }@b@@b@ public String getEntryName()@b@ {@b@ return this.entryName;@b@ }@b@@b@ public JarFile getJarFile()@b@ throws IOException@b@ {@b@ throw new FileSystemException("vfs.provider.jar/jar-file-no-access.error");@b@ }@b@@b@ public Manifest getManifest()@b@ throws IOException@b@ {@b@ return this.file.getManifest();@b@ }@b@@b@ public JarEntry getJarEntry()@b@ throws IOException@b@ {@b@ throw new FileSystemException("vfs.provider.jar/jar-entry-no-access.error");@b@ }@b@@b@ public Attributes getAttributes()@b@ throws IOException@b@ {@b@ return this.file.getAttributes();@b@ }@b@@b@ public Certificate[] getCertificates()@b@ {@b@ return this.file.doGetCertificates();@b@ }@b@@b@ public void connect()@b@ {@b@ this.connected = true;@b@ }@b@@b@ public InputStream getInputStream()@b@ throws IOException@b@ {@b@ return this.content.getInputStream();@b@ }@b@@b@ public OutputStream getOutputStream()@b@ throws IOException@b@ {@b@ return this.content.getOutputStream();@b@ }@b@@b@ public int getContentLength()@b@ {@b@ try@b@ {@b@ return (int)this.content.getSize();@b@ }@b@ catch (FileSystemException fse)@b@ {@b@ }@b@@b@ return -1;@b@ }@b@}