/Users/lyon/j4p/src/javassist/URLClassPath.java

1    /* 
2     * Javassist, a Java-bytecode translator toolkit. 
3     * Copyright (C) 1999-2003 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 "mypack" and a requested class is 
40        * "mypack.sub.Test", then the given URL is used for loading that class. 
41        * If <code>packageName</code> is <code>null</code>, the URL is used 
42        * for loading any class. 
43        * 
44        * @param host              host name 
45        * @param port              port number 
46        * @param directory         directory name ending with "/". 
47        *                          It can be "/" (root directory). 
48        * @param packageName       package name. 
49        */ 
50       public URLClassPath(String host, int port, 
51                           String directory, String packageName) { 
52           hostname = host; 
53           this.port = port; 
54           this.directory = directory; 
55           this.packageName = packageName; 
56       } 
57    
58       public String toString() { 
59           return hostname + ":" + port + directory; 
60       } 
61    
62       /** 
63        * Opens a class file with http. 
64        */ 
65       public InputStream openClassfile(String classname) { 
66           try { 
67               if (packageName == null || classname.startsWith(packageName)) { 
68                   String jarname 
69                           = directory + classname.replace('.', '/') + ".class"; 
70                   URLConnection con = fetchClass0(hostname, port, jarname); 
71                   return con.getInputStream(); 
72               } 
73           } catch (IOException e) { 
74           } 
75           return null;    // not found 
76       } 
77    
78       /** 
79        * Closes this class path. 
80        */ 
81       public void close() { 
82       } 
83    
84       /** 
85        * Reads a class file on an http server. 
86        * 
87        * @param host              host name 
88        * @param port              port number 
89        * @param directory         directory name ending with "/". 
90        *                          It can be "/" (root directory). 
91        * @param classname         fully-qualified class name 
92        */ 
93       public static byte[] fetchClass(String host, int port, 
94                                       String directory, String classname) 
95               throws IOException { 
96           byte[] b; 
97           URLConnection con = fetchClass0(host, port, 
98                   directory + classname.replace('.', '/') + ".class"); 
99           int size = con.getContentLength(); 
100          InputStream s = con.getInputStream(); 
101          try { 
102              if (size <= 0) 
103                  b = ClassPoolTail.readStream(s); 
104              else { 
105                  b = new byte[size]; 
106                  int len = 0; 
107                  do { 
108                      int n = s.read(b, len, size - len); 
109                      if (n < 0) 
110                          throw new IOException("the stream was closed: " 
111                                  + classname); 
112   
113                      len += n; 
114                  } while (len < size); 
115              } 
116          } finally { 
117              s.close(); 
118          } 
119   
120          return b; 
121      } 
122   
123      private static URLConnection fetchClass0(String host, int port, 
124                                               String filename) 
125              throws IOException { 
126          URL url; 
127          try { 
128              url = new URL("http", host, port, filename); 
129          } catch (MalformedURLException e) { 
130              // should never reache here. 
131              throw new IOException("invalid URL?"); 
132          } 
133   
134          URLConnection con = url.openConnection(); 
135          con.connect(); 
136          return con; 
137      } 
138  } 
139