javassist.URLClassPath Maven / Gradle / Ivy
/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. Alternatively, the contents of this file may be used under
* the terms of the GNU Lesser General Public License Version 2.1 or later,
* or the Apache License Version 2.0.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*/
package javassist;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
/**
* A class search-path specified with URL (http).
*
* @see javassist.ClassPath
* @see ClassPool#insertClassPath(ClassPath)
* @see ClassPool#appendClassPath(ClassPath)
*/
public class URLClassPath implements ClassPath {
protected String hostname;
protected int port;
protected String directory;
protected String packageName;
/**
* Creates a search path specified with URL (http).
*
* This search path is used only if a requested
* class name starts with the name specified by packageName
.
* If packageName
is "org.javassist." and a requested class is
* "org.javassist.test.Main", then the given URL is used for loading that class.
* The URLClassPath
obtains a class file from:
*
*
http://www.javassist.org:80/java/classes/org/javassist/test/Main.class
*
*
* Here, we assume that host
is "www.javassist.org",
* port
is 80, and directory
is "/java/classes/".
*
*
If packageName
is null
, the URL is used
* for loading any class.
*
* @param host host name
* @param port port number
* @param directory directory name ending with "/".
* It can be "/" (root directory).
* It must start with "/".
* @param packageName package name. It must end with "." (dot).
*/
public URLClassPath(String host, int port,
String directory, String packageName) {
hostname = host;
this.port = port;
this.directory = directory;
this.packageName = packageName;
}
@Override
public String toString() {
return hostname + ":" + port + directory;
}
/**
* Opens a class file with http.
*
* @return null if the class file could not be found.
*/
@Override
public InputStream openClassfile(String classname) {
try {
URLConnection con = openClassfile0(classname);
if (con != null)
return con.getInputStream();
}
catch (IOException e) {}
return null; // not found
}
private URLConnection openClassfile0(String classname) throws IOException {
if (packageName == null || classname.startsWith(packageName)) {
String jarname
= directory + classname.replace('.', '/') + ".class";
return fetchClass0(hostname, port, jarname);
}
return null; // not found
}
/**
* Returns the URL.
*
* @return null if the class file could not be obtained.
*/
@Override
public URL find(String classname) {
try {
URLConnection con = openClassfile0(classname);
InputStream is = con.getInputStream();
if (is != null) {
is.close();
return con.getURL();
}
}
catch (IOException e) {}
return null;
}
/**
* Reads a class file on an http server.
*
* @param host host name
* @param port port number
* @param directory directory name ending with "/".
* It can be "/" (root directory).
* It must start with "/".
* @param classname fully-qualified class name
*/
public static byte[] fetchClass(String host, int port,
String directory, String classname)
throws IOException
{
byte[] b;
URLConnection con = fetchClass0(host, port,
directory + classname.replace('.', '/') + ".class");
int size = con.getContentLength();
InputStream s = con.getInputStream();
try {
if (size <= 0)
b = ClassPoolTail.readStream(s);
else {
b = new byte[size];
int len = 0;
do {
int n = s.read(b, len, size - len);
if (n < 0)
throw new IOException("the stream was closed: "
+ classname);
len += n;
} while (len < size);
}
}
finally {
s.close();
}
return b;
}
private static URLConnection fetchClass0(String host, int port,
String filename)
throws IOException
{
URL url;
try {
url = new URL("http", host, port, filename);
}
catch (MalformedURLException e) {
// should never reache here.
throw new IOException("invalid URL?");
}
URLConnection con = url.openConnection();
con.connect();
return con;
}
}