/* * 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.apache.harmony.jndi.provider.ldap; import java.lang.reflect.Constructor; import java.util.HashMap; import java.util.Hashtable; import javax.naming.AuthenticationException; import javax.naming.AuthenticationNotSupportedException; import javax.naming.CommunicationException; import javax.naming.ConfigurationException; import javax.naming.Context; import javax.naming.ContextNotEmptyException; import javax.naming.InvalidNameException; import javax.naming.LimitExceededException; import javax.naming.Name; import javax.naming.NameAlreadyBoundException; import javax.naming.NameNotFoundException; import javax.naming.NamingException; import javax.naming.NoPermissionException; import javax.naming.OperationNotSupportedException; import javax.naming.PartialResultException; import javax.naming.ServiceUnavailableException; import javax.naming.SizeLimitExceededException; import javax.naming.TimeLimitExceededException; import javax.naming.directory.AttributeInUseException; import javax.naming.directory.InvalidAttributeIdentifierException; import javax.naming.directory.InvalidAttributeValueException; import javax.naming.directory.InvalidSearchFilterException; import javax.naming.directory.NoSuchAttributeException; import javax.naming.directory.SchemaViolationException; import javax.naming.ldap.LdapName; import javax.net.SocketFactory; import javax.net.ssl.SSLSocketFactory; import org.apache.harmony.jndi.internal.nls.Messages; import org.apache.harmony.jndi.provider.ldap.parser.FilterParser; import org.apache.harmony.jndi.provider.ldap.parser.LdapUrlParser; import org.apache.harmony.jndi.provider.ldap.parser.ParseException; @SuppressWarnings("boxing") public class LdapUtils { private static HashMap<Integer, Class<?>> errorCodesMap = new HashMap<Integer, Class<?>>(); static { errorCodesMap.put(1, NamingException.class); errorCodesMap.put(2, CommunicationException.class); errorCodesMap.put(3, TimeLimitExceededException.class); errorCodesMap.put(4, SizeLimitExceededException.class); errorCodesMap.put(7, AuthenticationNotSupportedException.class); errorCodesMap.put(8, AuthenticationNotSupportedException.class); errorCodesMap.put(9, PartialResultException.class); errorCodesMap.put(11, LimitExceededException.class); errorCodesMap.put(12, OperationNotSupportedException.class); errorCodesMap.put(13, AuthenticationNotSupportedException.class); errorCodesMap.put(16, NoSuchAttributeException.class); errorCodesMap.put(17, InvalidAttributeIdentifierException.class); errorCodesMap.put(18, InvalidSearchFilterException.class); errorCodesMap.put(19, InvalidAttributeValueException.class); errorCodesMap.put(20, AttributeInUseException.class); errorCodesMap.put(21, InvalidAttributeValueException.class); errorCodesMap.put(32, NameNotFoundException.class); errorCodesMap.put(33, NamingException.class); errorCodesMap.put(34, InvalidNameException.class); errorCodesMap.put(36, NamingException.class); errorCodesMap.put(48, AuthenticationNotSupportedException.class); errorCodesMap.put(49, AuthenticationException.class); errorCodesMap.put(50, NoPermissionException.class); errorCodesMap.put(51, ServiceUnavailableException.class); errorCodesMap.put(52, ServiceUnavailableException.class); errorCodesMap.put(53, OperationNotSupportedException.class); errorCodesMap.put(54, NamingException.class); errorCodesMap.put(64, InvalidNameException.class); errorCodesMap.put(65, SchemaViolationException.class); errorCodesMap.put(66, ContextNotEmptyException.class); errorCodesMap.put(67, SchemaViolationException.class); errorCodesMap.put(68, NameAlreadyBoundException.class); errorCodesMap.put(69, SchemaViolationException.class); errorCodesMap.put(71, NamingException.class); errorCodesMap.put(80, NamingException.class); } public static Filter parseFilter(String filter, Object[] args) throws InvalidSearchFilterException { if (filter == null) { // ldap.28=Parameter of filter should not be null throw new NullPointerException(Messages.getString("ldap.28")); //$NON-NLS-1$ } FilterParser parser = new FilterParser(filter); if (args == null) { args = new Object[0]; } parser.setArgs(args); try { return parser.parse(); } catch (ParseException e) { // ldap.29=Invalid search filter InvalidSearchFilterException ex = new InvalidSearchFilterException( Messages.getString("ldap.29")); //$NON-NLS-1$ ex.setRootCause(e); throw ex; } } public static LdapUrlParser parserURL(String url, boolean isAllowedQuery) throws InvalidNameException { if (url == null) { // ldap.2B=LDAP URL should not be null throw new NullPointerException(Messages.getString("ldap.2B")); //$NON-NLS-1$ } LdapUrlParser parser = new LdapUrlParser(url); try { parser.parseURL(); } catch (ParseException e) { // ldap.2C=Invalid LDAP URL IllegalArgumentException ex = new IllegalArgumentException(Messages .getString("ldap.2C")); //$NON-NLS-1$ ex.initCause(e); throw ex; } if (!isAllowedQuery && (parser.getFilter() != null || parser.getControls() != null)) { // ldap.2D=LDAP URL may only contain host, port and dn components throw new InvalidNameException(Messages.getString("ldap.2D")); //$NON-NLS-1$ } return parser; } public static NamingException getExceptionFromResult(LdapResult result) { int errorCode = result.getResultCode(); // 0 means successful if (errorCode == 0) { return null; } Class<?> exceptionClass = errorCodesMap.get(errorCode); // not in map, using NamingException if (exceptionClass == null) { exceptionClass = NamingException.class; } try { Constructor<?> constructor = exceptionClass .getConstructor(new Class[] { String.class }); String message = null; if (result.getErrorMessage() != null && !result.getErrorMessage().equals("")) { //$NON-NLS-1$ // ldap.34=[LDAP: error code {0} - {1}] message = Messages.getString("ldap.34", new Object[] { //$NON-NLS-1$ errorCode, result.getErrorMessage() }); } else { // ldap.35=[LDAP: error code {0}] message = Messages.getString("ldap.35", //$NON-NLS-1$ new Object[] { errorCode }); } return (NamingException) constructor .newInstance(new Object[] { message }); } catch (Exception e) { // ldap.35=[LDAP: error code {0}] return new NamingException(Messages.getString("ldap.35", //$NON-NLS-1$ new Object[] { errorCode })); } } /** * convert absolute dn to the dn relatived to the dn of * <code>targetContextDN</code>. * * @param dn * absolute dn * @param base * base dn of the relative name * @return dn relatived to the <code>dn</code> of <code>base</code> * @throws NamingException * @throws InvalidNameException */ public static String convertToRelativeName(String dn, String base) throws InvalidNameException, NamingException { return convertToRelativeName(new LdapName(dn), new LdapName(base)) .toString(); } public static LdapName convertToRelativeName(LdapName dn, LdapName base) throws NamingException { if (base.size() == 0) { return dn; } if (dn.size() < base.size()) { // TODO add error message throw new NamingException(""); } Name prefix = dn.getPrefix(base.size()); if (!prefix.equals(base)) { // TODO add error message throw new NamingException(""); } return (LdapName) dn.getSuffix(base.size()); } /** * Get SocketFactory according three properties: * "java.naming.ldap.factory.socket", "java.naming.security.protocol" and * protocol defined in URL. If "java.naming.ldap.factory.socket" set, then * use it. otherwise check protocol defined in URL: "ldaps" use * <code>SSLSocketFactory.getDefault()</code> to retrieve factory; If is * "ldap", check whether "java.naming.security.protocol" is set to "ssl", if * set, use <code>SSLSocketFactory.getDefault()</code> get factory. * * @param envmt * @param isLdaps * @return * @throws ConfigurationException */ public static SocketFactory getSocketFactory(Hashtable<?, ?> envmt, boolean isLdaps) throws ConfigurationException { String factoryName = (String) envmt .get("java.naming.ldap.factory.socket"); SocketFactory factory = null; // if "java.naming.ldap.factory.socket" set, use it if (factoryName != null && !("".equals(factoryName))) { try { factory = (SocketFactory) classForName(factoryName) .newInstance(); } catch (Exception e) { ConfigurationException ex = new ConfigurationException(); ex.setRootCause(e); throw ex; } } // factory name not set if (factory == null) { if (isLdaps) { factory = SSLSocketFactory.getDefault(); } // It's case sensitive in RI else if ("ssl".equalsIgnoreCase((String) envmt .get(Context.SECURITY_PROTOCOL))) { factory = SSLSocketFactory.getDefault(); } else { factory = SocketFactory.getDefault(); } } return factory; } public static boolean isLdapsURL(String url) { return url.toLowerCase().startsWith("ldaps://"); } private static Class<?> classForName(final String className) throws ClassNotFoundException { Class<?> cls = null; // try thread context class loader first try { cls = Class.forName(className, true, Thread.currentThread() .getContextClassLoader()); } catch (ClassNotFoundException e) { // try system class loader second cls = Class.forName(className, true, ClassLoader .getSystemClassLoader()); } return cls; } }