InputStream getResourceAsStream(String name) {

    InputStream is =
        (myLoader == null)
            ? ClassLoader.getSystemResourceAsStream(name)
            : myLoader.getResourceAsStream(name);

    if (is != null) return is;

    // match behaviour of standard class loaders.
    if (name.endsWith(".class")) return null;

    boolean unlockLoader = false;
    try {
      unlockLoader = lockClassLoader(ShExQual.SH);

      synchronized (this) {
        if (needReload) {
          reload();
        }

        if (!initDone) initLoaders();

        for (int i = 0; i < jarList.length; i++) {

          JarLoader jl = jarList[i];

          is = jl.getStream(name);
          if (is != null) {
            return is;
          }
        }
      }
      return null;

    } catch (StandardException se) {
      return null;
    } finally {
      if (unlockLoader) {
        lf.unlock(compat, this, classLoaderLock, ShExQual.SH);
      }
    }
  }
  /**
   * Load the class from the class path. Called by JarLoader when it has a request to load a class
   * to fulfill the sematics of db.database.classpath.
   *
   * <p>Enforces two restrictions:
   *
   * <UL>
   *   <LI>Do not allow classes in certain name spaces to be loaded from installed jars, see
   *       RESTRICTED_PACKAGES for the list.
   *   <LI>Referencing Derby's internal classes (those outside the public api) from installed is
   *       disallowed. This is to stop user defined routines bypassing security or taking advantage
   *       of security holes in Derby. E.g. allowing a routine to call a public method in db would
   *       allow such routines to call public static methods for system procedures without having
   *       been granted permission on them, such as setting database properties.
   * </UL>
   *
   * @exception ClassNotFoundException Class can not be found or the installed jar is restricted
   *     from loading it.
   */
  Class loadClass(String className, boolean resolve) throws ClassNotFoundException {

    JarLoader jl = null;

    boolean unlockLoader = false;
    try {
      unlockLoader = lockClassLoader(ShExQual.SH);

      synchronized (this) {
        if (needReload) {
          reload();
        }

        Class clazz = checkLoaded(className, resolve);
        if (clazz != null) return clazz;

        // Refuse to load classes from restricted name spaces
        // That is classes in those name spaces can be not
        // loaded from installed jar files.
        for (int i = 0; i < RESTRICTED_PACKAGES.length; i++) {
          if (className.startsWith(RESTRICTED_PACKAGES[i]))
            throw new ClassNotFoundException(className);
        }

        String jvmClassName = className.replace('.', '/').concat(".class");

        if (!initDone) initLoaders();

        for (int i = 0; i < jarList.length; i++) {
          jl = jarList[i];
          Class c = jl.loadClassData(className, jvmClassName, resolve);
          if (c != null) {
            if (vs != null)
              vs.println(
                  MessageService.getTextMessage(
                      MessageId.CM_CLASS_LOAD, className, jl.getJarName()));

            return c;
          }
        }
        // Ok we are missing the class, we will try to reload once and Find it...
        reload();
        initDone = false;
        initLoaders();
        for (int i = 0; i < jarList.length; i++) {
          jl = jarList[i];
          Class c = jl.loadClassData(className, jvmClassName, resolve);
          if (c != null) {
            if (vs != null)
              vs.println(
                  MessageService.getTextMessage(
                      MessageId.CM_CLASS_LOAD, className, jl.getJarName()));

            return c;
          }
        }
      }

      return null;

    } catch (StandardException se) {
      throw new ClassNotFoundException(
          MessageService.getTextMessage(
              MessageId.CM_CLASS_LOAD_EXCEPTION,
              className,
              jl == null ? null : jl.getJarName(),
              se));
    } finally {
      if (unlockLoader) {
        lf.unlock(compat, this, classLoaderLock, ShExQual.SH);
      }
    }
  }
    /*
     * Version of getResource() that tracks the jar files that have been
     * visited by linking through the index files. This helper method uses
     * a HashSet to store the URLs of jar files that have been searched and
     * uses it to avoid going into an infinite loop, looking for a
     * non-existent resource
     */
    Resource getResource(final String name, boolean check, Set visited) {

      Resource res;
      Object[] jarFiles;
      int count = 0;
      LinkedList jarFilesList = null;

      /* If there no jar files in the index that can potential contain
       * this resource then return immediately.
       */
      if ((jarFilesList = index.get(name)) == null) return null;

      do {
        jarFiles = jarFilesList.toArray();
        int size = jarFilesList.size();
        /* loop through the mapped jar file list */
        while (count < size) {
          String jarName = (String) jarFiles[count++];
          JarLoader newLoader;
          final URL url;

          try {
            url = new URL(csu, jarName);
            if ((newLoader = (JarLoader) lmap.get(url)) == null) {
              /* no loader has been set up for this jar file
               * before
               */
              newLoader =
                  (JarLoader)
                      AccessController.doPrivileged(
                          new PrivilegedExceptionAction() {
                            public Object run() throws IOException {
                              return new JarLoader(url, handler, lmap);
                            }
                          });

              /* this newly opened jar file has its own index,
               * merge it into the parent's index, taking into
               * account the relative path.
               */
              JarIndex newIndex = ((JarLoader) newLoader).getIndex();
              if (newIndex != null) {
                int pos = jarName.lastIndexOf("/");
                newIndex.merge(this.index, (pos == -1 ? null : jarName.substring(0, pos + 1)));
              }

              /* put it in the global hashtable */
              lmap.put(url, newLoader);
            }
          } catch (java.security.PrivilegedActionException pae) {
            continue;
          } catch (MalformedURLException e) {
            continue;
          }

          /* Note that the addition of the url to the list of visited
           * jars incorporates a check for presence in the hashmap
           */
          boolean visitedURL = !visited.add(url);
          if (!visitedURL) {
            final JarEntry entry = newLoader.jar.getJarEntry(name);
            if (entry != null) {
              return newLoader.checkResource(name, check, entry);
            }

            /* Verify that at least one other resource with the
             * same package name as the lookedup resource is
             * present in the new jar
             */
            if (!newLoader.validIndex(name)) {
              /* the mapping is wrong */
              throw new InvalidJarIndexException("Invalid index");
            }
          }

          /* If newLoader is the current loader or if it is a
           * loader that has already been searched or if the new
           * loader does not have an index then skip it
           * and move on to the next loader.
           */
          if (visitedURL || newLoader == this || newLoader.getIndex() == null) {
            continue;
          }

          /* Process the index of the new loader
           */
          if ((res = newLoader.getResource(name, check, visited)) != null) {
            return res;
          }
        }
        // Get the list of jar files again as the list could have grown
        // due to merging of index files.
        jarFilesList = index.get(name);

        // If the count is unchanged, we are done.
      } while (count < jarFilesList.size());
      return null;
    }