001/*
002 * Copyright 2002-2018 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.beans.factory.InitializingBean;
022import org.springframework.lang.Nullable;
023import org.springframework.util.Assert;
024import org.springframework.util.StringUtils;
025
026/**
027 * Convenient superclass for JNDI-based service locators,
028 * providing configurable lookup of a specific JNDI resource.
029 *
030 * <p>Exposes a {@link #setJndiName "jndiName"} property. This may or may not
031 * include the "java:comp/env/" prefix expected by Java EE applications when
032 * accessing a locally mapped (Environmental Naming Context) resource. If it
033 * doesn't, the "java:comp/env/" prefix will be prepended if the "resourceRef"
034 * property is true (the default is <strong>false</strong>) and no other scheme
035 * (e.g. "java:") is given.
036 *
037 * <p>Subclasses may invoke the {@link #lookup()} method whenever it is appropriate.
038 * Some classes might do this on initialization, while others might do it
039 * on demand. The latter strategy is more flexible in that it allows for
040 * initialization of the locator before the JNDI object is available.
041 *
042 * @author Juergen Hoeller
043 * @since 1.1
044 * @see #setJndiName
045 * @see #setJndiTemplate
046 * @see #setJndiEnvironment
047 * @see #setResourceRef
048 * @see #lookup()
049 */
050public abstract class JndiObjectLocator extends JndiLocatorSupport implements InitializingBean {
051
052        @Nullable
053        private String jndiName;
054
055        @Nullable
056        private Class<?> expectedType;
057
058
059        /**
060         * Specify the JNDI name to look up. If it doesn't begin with "java:comp/env/"
061         * this prefix is added automatically if "resourceRef" is set to "true".
062         * @param jndiName the JNDI name to look up
063         * @see #setResourceRef
064         */
065        public void setJndiName(@Nullable String jndiName) {
066                this.jndiName = jndiName;
067        }
068
069        /**
070         * Return the JNDI name to look up.
071         */
072        @Nullable
073        public String getJndiName() {
074                return this.jndiName;
075        }
076
077        /**
078         * Specify the type that the located JNDI object is supposed
079         * to be assignable to, if any.
080         */
081        public void setExpectedType(@Nullable Class<?> expectedType) {
082                this.expectedType = expectedType;
083        }
084
085        /**
086         * Return the type that the located JNDI object is supposed
087         * to be assignable to, if any.
088         */
089        @Nullable
090        public Class<?> getExpectedType() {
091                return this.expectedType;
092        }
093
094        @Override
095        public void afterPropertiesSet() throws IllegalArgumentException, NamingException {
096                if (!StringUtils.hasLength(getJndiName())) {
097                        throw new IllegalArgumentException("Property 'jndiName' is required");
098                }
099        }
100
101
102        /**
103         * Perform the actual JNDI lookup for this locator's target resource.
104         * @return the located target object
105         * @throws NamingException if the JNDI lookup failed or if the
106         * located JNDI object is not assignable to the expected type
107         * @see #setJndiName
108         * @see #setExpectedType
109         * @see #lookup(String, Class)
110         */
111        protected Object lookup() throws NamingException {
112                String jndiName = getJndiName();
113                Assert.state(jndiName != null, "No JNDI name specified");
114                return lookup(jndiName, getExpectedType());
115        }
116
117}