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" BASIS, 013 * 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 018 package org.apache.logging.log4j.core.net; 019 020 import java.util.Properties; 021 022 import javax.naming.Context; 023 import javax.naming.InitialContext; 024 import javax.naming.NamingException; 025 026 import org.apache.logging.log4j.core.appender.AbstractManager; 027 import org.apache.logging.log4j.core.appender.ManagerFactory; 028 import org.apache.logging.log4j.core.util.JndiCloser; 029 030 /** 031 * JNDI {@link javax.naming.Context} manager. 032 * 033 * @since 2.1 034 */ 035 public class JndiManager extends AbstractManager { 036 037 private static final JndiManagerFactory FACTORY = new JndiManagerFactory(); 038 039 private final Context context; 040 041 private JndiManager(final String name, final Context context) { 042 super(name); 043 this.context = context; 044 } 045 046 /** 047 * Gets the default JndiManager using the default {@link javax.naming.InitialContext}. 048 * 049 * @return the default JndiManager 050 */ 051 public static JndiManager getDefaultManager() { 052 return getManager(JndiManager.class.getName(), FACTORY, null); 053 } 054 055 /** 056 * Gets a named JndiManager using the default {@link javax.naming.InitialContext}. 057 * @param name the name of the JndiManager instance to create or use if available 058 * @return a default JndiManager 059 */ 060 public static JndiManager getDefaultManager(final String name) { 061 return getManager(name, FACTORY, null); 062 } 063 064 /** 065 * Gets a JndiManager with the provided configuration information. 066 * 067 * @param initialContextFactoryName Fully qualified class name of an implementation of 068 * {@link javax.naming.spi.InitialContextFactory}. 069 * @param providerURL The provider URL to use for the JNDI connection (specific to the above factory). 070 * @param urlPkgPrefixes A colon-separated list of package prefixes for the class name of the factory 071 * class that will create a URL context factory 072 * @param securityPrincipal The name of the identity of the Principal. 073 * @param securityCredentials The security credentials of the Principal. 074 * @param additionalProperties Any additional JNDI environment properties to set or {@code null} for none. 075 * @return the JndiManager for the provided parameters. 076 */ 077 public static JndiManager getJndiManager(final String initialContextFactoryName, 078 final String providerURL, 079 final String urlPkgPrefixes, 080 final String securityPrincipal, 081 final String securityCredentials, 082 final Properties additionalProperties) { 083 final String name = JndiManager.class.getName() + '@' + JndiManager.class.hashCode(); 084 if (initialContextFactoryName == null) { 085 return getManager(name, FACTORY, null); 086 } 087 final Properties properties = new Properties(); 088 properties.setProperty(Context.INITIAL_CONTEXT_FACTORY, initialContextFactoryName); 089 if (providerURL != null) { 090 properties.setProperty(Context.PROVIDER_URL, providerURL); 091 } else { 092 LOGGER.warn("The JNDI InitialContextFactory class name [{}] was provided, but there was no associated " + 093 "provider URL. This is likely to cause problems.", initialContextFactoryName); 094 } 095 if (urlPkgPrefixes != null) { 096 properties.setProperty(Context.URL_PKG_PREFIXES, urlPkgPrefixes); 097 } 098 if (securityPrincipal != null) { 099 properties.setProperty(Context.SECURITY_PRINCIPAL, securityPrincipal); 100 if (securityCredentials != null) { 101 properties.setProperty(Context.SECURITY_CREDENTIALS, securityCredentials); 102 } else { 103 LOGGER.warn("A security principal [{}] was provided, but with no corresponding security credentials.", 104 securityPrincipal); 105 } 106 } 107 if (additionalProperties != null) { 108 properties.putAll(additionalProperties); 109 } 110 return getManager(name, FACTORY, properties); 111 } 112 113 @Override 114 protected void releaseSub() { 115 JndiCloser.closeSilently(this.context); 116 } 117 118 /** 119 * Looks up a named object through this JNDI context. 120 * 121 * @param name name of the object to look up. 122 * @param <T> the type of the object. 123 * @return the named object if it could be located. 124 * @throws NamingException 125 */ 126 @SuppressWarnings("unchecked") 127 public <T> T lookup(final String name) throws NamingException { 128 return (T) this.context.lookup(name); 129 } 130 131 private static class JndiManagerFactory implements ManagerFactory<JndiManager, Properties> { 132 133 @Override 134 public JndiManager createManager(final String name, final Properties data) { 135 try { 136 return new JndiManager(name, new InitialContext(data)); 137 } catch (final NamingException e) { 138 LOGGER.error("Error creating JNDI InitialContext.", e); 139 return null; 140 } 141 } 142 } 143 }