• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Javassist, a Java-bytecode translator toolkit.
3  * Copyright (C) 1999-2007 Shigeru Chiba. All Rights Reserved.
4  *
5  * The contents of this file are subject to the Mozilla Public License Version
6  * 1.1 (the "License"); you may not use this file except in compliance with
7  * the License.  Alternatively, the contents of this file may be used under
8  * the terms of the GNU Lesser General Public License Version 2.1 or later.
9  *
10  * Software distributed under the License is distributed on an "AS IS" basis,
11  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12  * for the specific language governing rights and limitations under the
13  * License.
14  */
15 
16 package javassist;
17 
18 import java.io.*;
19 import java.net.*;
20 
21 /**
22  * A class search-path specified with URL (http).
23  *
24  * @see javassist.ClassPath
25  * @see ClassPool#insertClassPath(ClassPath)
26  * @see ClassPool#appendClassPath(ClassPath)
27  */
28 public class URLClassPath implements ClassPath {
29     protected String hostname;
30     protected int port;
31     protected String directory;
32     protected String packageName;
33 
34     /**
35      * Creates a search path specified with URL (http).
36      *
37      * <p>This search path is used only if a requested
38      * class name starts with the name specified by <code>packageName</code>.
39      * If <code>packageName</code> is "org.javassist." and a requested class is
40      * "org.javassist.test.Main", then the given URL is used for loading that class.
41      * The <code>URLClassPath</code> obtains a class file from:
42      *
43      * <ul><pre>http://www.javassist.org:80/java/classes/org/javassist/test/Main.class
44      * </pre></ul>
45      *
46      * <p>Here, we assume that <code>host</code> is "www.javassist.org",
47      * <code>port</code> is 80, and <code>directory</code> is "/java/classes/".
48      *
49      * <p>If <code>packageName</code> is <code>null</code>, the URL is used
50      * for loading any class.
51      *
52      * @param host              host name
53      * @param port              port number
54      * @param directory         directory name ending with "/".
55      *                          It can be "/" (root directory).
56      *                          It must start with "/".
57      * @param packageName       package name.  It must end with "." (dot).
58      */
URLClassPath(String host, int port, String directory, String packageName)59     public URLClassPath(String host, int port,
60                         String directory, String packageName) {
61         hostname = host;
62         this.port = port;
63         this.directory = directory;
64         this.packageName = packageName;
65     }
66 
toString()67     public String toString() {
68         return hostname + ":" + port + directory;
69     }
70 
71     /**
72      * Opens a class file with http.
73      *
74      * @return null if the class file could not be found.
75      */
openClassfile(String classname)76     public InputStream openClassfile(String classname) {
77         try {
78             URLConnection con = openClassfile0(classname);
79             if (con != null)
80                 return con.getInputStream();
81         }
82         catch (IOException e) {}
83         return null;        // not found
84     }
85 
openClassfile0(String classname)86     private URLConnection openClassfile0(String classname) throws IOException {
87         if (packageName == null || classname.startsWith(packageName)) {
88             String jarname
89                     = directory + classname.replace('.', '/') + ".class";
90             return fetchClass0(hostname, port, jarname);
91         }
92         else
93             return null;    // not found
94     }
95 
96     /**
97      * Returns the URL.
98      *
99      * @return null if the class file could not be obtained.
100      */
find(String classname)101     public URL find(String classname) {
102         try {
103             URLConnection con = openClassfile0(classname);
104             InputStream is = con.getInputStream();
105             if (is != null) {
106                 is.close();
107                 return con.getURL();
108             }
109         }
110         catch (IOException e) {}
111         return null;
112     }
113 
114     /**
115      * Closes this class path.
116      */
close()117     public void close() {}
118 
119     /**
120      * Reads a class file on an http server.
121      *
122      * @param host              host name
123      * @param port              port number
124      * @param directory         directory name ending with "/".
125      *                          It can be "/" (root directory).
126      *                          It must start with "/".
127      * @param classname         fully-qualified class name
128      */
fetchClass(String host, int port, String directory, String classname)129     public static byte[] fetchClass(String host, int port,
130                                     String directory, String classname)
131         throws IOException
132     {
133         byte[] b;
134         URLConnection con = fetchClass0(host, port,
135                 directory + classname.replace('.', '/') + ".class");
136         int size = con.getContentLength();
137         InputStream s = con.getInputStream();
138         try {
139             if (size <= 0)
140                 b = ClassPoolTail.readStream(s);
141             else {
142                 b = new byte[size];
143                 int len = 0;
144                 do {
145                     int n = s.read(b, len, size - len);
146                     if (n < 0)
147                         throw new IOException("the stream was closed: "
148                                               + classname);
149 
150                     len += n;
151                 } while (len < size);
152             }
153         }
154         finally {
155             s.close();
156         }
157 
158         return b;
159     }
160 
fetchClass0(String host, int port, String filename)161     private static URLConnection fetchClass0(String host, int port,
162                                              String filename)
163         throws IOException
164     {
165         URL url;
166         try {
167             url = new URL("http", host, port, filename);
168         }
169         catch (MalformedURLException e) {
170             // should never reache here.
171             throw new IOException("invalid URL?");
172         }
173 
174         URLConnection con = url.openConnection();
175         con.connect();
176         return con;
177     }
178 }
179