/**
   * Crete a new Resource env instance.
   *
   * @param obj The reference object describing the DataSource
   */
  public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable environment)
      throws Exception {

    if (obj instanceof ResourceEnvRef) {
      Reference ref = (Reference) obj;
      ObjectFactory factory = null;
      RefAddr factoryRefAddr = ref.get(Constants.FACTORY);
      if (factoryRefAddr != null) {
        // Using the specified factory
        String factoryClassName = factoryRefAddr.getContent().toString();
        // Loading factory
        ClassLoader tcl = Thread.currentThread().getContextClassLoader();
        Class factoryClass = null;
        if (tcl != null) {
          try {
            factoryClass = tcl.loadClass(factoryClassName);
          } catch (ClassNotFoundException e) {
            NamingException ex = new NamingException("Could not load resource factory class");
            ex.initCause(e);
            throw ex;
          }
        } else {
          try {
            factoryClass = Class.forName(factoryClassName);
          } catch (ClassNotFoundException e) {
            NamingException ex = new NamingException("Could not load resource factory class");
            ex.initCause(e);
            throw ex;
          }
        }
        if (factoryClass != null) {
          try {
            factory = (ObjectFactory) factoryClass.newInstance();
          } catch (Throwable t) {
            if (t instanceof NamingException) throw (NamingException) t;
            NamingException ex = new NamingException("Could not create resource factory instance");
            ex.initCause(t);
            throw ex;
          }
        }
      }
      // Note: No defaults here
      if (factory != null) {
        return factory.getObjectInstance(obj, name, nameCtx, environment);
      } else {
        throw new NamingException("Cannot create resource instance");
      }
    }

    return null;
  }
示例#2
0
  @Override
  public Object getObjectInstance(
      Object obj, Name name, Context nameCtx, Hashtable<?, ?> environment) throws Exception {
    // What kind of resource should we create?
    JndiResourceDescriptor resource = (JndiResourceDescriptor) obj;

    // Get class loader, we'll need it to load the factory class
    Class<?> factoryClass = null;
    ObjectFactory factory = null;

    try {
      factoryClass = clResourceClasses.loadClass(resource.getFactoryClassName());
    } catch (ClassNotFoundException e) {
      NamingException ex =
          new NamingException("Could not find resource or resource factory class in the classpath");
      ex.initCause(e);
      throw ex;
    } catch (Exception e) {
      NamingException ex =
          new NamingException(
              "Could not load resource or resource factory class for an unknown reason");
      ex.initCause(e);
      throw ex;
    }

    try {
      factory = (ObjectFactory) factoryClass.newInstance();
    } catch (Exception e) {
      NamingException ex = new NamingException("Could not create resource factory instance");
      ex.initCause(e);
      throw ex;
    }

    Object result = null;
    try {
      result = factory.getObjectInstance(obj, name, nameCtx, environment);
    } catch (Exception e) {
      NamingException ex =
          new NamingException(
              "Could not create object resource from resource factory. JNDI definition & parameters may be incorrect.");
      ex.initCause(e);
      throw ex;
    }
    return result;
  }
  /**
   * This is just a commodity method used to try to get an InitialLdapContext.
   *
   * @param t the Thread to be used to create the InitialLdapContext.
   * @param pair an Object[] array that contains the InitialLdapContext and the Throwable if any
   *     occurred.
   * @param timeout the timeout in milliseconds. If we do not get to create the connection before
   *     the timeout a CommunicationException will be thrown.
   * @return the created InitialLdapContext
   * @throws NamingException if something goes wrong during the creation.
   */
  private static InitialLdapContext getInitialLdapContext(Thread t, Object[] pair, int timeout)
      throws NamingException {
    try {
      if (timeout > 0) {
        t.start();
        t.join(timeout);
      } else {
        t.run();
      }

    } catch (InterruptedException x) {
      // This might happen for problems in sockets
      // so it does not necessarily imply a bug
    }

    boolean throwException = false;

    if ((timeout > 0) && t.isAlive()) {
      t.interrupt();
      try {
        t.join(2000);
      } catch (InterruptedException x) {
        // This might happen for problems in sockets
        // so it does not necessarily imply a bug
      }
      throwException = true;
    }

    if ((pair[0] == null) && (pair[1] == null)) {
      throwException = true;
    }

    if (throwException) {
      NamingException xx;
      ConnectException x = new ConnectException("Connection timed out");
      xx = new CommunicationException("Connection timed out");
      xx.initCause(x);
      throw xx;
    }

    if (pair[1] != null) {
      if (pair[1] instanceof NamingException) {
        throw (NamingException) pair[1];

      } else if (pair[1] instanceof RuntimeException) {
        throw (RuntimeException) pair[1];

      } else if (pair[1] instanceof Throwable) {
        throw new IllegalStateException("Unexpected throwable occurred", (Throwable) pair[1]);
      }
    }
    return (InitialLdapContext) pair[0];
  }
  /**
   * Binds a name to an object, along with associated attributes, overwriting any existing binding.
   * If attrs is null and obj is a DirContext, the attributes from obj are used. If attrs is null
   * and obj is not a DirContext, any existing attributes associated with the object already bound
   * in the directory remain unchanged. If attrs is non-null, any existing attributes associated
   * with the object already bound in the directory are removed and attrs is associated with the
   * named object. If obj is a DirContext and attrs is non-null, the attributes of obj are ignored.
   *
   * @param name the name to bind; may not be empty
   * @param obj the object to bind; possibly null
   * @param attrs the attributes to associate with the binding
   * @exception javax.naming.directory.InvalidAttributesException if some "mandatory" attributes of
   *     the binding are not supplied
   * @exception NamingException if a naming exception is encountered
   */
  @Override
  public void rebind(String name, Object obj, Attributes attrs) throws NamingException {

    // Note: No custom attributes allowed
    // Check obj type

    File file = new File(base, name);

    InputStream is = null;
    if (obj instanceof Resource) {
      try {
        is = ((Resource) obj).streamContent();
      } catch (IOException e) {
        // Ignore
      }
    } else if (obj instanceof InputStream) {
      is = (InputStream) obj;
    } else if (obj instanceof DirContext) {
      if (file.exists()) {
        if (!file.delete()) throw new NamingException(sm.getString("resources.bindFailed", name));
      }
      if (!file.mkdir()) throw new NamingException(sm.getString("resources.bindFailed", name));
    }
    if (is == null) throw new NamingException(sm.getString("resources.bindFailed", name));

    // Open os

    try {
      FileOutputStream os = null;
      byte buffer[] = new byte[BUFFER_SIZE];
      int len = -1;
      try {
        os = new FileOutputStream(file);
        while (true) {
          len = is.read(buffer);
          if (len == -1) break;
          os.write(buffer, 0, len);
        }
      } finally {
        if (os != null) os.close();
        is.close();
      }
    } catch (IOException e) {
      NamingException ne = new NamingException(sm.getString("resources.bindFailed", e));
      ne.initCause(e);
      throw ne;
    }
  }
    /**
     * Use DNS and obtains the LDAP servers that we should try.
     *
     * @param preferredServers If non-null, these servers are reported instead of doing the
     *     discovery. In previous versions, this was simply added on top of the auto-discovered
     *     list, but this option is useful when you have many domain controllers (because a single
     *     mistyped password can cause an authentication attempt with every listed server, which can
     *     lock the user out!) This also puts this feature in alignment with {@link
     *     #DOMAIN_CONTROLLERS}, which seems to indicate that there are users who prefer this
     *     behaviour.
     * @return A list with at least one item.
     */
    public List<SocketInfo> obtainLDAPServer(
        DirContext ictx, String domainName, String site, String preferredServers)
        throws NamingException {
      List<SocketInfo> result = new ArrayList<SocketInfo>();
      if (preferredServers == null) preferredServers = DOMAIN_CONTROLLERS;

      if (preferredServers != null) {
        for (String token : preferredServers.split(",")) {
          result.add(new SocketInfo(token.trim()));
        }
        return result;
      }

      String ldapServer = null;
      Attribute a = null;
      NamingException failure = null;

      // try global catalog if it exists first, then the particular domain
      for (String candidate : CANDIDATES) {
        ldapServer = candidate + (site != null ? site + "._sites." : "") + domainName;
        LOGGER.fine("Attempting to resolve " + ldapServer + " to SRV record");
        try {
          Attributes attributes = ictx.getAttributes(ldapServer, new String[] {"SRV"});
          a = attributes.get("SRV");
          if (a != null) break;
        } catch (NamingException e) {
          // failed retrieval. try next option.
          failure = e;
        }
      }

      if (a != null) {
        // discover servers
        class PrioritizedSocketInfo implements Comparable<PrioritizedSocketInfo> {
          SocketInfo socket;
          int priority;

          PrioritizedSocketInfo(SocketInfo socket, int priority) {
            this.socket = socket;
            this.priority = priority;
          }

          public int compareTo(PrioritizedSocketInfo that) {
            return that.priority - this.priority; // sort them so that bigger priority comes first
          }
        }
        List<PrioritizedSocketInfo> plist = new ArrayList<PrioritizedSocketInfo>();
        for (NamingEnumeration ne = a.getAll(); ne.hasMoreElements(); ) {
          String record = ne.next().toString();
          LOGGER.fine("SRV record found: " + record);
          String[] fields = record.split(" ");
          // fields[1]: weight
          // fields[2]: port
          // fields[3]: target host name

          String hostName = fields[3];
          // cut off trailing ".". JENKINS-2647
          if (hostName.endsWith(".")) hostName = hostName.substring(0, hostName.length() - 1);
          int port = Integer.parseInt(fields[2]);
          if (FORCE_LDAPS) {
            // map to LDAPS ports. I don't think there's any SRV records specifically for LDAPS.
            // I think Microsoft considers LDAP+TLS the way to go, or else there should have been
            // separate SRV entries.
            if (port == 389) port = 686;
            if (port == 3268) port = 3269;
          }
          int p = Integer.parseInt(fields[0]);
          plist.add(new PrioritizedSocketInfo(new SocketInfo(hostName, port), p));
        }
        Collections.sort(plist);
        for (PrioritizedSocketInfo psi : plist) result.add(psi.socket);
      }

      if (result.isEmpty()) {
        NamingException x = new NamingException("No SRV record found for " + ldapServer);
        if (failure != null) x.initCause(failure);
        throw x;
      }

      LOGGER.fine(ldapServer + " resolved to " + result);
      return result;
    }
示例#6
0
 /**
  * Return a general naming exception with a root cause.
  *
  * @param message the message
  * @param cause the exception cause, or {@code null} for none
  * @return the exception
  */
 public static NamingException namingException(final String message, final Throwable cause) {
   final NamingException exception = new NamingException(message);
   if (cause != null) exception.initCause(cause);
   return exception;
 }