001/*
002 * Copyright 2002-2010 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *      https://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package org.springframework.jndi;
018
019import javax.naming.NamingException;
020
021import org.springframework.util.Assert;
022
023/**
024 * Convenient superclass for classes that can locate any number of JNDI objects.
025 * Derives from JndiAccessor to inherit the "jndiTemplate" and "jndiEnvironment"
026 * bean properties.
027 *
028 * <p>JNDI names may or may not include the "java:comp/env/" prefix expected
029 * by J2EE applications when accessing a locally mapped (ENC - Environmental
030 * Naming Context) resource. If it doesn't, the "java:comp/env/" prefix will
031 * be prepended if the "resourceRef" property is true (the default is
032 * <strong>false</strong>) and no other scheme (e.g. "java:") is given.
033 *
034 * @author Juergen Hoeller
035 * @since 1.1
036 * @see #setJndiTemplate
037 * @see #setJndiEnvironment
038 * @see #setResourceRef
039 */
040public abstract class JndiLocatorSupport extends JndiAccessor {
041
042        /** JNDI prefix used in a J2EE container */
043        public static final String CONTAINER_PREFIX = "java:comp/env/";
044
045
046        private boolean resourceRef = false;
047
048
049        /**
050         * Set whether the lookup occurs in a J2EE container, i.e. if the prefix
051         * "java:comp/env/" needs to be added if the JNDI name doesn't already
052         * contain it. Default is "false".
053         * <p>Note: Will only get applied if no other scheme (e.g. "java:") is given.
054         */
055        public void setResourceRef(boolean resourceRef) {
056                this.resourceRef = resourceRef;
057        }
058
059        /**
060         * Return whether the lookup occurs in a J2EE container.
061         */
062        public boolean isResourceRef() {
063                return this.resourceRef;
064        }
065
066
067        /**
068         * Perform an actual JNDI lookup for the given name via the JndiTemplate.
069   * <p>If the name doesn't begin with "java:comp/env/", this prefix is added
070         * if "resourceRef" is set to "true".
071         * @param jndiName the JNDI name to look up
072         * @return the obtained object
073         * @throws NamingException if the JNDI lookup failed
074         * @see #setResourceRef
075         */
076        protected Object lookup(String jndiName) throws NamingException {
077                return lookup(jndiName, null);
078        }
079
080        /**
081         * Perform an actual JNDI lookup for the given name via the JndiTemplate.
082         * <p>If the name doesn't begin with "java:comp/env/", this prefix is added
083         * if "resourceRef" is set to "true".
084         * @param jndiName the JNDI name to look up
085         * @param requiredType the required type of the object
086         * @return the obtained object
087         * @throws NamingException if the JNDI lookup failed
088         * @see #setResourceRef
089         */
090        protected <T> T lookup(String jndiName, Class<T> requiredType) throws NamingException {
091                Assert.notNull(jndiName, "'jndiName' must not be null");
092                String convertedName = convertJndiName(jndiName);
093                T jndiObject;
094                try {
095                        jndiObject = getJndiTemplate().lookup(convertedName, requiredType);
096                }
097                catch (NamingException ex) {
098                        if (!convertedName.equals(jndiName)) {
099                                // Try fallback to originally specified name...
100                                if (logger.isDebugEnabled()) {
101                                        logger.debug("Converted JNDI name [" + convertedName +
102                                                        "] not found - trying original name [" + jndiName + "]. " + ex);
103                                }
104                                jndiObject = getJndiTemplate().lookup(jndiName, requiredType);
105                        }
106                        else {
107                                throw ex;
108                        }
109                }
110                if (logger.isDebugEnabled()) {
111                        logger.debug("Located object with JNDI name [" + convertedName + "]");
112                }
113                return jndiObject;
114        }
115
116        /**
117         * Convert the given JNDI name into the actual JNDI name to use.
118         * <p>The default implementation applies the "java:comp/env/" prefix if
119         * "resourceRef" is "true" and no other scheme (e.g. "java:") is given.
120         * @param jndiName the original JNDI name
121         * @return the JNDI name to use
122         * @see #CONTAINER_PREFIX
123         * @see #setResourceRef
124         */
125        protected String convertJndiName(String jndiName) {
126                // Prepend container prefix if not already specified and no other scheme given.
127                if (isResourceRef() && !jndiName.startsWith(CONTAINER_PREFIX) && jndiName.indexOf(':') == -1) {
128                        jndiName = CONTAINER_PREFIX + jndiName;
129                }
130                return jndiName;
131        }
132
133}