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.entry;
21
22
23 import java.text.ParseException;
24 import java.util.Arrays;
25 import java.util.Iterator;
26
27 import javax.naming.NamingEnumeration;
28 import javax.naming.NamingException;
29 import javax.naming.directory.Attributes;
30 import javax.naming.directory.BasicAttribute;
31 import javax.naming.directory.BasicAttributes;
32
33 import org.apache.directory.api.i18n.I18n;
34 import org.apache.directory.api.ldap.model.exception.LdapException;
35 import org.apache.directory.api.ldap.model.exception.LdapInvalidAttributeTypeException;
36 import org.apache.directory.api.ldap.model.exception.LdapInvalidAttributeValueException;
37 import org.apache.directory.api.ldap.model.name.Dn;
38 import org.apache.directory.api.util.Chars;
39 import org.apache.directory.api.util.Position;
40 import org.apache.directory.api.util.Strings;
41
42
43
44
45
46
47
48 public final class AttributeUtils
49 {
50 private AttributeUtils()
51 {
52 }
53
54
55
56
57
58
59
60
61
62
63
64 public static boolean containsValueCaseIgnore( javax.naming.directory.Attribute attr, Object value )
65 {
66
67 if ( attr.contains( value ) )
68 {
69 return true;
70 }
71
72 try
73 {
74 if ( value instanceof String )
75 {
76 String strVal = ( String ) value;
77
78 NamingEnumeration<?> attrVals = attr.getAll();
79
80 while ( attrVals.hasMoreElements() )
81 {
82 Object attrVal = attrVals.nextElement();
83
84 if ( attrVal instanceof String && strVal.equalsIgnoreCase( ( String ) attrVal ) )
85 {
86 return true;
87 }
88 }
89 }
90 else
91 {
92 byte[] valueBytes = ( byte[] ) value;
93
94 NamingEnumeration<?> attrVals = attr.getAll();
95
96 while ( attrVals.hasMoreElements() )
97 {
98 Object attrVal = attrVals.nextElement();
99
100 if ( attrVal instanceof byte[] && Arrays.equals( ( byte[] ) attrVal, valueBytes ) )
101 {
102 return true;
103 }
104 }
105 }
106 }
107 catch ( NamingException ne )
108 {
109 return false;
110 }
111
112 return false;
113 }
114
115
116
117
118
119
120
121
122
123
124 public static Attributes toCaseInsensitive( Attributes attributes )
125 {
126 if ( attributes == null )
127 {
128 return attributes;
129 }
130
131 if ( attributes instanceof BasicAttributes )
132 {
133 if ( attributes.isCaseIgnored() )
134 {
135
136 return attributes;
137 }
138 else
139 {
140
141
142 Attributes newAttrs = new BasicAttributes( true );
143
144 NamingEnumeration<?> attrs = attributes.getAll();
145
146 if ( attrs != null )
147 {
148
149 while ( attrs.hasMoreElements() )
150 {
151 newAttrs.put( ( javax.naming.directory.Attribute ) attrs.nextElement() );
152 }
153 }
154
155 return newAttrs;
156 }
157 }
158 else
159 {
160
161 return attributes;
162 }
163 }
164
165
166
167
168
169
170
171
172
173 private static void parseOptions( byte[] str, Position pos ) throws ParseException
174 {
175 while ( Strings.isCharASCII( str, pos.start, ';' ) )
176 {
177 pos.start++;
178
179
180 if ( !Chars.isAlphaDigitMinus( str, pos.start ) )
181 {
182
183 throw new ParseException( I18n.err( I18n.ERR_04343 ), pos.start );
184 }
185
186 pos.start++;
187
188 while ( Chars.isAlphaDigitMinus( str, pos.start ) )
189 {
190 pos.start++;
191 }
192 }
193 }
194
195
196
197
198
199
200
201
202
203
204 private static boolean parseNumber( byte[] filter, Position pos )
205 {
206 byte b = Strings.byteAt( filter, pos.start );
207
208 switch ( b )
209 {
210 case '0':
211
212 pos.start++;
213 return true;
214
215 case '1':
216 case '2':
217 case '3':
218 case '4':
219 case '5':
220 case '6':
221 case '7':
222 case '8':
223 case '9':
224 pos.start++;
225 break;
226
227 default:
228
229 return false;
230 }
231
232 while ( Chars.isDigit( filter, pos.start ) )
233 {
234 pos.start++;
235 }
236
237 return true;
238 }
239
240
241
242
243
244
245
246
247
248
249
250
251
252 private static void parseOID( byte[] str, Position pos ) throws ParseException
253 {
254
255 parseNumber( str, pos );
256
257
258 if ( !Strings.isCharASCII( str, pos.start, '.' ) )
259 {
260 throw new ParseException( I18n.err( I18n.ERR_04344 ), pos.start );
261 }
262
263 pos.start++;
264
265 if ( !parseNumber( str, pos ) )
266 {
267 throw new ParseException( I18n.err( I18n.ERR_04345 ), pos.start );
268 }
269
270 while ( true )
271 {
272
273 if ( !Strings.isCharASCII( str, pos.start, '.' ) )
274 {
275 break;
276 }
277
278 pos.start++;
279
280 if ( !parseNumber( str, pos ) )
281 {
282 throw new ParseException( I18n.err( I18n.ERR_04345 ), pos.start );
283 }
284 }
285 }
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309 public static String parseAttribute( byte[] str, Position pos, boolean withOption, boolean relaxed )
310 throws ParseException
311 {
312
313 byte b = Strings.byteAt( str, pos.start );
314
315 if ( b == '\0' )
316 {
317 throw new ParseException( I18n.err( I18n.ERR_04346 ), pos.start );
318 }
319
320 int start = pos.start;
321
322 if ( Chars.isAlpha( b ) )
323 {
324
325 pos.start++;
326
327 while ( Chars.isAlphaDigitMinus( str, pos.start ) || ( relaxed && Chars.isUnderscore( str, pos.start ) ) )
328 {
329 pos.start++;
330 }
331
332
333 if ( withOption )
334 {
335 parseOptions( str, pos );
336 }
337
338 return Strings.getString( str, start, pos.start - start, "UTF-8" );
339 }
340 else if ( Chars.isDigit( b ) )
341 {
342
343 pos.start++;
344
345
346 parseOID( str, pos );
347
348
349 if ( withOption )
350 {
351 parseOptions( str, pos );
352 }
353
354 return Strings.getString( str, start, pos.start - start, "UTF-8" );
355 }
356 else
357 {
358 throw new ParseException( I18n.err( I18n.ERR_04347 ), pos.start );
359 }
360 }
361
362
363
364
365
366
367
368
369
370 public static void applyModification( Entry entry, Modification modification ) throws LdapException
371 {
372 Attribute modAttr = modification.getAttribute();
373 String modificationId = modAttr.getUpId();
374
375 switch ( modification.getOperation() )
376 {
377 case ADD_ATTRIBUTE:
378 Attribute modifiedAttr = entry.get( modificationId );
379
380 if ( modifiedAttr == null )
381 {
382
383 entry.put( modAttr );
384 }
385 else
386 {
387
388
389 for ( Value<?> value : modAttr )
390 {
391
392
393
394 modifiedAttr.add( value );
395 }
396 }
397
398 break;
399
400 case REMOVE_ATTRIBUTE:
401 if ( modAttr.get() == null )
402 {
403
404
405
406 entry.removeAttributes( modificationId );
407 }
408 else
409 {
410
411
412 modifiedAttr = entry.get( modificationId );
413
414 if ( modifiedAttr == null )
415 {
416 break;
417 }
418
419 for ( Value<?> value : modAttr )
420 {
421
422
423
424 modifiedAttr.remove( value );
425 }
426
427 if ( modifiedAttr.size() == 0 )
428 {
429
430 entry.removeAttributes( modifiedAttr.getUpId() );
431 }
432 }
433
434 break;
435
436 case REPLACE_ATTRIBUTE:
437 if ( modAttr.get() == null )
438 {
439
440
441 entry.removeAttributes( modificationId );
442 }
443 else
444 {
445
446 entry.put( modAttr );
447 }
448
449 break;
450 default:
451 break;
452 }
453 }
454
455
456
457
458
459
460
461
462
463
464
465 public static Entry toEntry( Attributes attributes, Dn dn ) throws LdapException
466 {
467 if ( attributes instanceof BasicAttributes )
468 {
469 try
470 {
471 Entry entry = new DefaultEntry( dn );
472
473 for ( NamingEnumeration<? extends javax.naming.directory.Attribute> attrs = attributes.getAll(); attrs
474 .hasMoreElements(); )
475 {
476 javax.naming.directory.Attribute attr = attrs.nextElement();
477
478 Attribute entryAttribute = toApiAttribute( attr );
479
480 if ( entryAttribute != null )
481 {
482 entry.put( entryAttribute );
483 }
484 }
485
486 return entry;
487 }
488 catch ( LdapException ne )
489 {
490 throw new LdapInvalidAttributeTypeException( ne.getMessage(), ne );
491 }
492 }
493 else
494 {
495 return null;
496 }
497 }
498
499
500
501
502
503
504
505
506
507
508 public static Attributes toAttributes( Entry entry )
509 {
510 if ( entry != null )
511 {
512 Attributes attributes = new BasicAttributes( true );
513
514
515 for ( Iterator<Attribute> attributeIterator = entry.iterator(); attributeIterator.hasNext(); )
516 {
517 Attribute entryAttribute = attributeIterator.next();
518
519 attributes.put( toJndiAttribute( entryAttribute ) );
520 }
521
522 return attributes;
523 }
524
525 return null;
526 }
527
528
529
530
531
532
533
534
535 public static javax.naming.directory.Attribute toJndiAttribute( Attribute attribute )
536 {
537 if ( attribute != null )
538 {
539 javax.naming.directory.Attribute jndiAttribute = new BasicAttribute( attribute.getUpId() );
540
541
542 for ( Iterator<Value<?>> valueIterator = attribute.iterator(); valueIterator.hasNext(); )
543 {
544 Value<?> value = valueIterator.next();
545 jndiAttribute.add( value.getValue() );
546 }
547
548 return jndiAttribute;
549 }
550
551 return null;
552 }
553
554
555
556
557
558
559
560
561
562 public static Attribute toApiAttribute( javax.naming.directory.Attribute jndiAttribute )
563 throws LdapInvalidAttributeValueException
564 {
565 if ( jndiAttribute == null )
566 {
567 return null;
568 }
569
570 try
571 {
572 Attribute attribute = new DefaultAttribute( jndiAttribute.getID() );
573
574 for ( NamingEnumeration<?> values = jndiAttribute.getAll(); values.hasMoreElements(); )
575 {
576 Object value = values.nextElement();
577
578 if ( value instanceof String )
579 {
580 attribute.add( ( String ) value );
581 }
582 else if ( value instanceof byte[] )
583 {
584 attribute.add( ( byte[] ) value );
585 }
586 else
587 {
588 attribute.add( ( String ) null );
589 }
590 }
591
592 return attribute;
593 }
594 catch ( NamingException ne )
595 {
596 return null;
597 }
598 }
599 }