Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.naming/share/classes/com/sun/jndi/ldap/LdapSchemaCtx.java
41161 views
1
/*
2
* Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
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
7
* published by the Free Software Foundation. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
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
*
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.
24
*/
25
26
package com.sun.jndi.ldap;
27
28
import javax.naming.*;
29
import javax.naming.directory.*;
30
import java.util.Hashtable;
31
import com.sun.jndi.toolkit.dir.HierMemDirCtx;
32
33
/**
34
* This is the class used to implement LDAP's GetSchema call.
35
*
36
* It subclasses HierMemDirContext for most of the functionality. It
37
* overrides functions that cause the schema definitions to change.
38
* In such a case, it write the schema to the LdapServer and (assuming
39
* there are no errors), calls it's superclass's equivalent function.
40
* Thus, the schema tree and the LDAP server's schema attributes are
41
* always in sync.
42
*/
43
44
final class LdapSchemaCtx extends HierMemDirCtx {
45
46
private static final boolean debug = false;
47
48
private static final int LEAF = 0; // schema object (e.g. attribute type defn)
49
private static final int SCHEMA_ROOT = 1; // schema tree root
50
static final int OBJECTCLASS_ROOT = 2; // root of object class subtree
51
static final int ATTRIBUTE_ROOT = 3; // root of attribute type subtree
52
static final int SYNTAX_ROOT = 4; // root of syntax subtree
53
static final int MATCHRULE_ROOT = 5; // root of matching rule subtree
54
static final int OBJECTCLASS = 6; // an object class definition
55
static final int ATTRIBUTE = 7; // an attribute type definition
56
static final int SYNTAX = 8; // a syntax definition
57
static final int MATCHRULE = 9; // a matching rule definition
58
59
private SchemaInfo info= null;
60
private boolean setupMode = true;
61
62
private int objectType;
63
64
static DirContext createSchemaTree(Hashtable<String,Object> env,
65
String subschemasubentry, LdapCtx schemaEntry,
66
Attributes schemaAttrs, boolean netscapeBug)
67
throws NamingException {
68
try {
69
LdapSchemaParser parser = new LdapSchemaParser(netscapeBug);
70
71
SchemaInfo allinfo = new SchemaInfo(subschemasubentry,
72
schemaEntry, parser);
73
74
LdapSchemaCtx root = new LdapSchemaCtx(SCHEMA_ROOT, env, allinfo);
75
LdapSchemaParser.LDAP2JNDISchema(schemaAttrs, root);
76
return root;
77
} catch (NamingException e) {
78
schemaEntry.close(); // cleanup
79
throw e;
80
}
81
}
82
83
// Called by createNewCtx
84
private LdapSchemaCtx(int objectType, Hashtable<String,Object> environment,
85
SchemaInfo info) {
86
super(environment, LdapClient.caseIgnore);
87
88
this.objectType = objectType;
89
this.info = info;
90
}
91
92
// override HierMemDirCtx.close to prevent premature GC of shared data
93
public void close() throws NamingException {
94
info.close();
95
}
96
97
// override to ignore obj and use attrs
98
// treat same as createSubcontext
99
public final void bind(Name name, Object obj, Attributes attrs)
100
throws NamingException {
101
if (!setupMode) {
102
if (obj != null) {
103
throw new IllegalArgumentException("obj must be null");
104
}
105
106
// Update server
107
addServerSchema(attrs);
108
}
109
110
// Update in-memory copy
111
LdapSchemaCtx newEntry =
112
(LdapSchemaCtx)super.doCreateSubcontext(name, attrs);
113
}
114
115
protected final void doBind(Name name, Object obj, Attributes attrs,
116
boolean useFactory) throws NamingException {
117
if (!setupMode) {
118
throw new SchemaViolationException(
119
"Cannot bind arbitrary object; use createSubcontext()");
120
} else {
121
super.doBind(name, obj, attrs, false); // always ignore factories
122
}
123
}
124
125
// override to use bind() instead
126
public final void rebind(Name name, Object obj, Attributes attrs)
127
throws NamingException {
128
try {
129
doLookup(name, false);
130
throw new SchemaViolationException(
131
"Cannot replace existing schema object");
132
} catch (NameNotFoundException e) {
133
bind(name, obj, attrs);
134
}
135
}
136
137
protected final void doRebind(Name name, Object obj, Attributes attrs,
138
boolean useFactory) throws NamingException {
139
if (!setupMode) {
140
throw new SchemaViolationException(
141
"Cannot bind arbitrary object; use createSubcontext()");
142
} else {
143
super.doRebind(name, obj, attrs, false); // always ignore factories
144
}
145
}
146
147
protected final void doUnbind(Name name) throws NamingException {
148
if (!setupMode) {
149
// Update server
150
try {
151
// Lookup entry from memory
152
LdapSchemaCtx target = (LdapSchemaCtx)doLookup(name, false);
153
154
deleteServerSchema(target.attrs);
155
} catch (NameNotFoundException e) {
156
return;
157
}
158
}
159
// Update in-memory copy
160
super.doUnbind(name);
161
}
162
163
protected final void doRename(Name oldname, Name newname)
164
throws NamingException {
165
if (!setupMode) {
166
throw new SchemaViolationException("Cannot rename a schema object");
167
} else {
168
super.doRename(oldname, newname);
169
}
170
}
171
172
protected final void doDestroySubcontext(Name name) throws NamingException {
173
if (!setupMode) {
174
// Update server
175
try {
176
// Lookup entry from memory
177
LdapSchemaCtx target = (LdapSchemaCtx)doLookup(name, false);
178
179
deleteServerSchema(target.attrs);
180
} catch (NameNotFoundException e) {
181
return;
182
}
183
}
184
185
// Update in-memory copy
186
super.doDestroySubcontext(name);
187
}
188
189
// Called to create oc, attr, syntax or matching rule roots and leaf entries
190
final LdapSchemaCtx setup(int objectType, String name, Attributes attrs)
191
throws NamingException{
192
try {
193
setupMode = true;
194
LdapSchemaCtx answer =
195
(LdapSchemaCtx) super.doCreateSubcontext(
196
new CompositeName(name), attrs);
197
198
answer.objectType = objectType;
199
answer.setupMode = false;
200
return answer;
201
} finally {
202
setupMode = false;
203
}
204
}
205
206
protected final DirContext doCreateSubcontext(Name name, Attributes attrs)
207
throws NamingException {
208
209
if (attrs == null || attrs.size() == 0) {
210
throw new SchemaViolationException(
211
"Must supply attributes describing schema");
212
}
213
214
if (!setupMode) {
215
// Update server
216
addServerSchema(attrs);
217
}
218
219
// Update in-memory copy
220
LdapSchemaCtx newEntry =
221
(LdapSchemaCtx) super.doCreateSubcontext(name, attrs);
222
return newEntry;
223
}
224
225
private static final Attributes deepClone(Attributes orig)
226
throws NamingException {
227
BasicAttributes copy = new BasicAttributes(true);
228
NamingEnumeration<? extends Attribute> attrs = orig.getAll();
229
while (attrs.hasMore()) {
230
copy.put((Attribute)attrs.next().clone());
231
}
232
return copy;
233
}
234
235
protected final void doModifyAttributes(ModificationItem[] mods)
236
throws NamingException {
237
if (setupMode) {
238
super.doModifyAttributes(mods);
239
} else {
240
Attributes copy = deepClone(attrs);
241
242
// Apply modifications to copy
243
applyMods(mods, copy);
244
245
// Update server copy
246
modifyServerSchema(attrs, copy);
247
248
// Update in-memory copy
249
attrs = copy;
250
}
251
}
252
253
// we override this so the superclass creates the right kind of contexts
254
// Default is to create LEAF objects; caller will change after creation
255
// if necessary
256
protected final HierMemDirCtx createNewCtx() {
257
LdapSchemaCtx ctx = new LdapSchemaCtx(LEAF, myEnv, info);
258
return ctx;
259
}
260
261
262
private final void addServerSchema(Attributes attrs)
263
throws NamingException {
264
Attribute schemaAttr;
265
266
switch (objectType) {
267
case OBJECTCLASS_ROOT:
268
schemaAttr = info.parser.stringifyObjDesc(attrs);
269
break;
270
271
case ATTRIBUTE_ROOT:
272
schemaAttr = info.parser.stringifyAttrDesc(attrs);
273
break;
274
275
case SYNTAX_ROOT:
276
schemaAttr = info.parser.stringifySyntaxDesc(attrs);
277
break;
278
279
case MATCHRULE_ROOT:
280
schemaAttr = info.parser.stringifyMatchRuleDesc(attrs);
281
break;
282
283
case SCHEMA_ROOT:
284
throw new SchemaViolationException(
285
"Cannot create new entry under schema root");
286
287
default:
288
throw new SchemaViolationException(
289
"Cannot create child of schema object");
290
}
291
292
Attributes holder = new BasicAttributes(true);
293
holder.put(schemaAttr);
294
//System.err.println((String)schemaAttr.get());
295
296
info.modifyAttributes(myEnv, DirContext.ADD_ATTRIBUTE, holder);
297
298
}
299
300
/**
301
* When we delete an entry, we use the original to make sure that
302
* any formatting inconsistencies are eliminated.
303
* This is because we're just deleting a value from an attribute
304
* on the server and there might not be any checks for extra spaces
305
* or parens.
306
*/
307
private final void deleteServerSchema(Attributes origAttrs)
308
throws NamingException {
309
310
Attribute origAttrVal;
311
312
switch (objectType) {
313
case OBJECTCLASS_ROOT:
314
origAttrVal = info.parser.stringifyObjDesc(origAttrs);
315
break;
316
317
case ATTRIBUTE_ROOT:
318
origAttrVal = info.parser.stringifyAttrDesc(origAttrs);
319
break;
320
321
case SYNTAX_ROOT:
322
origAttrVal = info.parser.stringifySyntaxDesc(origAttrs);
323
break;
324
325
case MATCHRULE_ROOT:
326
origAttrVal = info.parser.stringifyMatchRuleDesc(origAttrs);
327
break;
328
329
case SCHEMA_ROOT:
330
throw new SchemaViolationException(
331
"Cannot delete schema root");
332
333
default:
334
throw new SchemaViolationException(
335
"Cannot delete child of schema object");
336
}
337
338
ModificationItem[] mods = new ModificationItem[1];
339
mods[0] = new ModificationItem(DirContext.REMOVE_ATTRIBUTE, origAttrVal);
340
341
info.modifyAttributes(myEnv, mods);
342
}
343
344
/**
345
* When we modify an entry, we use the original attribute value
346
* in the schema to make sure that any formatting inconsistencies
347
* are eliminated. A modification is done by deleting the original
348
* value and adding a new value with the modification.
349
*/
350
private final void modifyServerSchema(Attributes origAttrs,
351
Attributes newAttrs) throws NamingException {
352
353
Attribute newAttrVal;
354
Attribute origAttrVal;
355
356
switch (objectType) {
357
case OBJECTCLASS:
358
origAttrVal = info.parser.stringifyObjDesc(origAttrs);
359
newAttrVal = info.parser.stringifyObjDesc(newAttrs);
360
break;
361
362
case ATTRIBUTE:
363
origAttrVal = info.parser.stringifyAttrDesc(origAttrs);
364
newAttrVal = info.parser.stringifyAttrDesc(newAttrs);
365
break;
366
367
case SYNTAX:
368
origAttrVal = info.parser.stringifySyntaxDesc(origAttrs);
369
newAttrVal = info.parser.stringifySyntaxDesc(newAttrs);
370
break;
371
372
case MATCHRULE:
373
origAttrVal = info.parser.stringifyMatchRuleDesc(origAttrs);
374
newAttrVal = info.parser.stringifyMatchRuleDesc(newAttrs);
375
break;
376
377
default:
378
throw new SchemaViolationException(
379
"Cannot modify schema root");
380
}
381
382
ModificationItem[] mods = new ModificationItem[2];
383
mods[0] = new ModificationItem(DirContext.REMOVE_ATTRIBUTE, origAttrVal);
384
mods[1] = new ModificationItem(DirContext.ADD_ATTRIBUTE, newAttrVal);
385
386
info.modifyAttributes(myEnv, mods);
387
}
388
389
private static final class SchemaInfo {
390
private LdapCtx schemaEntry;
391
private String schemaEntryName;
392
LdapSchemaParser parser;
393
private String host;
394
private int port;
395
private boolean hasLdapsScheme;
396
397
SchemaInfo(String schemaEntryName, LdapCtx schemaEntry,
398
LdapSchemaParser parser) {
399
this.schemaEntryName = schemaEntryName;
400
this.schemaEntry = schemaEntry;
401
this.parser = parser;
402
this.port = schemaEntry.port_number;
403
this.host = schemaEntry.hostname;
404
this.hasLdapsScheme = schemaEntry.hasLdapsScheme;
405
}
406
407
synchronized void close() throws NamingException {
408
if (schemaEntry != null) {
409
schemaEntry.close();
410
schemaEntry = null;
411
}
412
}
413
414
private LdapCtx reopenEntry(Hashtable<?,?> env) throws NamingException {
415
// Use subschemasubentry name as DN
416
return new LdapCtx(schemaEntryName, host, port,
417
env, hasLdapsScheme);
418
}
419
420
synchronized void modifyAttributes(Hashtable<?,?> env,
421
ModificationItem[] mods)
422
throws NamingException {
423
if (schemaEntry == null) {
424
schemaEntry = reopenEntry(env);
425
}
426
schemaEntry.modifyAttributes("", mods);
427
}
428
429
synchronized void modifyAttributes(Hashtable<?,?> env, int mod,
430
Attributes attrs) throws NamingException {
431
if (schemaEntry == null) {
432
schemaEntry = reopenEntry(env);
433
}
434
schemaEntry.modifyAttributes("", mod, attrs);
435
}
436
}
437
}
438
439