001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS"
013: * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.jetspeed.security.spi.impl.ldap;
018:
019: import java.lang.reflect.InvocationHandler;
020: import java.lang.reflect.InvocationTargetException;
021: import java.lang.reflect.Method;
022: import java.lang.reflect.Proxy;
023: import java.util.Properties;
024:
025: import javax.naming.CommunicationException;
026: import javax.naming.Context;
027: import javax.naming.NamingException;
028: import javax.naming.ServiceUnavailableException;
029: import javax.naming.ldap.InitialLdapContext;
030: import javax.naming.ldap.LdapContext;
031:
032: import org.apache.commons.lang.StringUtils;
033:
034: /**
035: * Proxy providing recoverable LdapContext connections.
036: *
037: * @author <a href="mailto:ate@douma.nu">Ate Douma</a>
038: * @version $Id: LdapContextProxy.java 516448 2007-03-09 16:25:47Z ate $
039: */
040: public class LdapContextProxy implements InvocationHandler {
041: private Properties env;
042: private LdapContext ctx;
043:
044: public static LdapContext createProxy(LdapBindingConfig config) {
045: LdapContext proxy = config.getContext();
046:
047: if (proxy == null
048: || !(Proxy.getInvocationHandler(proxy) instanceof LdapContextProxy)) {
049: proxy = (LdapContext) Proxy.newProxyInstance(
050: LdapContext.class.getClassLoader(),
051: new Class[] { LdapContext.class },
052: new LdapContextProxy(config));
053: config.setContext(proxy);
054: }
055: return proxy;
056: }
057:
058: private LdapContextProxy(LdapBindingConfig ldapBindingConfig) {
059: env = new Properties();
060: env.put(Context.INITIAL_CONTEXT_FACTORY, ldapBindingConfig
061: .getInitialContextFactory());
062: env.put(Context.PROVIDER_URL, ldapBindingConfig.getLdapScheme()
063: + "://" + ldapBindingConfig.getLdapServerName() + ":"
064: + ldapBindingConfig.getLdapServerPort() + "/"
065: + ldapBindingConfig.getRootContext());
066: env.put(Context.SECURITY_PRINCIPAL, ldapBindingConfig
067: .getRootDn());
068: env.put(Context.SECURITY_CREDENTIALS, ldapBindingConfig
069: .getRootPassword());
070: env.put(Context.SECURITY_AUTHENTICATION, ldapBindingConfig
071: .getLdapSecurityLevel());
072: if (!StringUtils.isEmpty(ldapBindingConfig
073: .getLdapSecurityProtocol())) {
074: env.put(Context.SECURITY_PROTOCOL, ldapBindingConfig
075: .getLdapSecurityProtocol());
076: }
077: if (!StringUtils.isEmpty(ldapBindingConfig
078: .getLdapSocketFactory())) {
079: env.put("java.naming.ldap.factory.socket",
080: ldapBindingConfig.getLdapSocketFactory());
081: }
082: }
083:
084: private LdapContext getCtx() throws NamingException {
085: if (ctx == null) {
086: ctx = new InitialLdapContext(env, null);
087: }
088: return ctx;
089: }
090:
091: private void closeCtx() {
092: if (ctx != null) {
093: try {
094: ctx.close();
095: } catch (Exception e) {
096: }
097: ctx = null;
098: }
099: }
100:
101: /*
102: * (non-Javadoc)
103: *
104: * @see java.lang.reflect.InvocationHandler#invoke(java.lang.Object,
105: * java.lang.reflect.Method, java.lang.Object[])
106: */
107: public synchronized Object invoke(Object proxy, Method m,
108: Object[] args) throws Throwable {
109: Object result = null;
110: boolean close = "close".equals(m.getName()) && args.length == 0;
111: if (close && ctx == null) {
112: // don't need to do anything
113: ;
114: } else {
115: LdapContext ctx = getCtx();
116:
117: try {
118: result = m.invoke(ctx, args);
119: if (close) {
120: closeCtx();
121: }
122: } catch (Throwable t) {
123: closeCtx();
124:
125: if (t instanceof InvocationTargetException) {
126: t = ((InvocationTargetException) t)
127: .getTargetException();
128: }
129: if (t instanceof ServiceUnavailableException
130: || t instanceof CommunicationException) {
131: try {
132: ctx = getCtx();
133: result = m.invoke(ctx, args);
134: } catch (Throwable t2) {
135: closeCtx();
136: if (t2 instanceof InvocationTargetException) {
137: t2 = ((InvocationTargetException) t2)
138: .getTargetException();
139: }
140:
141: throw t2;
142: }
143: }
144: throw t;
145: }
146: }
147: return result;
148: }
149: }
|