1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.settings4j.connector;
18
19 import java.util.Properties;
20
21 import javax.naming.Context;
22 import javax.naming.InitialContext;
23 import javax.naming.NameNotFoundException;
24 import javax.naming.NamingException;
25 import javax.naming.NoInitialContextException;
26
27 import org.apache.commons.lang3.BooleanUtils;
28 import org.apache.commons.lang3.StringUtils;
29 import org.settings4j.Constants;
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86 public class JNDIConnector extends AbstractConnector {
87
88
89 private static final org.slf4j.Logger LOG = org.slf4j.LoggerFactory.getLogger(JNDIConnector.class);
90
91 private String providerUrl;
92
93 private String initialContextFactory;
94
95 private String urlPkgPrefixes;
96
97 private String contextPathPrefix = "java:comp/env/";
98
99 private Boolean isJNDIAvailable;
100
101
102 public byte[] getContent(final String key) {
103 final Object obj = lookupInContext(key);
104 if (obj == null) {
105 return null;
106 }
107
108
109
110 if (obj instanceof String && getContentResolver() != null) {
111 final byte[] content = getContentResolver().getContent((String) obj);
112 if (content != null) {
113 return content;
114 }
115 }
116
117 if (obj instanceof byte[]) {
118 return (byte[]) obj;
119 }
120
121 LOG.warn("Wrong Type: {} for Key: {}", obj.getClass().getName(), key);
122 return null;
123 }
124
125
126 public Object getObject(final String key) {
127 final Object obj = lookupInContext(key);
128
129
130
131 if (obj instanceof String && getObjectResolver() != null) {
132 final Object convertedObject = getObjectResolver().getObject((String) obj, getContentResolver());
133 if (convertedObject != null) {
134 return convertedObject;
135 }
136 }
137
138 return obj;
139 }
140
141
142 public String getString(final String key) {
143 final Object obj = lookupInContext(key);
144 try {
145 return (String) obj;
146 } catch (final ClassCastException e) {
147 LOG.warn("Wrong Type: {} for Key: {}", obj.getClass().getName(), key);
148 LOG.debug(e.getMessage(), e);
149 return null;
150 }
151 }
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166 public int setObject(final String key, final Object value) {
167 return rebindToContext(normalizeKey(key), value);
168 }
169
170 private InitialContext getJNDIContext() throws NamingException {
171 InitialContext initialContext;
172
173 if (StringUtils.isEmpty(this.providerUrl) && StringUtils.isEmpty(this.initialContextFactory)
174 && StringUtils.isEmpty(this.urlPkgPrefixes)) {
175
176 initialContext = new InitialContext();
177 } else {
178 final Properties prop = new Properties();
179 prop.put(Context.PROVIDER_URL, this.providerUrl);
180 prop.put(Context.INITIAL_CONTEXT_FACTORY, this.initialContextFactory);
181 prop.put(Context.URL_PKG_PREFIXES, this.urlPkgPrefixes);
182 initialContext = new InitialContext(prop);
183 }
184
185 return initialContext;
186 }
187
188
189
190
191
192
193
194
195 public boolean isJNDIAvailable() {
196 if (this.isJNDIAvailable == null) {
197 try {
198 getJNDIContext().lookup(getContextPathPrefix());
199 LOG.debug("JNDI Context is available.");
200 this.isJNDIAvailable = Boolean.TRUE;
201 } catch (final NoInitialContextException e) {
202 LOG.info("No JNDI Context available! JNDIConnector will be disabled: {}", e.getMessage());
203 this.isJNDIAvailable = Boolean.FALSE;
204 } catch (final NamingException e) {
205 LOG.info("JNDI Context is available but {}", e.getMessage());
206 LOG.debug("NamingException in isJNDIAvailable: " + e.getMessage(), e);
207 this.isJNDIAvailable = Boolean.TRUE;
208 }
209 }
210
211 return this.isJNDIAvailable.booleanValue();
212 }
213
214 public void setProviderUrl(final String providerUrl) {
215 this.providerUrl = providerUrl;
216 }
217
218 public void setInitialContextFactory(final String initialContextFactory) {
219 this.initialContextFactory = initialContextFactory;
220 }
221
222 public void setUrlPkgPrefixes(final String urlPkgPrefixes) {
223 this.urlPkgPrefixes = urlPkgPrefixes;
224 }
225
226 private Object lookupInContext(final String key) {
227 return lookupInContext(key, true);
228 }
229
230 private Object lookupInContext(final String key, final boolean withPrefix) {
231 if (!isJNDIAvailable()) {
232 return null;
233 }
234 final String normalizedKey = normalizeKey(key, withPrefix);
235 InitialContext ctx = null;
236 Object result = null;
237 try {
238 ctx = getJNDIContext();
239 result = ctx.lookup(normalizedKey);
240 } catch (final NoInitialContextException e) {
241 LOG.info("Maybe no JNDI-Context available.");
242 LOG.debug(e.getMessage(), e);
243 } catch (final NamingException e) {
244 LOG.debug("cannot lookup key: " + key + " (" + normalizedKey + ")", e);
245 if (withPrefix) {
246 result = lookupInContext(key, false);
247 }
248 } finally {
249 if (ctx != null) {
250 try {
251 ctx.close();
252 } catch (final NamingException e) {
253 LOG.info("cannot close context: " + key + " (" + normalizedKey + ")", e);
254 }
255 }
256 }
257 return result;
258 }
259
260
261
262
263
264
265 public int rebindToContext(final String key, final Object value) {
266
267 if (BooleanUtils.isFalse(this.isJNDIAvailable)) {
268
269 return Constants.SETTING_NOT_POSSIBLE;
270 }
271
272 LOG.debug("Try to rebind Key '{}' with value: {}", key, value);
273
274 InitialContext ctx = null;
275 int result = Constants.SETTING_NOT_POSSIBLE;
276 try {
277 ctx = getJNDIContext();
278 createParentContext(ctx, key);
279 ctx.rebind(key, value);
280 result = Constants.SETTING_SUCCESS;
281 } catch (final NoInitialContextException e) {
282 LOG.info("Maybe no JNDI-Context available.");
283 LOG.debug(e.getMessage(), e);
284 } catch (final NamingException e) {
285
286
287
288 LOG.info("cannot bind key: '{}'. {}", key, e.getMessage());
289 if (LOG.isDebugEnabled()) {
290 LOG.debug("cannot bind key: " + key, e);
291 }
292 } finally {
293 if (ctx != null) {
294 try {
295 ctx.close();
296 } catch (final NamingException e) {
297 LOG.info("cannot close context: " + key, e);
298 }
299 }
300 }
301 return result;
302 }
303
304 private static void createParentContext(final Context ctx, final String key) throws NamingException {
305
306
307 LOG.debug("createParentContext: {}", key);
308
309 final String[] path = key.split("/");
310
311 final int lastIndex = path.length - 1;
312
313 Context tmpCtx = ctx;
314
315 for (int i = 0; i < lastIndex; i++) {
316 Object obj = null;
317 try {
318 obj = tmpCtx.lookup(path[i]);
319 } catch (final NameNotFoundException e) {
320 LOG.debug("obj is null and subcontext will be generated: {}", path[i]);
321 }
322
323 if (obj == null) {
324 tmpCtx = tmpCtx.createSubcontext(path[i]);
325 LOG.debug("createSubcontext: {}", path[i]);
326 } else if (obj instanceof Context) {
327 tmpCtx = (Context) obj;
328 } else {
329 throw new RuntimeException("Illegal node/branch clash. At branch value '" + path[i]
330 + "' an Object was found: " + obj);
331 }
332 }
333 }
334
335 private String normalizeKey(final String key) {
336 return normalizeKey(key, true);
337 }
338
339 private String normalizeKey(final String key, final boolean withPrefix) {
340 if (key == null) {
341 return null;
342 }
343 String normalizeKey = key;
344 if (normalizeKey.startsWith(this.contextPathPrefix)) {
345 return normalizeKey;
346 }
347
348 normalizeKey = normalizeKey.replace('\\', '/');
349
350 if (normalizeKey.startsWith("/")) {
351 normalizeKey = normalizeKey.substring(1);
352 }
353 if (withPrefix) {
354 return this.contextPathPrefix + normalizeKey;
355 } else {
356 return normalizeKey;
357 }
358 }
359
360 public String getContextPathPrefix() {
361 return this.contextPathPrefix;
362 }
363
364 public void setContextPathPrefix(final String contextPathPrefix) {
365 this.contextPathPrefix = contextPathPrefix;
366 }
367
368 protected Boolean getIsJNDIAvailable() {
369 return this.isJNDIAvailable;
370 }
371
372 protected void setIsJNDIAvailable(final Boolean isJNDIAvailable) {
373 this.isJNDIAvailable = isJNDIAvailable;
374 }
375
376 }