View Javadoc

1   // ========================================================================
2   // Copyright (c) 2002-2009 Mort Bay Consulting Pty. Ltd.
3   // ------------------------------------------------------------------------
4   // All rights reserved. This program and the accompanying materials
5   // are made available under the terms of the Eclipse Public License v1.0
6   // and Apache License v2.0 which accompanies this distribution.
7   // The Eclipse Public License is available at 
8   // http://www.eclipse.org/legal/epl-v10.html
9   // The Apache License v2.0 is available at
10  // http://www.opensource.org/licenses/apache2.0.php
11  // You may elect to redistribute this code under either of these licenses. 
12  // ========================================================================
13  
14  package org.eclipse.jetty.start;
15  
16  import java.io.File;
17  import java.io.IOException;
18  import java.io.PrintStream;
19  import java.io.UnsupportedEncodingException;
20  import java.net.MalformedURLException;
21  import java.net.URL;
22  import java.net.URLClassLoader;
23  import java.util.StringTokenizer;
24  import java.util.Vector;
25  
26  
27  /**
28   * Class to handle CLASSPATH construction
29   */
30  public class Classpath {
31  
32      private final Vector<File> _elements = new Vector<File>();    
33  
34      public Classpath()
35      {}    
36  
37      public Classpath(String initial)
38      {
39          addClasspath(initial);
40      }
41      
42      public File[] getElements()
43      {
44          return _elements.toArray(new File[_elements.size()]);
45      }
46      
47      public int count()
48      {
49          return _elements.size();
50      }
51          
52      public boolean addComponent(String component)
53      {
54          if ((component != null)&&(component.length()>0)) {
55              try {
56                  File f = new File(component);
57                  if (f.exists())
58                  {
59                      File key = f.getCanonicalFile();
60                      if (!_elements.contains(key))
61                      {
62                          _elements.add(key);
63                          return true;
64                      }
65                  }
66              } catch (IOException e) {}
67          }
68          return false;
69      }
70      
71      public boolean addComponent(File component)
72      {
73          if (component != null) {
74              try {
75                  if (component.exists()) {
76                      File key = component.getCanonicalFile();
77                      if (!_elements.contains(key)) {
78                          _elements.add(key);
79                          return true;
80                      }
81                  }
82              } catch (IOException e) {}
83          }
84          return false;
85      }
86  
87      public boolean addClasspath(String s)
88      {
89          boolean added=false;
90          if (s != null)
91          {
92              StringTokenizer t = new StringTokenizer(s, File.pathSeparator);
93              while (t.hasMoreTokens())
94              {
95                  added|=addComponent(t.nextToken());
96              }
97          }
98          return added;
99      }
100 
101     public void dump(PrintStream out)
102     {
103         int i = 0;
104         for (File element : _elements)
105         {
106             out.printf("%2d: %s\n",i++,element.getAbsolutePath());
107         }
108     }
109     
110     @Override
111     public String toString()
112     {
113         StringBuffer cp = new StringBuffer(1024);
114         int cnt = _elements.size();
115         if (cnt >= 1) {
116             cp.append( ((_elements.elementAt(0))).getPath() );
117         }
118         for (int i=1; i < cnt; i++) {
119             cp.append(File.pathSeparatorChar);
120             cp.append( ((_elements.elementAt(i))).getPath() );
121         }
122         return cp.toString();
123     }
124     
125     public ClassLoader getClassLoader() {
126         int cnt = _elements.size();
127         URL[] urls = new URL[cnt];
128         for (int i=0; i < cnt; i++) {
129             try {
130                 String u=((_elements.elementAt(i))).toURL().toString();
131                 urls[i] = new URL(encodeFileURL(u));
132             } catch (MalformedURLException e) {}
133         }
134         
135         ClassLoader parent = Thread.currentThread().getContextClassLoader();
136         if (parent == null) {
137             parent = Classpath.class.getClassLoader();
138         }
139         if (parent == null) {
140             parent = ClassLoader.getSystemClassLoader();
141         }
142         return new Loader(urls, parent);
143     }
144 
145     private static class Loader extends URLClassLoader
146     {
147         Loader(URL[] urls, ClassLoader parent)
148         {
149             super(urls, parent);
150         }
151 
152         @Override
153         public String toString()
154         {
155             return "startJarLoader@"+Long.toHexString(hashCode());
156         }
157     }
158     
159     public static String encodeFileURL(String path)
160     {
161         byte[] bytes;
162         try 
163         { 
164             bytes=path.getBytes("utf-8");
165         } 
166         catch (UnsupportedEncodingException e) 
167         {
168             bytes=path.getBytes();
169         }
170         
171         StringBuffer buf = new StringBuffer(bytes.length*2);
172         buf.append("file:");
173         
174         synchronized(buf)
175         {
176             for (int i=5;i<bytes.length;i++)
177             {
178                 byte b=bytes[i]; 
179                 switch(b)
180                 {
181                   case '%':
182                       buf.append("%25");
183                       continue;
184                   case ' ':
185                       buf.append("%20");
186                       continue;
187                   case '/':
188                   case '.':
189                   case '-':
190                   case '_':
191                       buf.append((char)b);
192                       continue;
193                   default:
194                       // let's be over conservative here!
195                       if (Character.isJavaIdentifierPart((char)b))
196                       {
197                           if(b>='a' && b<='z' || b>='A' && b<='Z' || b>='0' && b<='9')
198                           {
199                               buf.append((char)b);
200                               continue;
201                           }
202                       }
203                       buf.append('%');
204                       buf.append(Integer.toHexString((0xf0&b)>>4));
205                       buf.append(Integer.toHexString((0x0f&b)));
206                       continue;
207                 }
208             }
209         }
210 
211         return buf.toString();
212     }
213 
214     /**
215      * Overlay another classpath, copying its elements into place on this Classpath, while eliminating duplicate entries
216      * on the classpath.
217      * 
218      * @param cpOther
219      *            the other classpath to overlay
220      */
221     public void overlay(Classpath cpOther)
222     {
223         for (File otherElement : cpOther._elements)
224         {
225             if (this._elements.contains(otherElement))
226             {
227                 // Skip duplicate entries
228                 continue;
229             }
230             this._elements.add(otherElement);
231         }
232     }
233 
234     public boolean isEmpty()
235     {
236         return (_elements == null) || (_elements.isEmpty());
237     }
238 }