View Javadoc
1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one
3    *  or more contributor license agreements.  See the NOTICE file
4    *  distributed with this work for additional information
5    *  regarding copyright ownership.  The ASF licenses this file
6    *  to you under the Apache License, Version 2.0 (the
7    *  "License"); you may not use this file except in compliance
8    *  with the License.  You may obtain a copy of the License at
9    *  
10   *    http://www.apache.org/licenses/LICENSE-2.0
11   *  
12   *  Unless required by applicable law or agreed to in writing,
13   *  software distributed under the License is distributed on an
14   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *  KIND, either express or implied.  See the License for the
16   *  specific language governing permissions and limitations
17   *  under the License. 
18   *  
19   */
20  package org.apache.directory.api.ldap.model.schema.normalizers;
21  
22  
23  import org.apache.directory.api.ldap.model.entry.BinaryValue;
24  import org.apache.directory.api.ldap.model.exception.LdapException;
25  import org.apache.directory.api.ldap.model.schema.AttributeType;
26  import org.apache.directory.api.ldap.model.schema.MatchingRule;
27  import org.apache.directory.api.ldap.model.schema.Normalizer;
28  import org.apache.directory.api.ldap.model.schema.SchemaManager;
29  import org.apache.directory.api.util.Hex;
30  import org.apache.directory.api.util.Strings;
31  
32  
33  /**
34   * A Dn Name component Normalizer which uses the bootstrap registries to find
35   * the appropriate normalizer for the attribute of the name component with which
36   * to normalize the name component value.
37   *
38   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
39   */
40  public class ConcreteNameComponentNormalizer implements NameComponentNormalizer
41  {
42      /** the schemaManager used to dynamically resolve Normalizers */
43      private final SchemaManager schemaManager;
44  
45  
46      /**
47       * Creates a Dn Name component Normalizer which uses the bootstrap
48       * registries to find the appropriate normalizer for the attribute of the
49       * name component with which to normalize the name component value.
50       *
51       * @param schemaManager the schemaManager used to dynamically resolve Normalizers
52       */
53      public ConcreteNameComponentNormalizer( SchemaManager schemaManager )
54      {
55          this.schemaManager = schemaManager;
56      }
57  
58  
59      private String unescape( String value )
60      {
61          char[] newVal = new char[value.length()];
62          int escaped = 0;
63          char high = 0;
64          char low;
65          int pos = 0;
66  
67          for ( int index = 0; index < value.length(); index++  )
68          {
69              char c = value.charAt( index );
70              
71              switch ( escaped )
72              {
73                  case 0:
74                      if ( c == '\\' )
75                      {
76                          escaped = 1;
77                      }
78                      else
79                      {
80                          newVal[pos++] = c;
81                      }
82  
83                      break;
84  
85                  case 1:
86                      escaped++;
87                      high = c;
88                      break;
89  
90                  case 2:
91                      escaped = 0;
92                      low = c;
93                      newVal[pos++] = ( char ) Hex.getHexValue( high, low );
94                      break;
95  
96                  default:
97                      throw new IllegalStateException( "escaped can never have such a value: " + value );
98              }
99          }
100 
101         return new String( newVal, 0, pos );
102     }
103 
104 
105     /**
106      * {@inheritDoc}
107      */
108     @Override
109     public Object normalizeByName( String name, String value ) throws LdapException
110     {
111         AttributeType attributeType = schemaManager.lookupAttributeTypeRegistry( name );
112 
113         if ( attributeType.getSyntax().isHumanReadable() )
114         {
115             return lookup( name ).normalize( value );
116         }
117         else
118         {
119             String unescaped = unescape( value );
120             byte[] valBytes = Strings.getBytesUtf8( unescaped );
121 
122             return lookup( name ).normalize( new BinaryValue( valBytes ) );
123         }
124 
125     }
126 
127 
128     /**
129      * {@inheritDoc}
130      */
131     @Override
132     public Object normalizeByName( String name, byte[] value ) throws LdapException
133     {
134         AttributeType attributeType = schemaManager.lookupAttributeTypeRegistry( name );
135 
136         if ( !attributeType.getSyntax().isHumanReadable() )
137         {
138             return lookup( name ).normalize( new BinaryValue( value ) );
139         }
140         else
141         {
142             String valStr = Strings.utf8ToString( value );
143             return lookup( name ).normalize( valStr );
144         }
145     }
146 
147 
148     /**
149      * {@inheritDoc}
150      */
151     @Override
152     public Object normalizeByOid( String oid, String value ) throws LdapException
153     {
154         return lookup( oid ).normalize( value );
155     }
156 
157 
158     /**
159      * {@inheritDoc}
160      */
161     @Override
162     public Object normalizeByOid( String oid, byte[] value ) throws LdapException
163     {
164         return lookup( oid ).normalize( new BinaryValue( value ) );
165     }
166 
167 
168     /**
169      * Looks up the Normalizer to use for a name component using the attributeId
170      * for the name component.  First the attribute is resolved, then its
171      * equality matching rule is looked up.  The normalizer of that matching
172      * rule is returned.
173      *
174      * @param id the name or oid of the attribute in the name component to
175      * normalize the value of
176      * @return the Normalizer to use for normalizing the value of the attribute
177      * @throws LdapException if there are failures resolving the Normalizer
178      */
179     private Normalizer lookup( String id ) throws LdapException
180     {
181         AttributeType type = schemaManager.lookupAttributeTypeRegistry( id );
182         MatchingRule mrule = type.getEquality();
183 
184         if ( mrule == null )
185         {
186             return new NoOpNormalizer( id );
187         }
188 
189         return mrule.getNormalizer();
190     }
191 
192 
193     /**
194      * @see NameComponentNormalizer#isDefined(String)
195      */
196     @Override
197     public boolean isDefined( String id )
198     {
199         return schemaManager.getAttributeTypeRegistry().contains( id );
200     }
201 
202 
203     @Override
204     public String normalizeName( String attributeName ) throws LdapException
205     {
206         return schemaManager.getAttributeTypeRegistry().getOidByName( attributeName );
207     }
208 }