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