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 021package org.apache.directory.api.ldap.schemaloader; 022 023 024import java.io.IOException; 025import java.io.InputStream; 026import java.net.URL; 027import java.util.ArrayList; 028import java.util.HashMap; 029import java.util.List; 030import java.util.Map; 031import java.util.regex.Pattern; 032 033import org.apache.directory.api.ldap.model.entry.Entry; 034import org.apache.directory.api.ldap.model.exception.LdapException; 035import org.apache.directory.api.ldap.model.ldif.LdifEntry; 036import org.apache.directory.api.ldap.model.ldif.LdifReader; 037import org.apache.directory.api.ldap.model.schema.registries.AbstractSchemaLoader; 038import org.apache.directory.api.ldap.model.schema.registries.Schema; 039import org.slf4j.Logger; 040import org.slf4j.LoggerFactory; 041 042 043/** 044 * A schema loader based on a single monolithic ldif file containing all the schema partition elements 045 * 046 * Performs better than any other existing LDIF schema loaders. NOT DOCUMENTED atm 047 * 048 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 049 */ 050public class SingleLdifSchemaLoader extends AbstractSchemaLoader 051{ 052 /** 053 * Pattern for start of schema Dn. 054 * java.util.regex.Pattern is immutable so only one instance is needed for all uses. 055 */ 056 private static final Pattern SCHEMA_START_PATTERN = Pattern 057 .compile( "cn\\s*=\\s*[a-z0-9-_]*\\s*,\\s*ou\\s*=\\s*schema" ); 058 059 /** The logger. */ 060 private static final Logger LOG = LoggerFactory.getLogger( SingleLdifSchemaLoader.class ); 061 062 /** The schema object Rdn attribute types. */ 063 private String[] schemaObjectTypeRdns = new String[] 064 { "attributetypes", "comparators", "ditContentRules", "ditStructureRules", "matchingRules", "matchingRuleUse", 065 "nameForms", "normalizers", "objectClasses", "syntaxes", "syntaxCheckers" }; 066 067 /** The map containing ... */ 068 private Map<String, Map<String, List<Entry>>> scObjEntryMap = new HashMap<String, Map<String, List<Entry>>>(); 069 070 071 /** 072 * Instantiates a new single LDIF schema loader. 073 */ 074 public SingleLdifSchemaLoader() 075 { 076 try 077 { 078 URL resource = getClass().getClassLoader().getResource( "schema-all.ldif" ); 079 080 LOG.debug( "URL of the all schema ldif file {}", resource ); 081 082 for ( String s : schemaObjectTypeRdns ) 083 { 084 scObjEntryMap.put( s, new HashMap<String, List<Entry>>() ); 085 } 086 087 InputStream in = resource.openStream(); 088 089 initializeSchemas( in ); 090 } 091 catch ( Exception e ) 092 { 093 throw new RuntimeException( e ); 094 } 095 } 096 097 098 private void initializeSchemas( InputStream in ) throws Exception 099 { 100 LdifReader ldifReader = new LdifReader( in ); 101 102 Schema currentSchema = null; 103 104 while ( ldifReader.hasNext() ) 105 { 106 LdifEntry ldifEntry = ldifReader.next(); 107 String dn = ldifEntry.getDn().getName(); 108 109 if ( SCHEMA_START_PATTERN.matcher( dn ).matches() ) 110 { 111 Schema schema = getSchema( ldifEntry.getEntry() ); 112 schemaMap.put( schema.getSchemaName(), schema ); 113 currentSchema = schema; 114 } 115 else 116 { 117 loadSchemaObject( currentSchema.getSchemaName(), ldifEntry ); 118 } 119 } 120 121 ldifReader.close(); 122 } 123 124 125 private void loadSchemaObject( String schemaName, LdifEntry ldifEntry ) throws Exception 126 { 127 for ( String scObjTypeRdn : schemaObjectTypeRdns ) 128 { 129 Pattern regex = Pattern.compile( "m-oid\\s*=\\s*[0-9\\.]*\\s*" + ",\\s*ou\\s*=\\s*" + scObjTypeRdn 130 + "\\s*,\\s*cn\\s*=\\s*" + schemaName 131 + "\\s*,\\s*ou=schema\\s*", Pattern.CASE_INSENSITIVE ); 132 133 String dn = ldifEntry.getDn().getName(); 134 135 if ( regex.matcher( dn ).matches() ) 136 { 137 Map<String, List<Entry>> m = scObjEntryMap.get( scObjTypeRdn ); 138 List<Entry> entryList = m.get( schemaName ); 139 if ( entryList == null ) 140 { 141 entryList = new ArrayList<Entry>(); 142 entryList.add( ldifEntry.getEntry() ); 143 m.put( schemaName, entryList ); 144 } 145 else 146 { 147 entryList.add( ldifEntry.getEntry() ); 148 } 149 150 break; 151 } 152 } 153 } 154 155 156 private List<Entry> loadSchemaObjects( String schemaObjectType, Schema... schemas ) throws LdapException, 157 IOException 158 { 159 Map<String, List<Entry>> m = scObjEntryMap.get( schemaObjectType ); 160 List<Entry> atList = new ArrayList<Entry>(); 161 162 for ( Schema s : schemas ) 163 { 164 List<Entry> preLoaded = m.get( s.getSchemaName() ); 165 if ( preLoaded != null ) 166 { 167 atList.addAll( preLoaded ); 168 } 169 } 170 171 return atList; 172 } 173 174 175 /** 176 * {@inheritDoc} 177 */ 178 public List<Entry> loadAttributeTypes( Schema... schemas ) throws LdapException, IOException 179 { 180 return loadSchemaObjects( "attributetypes", schemas ); 181 } 182 183 184 /** 185 * {@inheritDoc} 186 */ 187 public List<Entry> loadComparators( Schema... schemas ) throws LdapException, IOException 188 { 189 return loadSchemaObjects( "comparators", schemas ); 190 } 191 192 193 /** 194 * {@inheritDoc} 195 */ 196 public List<Entry> loadDitContentRules( Schema... schemas ) throws LdapException, IOException 197 { 198 return loadSchemaObjects( "ditContentRules", schemas ); 199 } 200 201 202 /** 203 * {@inheritDoc} 204 */ 205 public List<Entry> loadDitStructureRules( Schema... schemas ) throws LdapException, IOException 206 { 207 return loadSchemaObjects( "ditStructureRules", schemas ); 208 } 209 210 211 /** 212 * {@inheritDoc} 213 */ 214 public List<Entry> loadMatchingRules( Schema... schemas ) throws LdapException, IOException 215 { 216 return loadSchemaObjects( "matchingRules", schemas ); 217 } 218 219 220 /** 221 * {@inheritDoc} 222 */ 223 public List<Entry> loadMatchingRuleUses( Schema... schemas ) throws LdapException, IOException 224 { 225 return loadSchemaObjects( "matchingRuleUse", schemas ); 226 } 227 228 229 /** 230 * {@inheritDoc} 231 */ 232 public List<Entry> loadNameForms( Schema... schemas ) throws LdapException, IOException 233 { 234 return loadSchemaObjects( "nameForms", schemas ); 235 } 236 237 238 /** 239 * {@inheritDoc} 240 */ 241 public List<Entry> loadNormalizers( Schema... schemas ) throws LdapException, IOException 242 { 243 return loadSchemaObjects( "normalizers", schemas ); 244 } 245 246 247 /** 248 * {@inheritDoc} 249 */ 250 public List<Entry> loadObjectClasses( Schema... schemas ) throws LdapException, IOException 251 { 252 return loadSchemaObjects( "objectClasses", schemas ); 253 } 254 255 256 /** 257 * {@inheritDoc} 258 */ 259 public List<Entry> loadSyntaxes( Schema... schemas ) throws LdapException, IOException 260 { 261 return loadSchemaObjects( "syntaxes", schemas ); 262 } 263 264 265 /** 266 * {@inheritDoc} 267 */ 268 public List<Entry> loadSyntaxCheckers( Schema... schemas ) throws LdapException, IOException 269 { 270 return loadSchemaObjects( "syntaxCheckers", schemas ); 271 } 272 273} 274 275class SchemaMarker 276{ 277 /** The start marker. */ 278 private int start; 279 280 /** The end marker. */ 281 private int end; 282 283 284 public SchemaMarker( int start ) 285 { 286 this.start = start; 287 } 288 289 290 public void setEnd( int end ) 291 { 292 this.end = end; 293 } 294 295 296 public int getStart() 297 { 298 return start; 299 } 300 301 302 public int getEnd() 303 { 304 return end; 305 } 306}