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