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