All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jboss.ws.common.utils.JarUrlConnection Maven / Gradle / Ivy

The newest version!
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.jboss.ws.common.utils;

import java.io.IOException;
import java.io.InputStream;
import java.net.JarURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.JarInputStream;

import org.jboss.ws.common.Messages;

/** URLConnection capable of handling multiply-nested jars.
 *
 *  @author bob mcwhirter
 */
public class JarUrlConnection extends JarURLConnection
{
   // ----------------------------------------------------------------------
   //     Instance members
   // ----------------------------------------------------------------------

   /** Base resource. */
   private final URL baseResource;

   /** Additional nested segments. */
   private final String[] segments;

   /** Terminal input-stream. */
   private InputStream in;

   // ----------------------------------------------------------------------
   //     Constructors
   // ----------------------------------------------------------------------

   /** Construct.
    *
    *  @param url Target URL of the connections.
    *
    *  @throws java.io.IOException If an error occurs while attempting to initialize
    *          the connection.
    */
   public JarUrlConnection(URL url) throws IOException
   {
      super(url = normaliseURL(url));

      String baseText = url.getPath();

      int bangLoc = baseText.indexOf("!");

      String baseResourceText = baseText.substring(0, bangLoc);

      String extraText = "";

      if (bangLoc <= (baseText.length() - 2) && baseText.charAt(bangLoc + 1) == '/')
      {
         if (bangLoc + 2 == baseText.length())
         {
            extraText = "";
         }
         else
         {
            extraText = baseText.substring(bangLoc + 1);
         }
      }
      else
      {
         throw Messages.MESSAGES.jarUrlConnectionBuildError(url.toExternalForm());
      }

      List segments = new ArrayList();

      StringTokenizer tokens = new StringTokenizer(extraText, "!");

      while (tokens.hasMoreTokens())
      {
         segments.add(tokens.nextToken());
      }

      this.segments = segments.toArray(new String[segments.size()]);

      this.baseResource = new URL(baseResourceText);
   }

   protected static URL normaliseURL(URL url) throws MalformedURLException
   {
      String text = normalizeUrlPath(url.toString());

      if (!text.startsWith("jar:"))
      {
         text = "jar:" + text;
      }

      if (text.indexOf('!') < 0)
      {
         text = text + "!/";
      }

      return new URL(text);
   }

   // ----------------------------------------------------------------------
   //     Instance methods
   // ----------------------------------------------------------------------

   /** Retrieve the nesting path segments.
    *
    *  @return The segments.
    */
   protected String[] getSegments()
   {
      return this.segments;
   }

   /** Retrieve the base resource URL.
    *
    *  @return The base resource url.
    */
   protected URL getBaseResource()
   {
      return this.baseResource;
   }

   /** @see java.net.URLConnection
    */
   public void connect() throws IOException
   {
      if (this.segments.length == 0)
      {
         setupBaseResourceInputStream();
      }
      else
      {
         setupPathedInputStream();
      }
   }

   /** Setup the InputStream purely from the base resource.
    *
    *  @throws java.io.IOException If an I/O error occurs.
    */
   protected void setupBaseResourceInputStream() throws IOException
   {
      this.in = getBaseResource().openStream();
   }

   /** Setup the InputStream for URL with nested segments.
    *
    *  @throws java.io.IOException If an I/O error occurs.
    */
   protected void setupPathedInputStream() throws IOException
   {
      InputStream curIn = getBaseResource().openStream();

      for (int i = 0; i < this.segments.length; ++i)
      {
         curIn = getSegmentInputStream(curIn, segments[i]);
      }

      this.in = curIn;
   }

   /** Retrieve the InputStream for the nesting
    *  segment relative to a base InputStream.
    *
    *  @param baseIn The base input-stream.
    *  @param segment The nesting segment path.
    *
    *  @return The input-stream to the segment.
    *
    *  @throws java.io.IOException If an I/O error occurs.
    */
   protected InputStream getSegmentInputStream(InputStream baseIn, String segment) throws IOException
   {
      JarInputStream jarIn = new JarInputStream(baseIn);
      JarEntry entry = null;

      while (jarIn.available() != 0)
      {
         entry = jarIn.getNextJarEntry();

         if (entry == null)
         {
            break;
         }

         if (("/" + entry.getName()).equals(segment))
         {
            return jarIn;
         }
      }

      throw Messages.MESSAGES.jarUrlConnectionUnableToLocateSegment(segment, getURL().toExternalForm());
   }

   /** @see java.net.URLConnection
    */
   public InputStream getInputStream() throws IOException
   {
      if (this.in == null)
      {
         connect();
      }
      return this.in;
   }

   /**
    * @return JarFile
    * @throws java.io.IOException
    * @see java.net.JarURLConnection#getJarFile()
    */
   public JarFile getJarFile() throws IOException
   {
      String url = baseResource.toExternalForm();

      if (url.startsWith("file:/"))
      {
         url = url.substring(6);
      }

      return new JarFile(URLDecoder.decode(url, "UTF-8"));
   }

   private static String normalizeUrlPath(String name)
   {
      if (name.startsWith("/"))
      {
         name = name.substring(1);

         System.out.println("1 name = " + name);
      }

      // Looking for org/codehaus/werkflow/personality/basic/../common/core-idioms.xml
      //                                               |    i  |
      //                                               +-------+ remove
      //
      int i = name.indexOf("/..");

      // Can't be at the beginning because we have no root to refer to so
      // we start at 1.
      if (i > 0)
      {
         int j = name.lastIndexOf("/", i - 1);

         name = name.substring(0, j) + name.substring(i + 3);

         System.out.println("2 name = " + name);
      }

      return name;
   }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy