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 org.apache.directory.shared.i18n.I18n; 026 import org.apache.directory.shared.ldap.entry.BinaryValue; 027 import org.apache.directory.shared.ldap.exception.LdapException; 028 import org.apache.directory.shared.ldap.name.NameComponentNormalizer; 029 import org.apache.directory.shared.ldap.schema.AttributeType; 030 import org.apache.directory.shared.ldap.schema.MatchingRule; 031 import org.apache.directory.shared.ldap.schema.Normalizer; 032 import org.apache.directory.shared.ldap.schema.SchemaManager; 033 import org.apache.directory.shared.ldap.util.StringTools; 034 import org.slf4j.Logger; 035 import org.slf4j.LoggerFactory; 036 037 038 /** 039 * A DN Name component Normalizer which uses the bootstrap registries to find 040 * the appropriate normalizer for the attribute of the name component with which 041 * to normalize the name component value. 042 * 043 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 044 * @version $Rev: 928296 $ 045 */ 046 public class ConcreteNameComponentNormalizer implements NameComponentNormalizer 047 { 048 /** The LoggerFactory used by this Interceptor */ 049 private static Logger LOG = LoggerFactory.getLogger( ConcreteNameComponentNormalizer.class ); 050 051 /** the schemaManager used to dynamically resolve Normalizers */ 052 private final SchemaManager schemaManager; 053 054 055 /** 056 * Creates a DN Name component Normalizer which uses the bootstrap 057 * registries to find the appropriate normalizer for the attribute of the 058 * name component with which to normalize the name component value. 059 * 060 * @param schemaManager the schemaManager used to dynamically resolve Normalizers 061 */ 062 public ConcreteNameComponentNormalizer( SchemaManager schemaManager ) 063 { 064 this.schemaManager = schemaManager; 065 } 066 067 068 private String unescape( String value ) 069 { 070 char[] newVal = new char[value.length()]; 071 int escaped = 0; 072 char high = 0; 073 char low = 0; 074 int pos = 0; 075 076 for ( char c:value.toCharArray() ) 077 { 078 switch ( escaped ) 079 { 080 case 0 : 081 if ( c == '\\' ) 082 { 083 escaped = 1; 084 } 085 else 086 { 087 newVal[pos++] = c; 088 } 089 090 break; 091 092 case 1 : 093 escaped++; 094 high = c; 095 break; 096 097 case 2 : 098 escaped=0; 099 low = c; 100 newVal[pos++] = (char)StringTools.getHexValue( high, low ); 101 102 } 103 } 104 105 return new String( newVal, 0, pos ); 106 } 107 108 /** 109 * @see NameComponentNormalizer#normalizeByName(String, String) 110 */ 111 public Object normalizeByName( String name, String value ) throws LdapException 112 { 113 AttributeType attributeType = schemaManager.lookupAttributeTypeRegistry( name ); 114 115 if ( attributeType.getSyntax().isHumanReadable() ) 116 { 117 return lookup( name ).normalize( value ); 118 } 119 else 120 { 121 try 122 { 123 String unescaped = unescape( value ); 124 byte[] valBytes = unescaped.getBytes( "UTF-8" ); 125 126 return lookup( name ).normalize( new BinaryValue( valBytes ) ); 127 } 128 catch ( UnsupportedEncodingException uee ) 129 { 130 String message = I18n.err( I18n.ERR_04222 ); 131 LOG.error( message ); 132 throw new LdapException( message ); 133 } 134 } 135 136 } 137 138 139 /** 140 * @see NameComponentNormalizer#normalizeByName(String, String) 141 */ 142 public Object normalizeByName( String name, byte[] value ) throws LdapException 143 { 144 AttributeType attributeType = schemaManager.lookupAttributeTypeRegistry( name ); 145 146 if ( !attributeType.getSyntax().isHumanReadable() ) 147 { 148 return lookup( name ).normalize( new BinaryValue( value ) ); 149 } 150 else 151 { 152 try 153 { 154 String valStr = new String( value, "UTF-8" ); 155 return lookup( name ).normalize( valStr ); 156 } 157 catch ( UnsupportedEncodingException uee ) 158 { 159 String message = I18n.err( I18n.ERR_04223 ); 160 LOG.error( message ); 161 throw new LdapException( message ); 162 } 163 } 164 } 165 166 167 /** 168 * @see NameComponentNormalizer#normalizeByOid(String, String) 169 */ 170 public Object normalizeByOid( String oid, String value ) throws LdapException 171 { 172 return lookup( oid ).normalize( value ); 173 } 174 175 176 /** 177 * @see NameComponentNormalizer#normalizeByOid(String, String) 178 */ 179 public Object normalizeByOid( String oid, byte[] value ) throws LdapException 180 { 181 return lookup( oid ).normalize( new BinaryValue( value ) ); 182 } 183 184 185 /** 186 * Looks up the Normalizer to use for a name component using the attributeId 187 * for the name component. First the attribute is resolved, then its 188 * equality matching rule is looked up. The normalizer of that matching 189 * rule is returned. 190 * 191 * @param id the name or oid of the attribute in the name component to 192 * normalize the value of 193 * @return the Normalizer to use for normalizing the value of the attribute 194 * @throws LdapException if there are failures resolving the Normalizer 195 */ 196 private Normalizer lookup( String id ) throws LdapException 197 { 198 AttributeType type = schemaManager.lookupAttributeTypeRegistry( id ); 199 MatchingRule mrule = type.getEquality(); 200 201 if ( mrule == null ) 202 { 203 return new NoOpNormalizer( id ); 204 } 205 206 return mrule.getNormalizer(); 207 } 208 209 210 /** 211 * @see NameComponentNormalizer#isDefined(String) 212 */ 213 public boolean isDefined( String id ) 214 { 215 return schemaManager.getAttributeTypeRegistry().contains( id ); 216 } 217 218 219 public String normalizeName( String attributeName ) throws LdapException 220 { 221 return schemaManager.getAttributeTypeRegistry().getOidByName( attributeName ); 222 } 223 }