View Javadoc
1 package org.codehaus.classworlds.uberjar.protocol.jar; 2 3 /* 4 $Id: JarUrlConnection.java,v 1.1 2003/09/23 18:11:30 jvanzyl Exp $ 5 6 Copyright 2002 (C) The Werken Company. All Rights Reserved. 7 8 Redistribution and use of this software and associated documentation 9 ("Software"), with or without modification, are permitted provided 10 that the following conditions are met: 11 12 1. Redistributions of source code must retain copyright 13 statements and notices. Redistributions must also contain a 14 copy of this document. 15 16 2. Redistributions in binary form must reproduce the 17 above copyright notice, this list of conditions and the 18 following disclaimer in the documentation and/or other 19 materials provided with the distribution. 20 21 3. The name "classworlds" must not be used to endorse or promote 22 products derived from this Software without prior written 23 permission of The Werken Company. For written permission, 24 please contact bob@werken.com. 25 26 4. Products derived from this Software may not be called "classworlds" 27 nor may "classworlds" appear in their names without prior written 28 permission of The Werken Company. "classworlds" is a registered 29 trademark of The Werken Company. 30 31 5. Due credit should be given to The Werken Company. 32 (http://classworlds.werken.com/). 33 34 THIS SOFTWARE IS PROVIDED BY THE WERKEN COMPANY AND CONTRIBUTORS 35 ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT 36 NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 37 FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 38 THE WERKEN COMPANY OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 39 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 40 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 41 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 42 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 43 STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 44 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 45 OF THE POSSIBILITY OF SUCH DAMAGE. 46 47 */ 48 49 import org.codehaus.classworlds.UrlUtils; 50 51 import java.io.IOException; 52 import java.io.InputStream; 53 import java.net.JarURLConnection; 54 import java.net.MalformedURLException; 55 import java.net.URL; 56 import java.net.URLDecoder; 57 import java.util.ArrayList; 58 import java.util.List; 59 import java.util.StringTokenizer; 60 import java.util.jar.JarEntry; 61 import java.util.jar.JarFile; 62 import java.util.jar.JarInputStream; 63 64 /*** <code>URLConnection</code> capable of handling multiply-nested jars. 65 * 66 * 67 * @author <a href="mailto:bob@eng.werken.com">bob mcwhirter</a> 68 * 69 * @version $Id: JarUrlConnection.java,v 1.1 2003/09/23 18:11:30 jvanzyl Exp $ 70 */ 71 public class JarUrlConnection 72 extends JarURLConnection 73 { 74 // ---------------------------------------------------------------------- 75 // Instance members 76 // ---------------------------------------------------------------------- 77 78 /*** Base resource. */ 79 private URL baseResource; 80 81 /*** Additional nested segments. */ 82 private String[] segments; 83 84 /*** Terminal input-stream. */ 85 private InputStream in; 86 87 // ---------------------------------------------------------------------- 88 // Constructors 89 // ---------------------------------------------------------------------- 90 91 /*** Construct. 92 * 93 * @param url Target URL of the connections. 94 * 95 * @throws java.io.IOException If an error occurs while attempting to initialize 96 * the connection. 97 */ 98 JarUrlConnection( URL url ) 99 throws IOException 100 { 101 super( url = normaliseURL( url ) ); 102 103 String baseText = url.getPath(); 104 105 int bangLoc = baseText.indexOf( "!" ); 106 107 String baseResourceText = baseText.substring( 0, bangLoc ); 108 109 String extraText = ""; 110 111 if ( bangLoc <= ( baseText.length() - 2 ) 112 && 113 baseText.charAt( bangLoc + 1 ) == '/' ) 114 { 115 if ( bangLoc + 2 == baseText.length() ) 116 { 117 extraText = ""; 118 } 119 else 120 { 121 extraText = baseText.substring( bangLoc + 1 ); 122 } 123 } 124 else 125 { 126 throw new MalformedURLException( "No !/ in url: " + url.toExternalForm() ); 127 } 128 129 130 List segments = new ArrayList(); 131 132 StringTokenizer tokens = new StringTokenizer( extraText, "!" ); 133 134 while ( tokens.hasMoreTokens() ) 135 { 136 segments.add( tokens.nextToken() ); 137 } 138 139 this.segments = (String[]) segments.toArray( new String[segments.size()] ); 140 141 this.baseResource = new URL( baseResourceText ); 142 } 143 144 protected static URL normaliseURL( URL url ) throws MalformedURLException 145 { 146 String text = UrlUtils.normalizeUrlPath( url.toString() ); 147 148 if ( !text.startsWith( "jar:" ) ) 149 { 150 text = "jar:" + text; 151 } 152 153 if ( text.indexOf( '!' ) < 0 ) 154 { 155 text = text + "!/"; 156 } 157 158 return new URL( text ); 159 } 160 161 // ---------------------------------------------------------------------- 162 // Instance methods 163 // ---------------------------------------------------------------------- 164 165 /*** Retrieve the nesting path segments. 166 * 167 * @return The segments. 168 */ 169 protected String[] getSegments() 170 { 171 return this.segments; 172 } 173 174 /*** Retrieve the base resource <code>URL</code>. 175 * 176 * @return The base resource url. 177 */ 178 protected URL getBaseResource() 179 { 180 return this.baseResource; 181 } 182 183 /*** @see java.net.URLConnection 184 */ 185 public void connect() 186 throws IOException 187 { 188 if ( this.segments.length == 0 ) 189 { 190 setupBaseResourceInputStream(); 191 } 192 else 193 { 194 setupPathedInputStream(); 195 } 196 } 197 198 /*** Setup the <code>InputStream</code> purely from the base resource. 199 * 200 * @throws java.io.IOException If an I/O error occurs. 201 */ 202 protected void setupBaseResourceInputStream() 203 throws IOException 204 { 205 this.in = getBaseResource().openStream(); 206 } 207 208 /*** Setup the <code>InputStream</code> for URL with nested segments. 209 * 210 * @throws java.io.IOException If an I/O error occurs. 211 */ 212 protected void setupPathedInputStream() 213 throws IOException 214 { 215 InputStream curIn = getBaseResource().openStream(); 216 217 for ( int i = 0; i < this.segments.length; ++i ) 218 { 219 curIn = getSegmentInputStream( curIn, 220 segments[i] ); 221 } 222 223 this.in = curIn; 224 } 225 226 /*** Retrieve the <code>InputStream</code> for the nesting 227 * segment relative to a base <code>InputStream</code>. 228 * 229 * @param baseIn The base input-stream. 230 * @param segment The nesting segment path. 231 * 232 * @return The input-stream to the segment. 233 * 234 * @throws java.io.IOException If an I/O error occurs. 235 */ 236 protected InputStream getSegmentInputStream( InputStream baseIn, 237 String segment ) 238 throws IOException 239 { 240 JarInputStream jarIn = new JarInputStream( baseIn ); 241 JarEntry entry = null; 242 243 while ( jarIn.available() != 0 ) 244 { 245 entry = jarIn.getNextJarEntry(); 246 247 if ( entry == null ) 248 { 249 break; 250 } 251 252 if ( ( "/" + entry.getName() ).equals( segment ) ) 253 { 254 return jarIn; 255 } 256 } 257 258 throw new IOException( "unable to locate segment: " + segment ); 259 } 260 261 /*** @see java.net.URLConnection 262 */ 263 public InputStream getInputStream() 264 throws IOException 265 { 266 if ( this.in == null ) 267 { 268 connect(); 269 } 270 return this.in; 271 } 272 273 /*** 274 * @return JarFile 275 * @throws java.io.IOException 276 * @see java.net.JarURLConnection#getJarFile() 277 */ 278 public JarFile getJarFile() throws IOException 279 { 280 String url = baseResource.toExternalForm(); 281 282 if ( url.startsWith( "file:/" ) ) 283 { 284 url = url.substring( 6 ); 285 } 286 287 return new JarFile( URLDecoder.decode( url, "UTF-8" ) ); 288 } 289 }

This page was automatically generated by Maven