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   *    https://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.i18n.I18n;
24  import org.apache.directory.api.ldap.model.entry.Value;
25  import org.apache.directory.api.ldap.model.exception.LdapException;
26  import org.apache.directory.api.ldap.model.schema.AttributeType;
27  import org.apache.directory.api.ldap.model.schema.MatchingRule;
28  import org.apache.directory.api.ldap.model.schema.Normalizer;
29  import org.apache.directory.api.ldap.model.schema.SchemaManager;
30  import org.apache.directory.api.util.Hex;
31  import org.apache.directory.api.util.Strings;
32  
33  
34  /**
35   * A Dn Name component Normalizer which uses the bootstrap registries to find
36   * the appropriate normalizer for the attribute of the name component with which
37   * to normalize the name component value.
38   *
39   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
40   */
41  public class ConcreteNameComponentNormalizer implements NameComponentNormalizer
42  {
43      /** the schemaManager used to dynamically resolve Normalizers */
44      private final SchemaManager schemaManager;
45  
46  
47      /**
48       * Creates a Dn Name component Normalizer which uses the bootstrap
49       * registries to find the appropriate normalizer for the attribute of the
50       * name component with which to normalize the name component value.
51       *
52       * @param schemaManager the schemaManager used to dynamically resolve Normalizers
53       */
54      public ConcreteNameComponentNormalizer( SchemaManager schemaManager )
55      {
56          this.schemaManager = schemaManager;
57      }
58  
59  
60      private String unescape( String value )
61      {
62          char[] newVal = new char[value.length()];
63          int escaped = 0;
64          char high = 0;
65          char low;
66          int pos = 0;
67  
68          for ( int index = 0; index < value.length(); index++  )
69          {
70              char c = value.charAt( index );
71              
72              switch ( escaped )
73              {
74                  case 0:
75                      if ( c == '\\' )
76                      {
77                          escaped = 1;
78                      }
79                      else
80                      {
81                          newVal[pos++] = c;
82                      }
83  
84                      break;
85  
86                  case 1:
87                      escaped++;
88                      high = c;
89                      break;
90  
91                  case 2:
92                      escaped = 0;
93                      low = c;
94                      newVal[pos++] = ( char ) Hex.getHexValue( high, low );
95                      break;
96  
97                  default:
98                      throw new IllegalStateException( I18n.err( I18n.ERR_13713_ESCAPED_WRONG_VALUE, value ) );
99              }
100         }
101 
102         return new String( newVal, 0, pos );
103     }
104 
105 
106     /**
107      * {@inheritDoc}
108      */
109     @Override
110     public Object normalizeByName( String name, String value ) throws LdapException
111     {
112         AttributeType attributeType = schemaManager.lookupAttributeTypeRegistry( name );
113         Normalizer normalizer = lookup( name );
114 
115         if ( attributeType.getSyntax().isHumanReadable() )
116         {
117             return normalizer.normalize( value );
118         }
119         else
120         {
121             String unescaped = unescape( value );
122 
123             return normalizer.normalize( unescaped );
124         }
125     }
126 
127 
128     /**
129      * {@inheritDoc}
130      */
131     @Override
132     public Object normalizeByName( AttributeType attributeType, String value ) throws LdapException
133     {
134         MatchingRule mrule = attributeType.getEquality();
135         Normalizer normalizer;
136             
137         if ( mrule == null )
138         {
139             return new NoOpNormalizer( attributeType.getOid() );
140         }
141         else
142         {
143             normalizer = attributeType.getEquality().getNormalizer();
144         }
145 
146         if ( attributeType.getSyntax().isHumanReadable() )
147         {
148             return normalizer.normalize( value );
149         }
150         else
151         {
152             String unescaped = unescape( value );
153 
154             return normalizer.normalize( unescaped );
155         }
156     }
157 
158 
159     /**
160      * {@inheritDoc}
161      */
162     @Override
163     public Object normalizeByName( String name, byte[] value ) throws LdapException
164     {
165         AttributeType attributeType = schemaManager.getAttributeType( name );
166         
167         return new Value( attributeType, value );
168     }
169 
170 
171     /**
172      * {@inheritDoc}
173      */
174     @Override
175     public Object normalizeByOid( String oid, String value ) throws LdapException
176     {
177         return lookup( oid ).normalize( value );
178     }
179 
180 
181     /**
182      * {@inheritDoc}
183      */
184     @Override
185     public Object normalizeByOid( String oid, byte[] value ) throws LdapException
186     {
187         return lookup( oid ).normalize( Strings.utf8ToString( value ) );
188     }
189 
190 
191     /**
192      * Looks up the Normalizer to use for a name component using the attributeId
193      * for the name component.  First the attribute is resolved, then its
194      * equality matching rule is looked up.  The normalizer of that matching
195      * rule is returned.
196      *
197      * @param id the name or oid of the attribute in the name component to
198      * normalize the value of
199      * @return the Normalizer to use for normalizing the value of the attribute
200      * @throws LdapException if there are failures resolving the Normalizer
201      */
202     private Normalizer lookup( String id ) throws LdapException
203     {
204         AttributeType type = schemaManager.lookupAttributeTypeRegistry( id );
205         MatchingRule mrule = type.getEquality();
206 
207         if ( mrule == null )
208         {
209             return new NoOpNormalizer( id );
210         }
211 
212         return mrule.getNormalizer();
213     }
214 
215 
216     /**
217      * @see NameComponentNormalizer#isDefined(String)
218      */
219     @Override
220     public boolean isDefined( String id )
221     {
222         return schemaManager.getAttributeTypeRegistry().contains( id );
223     }
224 
225 
226     /**
227      * {@inheritDoc}
228      */
229     @Override
230     public String normalizeName( String attributeName ) throws LdapException
231     {
232         return schemaManager.getAttributeTypeRegistry().getOidByName( attributeName );
233     }
234 }