1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.directory.api.ldap.model.schema;
21
22
23 import java.util.HashSet;
24 import java.util.List;
25 import java.util.Map;
26 import java.util.Set;
27 import java.util.UUID;
28
29 import org.apache.directory.api.i18n.I18n;
30 import org.apache.directory.api.ldap.model.constants.MetaSchemaConstants;
31 import org.apache.directory.api.ldap.model.entry.Attribute;
32 import org.apache.directory.api.ldap.model.entry.Entry;
33 import org.apache.directory.api.ldap.model.entry.Modification;
34 import org.apache.directory.api.ldap.model.entry.Value;
35 import org.apache.directory.api.ldap.model.exception.LdapException;
36 import org.apache.directory.api.util.Strings;
37
38
39
40
41
42
43
44 public final class SchemaUtils
45 {
46
47
48
49 private SchemaUtils()
50 {
51 }
52
53
54
55
56
57
58
59
60
61
62
63 public static Entry getTargetEntry( List<? extends Modification> mods, Entry entry )
64 throws LdapException
65 {
66 Entry targetEntry = entry.clone();
67
68 for ( Modification mod : mods )
69 {
70 String id = mod.getAttribute().getId();
71
72 switch ( mod.getOperation() )
73 {
74 case REPLACE_ATTRIBUTE:
75 targetEntry.put( mod.getAttribute() );
76 break;
77
78 case ADD_ATTRIBUTE:
79 Attribute combined = mod.getAttribute().clone();
80 Attribute toBeAdded = mod.getAttribute();
81 Attribute existing = entry.get( id );
82
83 if ( existing != null )
84 {
85 for ( Value<?> value : existing )
86 {
87 combined.add( value );
88 }
89 }
90
91 for ( Value<?> value : toBeAdded )
92 {
93 combined.add( value );
94 }
95
96 targetEntry.put( combined );
97 break;
98
99 case REMOVE_ATTRIBUTE:
100 Attribute toBeRemoved = mod.getAttribute();
101
102 if ( toBeRemoved.size() == 0 )
103 {
104 targetEntry.removeAttributes( id );
105 }
106 else
107 {
108 existing = targetEntry.get( id );
109
110 if ( existing != null )
111 {
112 for ( Value<?> value : toBeRemoved )
113 {
114 existing.remove( value );
115 }
116 }
117 }
118
119 break;
120
121 default:
122 throw new IllegalStateException( I18n.err( I18n.ERR_04328, mod.getOperation() ) );
123 }
124 }
125
126 return targetEntry;
127 }
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143 public static StringBuilder render( StringBuilder buf, List<String> qdescrs )
144 {
145 if ( ( qdescrs == null ) || qdescrs.isEmpty() )
146 {
147 return buf;
148 }
149 else if ( qdescrs.size() == 1 )
150 {
151 buf.append( "'" ).append( qdescrs.get( 0 ) ).append( "'" );
152 }
153 else
154 {
155 buf.append( "( " );
156
157 for ( String qdescr : qdescrs )
158 {
159 buf.append( "'" ).append( qdescr ).append( "' " );
160 }
161
162 buf.append( ")" );
163 }
164
165 return buf;
166 }
167
168
169
170
171
172
173
174
175
176
177
178
179 static StringBuilder renderQDescrs( StringBuilder buf, List<String> qdescrs )
180 {
181 if ( ( qdescrs == null ) || qdescrs.isEmpty() )
182 {
183 return buf;
184 }
185
186 if ( qdescrs.size() == 1 )
187 {
188 buf.append( '\'' ).append( qdescrs.get( 0 ) ).append( '\'' );
189 }
190 else
191 {
192 buf.append( "( " );
193
194 for ( String qdescr : qdescrs )
195 {
196 buf.append( '\'' ).append( qdescr ).append( "' " );
197 }
198
199 buf.append( ")" );
200 }
201
202 return buf;
203 }
204
205
206
207
208
209
210
211
212 private static StringBuilder renderQDString( StringBuilder buf, String qdString )
213 {
214 buf.append( '\'' );
215
216 for ( char c : qdString.toCharArray() )
217 {
218 switch ( c )
219 {
220 case 0x27:
221 buf.append( "\\27" );
222 break;
223
224 case 0x5C:
225 buf.append( "\\5C" );
226 break;
227
228 default:
229 buf.append( c );
230 break;
231 }
232 }
233
234 buf.append( '\'' );
235
236 return buf;
237 }
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252 public static StringBuilder render( ObjectClass[] ocs )
253 {
254 StringBuilder buf = new StringBuilder();
255
256 return render( buf, ocs );
257 }
258
259
260
261
262
263
264
265
266
267
268
269
270 public static StringBuilder render( StringBuilder buf, ObjectClass[] ocs )
271 {
272 if ( ocs == null || ocs.length == 0 )
273 {
274 return buf;
275 }
276 else if ( ocs.length == 1 )
277 {
278 buf.append( ocs[0].getName() );
279 }
280 else
281 {
282 buf.append( "( " );
283
284 for ( int ii = 0; ii < ocs.length; ii++ )
285 {
286 if ( ii + 1 < ocs.length )
287 {
288 buf.append( ocs[ii].getName() ).append( " $ " );
289 }
290 else
291 {
292 buf.append( ocs[ii].getName() );
293 }
294 }
295
296 buf.append( " )" );
297 }
298
299 return buf;
300 }
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315 public static StringBuilder render( AttributeType[] ats )
316 {
317 StringBuilder buf = new StringBuilder();
318
319 return render( buf, ats );
320 }
321
322
323
324
325
326
327
328
329
330
331
332
333 public static StringBuilder render( StringBuilder buf, AttributeType[] ats )
334 {
335 if ( ats == null || ats.length == 0 )
336 {
337 return buf;
338 }
339 else if ( ats.length == 1 )
340 {
341 buf.append( ats[0].getName() );
342 }
343 else
344 {
345 buf.append( "( " );
346 for ( int ii = 0; ii < ats.length; ii++ )
347 {
348 if ( ii + 1 < ats.length )
349 {
350 buf.append( ats[ii].getName() ).append( " $ " );
351 }
352 else
353 {
354 buf.append( ats[ii].getName() );
355 }
356 }
357 buf.append( " )" );
358 }
359
360 return buf;
361 }
362
363
364
365
366
367
368
369
370
371
372
373
374 public static StringBuilder render( Map<String, List<String>> extensions )
375 {
376 StringBuilder buf = new StringBuilder();
377
378 if ( extensions.isEmpty() )
379 {
380 return buf;
381 }
382
383 for ( Map.Entry<String, List<String>> entry : extensions.entrySet() )
384 {
385 buf.append( " " ).append( entry.getKey() ).append( " " );
386
387 List<String> values = entry.getValue();
388
389
390 if ( values == null || values.isEmpty() )
391 {
392 continue;
393 }
394
395
396 if ( values.size() == 1 )
397 {
398 buf.append( "'" ).append( values.get( 0 ) ).append( "' " );
399 continue;
400 }
401
402
403
404 buf.append( "( " );
405 for ( String value : values )
406 {
407 buf.append( "'" ).append( value ).append( "' " );
408 }
409 buf.append( ")" );
410 }
411
412 if ( buf.charAt( buf.length() - 1 ) != ' ' )
413 {
414 buf.append( " " );
415 }
416
417 return buf;
418 }
419
420
421
422
423
424
425
426
427
428
429 public static String render( LoadableSchemaObject description )
430 {
431 StringBuilder buf = new StringBuilder();
432 buf.append( "( " ).append( description.getOid() );
433
434 if ( description.getDescription() != null )
435 {
436 buf.append( " DESC " );
437 renderQDString( buf, description.getDescription() );
438 }
439
440 buf.append( " FQCN " ).append( description.getFqcn() );
441
442 if ( !Strings.isEmpty( description.getBytecode() ) )
443 {
444 buf.append( " BYTECODE " ).append( description.getBytecode() );
445 }
446
447 buf.append( " X-SCHEMA '" );
448 buf.append( getSchemaName( description ) );
449 buf.append( "' )" );
450
451 return buf.toString();
452 }
453
454
455 private static String getSchemaName( SchemaObject desc )
456 {
457 List<String> values = desc.getExtension( MetaSchemaConstants.X_SCHEMA_AT );
458
459 if ( values == null || values.isEmpty() )
460 {
461 return MetaSchemaConstants.SCHEMA_OTHER;
462 }
463
464 return values.get( 0 );
465 }
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482 public static String stripOptions( String attributeId )
483 {
484 int optionsPos = attributeId.indexOf( ';' );
485
486 if ( optionsPos != -1 )
487 {
488 return attributeId.substring( 0, optionsPos );
489 }
490 else
491 {
492 return attributeId;
493 }
494 }
495
496
497
498
499
500
501
502
503
504
505
506
507
508 public static Set<String> getOptions( String attributeId )
509 {
510 int optionsPos = attributeId.indexOf( ';' );
511
512 if ( optionsPos != -1 )
513 {
514 Set<String> options = new HashSet<>();
515
516 String[] res = attributeId.substring( optionsPos + 1 ).split( ";" );
517
518 for ( String option : res )
519 {
520 if ( !Strings.isEmpty( option ) )
521 {
522 options.add( option );
523 }
524 }
525
526 return options;
527 }
528 else
529 {
530 return null;
531 }
532 }
533
534
535
536
537
538
539
540 public static byte[] uuidToBytes( UUID uuid )
541 {
542 Long low = uuid.getLeastSignificantBits();
543 Long high = uuid.getMostSignificantBits();
544 byte[] bytes = new byte[16];
545
546 bytes[0] = ( byte ) ( ( high & 0xff00000000000000L ) >> 56 );
547 bytes[1] = ( byte ) ( ( high & 0x00ff000000000000L ) >> 48 );
548 bytes[2] = ( byte ) ( ( high & 0x0000ff0000000000L ) >> 40 );
549 bytes[3] = ( byte ) ( ( high & 0x000000ff00000000L ) >> 32 );
550 bytes[4] = ( byte ) ( ( high & 0x00000000ff000000L ) >> 24 );
551 bytes[5] = ( byte ) ( ( high & 0x0000000000ff0000L ) >> 16 );
552 bytes[6] = ( byte ) ( ( high & 0x000000000000ff00L ) >> 8 );
553 bytes[7] = ( byte ) ( high & 0x00000000000000ffL );
554 bytes[8] = ( byte ) ( ( low & 0xff00000000000000L ) >> 56 );
555 bytes[9] = ( byte ) ( ( low & 0x00ff000000000000L ) >> 48 );
556 bytes[10] = ( byte ) ( ( low & 0x0000ff0000000000L ) >> 40 );
557 bytes[11] = ( byte ) ( ( low & 0x000000ff00000000L ) >> 32 );
558 bytes[12] = ( byte ) ( ( low & 0x00000000ff000000L ) >> 24 );
559 bytes[13] = ( byte ) ( ( low & 0x0000000000ff0000L ) >> 16 );
560 bytes[14] = ( byte ) ( ( low & 0x000000000000ff00L ) >> 8 );
561 bytes[15] = ( byte ) ( low & 0x00000000000000ffL );
562
563 return bytes;
564 }
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591 public static boolean isAttributeNameValid( String attributeName )
592 {
593 if ( Strings.isEmpty( attributeName ) )
594 {
595 return false;
596 }
597
598
599 boolean descr;
600 boolean zero = false;
601 boolean dot = false;
602
603 char c = attributeName.charAt( 0 );
604
605 if ( ( ( c >= 'a' ) && ( c <= 'z' ) ) || ( ( c >= 'A' ) && ( c <= 'Z' ) ) )
606 {
607 descr = true;
608 }
609 else if ( ( c >= '0' ) && ( c <= '9' ) )
610 {
611 descr = false;
612
613 zero = c == '0';
614 }
615 else
616 {
617 return false;
618 }
619
620 for ( int i = 1; i < attributeName.length(); i++ )
621 {
622 c = attributeName.charAt( i );
623
624 if ( descr )
625 {
626
627 if ( ( ( c < 'a' ) || ( c > 'z' ) )
628 && ( ( c < 'A' ) || ( c > 'Z' ) )
629 && ( ( c < '0' ) || ( c > '9' ) )
630 && ( c != '-' )
631 && ( c != '_' ) )
632 {
633 return false;
634 }
635 }
636 else
637 {
638
639 if ( c == '.' )
640 {
641
642 if ( dot )
643 {
644 return false;
645 }
646
647 dot = true;
648 zero = false;
649 }
650 else if ( ( c >= '0' ) && ( c <= '9' ) )
651 {
652 dot = false;
653
654 if ( zero )
655 {
656
657 return false;
658 }
659 else if ( c == '0' )
660 {
661 zero = true;
662 }
663 }
664 else
665 {
666
667 return false;
668 }
669 }
670 }
671
672 return true;
673 }
674 }