<commit_before>/*
 * $Id$
 *
 * Copyright 2003-2006 Wanadoo Nederland B.V.
 * See the COPYRIGHT file for redistribution and use restrictions.
 */
package org.xins.common.servlet.container;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
import java.util.jar.JarEntry;
import java.util.jar.JarInputStream;

/**
 * Class used to get the Servlet Class loader.
 * The class loader returned is a child first class loader.
 *
 * @version $Revision$ $Date$
 * @author <NAME> (<a href="mailto:<EMAIL>"><EMAIL></a>)
 */
public class ServletClassLoader {

   //-------------------------------------------------------------------------
   // Class functions
   //-------------------------------------------------------------------------

   /**
    * Gest the class loader that will loader the servlet.
    *
    * @param warFile
    *    the WAR file containing the Servlet.
    *
    * @param mode
    *    the mode in which the servlet should be loaded. The possible values are
    *    <code>USE_CURRENT_CLASSPATH</code>, <code>USE_CLASSPATH_LIB</code>,
    *    <code>USE_XINS_LIB</code>, <code>USE_WAR_LIB</code>,
    *    <code>USE_WAR_EXTERNAL_LIB</code>.
    *
    * @return
    *    the Class loader to use to load the Servlet.
    *
    * @throws IOException
    *    if the file cannot be read or is incorrect.
    */
   public static ClassLoader getServletClassLoader(File warFile, int mode) throws IOException {
      if (mode == USE_CURRENT_CLASSPATH) {
         return ServletClassLoader.class.getClassLoader();
      }

      List urlList = new ArrayList();

      // Add the WAR file so that it can locate web pages included in the WAR file
      urlList.add(warFile.toURL());

      if (mode != USE_WAR_EXTERNAL_LIB) {
         URL classesURL = new URL("jar:file:" + warFile.getAbsolutePath().replace(File.separatorChar, '/') + "!/WEB-INF/classes/");
         urlList.add(classesURL);
      }

      List standardLibs = new ArrayList();
      if (mode == USE_XINS_LIB) {
         String classLocation = ServletClassLoader.class.getProtectionDomain().getCodeSource().getLocation().toString();
         String commonJar = classLocation.substring(6).replace('/', File.separatorChar);
         File baseDir = new File(commonJar).getParentFile();
         File[] xinsFiles = baseDir.listFiles();
         for (int i = 0; i < xinsFiles.length; i++) {
            if (xinsFiles[i].getName().endsWith(".jar")) {
               urlList.add(xinsFiles[i].toURL());
            }
         }
         File libDir = new File(baseDir, ".." + File.separator + "lib");
         File[] libFiles = libDir.listFiles();
         for (int i = 0; i < libFiles.length; i++) {
            if (libFiles[i].getName().endsWith(".jar")) {
               urlList.add(libFiles[i].toURL());
            }
         }
      }
      if (mode == USE_CLASSPATH_LIB || mode == USE_WAR_EXTERNAL_LIB) {
         String classPath = System.getProperty("java.class.path");
         StringTokenizer stClassPath = new StringTokenizer(classPath, File.pathSeparator);
         while (stClassPath.hasMoreTokens()) {
            String nextPath = stClassPath.nextToken();
            if (nextPath.toLowerCase().endsWith(".jar")) {
               standardLibs.add(nextPath.substring(nextPath.lastIndexOf(File.separatorChar) + 1));
            }
            urlList.add(new File(nextPath).toURL());
         }
      }
      if (mode == USE_WAR_LIB || mode == USE_WAR_EXTERNAL_LIB) {
         JarInputStream jarStream = new JarInputStream(new FileInputStream(warFile));
         JarEntry entry = jarStream.getNextJarEntry();
         while(entry != null) {
            String entryName = entry.getName();
            if (entryName.startsWith("WEB-INF/lib/") && entryName.endsWith(".jar") && !standardLibs.contains(entryName.substring(12))) {
               File tempJarFile = unpack(jarStream, entryName);
               urlList.add(tempJarFile.toURL());
            }
            entry = jarStream.getNextJarEntry();
         }
         jarStream.close();
      }
      URL[] urls = new URL[urlList.size()];
      for (int i=0; i<urlList.size(); i++) {
         urls[i] = (URL) urlList.get(i);
      }
      ClassLoader loader = new ChildFirstClassLoader(urls, ServletClassLoader.class.getClassLoader());
      Thread.currentThread().setContextClassLoader(loader);
      return loader;
   }

   /**
    * Unpack the specified entry from the JAR file.
    *
    * @param jarStream
    *    The input stream of the JAR file positioned at the entry.
    * @param entryName
    *    The name of the entry to extract.
    *
    * @return
    *    The extracted file. The created file is a temporary file in the
    *    temporary directory.
    *
    * @throws IOException
    *    if the JAR file cannot be read or is incorrect.
    */
   private static File unpack(JarInputStream jarStream, String entryName) throws IOException {
      String libName = entryName.substring(entryName.lastIndexOf('/') + 1, entryName.length() - 4);
      File tempJarFile = File.createTempFile(libName, ".jar");
      FileOutputStream out = new FileOutputStream(tempJarFile);

      // Transfer bytes from the JAR file to the output file
      byte[] buf = new byte[8192];
      int len;
      while ((len = jarStream.read(buf)) > 0) {
         out.write(buf, 0, len);
      }
      out.close();
      return tempJarFile;
   }

   //-------------------------------------------------------------------------
   // Class fields
   //-------------------------------------------------------------------------

   /**
    * Use the current class loader to load the servlet and the libraries.
    */
   public final static int USE_CURRENT_CLASSPATH = 1;

   /**
    * Load the Servlet code from the WAR file and use the current
    * classpath for the libraries.
    */
   public final static int USE_CLASSPATH_LIB = 2;

   /**
    * Load the servlet code from the WAR file and try to find the libraries<commit_msg>- Fixed SF bug #1463644: "Prefix string too short" when deploying jar-files.<commit_after>/*
 * $Id$
 *
 * Copyright 2003-2006 Wanadoo Nederland B.V.
 * See the COPYRIGHT file for redistribution and use restrictions.
 */
package org.xins.common.servlet.container;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
import java.util.jar.JarEntry;
import java.util.jar.JarInputStream;

/**
 * Class used to get the Servlet Class loader.
 * The class loader returned is a child first class loader.
 *
 * @version $Revision$ $Date$
 * @author <NAME> (<a href="mailto:<EMAIL>"><EMAIL></a>)
 */
public class ServletClassLoader {

   //-------------------------------------------------------------------------
   // Class functions
   //-------------------------------------------------------------------------

   /**
    * Gest the class loader that will loader the servlet.
    *
    * @param warFile
    *    the WAR file containing the Servlet.
    *
    * @param mode
    *    the mode in which the servlet should be loaded. The possible values are
    *    <code>USE_CURRENT_CLASSPATH</code>, <code>USE_CLASSPATH_LIB</code>,
    *    <code>USE_XINS_LIB</code>, <code>USE_WAR_LIB</code>,
    *    <code>USE_WAR_EXTERNAL_LIB</code>.
    *
    * @return
    *    the Class loader to use to load the Servlet.
    *
    * @throws IOException
    *    if the file cannot be read or is incorrect.
    */
   public static ClassLoader getServletClassLoader(File warFile, int mode) throws IOException {
      if (mode == USE_CURRENT_CLASSPATH) {
         return ServletClassLoader.class.getClassLoader();
      }

      List urlList = new ArrayList();

      // Add the WAR file so that it can locate web pages included in the WAR file
      urlList.add(warFile.toURL());

      if (mode != USE_WAR_EXTERNAL_LIB) {
         URL classesURL = new URL("jar:file:" + warFile.getAbsolutePath().replace(File.separatorChar, '/') + "!/WEB-INF/classes/");
         urlList.add(classesURL);
      }

      List standardLibs = new ArrayList();
      if (mode == USE_XINS_LIB) {
         String classLocation = ServletClassLoader.class.getProtectionDomain().getCodeSource().getLocation().toString();
         String commonJar = classLocation.substring(6).replace('/', File.separatorChar);
         File baseDir = new File(commonJar).getParentFile();
         File[] xinsFiles = baseDir.listFiles();
         for (int i = 0; i < xinsFiles.length; i++) {
            if (xinsFiles[i].getName().endsWith(".jar")) {
               urlList.add(xinsFiles[i].toURL());
            }
         }
         File libDir = new File(baseDir, ".." + File.separator + "lib");
         File[] libFiles = libDir.listFiles();
         for (int i = 0; i < libFiles.length; i++) {
            if (libFiles[i].getName().endsWith(".jar")) {
               urlList.add(libFiles[i].toURL());
            }
         }
      }
      if (mode == USE_CLASSPATH_LIB || mode == USE_WAR_EXTERNAL_LIB) {
         String classPath = System.getProperty("java.class.path");
         StringTokenizer stClassPath = new StringTokenizer(classPath, File.pathSeparator);
         while (stClassPath.hasMoreTokens()) {
            String nextPath = stClassPath.nextToken();
            if (nextPath.toLowerCase().endsWith(".jar")) {
               standardLibs.add(nextPath.substring(nextPath.lastIndexOf(File.separatorChar) + 1));
            }
            urlList.add(new File(nextPath).toURL());
         }
      }
      if (mode == USE_WAR_LIB || mode == USE_WAR_EXTERNAL_LIB) {
         JarInputStream jarStream = new JarInputStream(new FileInputStream(warFile));
         JarEntry entry = jarStream.getNextJarEntry();
         while(entry != null) {
            String entryName = entry.getName();
            if (entryName.startsWith("WEB-INF/lib/") && entryName.endsWith(".jar") && !standardLibs.contains(entryName.substring(12))) {
               File tempJarFile = unpack(jarStream, entryName);
               urlList.add(tempJarFile.toURL());
            }
            entry = jarStream.getNextJarEntry();
         }
         jarStream.close();
      }
      URL[] urls = new URL[urlList.size()];
      for (int i=0; i<urlList.size(); i++) {
         urls[i] = (URL) urlList.get(i);
      }
      ClassLoader loader = new ChildFirstClassLoader(urls, ServletClassLoader.class.getClassLoader());
      Thread.currentThread().setContextClassLoader(loader);
      return loader;
   }

   /**
    * Unpack the specified entry from the JAR file.
    *
    * @param jarStream
    *    The input stream of the JAR file positioned at the entry.
    * @param entryName
    *    The name of the entry to extract.
    *
    * @return
    *    The extracted file. The created file is a temporary file in the
    *    temporary directory.
    *
    * @throws IOException
    *    if the JAR file cannot be read or is incorrect.
    */
   private static File unpack(JarInputStream jarStream, String entryName) throws IOException {
      String libName = entryName.substring(entryName.lastIndexOf('/') + 1, entryName.length() - 4);
      File tempJarFile = File.createTempFile("tmp_" + libName, ".jar");
      FileOutputStream out = new FileOutputStream(tempJarFile);

      // Transfer bytes from the JAR file to the output file
      byte[] buf = new byte[8192];
      int len;
      while ((len = jarStream.read(buf)) > 0) {
         out.write(buf, 0, len);
      }
      out.close();
      return tempJarFile;
   }

   //-------------------------------------------------------------------------
   // Class fields
   //-------------------------------------------------------------------------

   /**
    * Use the current class loader to load the servlet and the libraries.
    */
   public final static int USE_CURRENT_CLASSPATH = 1;

   /**
    * Load the Servlet code from the WAR file and use the current
    * classpath for the libraries.
    */
   public final static int USE_CLASSPATH_LIB = 2;

   /**
    * Load the servlet code from the WAR file and try to find the libraries
{'fraction_non_alphanumeric': 0.16006467259498788, 'fraction_numerical': 0.004607922392886015, 'mean_word_length': 2.167989756722151, 'pattern_counts': {'":': 0, '<': 39, '<?xml version=': 0, '>': 35, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6274223', 'n_tokens_mistral': 3522, 'n_tokens_neox': 3505, 'n_words': 933}