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