001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements. See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership. The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License. You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied. See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 *
019 */
020 package org.apache.directory.shared.ldap.schema.normalizers;
021
022
023 import java.io.UnsupportedEncodingException;
024
025 import javax.naming.NamingException;
026
027 import org.apache.directory.shared.i18n.I18n;
028 import org.apache.directory.shared.ldap.entry.client.ClientBinaryValue;
029 import org.apache.directory.shared.ldap.name.NameComponentNormalizer;
030 import org.apache.directory.shared.ldap.schema.AttributeType;
031 import org.apache.directory.shared.ldap.schema.MatchingRule;
032 import org.apache.directory.shared.ldap.schema.Normalizer;
033 import org.apache.directory.shared.ldap.schema.SchemaManager;
034 import org.apache.directory.shared.ldap.util.StringTools;
035 import org.slf4j.Logger;
036 import org.slf4j.LoggerFactory;
037
038
039 /**
040 * A DN Name component Normalizer which uses the bootstrap registries to find
041 * the appropriate normalizer for the attribute of the name component with which
042 * to normalize the name component value.
043 *
044 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
045 * @version $Rev: 912436 $
046 */
047 public class ConcreteNameComponentNormalizer implements NameComponentNormalizer
048 {
049 /** The LoggerFactory used by this Interceptor */
050 private static Logger LOG = LoggerFactory.getLogger( ConcreteNameComponentNormalizer.class );
051
052 /** the schemaManager used to dynamically resolve Normalizers */
053 private final SchemaManager schemaManager;
054
055
056 /**
057 * Creates a DN Name component Normalizer which uses the bootstrap
058 * registries to find the appropriate normalizer for the attribute of the
059 * name component with which to normalize the name component value.
060 *
061 * @param schemaManager the schemaManager used to dynamically resolve Normalizers
062 */
063 public ConcreteNameComponentNormalizer( SchemaManager schemaManager )
064 {
065 this.schemaManager = schemaManager;
066 }
067
068
069 private String unescape( String value )
070 {
071 char[] newVal = new char[value.length()];
072 int escaped = 0;
073 char high = 0;
074 char low = 0;
075 int pos = 0;
076
077 for ( char c:value.toCharArray() )
078 {
079 switch ( escaped )
080 {
081 case 0 :
082 if ( c == '\\' )
083 {
084 escaped = 1;
085 }
086 else
087 {
088 newVal[pos++] = c;
089 }
090
091 break;
092
093 case 1 :
094 escaped++;
095 high = c;
096 break;
097
098 case 2 :
099 escaped=0;
100 low = c;
101 newVal[pos++] = (char)StringTools.getHexValue( high, low );
102
103 }
104 }
105
106 return new String( newVal, 0, pos );
107 }
108
109 /**
110 * @see NameComponentNormalizer#normalizeByName(String, String)
111 */
112 public Object normalizeByName( String name, String value ) throws NamingException
113 {
114 AttributeType attributeType = schemaManager.lookupAttributeTypeRegistry( name );
115
116 if ( attributeType.getSyntax().isHumanReadable() )
117 {
118 return lookup( name ).normalize( value );
119 }
120 else
121 {
122 try
123 {
124 String unescaped = unescape( value );
125 byte[] valBytes = unescaped.getBytes( "UTF-8" );
126
127 return lookup( name ).normalize( new ClientBinaryValue( valBytes ) );
128 }
129 catch ( UnsupportedEncodingException uee )
130 {
131 String message = I18n.err( I18n.ERR_04222 );
132 LOG.error( message );
133 throw new NamingException( message );
134 }
135 }
136
137 }
138
139
140 /**
141 * @see NameComponentNormalizer#normalizeByName(String, String)
142 */
143 public Object normalizeByName( String name, byte[] value ) throws NamingException
144 {
145 AttributeType attributeType = schemaManager.lookupAttributeTypeRegistry( name );
146
147 if ( !attributeType.getSyntax().isHumanReadable() )
148 {
149 return lookup( name ).normalize( new ClientBinaryValue( value ) );
150 }
151 else
152 {
153 try
154 {
155 String valStr = new String( value, "UTF-8" );
156 return lookup( name ).normalize( valStr );
157 }
158 catch ( UnsupportedEncodingException uee )
159 {
160 String message = I18n.err( I18n.ERR_04223 );
161 LOG.error( message );
162 throw new NamingException( message );
163 }
164 }
165 }
166
167
168 /**
169 * @see NameComponentNormalizer#normalizeByOid(String, String)
170 */
171 public Object normalizeByOid( String oid, String value ) throws NamingException
172 {
173 return lookup( oid ).normalize( value );
174 }
175
176
177 /**
178 * @see NameComponentNormalizer#normalizeByOid(String, String)
179 */
180 public Object normalizeByOid( String oid, byte[] value ) throws NamingException
181 {
182 return lookup( oid ).normalize( new ClientBinaryValue( value ) );
183 }
184
185
186 /**
187 * Looks up the Normalizer to use for a name component using the attributeId
188 * for the name component. First the attribute is resolved, then its
189 * equality matching rule is looked up. The normalizer of that matching
190 * rule is returned.
191 *
192 * @param id the name or oid of the attribute in the name component to
193 * normalize the value of
194 * @return the Normalizer to use for normalizing the value of the attribute
195 * @throws NamingException if there are failures resolving the Normalizer
196 */
197 private Normalizer lookup( String id ) throws NamingException
198 {
199 AttributeType type = schemaManager.lookupAttributeTypeRegistry( id );
200 MatchingRule mrule = type.getEquality();
201
202 if ( mrule == null )
203 {
204 return new NoOpNormalizer( id );
205 }
206
207 return mrule.getNormalizer();
208 }
209
210
211 /**
212 * @see NameComponentNormalizer#isDefined(String)
213 */
214 public boolean isDefined( String id )
215 {
216 return schemaManager.getAttributeTypeRegistry().contains( id );
217 }
218
219
220 public String normalizeName( String attributeName ) throws NamingException
221 {
222 return schemaManager.getAttributeTypeRegistry().getOidByName( attributeName );
223 }
224 }