Coverage Report - org.apache.shiro.jndi.JndiTemplate
 
Classes in this File Line Coverage Branch Coverage Complexity
JndiTemplate
7%
3/41
0%
0/8
1.6
JndiTemplate$1
0%
0/5
0%
0/2
1.6
JndiTemplate$2
0%
0/3
N/A
1.6
JndiTemplate$3
0%
0/3
N/A
1.6
JndiTemplate$4
0%
0/3
N/A
1.6
 
 1  
 /*
 2  
  * Licensed to the Apache Software Foundation (ASF) under one
 3  
  * or more contributor license agreements.  See the NOTICE file
 4  
  * distributed with this work for additional information
 5  
  * regarding copyright ownership.  The ASF licenses this file
 6  
  * to you under the Apache License, Version 2.0 (the
 7  
  * "License"); you may not use this file except in compliance
 8  
  * with the License.  You may obtain a copy of the License at
 9  
  *
 10  
  *     http://www.apache.org/licenses/LICENSE-2.0
 11  
  *
 12  
  * Unless required by applicable law or agreed to in writing,
 13  
  * software distributed under the License is distributed on an
 14  
  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 15  
  * KIND, either express or implied.  See the License for the
 16  
  * specific language governing permissions and limitations
 17  
  * under the License.
 18  
  */
 19  
 package org.apache.shiro.jndi;
 20  
 
 21  
 import java.util.Enumeration;
 22  
 import java.util.Hashtable;
 23  
 import java.util.Properties;
 24  
 import javax.naming.Context;
 25  
 import javax.naming.InitialContext;
 26  
 import javax.naming.NameNotFoundException;
 27  
 import javax.naming.NamingException;
 28  
 
 29  
 import org.slf4j.Logger;
 30  
 import org.slf4j.LoggerFactory;
 31  
 
 32  
 /**
 33  
  * Helper class that simplifies JNDI operations. It provides methods to lookup and
 34  
  * bind objects, and allows implementations of the {@link JndiCallback} interface
 35  
  * to perform any operation they like with a JNDI naming context provided.
 36  
  * <p/>
 37  
  * <p>Note that this implementation is an almost exact copy of the Spring Framework's identically named class from
 38  
  * their 2.5.4 distribution - we didn't want to re-invent the wheel, but not require a full dependency on the
 39  
  * Spring framework, nor does Spring make available only its JNDI classes in a small jar, or we would have used that.
 40  
  * Since Shiro is also Apache 2.0 licensed, all regular licenses and conditions and authors have remained in tact.
 41  
  *
 42  
  * @see JndiCallback
 43  
  * @see #execute
 44  
  */
 45  
 public class JndiTemplate {
 46  
 
 47  1
     private static final Logger log = LoggerFactory.getLogger(JndiTemplate.class);
 48  
 
 49  
     private Properties environment;
 50  
 
 51  
     /** Create a new JndiTemplate instance. */
 52  4
     public JndiTemplate() {
 53  4
     }
 54  
 
 55  
     /**
 56  
      * Create a new JndiTemplate instance, using the given environment.
 57  
      *
 58  
      * @param environment the Properties to initialize with
 59  
      */
 60  0
     public JndiTemplate(Properties environment) {
 61  0
         this.environment = environment;
 62  0
     }
 63  
 
 64  
     /**
 65  
      * Set the environment for the JNDI InitialContext.
 66  
      *
 67  
      * @param environment the Properties to initialize with
 68  
      */
 69  
     public void setEnvironment(Properties environment) {
 70  0
         this.environment = environment;
 71  0
     }
 72  
 
 73  
     /**
 74  
      * Return the environment for the JNDI InitialContext, or <code>null</code> if none should be used.
 75  
      *
 76  
      * @return the environment for the JNDI InitialContext, or <code>null</code> if none should be used.
 77  
      */
 78  
     public Properties getEnvironment() {
 79  0
         return this.environment;
 80  
     }
 81  
 
 82  
     /**
 83  
      * Execute the given JNDI context callback implementation.
 84  
      *
 85  
      * @param contextCallback JndiCallback implementation
 86  
      * @return a result object returned by the callback, or <code>null</code>
 87  
      * @throws NamingException thrown by the callback implementation
 88  
      * @see #createInitialContext
 89  
      */
 90  
     public Object execute(JndiCallback contextCallback) throws NamingException {
 91  0
         Context ctx = createInitialContext();
 92  
         try {
 93  0
             return contextCallback.doInContext(ctx);
 94  
         }
 95  
         finally {
 96  0
             try {
 97  0
                 ctx.close();
 98  0
             } catch (NamingException ex) {
 99  0
                 log.debug("Could not close JNDI InitialContext", ex);
 100  0
             }
 101  
         }
 102  
     }
 103  
 
 104  
     /**
 105  
      * Create a new JNDI initial context. Invoked by {@link #execute}.
 106  
      * <p>The default implementation use this template's environment settings.
 107  
      * Can be subclassed for custom contexts, e.g. for testing.
 108  
      *
 109  
      * @return the initial Context instance
 110  
      * @throws NamingException in case of initialization errors
 111  
      */
 112  
     @SuppressWarnings({"unchecked"})
 113  
     protected Context createInitialContext() throws NamingException {
 114  0
         Properties env = getEnvironment();
 115  0
         Hashtable icEnv = null;
 116  0
         if (env != null) {
 117  0
             icEnv = new Hashtable(env.size());
 118  0
             for (Enumeration en = env.propertyNames(); en.hasMoreElements();) {
 119  0
                 String key = (String) en.nextElement();
 120  0
                 icEnv.put(key, env.getProperty(key));
 121  0
             }
 122  
         }
 123  0
         return new InitialContext(icEnv);
 124  
     }
 125  
 
 126  
     /**
 127  
      * Look up the object with the given name in the current JNDI context.
 128  
      *
 129  
      * @param name the JNDI name of the object
 130  
      * @return object found (cannot be <code>null</code>; if a not so well-behaved
 131  
      *         JNDI implementations returns null, a NamingException gets thrown)
 132  
      * @throws NamingException if there is no object with the given
 133  
      *                         name bound to JNDI
 134  
      */
 135  
     public Object lookup(final String name) throws NamingException {
 136  0
         log.debug("Looking up JNDI object with name '{}'", name);
 137  0
         return execute(new JndiCallback() {
 138  
             public Object doInContext(Context ctx) throws NamingException {
 139  0
                 Object located = ctx.lookup(name);
 140  0
                 if (located == null) {
 141  0
                     throw new NameNotFoundException(
 142  
                             "JNDI object with [" + name + "] not found: JNDI implementation returned null");
 143  
                 }
 144  0
                 return located;
 145  
             }
 146  
         });
 147  
     }
 148  
 
 149  
     /**
 150  
      * Look up the object with the given name in the current JNDI context.
 151  
      *
 152  
      * @param name         the JNDI name of the object
 153  
      * @param requiredType type the JNDI object must match. Can be an interface or
 154  
      *                     superclass of the actual class, or <code>null</code> for any match. For example,
 155  
      *                     if the value is <code>Object.class</code>, this method will succeed whatever
 156  
      *                     the class of the returned instance.
 157  
      * @return object found (cannot be <code>null</code>; if a not so well-behaved
 158  
      *         JNDI implementations returns null, a NamingException gets thrown)
 159  
      * @throws NamingException if there is no object with the given
 160  
      *                         name bound to JNDI
 161  
      */
 162  
     public Object lookup(String name, Class requiredType) throws NamingException {
 163  0
         Object jndiObject = lookup(name);
 164  0
         if (requiredType != null && !requiredType.isInstance(jndiObject)) {
 165  0
             String msg = "Jndi object acquired under name '" + name + "' is of type [" +
 166  
                     jndiObject.getClass().getName() + "] and not assignable to the required type [" +
 167  
                     requiredType.getName() + "].";
 168  0
             throw new NamingException(msg);
 169  
         }
 170  0
         return jndiObject;
 171  
     }
 172  
 
 173  
     /**
 174  
      * Bind the given object to the current JNDI context, using the given name.
 175  
      *
 176  
      * @param name   the JNDI name of the object
 177  
      * @param object the object to bind
 178  
      * @throws NamingException thrown by JNDI, mostly name already bound
 179  
      */
 180  
     public void bind(final String name, final Object object) throws NamingException {
 181  0
         log.debug("Binding JNDI object with name '{}'", name);
 182  0
         execute(new JndiCallback() {
 183  
             public Object doInContext(Context ctx) throws NamingException {
 184  0
                 ctx.bind(name, object);
 185  0
                 return null;
 186  
             }
 187  
         });
 188  0
     }
 189  
 
 190  
     /**
 191  
      * Rebind the given object to the current JNDI context, using the given name.
 192  
      * Overwrites any existing binding.
 193  
      *
 194  
      * @param name   the JNDI name of the object
 195  
      * @param object the object to rebind
 196  
      * @throws NamingException thrown by JNDI
 197  
      */
 198  
     public void rebind(final String name, final Object object) throws NamingException {
 199  0
         log.debug("Rebinding JNDI object with name '{}'", name);
 200  0
         execute(new JndiCallback() {
 201  
             public Object doInContext(Context ctx) throws NamingException {
 202  0
                 ctx.rebind(name, object);
 203  0
                 return null;
 204  
             }
 205  
         });
 206  0
     }
 207  
 
 208  
     /**
 209  
      * Remove the binding for the given name from the current JNDI context.
 210  
      *
 211  
      * @param name the JNDI name of the object
 212  
      * @throws NamingException thrown by JNDI, mostly name not found
 213  
      */
 214  
     public void unbind(final String name) throws NamingException {
 215  0
         log.debug("Unbinding JNDI object with name '{}'", name);
 216  0
         execute(new JndiCallback() {
 217  
             public Object doInContext(Context ctx) throws NamingException {
 218  0
                 ctx.unbind(name);
 219  0
                 return null;
 220  
             }
 221  
         });
 222  0
     }
 223  
 
 224  
 }