author | stefank |
Mon, 25 Aug 2014 09:10:13 +0200 | |
changeset 26314 | f8bc1966fb30 |
parent 25859 | 3317bb8137f4 |
child 36511 | 9d0388c6b336 |
permissions | -rw-r--r-- |
2 | 1 |
/* |
10324
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
5506
diff
changeset
|
2 |
* Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. |
2 | 3 |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 |
* |
|
5 |
* This code is free software; you can redistribute it and/or modify it |
|
6 |
* under the terms of the GNU General Public License version 2 only, as |
|
5506 | 7 |
* published by the Free Software Foundation. Oracle designates this |
2 | 8 |
* particular file as subject to the "Classpath" exception as provided |
5506 | 9 |
* by Oracle in the LICENSE file that accompanied this code. |
2 | 10 |
* |
11 |
* This code is distributed in the hope that it will be useful, but WITHOUT |
|
12 |
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
13 |
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
14 |
* version 2 for more details (a copy is included in the LICENSE file that |
|
15 |
* accompanied this code). |
|
16 |
* |
|
17 |
* You should have received a copy of the GNU General Public License version |
|
18 |
* 2 along with this work; if not, write to the Free Software Foundation, |
|
19 |
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
20 |
* |
|
5506 | 21 |
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
22 |
* or visit www.oracle.com if you need additional information or have any |
|
23 |
* questions. |
|
2 | 24 |
*/ |
25 |
||
26 |
package com.sun.jndi.ldap; |
|
27 |
||
28 |
import javax.naming.*; |
|
29 |
import javax.naming.directory.*; |
|
30 |
import javax.naming.spi.DirectoryManager; |
|
31 |
import javax.naming.spi.DirStateFactory; |
|
32 |
||
33 |
import java.io.IOException; |
|
34 |
import java.io.ByteArrayInputStream; |
|
35 |
import java.io.ByteArrayOutputStream; |
|
36 |
import java.io.ObjectInputStream; |
|
37 |
import java.io.ObjectOutputStream; |
|
38 |
import java.io.ObjectStreamClass; |
|
39 |
import java.io.InputStream; |
|
40 |
||
24043
81e42b05d08b
8035807: Convert use of sun.misc.BASE64Encoder/Decoder with java.util.Base64
mchung
parents:
10326
diff
changeset
|
41 |
import java.util.Base64; |
2 | 42 |
import java.util.Hashtable; |
43 |
import java.util.Vector; |
|
44 |
import java.util.StringTokenizer; |
|
45 |
||
46 |
import java.lang.reflect.Proxy; |
|
47 |
import java.lang.reflect.Modifier; |
|
48 |
||
49 |
/** |
|
50 |
* Class containing static methods and constants for dealing with |
|
51 |
* encoding/decoding JNDI References and Serialized Objects |
|
52 |
* in LDAP. |
|
53 |
* @author Vincent Ryan |
|
54 |
* @author Rosanna Lee |
|
55 |
*/ |
|
56 |
final class Obj { |
|
57 |
||
58 |
private Obj () {}; // Make sure no one can create one |
|
59 |
||
60 |
// package private; used by Connection |
|
61 |
static VersionHelper helper = VersionHelper.getVersionHelper(); |
|
62 |
||
63 |
// LDAP attributes used to support Java objects. |
|
64 |
static final String[] JAVA_ATTRIBUTES = { |
|
65 |
"objectClass", |
|
66 |
"javaSerializedData", |
|
67 |
"javaClassName", |
|
68 |
"javaFactory", |
|
69 |
"javaCodeBase", |
|
70 |
"javaReferenceAddress", |
|
71 |
"javaClassNames", |
|
72 |
"javaRemoteLocation" // Deprecated |
|
73 |
}; |
|
74 |
||
75 |
static final int OBJECT_CLASS = 0; |
|
76 |
static final int SERIALIZED_DATA = 1; |
|
77 |
static final int CLASSNAME = 2; |
|
78 |
static final int FACTORY = 3; |
|
79 |
static final int CODEBASE = 4; |
|
80 |
static final int REF_ADDR = 5; |
|
81 |
static final int TYPENAME = 6; |
|
82 |
/** |
|
83 |
* @deprecated |
|
84 |
*/ |
|
10324
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
5506
diff
changeset
|
85 |
@Deprecated |
2 | 86 |
private static final int REMOTE_LOC = 7; |
87 |
||
88 |
// LDAP object classes to support Java objects |
|
89 |
static final String[] JAVA_OBJECT_CLASSES = { |
|
90 |
"javaContainer", |
|
91 |
"javaObject", |
|
92 |
"javaNamingReference", |
|
93 |
"javaSerializedObject", |
|
94 |
"javaMarshalledObject", |
|
95 |
}; |
|
96 |
||
97 |
static final String[] JAVA_OBJECT_CLASSES_LOWER = { |
|
98 |
"javacontainer", |
|
99 |
"javaobject", |
|
100 |
"javanamingreference", |
|
101 |
"javaserializedobject", |
|
102 |
"javamarshalledobject", |
|
103 |
}; |
|
104 |
||
105 |
static final int STRUCTURAL = 0; // structural object class |
|
106 |
static final int BASE_OBJECT = 1; // auxiliary java object class |
|
107 |
static final int REF_OBJECT = 2; // auxiliary reference object class |
|
108 |
static final int SER_OBJECT = 3; // auxiliary serialized object class |
|
109 |
static final int MAR_OBJECT = 4; // auxiliary marshalled object class |
|
110 |
||
111 |
/** |
|
112 |
* Encode an object in LDAP attributes. |
|
113 |
* Supports binding Referenceable or Reference, Serializable, |
|
114 |
* and DirContext. |
|
115 |
* |
|
116 |
* If the object supports the Referenceable interface then encode |
|
117 |
* the reference to the object. See encodeReference() for details. |
|
118 |
*<p> |
|
119 |
* If the object is serializable, it is stored as follows: |
|
120 |
* javaClassName |
|
121 |
* value: Object.getClass(); |
|
122 |
* javaSerializedData |
|
123 |
* value: serialized form of Object (in binary form). |
|
124 |
* javaTypeName |
|
125 |
* value: getTypeNames(Object.getClass()); |
|
126 |
*/ |
|
127 |
private static Attributes encodeObject(char separator, |
|
128 |
Object obj, Attributes attrs, |
|
129 |
Attribute objectClass, boolean cloned) |
|
130 |
throws NamingException { |
|
131 |
boolean structural = |
|
132 |
(objectClass.size() == 0 || |
|
133 |
(objectClass.size() == 1 && objectClass.contains("top"))); |
|
134 |
||
135 |
if (structural) { |
|
136 |
objectClass.add(JAVA_OBJECT_CLASSES[STRUCTURAL]); |
|
137 |
} |
|
138 |
||
139 |
// References |
|
140 |
if (obj instanceof Referenceable) { |
|
141 |
objectClass.add(JAVA_OBJECT_CLASSES[BASE_OBJECT]); |
|
142 |
objectClass.add(JAVA_OBJECT_CLASSES[REF_OBJECT]); |
|
143 |
if (!cloned) { |
|
144 |
attrs = (Attributes)attrs.clone(); |
|
145 |
} |
|
146 |
attrs.put(objectClass); |
|
147 |
return (encodeReference(separator, |
|
148 |
((Referenceable)obj).getReference(), |
|
149 |
attrs, obj)); |
|
150 |
||
151 |
} else if (obj instanceof Reference) { |
|
152 |
objectClass.add(JAVA_OBJECT_CLASSES[BASE_OBJECT]); |
|
153 |
objectClass.add(JAVA_OBJECT_CLASSES[REF_OBJECT]); |
|
154 |
if (!cloned) { |
|
155 |
attrs = (Attributes)attrs.clone(); |
|
156 |
} |
|
157 |
attrs.put(objectClass); |
|
158 |
return (encodeReference(separator, (Reference)obj, attrs, null)); |
|
159 |
||
160 |
// Serializable Object |
|
161 |
} else if (obj instanceof java.io.Serializable) { |
|
162 |
objectClass.add(JAVA_OBJECT_CLASSES[BASE_OBJECT]); |
|
163 |
if (!(objectClass.contains(JAVA_OBJECT_CLASSES[MAR_OBJECT]) || |
|
164 |
objectClass.contains(JAVA_OBJECT_CLASSES_LOWER[MAR_OBJECT]))) { |
|
165 |
objectClass.add(JAVA_OBJECT_CLASSES[SER_OBJECT]); |
|
166 |
} |
|
167 |
if (!cloned) { |
|
168 |
attrs = (Attributes)attrs.clone(); |
|
169 |
} |
|
170 |
attrs.put(objectClass); |
|
171 |
attrs.put(new BasicAttribute(JAVA_ATTRIBUTES[SERIALIZED_DATA], |
|
172 |
serializeObject(obj))); |
|
173 |
if (attrs.get(JAVA_ATTRIBUTES[CLASSNAME]) == null) { |
|
174 |
attrs.put(JAVA_ATTRIBUTES[CLASSNAME], |
|
175 |
obj.getClass().getName()); |
|
176 |
} |
|
177 |
if (attrs.get(JAVA_ATTRIBUTES[TYPENAME]) == null) { |
|
178 |
Attribute tAttr = |
|
179 |
LdapCtxFactory.createTypeNameAttr(obj.getClass()); |
|
180 |
if (tAttr != null) { |
|
181 |
attrs.put(tAttr); |
|
182 |
} |
|
183 |
} |
|
184 |
// DirContext Object |
|
185 |
} else if (obj instanceof DirContext) { |
|
186 |
// do nothing |
|
187 |
} else { |
|
188 |
throw new IllegalArgumentException( |
|
189 |
"can only bind Referenceable, Serializable, DirContext"); |
|
190 |
} |
|
191 |
// System.err.println(attrs); |
|
192 |
return attrs; |
|
193 |
} |
|
194 |
||
195 |
/** |
|
196 |
* Each value in javaCodebase contains a list of space-separated |
|
197 |
* URLs. Each value is independent; we can pick any of the values |
|
198 |
* so we just use the first one. |
|
199 |
* @return an array of URL strings for the codebase |
|
200 |
*/ |
|
201 |
private static String[] getCodebases(Attribute codebaseAttr) throws |
|
202 |
NamingException { |
|
203 |
if (codebaseAttr == null) { |
|
204 |
return null; |
|
205 |
} else { |
|
206 |
StringTokenizer parser = |
|
207 |
new StringTokenizer((String)codebaseAttr.get()); |
|
10324
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
5506
diff
changeset
|
208 |
Vector<String> vec = new Vector<>(10); |
2 | 209 |
while (parser.hasMoreTokens()) { |
210 |
vec.addElement(parser.nextToken()); |
|
211 |
} |
|
212 |
String[] answer = new String[vec.size()]; |
|
213 |
for (int i = 0; i < answer.length; i++) { |
|
10324
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
5506
diff
changeset
|
214 |
answer[i] = vec.elementAt(i); |
2 | 215 |
} |
216 |
return answer; |
|
217 |
} |
|
218 |
} |
|
219 |
||
220 |
/* |
|
221 |
* Decode an object from LDAP attribute(s). |
|
222 |
* The object may be a Reference, or a Serialized object. |
|
223 |
* |
|
224 |
* See encodeObject() and encodeReference() for details on formats |
|
225 |
* expected. |
|
226 |
*/ |
|
227 |
static Object decodeObject(Attributes attrs) |
|
228 |
throws NamingException { |
|
229 |
||
230 |
Attribute attr; |
|
231 |
||
232 |
// Get codebase, which is used in all 3 cases. |
|
233 |
String[] codebases = getCodebases(attrs.get(JAVA_ATTRIBUTES[CODEBASE])); |
|
234 |
try { |
|
235 |
if ((attr = attrs.get(JAVA_ATTRIBUTES[SERIALIZED_DATA])) != null) { |
|
236 |
ClassLoader cl = helper.getURLClassLoader(codebases); |
|
237 |
return deserializeObject((byte[])attr.get(), cl); |
|
238 |
} else if ((attr = attrs.get(JAVA_ATTRIBUTES[REMOTE_LOC])) != null) { |
|
239 |
// For backward compatibility only |
|
240 |
return decodeRmiObject( |
|
241 |
(String)attrs.get(JAVA_ATTRIBUTES[CLASSNAME]).get(), |
|
242 |
(String)attr.get(), codebases); |
|
243 |
} |
|
244 |
||
245 |
attr = attrs.get(JAVA_ATTRIBUTES[OBJECT_CLASS]); |
|
246 |
if (attr != null && |
|
247 |
(attr.contains(JAVA_OBJECT_CLASSES[REF_OBJECT]) || |
|
248 |
attr.contains(JAVA_OBJECT_CLASSES_LOWER[REF_OBJECT]))) { |
|
249 |
return decodeReference(attrs, codebases); |
|
250 |
} |
|
251 |
return null; |
|
252 |
} catch (IOException e) { |
|
253 |
NamingException ne = new NamingException(); |
|
254 |
ne.setRootCause(e); |
|
255 |
throw ne; |
|
256 |
} |
|
257 |
} |
|
258 |
||
259 |
/** |
|
260 |
* Convert a Reference object into several LDAP attributes. |
|
261 |
* |
|
262 |
* A Reference is stored as into the following attributes: |
|
263 |
* javaClassName |
|
264 |
* value: Reference.getClassName(); |
|
265 |
* javaFactory |
|
266 |
* value: Reference.getFactoryClassName(); |
|
267 |
* javaCodeBase |
|
268 |
* value: Reference.getFactoryClassLocation(); |
|
269 |
* javaReferenceAddress |
|
270 |
* value: #0#typeA#valA |
|
271 |
* value: #1#typeB#valB |
|
272 |
* value: #2#typeC##[serialized RefAddr C] |
|
273 |
* value: #3#typeD#valD |
|
274 |
* |
|
275 |
* where |
|
276 |
* - the first character denotes the separator |
|
277 |
* - the number following the first separator denotes the position |
|
278 |
* of the RefAddr within the Reference |
|
279 |
* - "typeA" is RefAddr.getType() |
|
280 |
* - ## denotes that the Base64-encoded form of the non-StringRefAddr |
|
281 |
* is to follow; otherwise the value that follows is |
|
282 |
* StringRefAddr.getContents() |
|
283 |
* |
|
284 |
* The default separator is the hash character (#). |
|
285 |
* May provide property for this in future. |
|
286 |
*/ |
|
287 |
||
288 |
private static Attributes encodeReference(char separator, |
|
289 |
Reference ref, Attributes attrs, Object orig) |
|
290 |
throws NamingException { |
|
291 |
||
292 |
if (ref == null) |
|
293 |
return attrs; |
|
294 |
||
295 |
String s; |
|
296 |
||
297 |
if ((s = ref.getClassName()) != null) { |
|
298 |
attrs.put(new BasicAttribute(JAVA_ATTRIBUTES[CLASSNAME], s)); |
|
299 |
} |
|
300 |
||
301 |
if ((s = ref.getFactoryClassName()) != null) { |
|
302 |
attrs.put(new BasicAttribute(JAVA_ATTRIBUTES[FACTORY], s)); |
|
303 |
} |
|
304 |
||
305 |
if ((s = ref.getFactoryClassLocation()) != null) { |
|
306 |
attrs.put(new BasicAttribute(JAVA_ATTRIBUTES[CODEBASE], s)); |
|
307 |
} |
|
308 |
||
309 |
// Get original object's types if caller has not explicitly |
|
310 |
// specified other type names |
|
311 |
if (orig != null && attrs.get(JAVA_ATTRIBUTES[TYPENAME]) != null) { |
|
312 |
Attribute tAttr = |
|
313 |
LdapCtxFactory.createTypeNameAttr(orig.getClass()); |
|
314 |
if (tAttr != null) { |
|
315 |
attrs.put(tAttr); |
|
316 |
} |
|
317 |
} |
|
318 |
||
319 |
int count = ref.size(); |
|
320 |
||
321 |
if (count > 0) { |
|
322 |
||
323 |
Attribute refAttr = new BasicAttribute(JAVA_ATTRIBUTES[REF_ADDR]); |
|
324 |
RefAddr refAddr; |
|
24043
81e42b05d08b
8035807: Convert use of sun.misc.BASE64Encoder/Decoder with java.util.Base64
mchung
parents:
10326
diff
changeset
|
325 |
Base64.Encoder encoder = null; |
2 | 326 |
|
327 |
for (int i = 0; i < count; i++) { |
|
328 |
refAddr = ref.get(i); |
|
329 |
||
330 |
if (refAddr instanceof StringRefAddr) { |
|
331 |
refAttr.add(""+ separator + i + |
|
332 |
separator + refAddr.getType() + |
|
333 |
separator + refAddr.getContent()); |
|
334 |
} else { |
|
335 |
if (encoder == null) |
|
24043
81e42b05d08b
8035807: Convert use of sun.misc.BASE64Encoder/Decoder with java.util.Base64
mchung
parents:
10326
diff
changeset
|
336 |
encoder = Base64.getMimeEncoder(); |
2 | 337 |
|
338 |
refAttr.add(""+ separator + i + |
|
339 |
separator + refAddr.getType() + |
|
340 |
separator + separator + |
|
24043
81e42b05d08b
8035807: Convert use of sun.misc.BASE64Encoder/Decoder with java.util.Base64
mchung
parents:
10326
diff
changeset
|
341 |
encoder.encodeToString(serializeObject(refAddr))); |
2 | 342 |
} |
343 |
} |
|
344 |
attrs.put(refAttr); |
|
345 |
} |
|
346 |
return attrs; |
|
347 |
} |
|
348 |
||
349 |
/* |
|
350 |
* A RMI object is stored in the directory as |
|
351 |
* javaClassName |
|
352 |
* value: Object.getClass(); |
|
353 |
* javaRemoteLocation |
|
354 |
* value: URL of RMI object (accessed through the RMI Registry) |
|
355 |
* javaCodebase: |
|
356 |
* value: URL of codebase of where to find classes for object |
|
357 |
* |
|
358 |
* Return the RMI Location URL itself. This will be turned into |
|
359 |
* an RMI object when getObjectInstance() is called on it. |
|
360 |
* %%% Ignore codebase for now. Depend on RMI registry to send code.-RL |
|
361 |
* @deprecated For backward compatibility only |
|
362 |
*/ |
|
363 |
private static Object decodeRmiObject(String className, |
|
364 |
String rmiName, String[] codebases) throws NamingException { |
|
365 |
return new Reference(className, new StringRefAddr("URL", rmiName)); |
|
366 |
} |
|
367 |
||
368 |
/* |
|
369 |
* Restore a Reference object from several LDAP attributes |
|
370 |
*/ |
|
371 |
private static Reference decodeReference(Attributes attrs, |
|
372 |
String[] codebases) throws NamingException, IOException { |
|
373 |
||
374 |
Attribute attr; |
|
375 |
String className; |
|
376 |
String factory = null; |
|
377 |
||
378 |
if ((attr = attrs.get(JAVA_ATTRIBUTES[CLASSNAME])) != null) { |
|
379 |
className = (String)attr.get(); |
|
380 |
} else { |
|
381 |
throw new InvalidAttributesException(JAVA_ATTRIBUTES[CLASSNAME] + |
|
382 |
" attribute is required"); |
|
383 |
} |
|
384 |
||
385 |
if ((attr = attrs.get(JAVA_ATTRIBUTES[FACTORY])) != null) { |
|
386 |
factory = (String)attr.get(); |
|
387 |
} |
|
388 |
||
389 |
Reference ref = new Reference(className, factory, |
|
390 |
(codebases != null? codebases[0] : null)); |
|
391 |
||
392 |
/* |
|
393 |
* string encoding of a RefAddr is either: |
|
394 |
* |
|
395 |
* #posn#<type>#<address> |
|
396 |
* or |
|
397 |
* #posn#<type>##<base64-encoded address> |
|
398 |
*/ |
|
399 |
if ((attr = attrs.get(JAVA_ATTRIBUTES[REF_ADDR])) != null) { |
|
400 |
||
401 |
String val, posnStr, type; |
|
402 |
char separator; |
|
403 |
int start, sep, posn; |
|
24043
81e42b05d08b
8035807: Convert use of sun.misc.BASE64Encoder/Decoder with java.util.Base64
mchung
parents:
10326
diff
changeset
|
404 |
Base64.Decoder decoder = null; |
2 | 405 |
|
406 |
ClassLoader cl = helper.getURLClassLoader(codebases); |
|
407 |
||
408 |
/* |
|
409 |
* Temporary Vector for decoded RefAddr addresses - used to ensure |
|
410 |
* unordered addresses are correctly re-ordered. |
|
411 |
*/ |
|
10324
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
5506
diff
changeset
|
412 |
Vector<RefAddr> refAddrList = new Vector<>(); |
2 | 413 |
refAddrList.setSize(attr.size()); |
414 |
||
10324
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
5506
diff
changeset
|
415 |
for (NamingEnumeration<?> vals = attr.getAll(); vals.hasMore(); ) { |
2 | 416 |
|
417 |
val = (String)vals.next(); |
|
418 |
||
419 |
if (val.length() == 0) { |
|
420 |
throw new InvalidAttributeValueException( |
|
421 |
"malformed " + JAVA_ATTRIBUTES[REF_ADDR] + " attribute - "+ |
|
422 |
"empty attribute value"); |
|
423 |
} |
|
424 |
// first character denotes encoding separator |
|
425 |
separator = val.charAt(0); |
|
426 |
start = 1; // skip over separator |
|
427 |
||
428 |
// extract position within Reference |
|
429 |
if ((sep = val.indexOf(separator, start)) < 0) { |
|
430 |
throw new InvalidAttributeValueException( |
|
431 |
"malformed " + JAVA_ATTRIBUTES[REF_ADDR] + " attribute - " + |
|
432 |
"separator '" + separator + "'" + "not found"); |
|
433 |
} |
|
434 |
if ((posnStr = val.substring(start, sep)) == null) { |
|
435 |
throw new InvalidAttributeValueException( |
|
436 |
"malformed " + JAVA_ATTRIBUTES[REF_ADDR] + " attribute - " + |
|
437 |
"empty RefAddr position"); |
|
438 |
} |
|
439 |
try { |
|
440 |
posn = Integer.parseInt(posnStr); |
|
441 |
} catch (NumberFormatException nfe) { |
|
442 |
throw new InvalidAttributeValueException( |
|
443 |
"malformed " + JAVA_ATTRIBUTES[REF_ADDR] + " attribute - " + |
|
444 |
"RefAddr position not an integer"); |
|
445 |
} |
|
446 |
start = sep + 1; // skip over position and trailing separator |
|
447 |
||
448 |
// extract type |
|
449 |
if ((sep = val.indexOf(separator, start)) < 0) { |
|
450 |
throw new InvalidAttributeValueException( |
|
451 |
"malformed " + JAVA_ATTRIBUTES[REF_ADDR] + " attribute - " + |
|
452 |
"RefAddr type not found"); |
|
453 |
} |
|
454 |
if ((type = val.substring(start, sep)) == null) { |
|
455 |
throw new InvalidAttributeValueException( |
|
456 |
"malformed " + JAVA_ATTRIBUTES[REF_ADDR] + " attribute - " + |
|
457 |
"empty RefAddr type"); |
|
458 |
} |
|
459 |
start = sep + 1; // skip over type and trailing separator |
|
460 |
||
461 |
// extract content |
|
462 |
if (start == val.length()) { |
|
463 |
// Empty content |
|
464 |
refAddrList.setElementAt(new StringRefAddr(type, null), posn); |
|
465 |
} else if (val.charAt(start) == separator) { |
|
466 |
// Double separators indicate a non-StringRefAddr |
|
467 |
// Content is a Base64-encoded serialized RefAddr |
|
468 |
||
469 |
++start; // skip over consecutive separator |
|
470 |
// %%% RL: exception if empty after double separator |
|
471 |
||
472 |
if (decoder == null) |
|
24043
81e42b05d08b
8035807: Convert use of sun.misc.BASE64Encoder/Decoder with java.util.Base64
mchung
parents:
10326
diff
changeset
|
473 |
decoder = Base64.getMimeDecoder(); |
2 | 474 |
|
475 |
RefAddr ra = (RefAddr) |
|
476 |
deserializeObject( |
|
24043
81e42b05d08b
8035807: Convert use of sun.misc.BASE64Encoder/Decoder with java.util.Base64
mchung
parents:
10326
diff
changeset
|
477 |
decoder.decode(val.substring(start).getBytes()), |
2 | 478 |
cl); |
479 |
||
480 |
refAddrList.setElementAt(ra, posn); |
|
481 |
} else { |
|
482 |
// Single separator indicates a StringRefAddr |
|
483 |
refAddrList.setElementAt(new StringRefAddr(type, |
|
484 |
val.substring(start)), posn); |
|
485 |
} |
|
486 |
} |
|
487 |
||
488 |
// Copy to real reference |
|
489 |
for (int i = 0; i < refAddrList.size(); i++) { |
|
10324
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
5506
diff
changeset
|
490 |
ref.add(refAddrList.elementAt(i)); |
2 | 491 |
} |
492 |
} |
|
493 |
||
494 |
return (ref); |
|
495 |
} |
|
496 |
||
497 |
/* |
|
498 |
* Serialize an object into a byte array |
|
499 |
*/ |
|
500 |
private static byte[] serializeObject(Object obj) throws NamingException { |
|
501 |
||
502 |
try { |
|
503 |
ByteArrayOutputStream bytes = new ByteArrayOutputStream(); |
|
10324
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
5506
diff
changeset
|
504 |
try (ObjectOutputStream serial = new ObjectOutputStream(bytes)) { |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
5506
diff
changeset
|
505 |
serial.writeObject(obj); |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
5506
diff
changeset
|
506 |
} |
2 | 507 |
|
508 |
return (bytes.toByteArray()); |
|
509 |
||
510 |
} catch (IOException e) { |
|
511 |
NamingException ne = new NamingException(); |
|
512 |
ne.setRootCause(e); |
|
513 |
throw ne; |
|
514 |
} |
|
515 |
} |
|
516 |
||
517 |
/* |
|
518 |
* Deserializes a byte array into an object. |
|
519 |
*/ |
|
520 |
private static Object deserializeObject(byte[] obj, ClassLoader cl) |
|
521 |
throws NamingException { |
|
522 |
||
523 |
try { |
|
524 |
// Create ObjectInputStream for deserialization |
|
525 |
ByteArrayInputStream bytes = new ByteArrayInputStream(obj); |
|
10324
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
5506
diff
changeset
|
526 |
try (ObjectInputStream deserial = cl == null ? |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
5506
diff
changeset
|
527 |
new ObjectInputStream(bytes) : |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
5506
diff
changeset
|
528 |
new LoaderInputStream(bytes, cl)) { |
2 | 529 |
return deserial.readObject(); |
530 |
} catch (ClassNotFoundException e) { |
|
531 |
NamingException ne = new NamingException(); |
|
532 |
ne.setRootCause(e); |
|
533 |
throw ne; |
|
534 |
} |
|
535 |
} catch (IOException e) { |
|
536 |
NamingException ne = new NamingException(); |
|
537 |
ne.setRootCause(e); |
|
538 |
throw ne; |
|
539 |
} |
|
540 |
} |
|
541 |
||
542 |
/** |
|
543 |
* Returns the attributes to bind given an object and its attributes. |
|
544 |
*/ |
|
545 |
static Attributes determineBindAttrs( |
|
546 |
char separator, Object obj, Attributes attrs, boolean cloned, |
|
10324
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
5506
diff
changeset
|
547 |
Name name, Context ctx, Hashtable<?,?> env) |
2 | 548 |
throws NamingException { |
549 |
||
550 |
// Call state factories to convert object and attrs |
|
551 |
DirStateFactory.Result res = |
|
552 |
DirectoryManager.getStateToBind(obj, name, ctx, env, attrs); |
|
553 |
obj = res.getObject(); |
|
554 |
attrs = res.getAttributes(); |
|
555 |
||
556 |
// We're only storing attributes; no further processing required |
|
557 |
if (obj == null) { |
|
558 |
return attrs; |
|
559 |
} |
|
560 |
||
561 |
//if object to be bound is a DirContext extract its attributes |
|
562 |
if ((attrs == null) && (obj instanceof DirContext)) { |
|
563 |
cloned = true; |
|
564 |
attrs = ((DirContext)obj).getAttributes(""); |
|
565 |
} |
|
566 |
||
567 |
boolean ocNeedsCloning = false; |
|
568 |
||
569 |
// Create "objectClass" attribute |
|
570 |
Attribute objectClass; |
|
571 |
if (attrs == null || attrs.size() == 0) { |
|
572 |
attrs = new BasicAttributes(LdapClient.caseIgnore); |
|
573 |
cloned = true; |
|
574 |
||
575 |
// No objectclasses supplied, use "top" to start |
|
576 |
objectClass = new BasicAttribute("objectClass", "top"); |
|
577 |
||
578 |
} else { |
|
579 |
// Get existing objectclass attribute |
|
10324
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
5506
diff
changeset
|
580 |
objectClass = attrs.get("objectClass"); |
2 | 581 |
if (objectClass == null && !attrs.isCaseIgnored()) { |
582 |
// %%% workaround |
|
10324
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
5506
diff
changeset
|
583 |
objectClass = attrs.get("objectclass"); |
2 | 584 |
} |
585 |
||
586 |
// No objectclasses supplied, use "top" to start |
|
587 |
if (objectClass == null) { |
|
588 |
objectClass = new BasicAttribute("objectClass", "top"); |
|
589 |
} else if (ocNeedsCloning || !cloned) { |
|
590 |
objectClass = (Attribute)objectClass.clone(); |
|
591 |
} |
|
592 |
} |
|
593 |
||
594 |
// convert the supplied object into LDAP attributes |
|
595 |
attrs = encodeObject(separator, obj, attrs, objectClass, cloned); |
|
596 |
||
597 |
// System.err.println("Determined: " + attrs); |
|
598 |
return attrs; |
|
599 |
} |
|
600 |
||
601 |
/** |
|
602 |
* An ObjectInputStream that uses a class loader to find classes. |
|
603 |
*/ |
|
604 |
private static final class LoaderInputStream extends ObjectInputStream { |
|
605 |
private ClassLoader classLoader; |
|
606 |
||
607 |
LoaderInputStream(InputStream in, ClassLoader cl) throws IOException { |
|
608 |
super(in); |
|
609 |
classLoader = cl; |
|
610 |
} |
|
611 |
||
10324
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
5506
diff
changeset
|
612 |
protected Class<?> resolveClass(ObjectStreamClass desc) throws |
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
5506
diff
changeset
|
613 |
IOException, ClassNotFoundException { |
2 | 614 |
try { |
615 |
// %%% Should use Class.forName(desc.getName(), false, classLoader); |
|
616 |
// except we can't because that is only available on JDK1.2 |
|
617 |
return classLoader.loadClass(desc.getName()); |
|
618 |
} catch (ClassNotFoundException e) { |
|
619 |
return super.resolveClass(desc); |
|
620 |
} |
|
621 |
} |
|
622 |
||
10324
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
5506
diff
changeset
|
623 |
protected Class<?> resolveProxyClass(String[] interfaces) throws |
2 | 624 |
IOException, ClassNotFoundException { |
625 |
ClassLoader nonPublicLoader = null; |
|
626 |
boolean hasNonPublicInterface = false; |
|
627 |
||
628 |
// define proxy in class loader of non-public interface(s), if any |
|
10326
9feeb910a1e2
7077672: jdk8_tl nightly fail in step-2 build on 8/10/11
jjg
parents:
10324
diff
changeset
|
629 |
Class<?>[] classObjs = new Class<?>[interfaces.length]; |
2 | 630 |
for (int i = 0; i < interfaces.length; i++) { |
10324
e28265130e4f
7072353: JNDI libraries do not build with javac -Xlint:all -Werror
jjg
parents:
5506
diff
changeset
|
631 |
Class<?> cl = Class.forName(interfaces[i], false, classLoader); |
2 | 632 |
if ((cl.getModifiers() & Modifier.PUBLIC) == 0) { |
633 |
if (hasNonPublicInterface) { |
|
634 |
if (nonPublicLoader != cl.getClassLoader()) { |
|
635 |
throw new IllegalAccessError( |
|
636 |
"conflicting non-public interface class loaders"); |
|
637 |
} |
|
638 |
} else { |
|
639 |
nonPublicLoader = cl.getClassLoader(); |
|
640 |
hasNonPublicInterface = true; |
|
641 |
} |
|
642 |
} |
|
643 |
classObjs[i] = cl; |
|
644 |
} |
|
645 |
try { |
|
646 |
return Proxy.getProxyClass(hasNonPublicInterface ? |
|
647 |
nonPublicLoader : classLoader, classObjs); |
|
648 |
} catch (IllegalArgumentException e) { |
|
649 |
throw new ClassNotFoundException(null, e); |
|
650 |
} |
|
651 |
} |
|
652 |
||
653 |
} |
|
654 |
} |