BundleURLStreamHandler.java

00001 /*
00002  * Copyright (c) 2003-2006, KNOPFLERFISH project
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following
00007  * conditions are met:
00008  *
00009  * - Redistributions of source code must retain the above copyright
00010  *   notice, this list of conditions and the following disclaimer.
00011  *
00012  * - Redistributions in binary form must reproduce the above
00013  *   copyright notice, this list of conditions and the following
00014  *   disclaimer in the documentation and/or other materials
00015  *   provided with the distribution.
00016  *
00017  * - Neither the name of the KNOPFLERFISH project nor the names of its
00018  *   contributors may be used to endorse or promote products derived
00019  *   from this software without specific prior written permission.
00020  *
00021  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00022  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00023  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00024  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00025  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00026  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00027  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
00028  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00029  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
00030  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00031  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
00032  * OF THE POSSIBILITY OF SUCH DAMAGE.
00033  */
00034 
00035 package org.knopflerfish.framework;
00036 
00037 import java.net.*;
00038 
00039 
00045 public class BundleURLStreamHandler extends URLStreamHandler {
00046 
00047   final public static String PROTOCOL = "bundle";
00048 
00049   final public static String PERM_OK = "P";
00050 
00051   private Bundles bundles;
00052 
00053   private PermissionOps secure;
00054 
00055 
00056   // TODO, we need a more efficient and cleaner solution here.
00057 
00058   BundleURLStreamHandler(Bundles b, PermissionOps s) {
00059     bundles = b;
00060     secure = s;
00061   }
00062 
00063 
00064   public URLConnection openConnection(URL u) {
00065     if (u.getAuthority() != PERM_OK) {
00066       secure.checkResourceAdminPerm(bundles.getBundle(getId(u.getHost())));
00067     }
00068     return new BundleURLConnection(u, bundles);
00069   }
00070 
00071 
00072   protected void parseURL(URL u, String s, int start, int limit)  {
00073     String path = u.getPath();
00074     String host = u.getHost();
00075     long id = -1;
00076     int cpElem = u.getPort();
00077     if (limit > start) {
00078       int len = limit - start;
00079       char [] sc = new char[len];
00080       s.getChars(start, limit, sc, 0);
00081       int pos = 0;
00082       if (len >= 2 && sc[0] == '/' && sc[1] == '/') {
00083         for (pos = 2; pos < len; pos++) {
00084           if (sc[pos] == ':' || sc[pos] == '/') {
00085             break;
00086           } else if (sc[pos] == '.' || sc[pos] == '_') {
00087             if (id == -1) {
00088               id = Long.parseLong(new String(sc, 2, pos - 2));
00089             }
00090           } else if (!Character.isDigit(sc[pos])) {
00091             throw new IllegalArgumentException("Illegal chars in bundle id specification");
00092           }
00093         }
00094         host = new String(sc, 2, pos - 2);
00095         if (pos < len && sc[pos] == ':') {
00096           ++pos;
00097           cpElem = 0;
00098           while (pos < len) {
00099             if (sc[pos] == '/') {
00100               break;
00101             } else if (!Character.isDigit(sc[pos])) {
00102               throw new IllegalArgumentException("Illegal chars in bundle port specification");
00103             }
00104             cpElem = 10 * cpElem + (sc[pos++] - '0');
00105           }
00106         } else {
00107           cpElem = -1;
00108         }
00109       }
00110       if (pos < len) {
00111         int pstart;
00112         if (sc[pos] != '/') {
00113           if (path != null) { 
00114             int dirend = path.lastIndexOf('/') + 1;
00115             if (dirend > 0) {
00116               int plen = len - pos;
00117               pstart = path.startsWith("/") ? 0 : 1;
00118               len = dirend + plen + pstart;
00119               if (len > sc.length) {
00120                 char [] newsc = new char [len];
00121                 System.arraycopy(sc, pos, newsc, dirend + pstart, plen);
00122                 sc = newsc;
00123               } else if (pos != dirend) {
00124                 System.arraycopy(sc, pos, sc, dirend + pstart, plen);
00125               }
00126               path.getChars(1 - pstart, dirend, sc, 1);
00127             } else {
00128               len = 1;
00129             }
00130           } else {
00131             len = 1;
00132           }
00133           sc[0] = '/';
00134           pstart = 0;
00135           pos = 0;
00136         } else {
00137           pstart = pos;
00138         }
00139         int dots = 0;
00140         int ipos = pstart - 1;
00141         boolean slash = false;
00142         for (; pos < len; pos++) {
00143           if (sc[pos] == '/') {
00144             if (slash) {
00145               continue;
00146             }
00147             slash = true;
00148             if (dots == 1) {
00149               dots = 0;
00150               continue;
00151             } else if (dots == 2) {
00152               while (ipos > pstart && sc[--ipos] != '/')
00153                 ;
00154             }
00155           } else if (sc[pos] == '.') {
00156             if (slash) {
00157               dots = 1;
00158               slash = false;
00159               continue;
00160             } else if (dots == 1) {
00161               dots = 2;
00162               continue;
00163             }
00164           } else {
00165             slash = false;
00166           }
00167           while (dots-- > 0) {
00168             sc[++ipos] = '.';
00169           }
00170           if (++ipos != pos) {
00171             sc[ipos] = sc[pos];
00172           }
00173         }
00174         if (dots == 2) {
00175           while (ipos > pstart && sc[--ipos] != '/')
00176             ;
00177         }
00178         path = new String(sc, pstart, ipos - pstart + 1);
00179       }
00180     }
00181     if (id == -1) {
00182       id = getId(host);
00183     }
00184     secure.checkResourceAdminPerm(bundles.getBundle(id));
00185     setURL(u, u.getProtocol(), host, cpElem, PERM_OK, null, path, null, null);
00186   }
00187 
00188 
00196   protected boolean equals(URL u1, URL u2) {
00197     return sameFile(u1, u2);
00198   }
00199 
00200 
00205   protected int hashCode(URL u) {
00206     int h = 0;
00207 
00208     if (PROTOCOL.equals(u.getProtocol())) {
00209       String host = u.getHost();
00210       if (host != null)
00211         h = host.hashCode();
00212 
00213       String file = u.getFile();
00214       if (file != null)
00215         h += file.hashCode();
00216 
00217       h += u.getPort();
00218     } else {
00219       h = u.hashCode();
00220     }
00221     return h;
00222   }
00223 
00229   protected boolean sameFile(URL u1, URL u2) {
00230     String p1 = u1.getProtocol();
00231     if (PROTOCOL.equals(p1)) {
00232       if (!p1.equals(u2.getProtocol()))
00233         return false;
00234 
00235       if (!hostsEqual(u1, u2))
00236         return false;
00237 
00238       if (!(u1.getFile() == u2.getFile() ||
00239             (u1.getFile() != null && u1.getFile().equals(u2.getFile()))))
00240         return false;
00241 
00242       if (u1.getPort() != u2.getPort())
00243         return false;
00244 
00245       return true;
00246     } else {
00247       return u1.equals(u2);
00248     }
00249   }
00250 
00251 
00259   protected boolean hostsEqual(URL u1, URL u2) {
00260     String s1 = u1.getHost();
00261     String s2 = u2.getHost();
00262     return (s1 == s2) || (s1 != null && s1.equals(s2));
00263   }
00264 
00265   
00272   protected String toExternalForm(URL url) {
00273     StringBuffer res = new StringBuffer(url.getProtocol());
00274     res.append("://");
00275     res.append(url.getHost());
00276     int port = url.getPort();
00277     if (port >= 0) {
00278       res.append(":").append(port);
00279     }
00280     res.append(url.getPath());
00281     return res.toString();
00282   }
00283 
00284 
00285   protected synchronized InetAddress getHostAddress(URL url) {
00286     return null;
00287   }
00288 
00289   //
00290   // Private
00291   //
00292 
00293   private long getId(String host) {
00294     int i = host.indexOf(".");
00295     if (i == -1) {
00296       i = host.indexOf("_");
00297     }
00298     if (i >= 0) {
00299       host = host.substring(0, i);
00300     }
00301     return Long.parseLong(host);
00302   }
00303 
00304 }

Generated on Mon Jan 11 21:19:13 2010 for OpenMobileIS by  doxygen 1.5.4