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 * https://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 */ 020package org.apache.directory.api.ldap.model.schema.normalizers; 021 022 023import org.apache.directory.api.i18n.I18n; 024import org.apache.directory.api.ldap.model.entry.Value; 025import org.apache.directory.api.ldap.model.exception.LdapException; 026import org.apache.directory.api.ldap.model.schema.AttributeType; 027import org.apache.directory.api.ldap.model.schema.MatchingRule; 028import org.apache.directory.api.ldap.model.schema.Normalizer; 029import org.apache.directory.api.ldap.model.schema.SchemaManager; 030import org.apache.directory.api.util.Hex; 031import org.apache.directory.api.util.Strings; 032 033 034/** 035 * A Dn Name component Normalizer which uses the bootstrap registries to find 036 * the appropriate normalizer for the attribute of the name component with which 037 * to normalize the name component value. 038 * 039 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 040 */ 041public class ConcreteNameComponentNormalizer implements NameComponentNormalizer 042{ 043 /** the schemaManager used to dynamically resolve Normalizers */ 044 private final SchemaManager schemaManager; 045 046 047 /** 048 * Creates a Dn Name component Normalizer which uses the bootstrap 049 * registries to find the appropriate normalizer for the attribute of the 050 * name component with which to normalize the name component value. 051 * 052 * @param schemaManager the schemaManager used to dynamically resolve Normalizers 053 */ 054 public ConcreteNameComponentNormalizer( SchemaManager schemaManager ) 055 { 056 this.schemaManager = schemaManager; 057 } 058 059 060 private String unescape( String value ) 061 { 062 char[] newVal = new char[value.length()]; 063 int escaped = 0; 064 char high = 0; 065 char low; 066 int pos = 0; 067 068 for ( int index = 0; index < value.length(); index++ ) 069 { 070 char c = value.charAt( index ); 071 072 switch ( escaped ) 073 { 074 case 0: 075 if ( c == '\\' ) 076 { 077 escaped = 1; 078 } 079 else 080 { 081 newVal[pos++] = c; 082 } 083 084 break; 085 086 case 1: 087 escaped++; 088 high = c; 089 break; 090 091 case 2: 092 escaped = 0; 093 low = c; 094 newVal[pos++] = ( char ) Hex.getHexValue( high, low ); 095 break; 096 097 default: 098 throw new IllegalStateException( I18n.err( I18n.ERR_13713_ESCAPED_WRONG_VALUE, value ) ); 099 } 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}