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