/** Remove the objects under administration from the JNDI Context, and then destroy the objects */
 public void tearDown() {
   try {
     InitialContext ic = new InitialContext();
     for (Iterator i = this.objectsToCreate.keySet().iterator(); i.hasNext(); ) {
       String name = (String) i.next();
       try {
         ic.unbind(name);
       } catch (NamingException err) {
         Logger.log(
             Logger.ERROR,
             JNDI_RESOURCES,
             "ContainerJNDIManager.ErrorUnbindingResource",
             name,
             err);
       }
       Object unboundObject = this.objectsToCreate.get(name);
       if (unboundObject instanceof WinstoneDataSource)
         ((WinstoneDataSource) unboundObject).destroy();
       Logger.log(Logger.FULL_DEBUG, JNDI_RESOURCES, "ContainerJNDIManager.UnboundResource", name);
     }
     Logger.log(
         Logger.DEBUG,
         JNDI_RESOURCES,
         "ContainerJNDIManager.TeardownComplete",
         "" + this.objectsToCreate.size());
   } catch (NamingException err) {
     Logger.log(
         Logger.ERROR, JNDI_RESOURCES, "ContainerJNDIManager.ErrorGettingInitialContext", err);
   }
 }
  /** Add the objects passed to the constructor to the JNDI Context addresses specified */
  public void setup() {

    try {
      InitialContext ic = new InitialContext();
      for (Iterator i = this.objectsToCreate.keySet().iterator(); i.hasNext(); ) {
        String name = (String) i.next();
        try {
          Name fullName = new CompositeName(name);
          Context currentContext = ic;
          while (fullName.size() > 1) {
            // Make contexts that are not already present
            try {
              currentContext = currentContext.createSubcontext(fullName.get(0));
            } catch (NamingException err) {
              currentContext = (Context) currentContext.lookup(fullName.get(0));
            }
            fullName = fullName.getSuffix(1);
          }
          ic.bind(name, this.objectsToCreate.get(name));
          Logger.log(Logger.FULL_DEBUG, JNDI_RESOURCES, "ContainerJNDIManager.BoundResource", name);
        } catch (NamingException err) {
          Logger.log(
              Logger.ERROR, JNDI_RESOURCES, "ContainerJNDIManager.ErrorBindingResource", name, err);
        }
      }
      Logger.log(
          Logger.DEBUG,
          JNDI_RESOURCES,
          "ContainerJNDIManager.SetupComplete",
          "" + this.objectsToCreate.size());
    } catch (NamingException err) {
      Logger.log(
          Logger.ERROR, JNDI_RESOURCES, "ContainerJNDIManager.ErrorGettingInitialContext", err);
    }
  }
  /**
   * Used to get the base ssl context in which to create the server socket. This is basically just
   * so we can have a custom location for key stores.
   */
  public SSLContext getSSLContext(String keyStoreName, String password) throws IOException {
    try {
      // Check the key manager factory
      KeyManagerFactory kmf = KeyManagerFactory.getInstance(this.keyManagerType);

      File ksFile = new File(keyStoreName);
      if (!ksFile.exists() || !ksFile.isFile())
        throw new WinstoneException(
            SSL_RESOURCES.getString("HttpsListener.KeyStoreNotFound", ksFile.getPath()));
      InputStream in = new FileInputStream(ksFile);
      char[] passwordChars = password == null ? null : password.toCharArray();
      KeyStore ks = KeyStore.getInstance("JKS");
      ks.load(in, passwordChars);
      kmf.init(ks, passwordChars);
      Logger.log(Logger.FULL_DEBUG, SSL_RESOURCES, "HttpsListener.KeyCount", ks.size() + "");
      for (Enumeration e = ks.aliases(); e.hasMoreElements(); ) {
        String alias = (String) e.nextElement();
        Logger.log(
            Logger.FULL_DEBUG,
            SSL_RESOURCES,
            "HttpsListener.KeyFound",
            new String[] {alias, ks.getCertificate(alias) + ""});
      }

      SSLContext context = SSLContext.getInstance("SSL");
      context.init(kmf.getKeyManagers(), null, null);
      Arrays.fill(passwordChars, 'x');
      return context;
    } catch (IOException err) {
      throw err;
    } catch (Throwable err) {
      throw new WinstoneException(
          SSL_RESOURCES.getString("HttpsListener.ErrorGettingContext"), err);
    }
  }
  protected boolean doRoleCheck(
      HttpServletRequest request, HttpServletResponse response, String pathRequested)
      throws IOException, ServletException {
    // Loop through constraints
    boolean foundApplicable = false;
    for (int n = 0; (n < this.constraints.length) && !foundApplicable; n++) {
      Logger.log(
          Logger.FULL_DEBUG,
          AUTH_RESOURCES,
          "BaseAuthenticationHandler.EvalConstraint",
          this.constraints[n].getName());

      // Find one that applies, then
      if (this.constraints[n].isApplicable(pathRequested, request.getMethod())) {
        Logger.log(
            Logger.FULL_DEBUG,
            AUTH_RESOURCES,
            "BaseAuthenticationHandler.ApplicableConstraint",
            this.constraints[n].getName());
        foundApplicable = true;

        if (this.constraints[n].needsSSL() && !request.isSecure()) {
          Logger.log(
              Logger.DEBUG,
              AUTH_RESOURCES,
              "BaseAuthenticationHandler.ConstraintNeedsSSL",
              this.constraints[n].getName());
          response.sendError(
              HttpServletResponse.SC_FORBIDDEN,
              AUTH_RESOURCES.getString(
                  "BaseAuthenticationHandler.ConstraintNeedsSSL", this.constraints[n].getName()));
          return false;
        } else if (!this.constraints[n].isAllowed(request)) {
          // Logger.log(Logger.FULL_DEBUG, "Not allowed - requesting auth");
          requestAuthentication(request, response, pathRequested);
          return false;
        } else {
          // Logger.log(Logger.FULL_DEBUG, "Allowed - authorization accepted");
          // Ensure that secured resources are not cached
          setNoCache(response);
        }
      }
    }

    // If we made it this far without a check being run, there must be none applicable
    Logger.log(Logger.FULL_DEBUG, AUTH_RESOURCES, "BaseAuthenticationHandler.PassedAuthCheck");
    return true;
  }
 private void log(int level, String msgKey, String arg[], Throwable err) {
   if (getLogWriter() != null) {
     getLogWriter().println(DS_RESOURCES.getString(msgKey, arg));
     if (err != null) {
       err.printStackTrace(getLogWriter());
     }
   } else {
     Logger.log(level, DS_RESOURCES, msgKey, arg, err);
   }
 }
  /**
   * Evaluates any authentication constraints, intercepting if auth is required. The relevant
   * authentication handler subclass's logic is used to actually authenticate.
   *
   * @return A boolean indicating whether to continue after this request
   */
  public boolean processAuthentication(
      ServletRequest inRequest, ServletResponse inResponse, String pathRequested)
      throws IOException, ServletException {
    Logger.log(Logger.FULL_DEBUG, AUTH_RESOURCES, "BaseAuthenticationHandler.StartAuthCheck");

    HttpServletRequest request = (HttpServletRequest) inRequest;
    HttpServletResponse response = (HttpServletResponse) inResponse;

    // Give previous attempts a chance to be validated
    if (!validatePossibleAuthenticationResponse(request, response, pathRequested)) {
      return false;
    } else {
      return doRoleCheck(request, response, pathRequested);
    }
  }
  /**
   * Gets the relevant list of objects from the args, validating against the web.xml nodes supplied.
   * All node addresses are assumed to be relative to the java:/comp/env context
   */
  public ContainerJNDIManager(Map args, List webXmlNodes, ClassLoader loader) {
    // Build all the objects we wanted
    this.objectsToCreate = new HashMap();

    Collection keys = new ArrayList(args != null ? args.keySet() : (Collection) new ArrayList());
    for (Iterator i = keys.iterator(); i.hasNext(); ) {
      String key = (String) i.next();

      if (key.startsWith("jndi.resource.")) {
        String resName = key.substring(14);
        String className = (String) args.get(key);
        String value = (String) args.get("jndi.param." + resName + ".value");
        Logger.log(
            Logger.FULL_DEBUG,
            JNDI_RESOURCES,
            "ContainerJNDIManager.CreatingResourceArgs",
            resName);
        Object obj = createObject(resName.trim(), className.trim(), value, args, loader);
        if (obj != null) this.objectsToCreate.put(resName, obj);
      }
    }
  }
  /** Build an object to insert into the jndi space */
  protected Object createObject(
      String name, String className, String value, Map args, ClassLoader loader) {

    if ((className == null) || (name == null)) return null;

    // Set context class loader
    ClassLoader cl = Thread.currentThread().getContextClassLoader();
    Thread.currentThread().setContextClassLoader(loader);

    try {
      // If we are working with a datasource
      if (className.equals("javax.sql.DataSource")) {
        try {
          return new WinstoneDataSource(name, extractRelevantArgs(args, name), loader);
        } catch (Throwable err) {
          Logger.log(
              Logger.ERROR,
              JNDI_RESOURCES,
              "ContainerJNDIManager.ErrorBuildingDatasource",
              name,
              err);
        }
      }

      // If we are working with a mail session
      else if (className.equals("javax.mail.Session")) {
        try {
          Class smtpClass = Class.forName(className, true, loader);
          Method smtpMethod =
              smtpClass.getMethod(
                  "getInstance",
                  new Class[] {Properties.class, Class.forName("javax.mail.Authenticator")});
          return smtpMethod.invoke(null, new Object[] {extractRelevantArgs(args, name), null});
          // return Session.getInstance(extractRelevantArgs(args, name), null);
        } catch (Throwable err) {
          Logger.log(
              Logger.ERROR,
              JNDI_RESOURCES,
              "ContainerJNDIManager.ErrorBuildingMailSession",
              name,
              err);
        }
      }

      // If unknown type, try to instantiate with the string constructor
      else if (value != null) {
        try {
          Class objClass = Class.forName(className.trim(), true, loader);
          Constructor objConstr = objClass.getConstructor(new Class[] {String.class});
          return objConstr.newInstance(new Object[] {value});
        } catch (Throwable err) {
          Logger.log(
              Logger.ERROR,
              JNDI_RESOURCES,
              "ContainerJNDIManager.ErrorBuildingObject",
              new String[] {name, className},
              err);
        }
      }

      return null;

    } finally {
      Thread.currentThread().setContextClassLoader(cl);
    }
  }
  /**
   * The maintenance thread. This makes sure that any changes in the files in the classpath trigger
   * a classLoader self destruct and recreate.
   */
  public void run() {
    Logger.log(Logger.FULL_DEBUG, CL_RESOURCES, "ReloadingClassLoader.MaintenanceThreadStarted");

    Map classDateTable = new HashMap();
    Map classLocationTable = new HashMap();
    Set lostClasses = new HashSet();
    while (!interrupted) {
      try {
        String loadedClassesCopy[] = null;
        synchronized (this) {
          loadedClassesCopy = (String[]) this.loadedClasses.toArray(new String[0]);
        }

        for (int n = 0; (n < loadedClassesCopy.length) && !interrupted; n++) {
          Thread.sleep(RELOAD_SEARCH_SLEEP);
          String className = transformToFileFormat(loadedClassesCopy[n]);
          File location = (File) classLocationTable.get(className);
          Long classDate = null;
          if ((location == null) || !location.exists()) {
            for (int j = 0; (j < this.classPaths.length) && (classDate == null); j++) {
              File path = this.classPaths[j];
              if (!path.exists()) {
                continue;
              } else if (path.isDirectory()) {
                File classLocation = new File(path, className);
                if (classLocation.exists()) {
                  classDate = new Long(classLocation.lastModified());
                  classLocationTable.put(className, classLocation);
                }
              } else if (path.isFile()) {
                classDate = searchJarPath(className, path);
                if (classDate != null) classLocationTable.put(className, path);
              }
            }
          } else if (location.exists()) classDate = new Long(location.lastModified());

          // Has class vanished ? Leave a note and skip over it
          if (classDate == null) {
            if (!lostClasses.contains(className)) {
              lostClasses.add(className);
              Logger.log(Logger.DEBUG, CL_RESOURCES, "ReloadingClassLoader.ClassLost", className);
            }
            continue;
          }
          if ((classDate != null) && lostClasses.contains(className)) {
            lostClasses.remove(className);
          }

          // Stash date of loaded files, and compare with last
          // iteration
          Long oldClassDate = (Long) classDateTable.get(className);
          if (oldClassDate == null) {
            classDateTable.put(className, classDate);
          } else if (oldClassDate.compareTo(classDate) != 0) {
            // Trigger reset of webAppConfig
            Logger.log(
                Logger.INFO,
                CL_RESOURCES,
                "ReloadingClassLoader.ReloadRequired",
                new String[] {
                  className,
                  "" + new Date(classDate.longValue()),
                  "" + new Date(oldClassDate.longValue())
                });
            this.webAppConfig.resetClassLoader();
          }
        }
      } catch (Throwable err) {
        Logger.log(Logger.ERROR, CL_RESOURCES, "ReloadingClassLoader.MaintenanceThreadError", err);
      }
    }
    Logger.log(Logger.FULL_DEBUG, CL_RESOURCES, "ReloadingClassLoader.MaintenanceThreadFinished");
  }