1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.logging.log4j.core.net;
19
20 import java.net.URI;
21 import java.net.URISyntaxException;
22 import java.util.Properties;
23 import java.util.concurrent.TimeUnit;
24
25 import javax.naming.Context;
26 import javax.naming.InitialContext;
27 import javax.naming.NamingException;
28
29 import org.apache.logging.log4j.core.appender.AbstractManager;
30 import org.apache.logging.log4j.core.appender.ManagerFactory;
31 import org.apache.logging.log4j.core.util.JndiCloser;
32 import org.apache.logging.log4j.util.PropertiesUtil;
33
34
35
36
37
38
39 public class JndiManager extends AbstractManager {
40
41 private static final JndiManagerFactory FACTORY = new JndiManagerFactory();
42 private static final String PREFIX = "log4j2.enableJndi";
43 private static final String JAVA_SCHEME = "java";
44
45 private static final boolean JNDI_CONTEXT_SELECTOR_ENABLED = isJndiEnabled("ContextSelector");
46 private static final boolean JNDI_JDBC_ENABLED = isJndiEnabled("Jdbc");
47 private static final boolean JNDI_JMS_ENABLED = isJndiEnabled("Jms");
48 private static final boolean JNDI_LOOKUP_ENABLED = isJndiEnabled("Lookup");
49
50 private final InitialContext context;
51
52 private static boolean isJndiEnabled(final String subKey) {
53 return PropertiesUtil.getProperties().getBooleanProperty(PREFIX + subKey, false);
54 }
55
56 public static boolean isJndiEnabled() {
57 return isJndiContextSelectorEnabled() || isJndiJdbcEnabled() || isJndiJmsEnabled() || isJndiLookupEnabled();
58 }
59
60 public static boolean isJndiContextSelectorEnabled() {
61 return JNDI_CONTEXT_SELECTOR_ENABLED;
62 }
63
64 public static boolean isJndiJdbcEnabled() {
65 return JNDI_JDBC_ENABLED;
66 }
67
68 public static boolean isJndiJmsEnabled() {
69 return JNDI_JMS_ENABLED;
70 }
71
72 public static boolean isJndiLookupEnabled() {
73 return JNDI_LOOKUP_ENABLED;
74 }
75
76 private JndiManager(final String name, final InitialContext context) {
77 super(null, name);
78 this.context = context;
79 }
80
81
82
83
84
85
86 public static JndiManager getDefaultManager() {
87 return getManager(JndiManager.class.getName(), FACTORY, null);
88 }
89
90
91
92
93
94
95
96 public static JndiManager getDefaultManager(final String name) {
97 return getManager(name, FACTORY, null);
98 }
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113 public static JndiManager getJndiManager(final String initialContextFactoryName,
114 final String providerURL,
115 final String urlPkgPrefixes,
116 final String securityPrincipal,
117 final String securityCredentials,
118 final Properties additionalProperties) {
119 final Properties properties = createProperties(initialContextFactoryName, providerURL, urlPkgPrefixes,
120 securityPrincipal, securityCredentials, additionalProperties);
121 return getManager(createManagerName(), FACTORY, properties);
122 }
123
124
125
126
127
128
129
130
131
132 public static JndiManager getJndiManager(final Properties properties) {
133 return getManager(createManagerName(), FACTORY, properties);
134 }
135
136 private static String createManagerName() {
137 return JndiManager.class.getName() + '@' + JndiManager.class.hashCode();
138 }
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159 public static Properties createProperties(final String initialContextFactoryName, final String providerURL,
160 final String urlPkgPrefixes, final String securityPrincipal, final String securityCredentials,
161 final Properties additionalProperties) {
162 if (initialContextFactoryName == null) {
163 return null;
164 }
165 final Properties properties = new Properties();
166 properties.setProperty(Context.INITIAL_CONTEXT_FACTORY, initialContextFactoryName);
167 if (providerURL != null) {
168 properties.setProperty(Context.PROVIDER_URL, providerURL);
169 } else {
170 LOGGER.warn("The JNDI InitialContextFactory class name [{}] was provided, but there was no associated "
171 + "provider URL. This is likely to cause problems.", initialContextFactoryName);
172 }
173 if (urlPkgPrefixes != null) {
174 properties.setProperty(Context.URL_PKG_PREFIXES, urlPkgPrefixes);
175 }
176 if (securityPrincipal != null) {
177 properties.setProperty(Context.SECURITY_PRINCIPAL, securityPrincipal);
178 if (securityCredentials != null) {
179 properties.setProperty(Context.SECURITY_CREDENTIALS, securityCredentials);
180 } else {
181 LOGGER.warn("A security principal [{}] was provided, but with no corresponding security credentials.",
182 securityPrincipal);
183 }
184 }
185 if (additionalProperties != null) {
186 properties.putAll(additionalProperties);
187 }
188 return properties;
189 }
190
191 @Override
192 protected boolean releaseSub(final long timeout, final TimeUnit timeUnit) {
193 return JndiCloser.closeSilently(this.context);
194 }
195
196
197
198
199
200
201
202
203
204 @SuppressWarnings("unchecked")
205 public <T> T lookup(final String name) throws NamingException {
206 if (context == null) {
207 return null;
208 }
209 try {
210 URI uri = new URI(name);
211 if (uri.getScheme() == null || uri.getScheme().equals(JAVA_SCHEME)) {
212 return (T) this.context.lookup(name);
213 }
214 LOGGER.warn("Unsupported JNDI URI - {}", name);
215 } catch (URISyntaxException ex) {
216 LOGGER.warn("Invalid JNDI URI - {}", name);
217 }
218 return null;
219 }
220
221 private static class JndiManagerFactory implements ManagerFactory<JndiManager, Properties> {
222
223 @Override
224 public JndiManager createManager(final String name, final Properties data) {
225 if (!isJndiEnabled()) {
226 throw new IllegalStateException(String.format("JNDI must be enabled by setting one of the %s* properties to true", PREFIX));
227 }
228 try {
229 return new JndiManager(name, new InitialContext(data));
230 } catch (final NamingException e) {
231 LOGGER.error("Error creating JNDI InitialContext for '{}'.", name, e);
232 return null;
233 }
234 }
235
236 }
237
238 @Override
239 public String toString() {
240 return "JndiManager [context=" + context + ", count=" + count + "]";
241 }
242
243 }