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.server.protocol.shared.store; 021 022 023 import java.io.File; 024 import java.io.FileInputStream; 025 import java.io.FileNotFoundException; 026 import java.io.InputStream; 027 import java.util.Collections; 028 import java.util.List; 029 030 import javax.naming.NamingException; 031 032 import org.apache.directory.server.core.CoreSession; 033 import org.apache.directory.server.i18n.I18n; 034 import org.apache.directory.shared.ldap.entry.DefaultServerEntry; 035 import org.apache.directory.shared.ldap.entry.Entry; 036 import org.apache.directory.shared.ldap.entry.Modification; 037 import org.apache.directory.shared.ldap.ldif.LdifEntry; 038 import org.apache.directory.shared.ldap.ldif.LdifReader; 039 import org.apache.directory.shared.ldap.name.DN; 040 import org.slf4j.Logger; 041 import org.slf4j.LoggerFactory; 042 043 044 /** 045 * Support for commands to load an LDIF file into a DirContext. 046 * 047 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 048 * @version $Rev: 927404 $, $Date: 2010-03-25 14:55:18 +0100 (Thu, 25 Mar 2010) $ 049 */ 050 public class LdifFileLoader 051 { 052 /** 053 * the log for this class 054 */ 055 private static final Logger log = LoggerFactory.getLogger( LdifFileLoader.class ); 056 057 /** 058 * a handle on the top core session 059 */ 060 protected CoreSession coreSession; 061 /** 062 * the LDIF file or directory containing LDIFs to load 063 */ 064 protected File ldif; 065 /** 066 * the filters to use while loading entries into the server 067 */ 068 protected final List<LdifLoadFilter> filters; 069 /** 070 * the class loader to use if we cannot file the file as a path 071 */ 072 protected final ClassLoader loader; 073 /** 074 * the total count of entries loaded 075 */ 076 private int count; 077 078 079 /** 080 * Creates a new instance of LdifFileLoader. 081 * 082 * @param ctx the context to load the entries into. 083 * @param ldif the file of LDIF entries to load. 084 */ 085 public LdifFileLoader( CoreSession coreSession, String ldif ) 086 { 087 this( coreSession, new File( ldif ), null ); 088 } 089 090 091 /** 092 * Creates a new instance of LdifFileLoader. 093 * 094 * @param ctx 095 * @param ldif 096 * @param filters 097 */ 098 public LdifFileLoader( CoreSession coreSession, File ldif, List<? extends LdifLoadFilter> filters ) 099 { 100 this( coreSession, ldif, filters, null ); 101 } 102 103 104 /** 105 * Creates a new instance of LdifFileLoader. 106 * 107 * @param ctx 108 * @param ldif 109 * @param filters 110 * @param loader 111 */ 112 public LdifFileLoader( CoreSession coreSession, File ldif, List<? extends LdifLoadFilter> filters, ClassLoader loader ) 113 { 114 this.coreSession = coreSession; 115 this.ldif = ldif; 116 this.loader = loader; 117 118 if ( filters == null ) 119 { 120 this.filters = Collections.emptyList(); 121 } else 122 { 123 this.filters = Collections.unmodifiableList( filters ); 124 } 125 } 126 127 128 /** 129 * Applies filters making sure failures in one filter do not effect another. 130 * 131 * @param dn the DN of the entry 132 * @param entry the attributes of the entry 133 * @return true if all filters passed the entry, false otherwise 134 */ 135 private boolean applyFilters( DN dn, Entry entry ) 136 { 137 boolean accept = true; 138 final int limit = filters.size(); 139 140 if ( limit == 0 ) 141 { 142 return true; 143 } // don't waste time with loop 144 145 for ( int ii = 0; ii < limit; ii++ ) 146 { 147 try 148 { 149 accept &= ( filters.get( ii ) ).filter( ldif, dn, entry, coreSession ); 150 } 151 catch ( NamingException e ) 152 { 153 log.warn( "filter " + filters.get( ii ) + " was bypassed due to failures", e ); 154 } 155 156 // early bypass if entry is rejected 157 if ( !accept ) 158 { 159 return false; 160 } 161 } 162 return true; 163 } 164 165 166 /** 167 * Opens the LDIF file and loads the entries into the context. 168 * 169 * @return The count of entries created. 170 */ 171 public int execute() 172 { 173 DN rdn = null; 174 InputStream in = null; 175 176 try 177 { 178 in = getLdifStream(); 179 180 for ( LdifEntry ldifEntry:new LdifReader( in ) ) 181 { 182 DN dn = ldifEntry.getDn(); 183 184 if ( ldifEntry.isEntry() ) 185 { 186 Entry entry = ldifEntry.getEntry(); 187 boolean filterAccepted = applyFilters( dn, entry ); 188 189 if ( !filterAccepted ) 190 { 191 continue; 192 } 193 194 try 195 { 196 coreSession.lookup( dn ); 197 log.info( "Found {}, will not create.", rdn ); 198 } 199 catch ( Exception e ) 200 { 201 try 202 { 203 coreSession.add( 204 new DefaultServerEntry( 205 coreSession.getDirectoryService().getSchemaManager(), entry ) ); 206 count++; 207 log.info( "Created {}.", rdn ); 208 } 209 catch ( NamingException e1 ) 210 { 211 log.info( "Could not create entry " + entry, e1 ); 212 } 213 } 214 } else 215 { 216 //modify 217 List<Modification> items = ldifEntry.getModificationItems(); 218 219 try 220 { 221 coreSession.modify( dn, items ); 222 log.info( "Modified: " + dn + " with modificationItems: " + items ); 223 } 224 catch ( NamingException e ) 225 { 226 log.info( "Could not modify: " + dn + " with modificationItems: " + items, e ); 227 } 228 } 229 } 230 } 231 catch ( FileNotFoundException fnfe ) 232 { 233 log.error( I18n.err( I18n.ERR_173 ) ); 234 } 235 catch ( Exception ioe ) 236 { 237 log.error( I18n.err( I18n.ERR_174 ), ioe ); 238 } 239 finally 240 { 241 if ( in != null ) 242 { 243 try 244 { 245 in.close(); 246 } 247 catch ( Exception e ) 248 { 249 log.error( I18n.err( I18n.ERR_175 ), e ); 250 } 251 } 252 } 253 254 return count; 255 } 256 257 258 /** 259 * Tries to find an LDIF file either on the file system or packaged within a jar. 260 * 261 * @return the input stream to the ldif file. 262 * @throws FileNotFoundException if the file cannot be found. 263 */ 264 private InputStream getLdifStream() throws FileNotFoundException 265 { 266 InputStream in; 267 268 if ( ldif.exists() ) 269 { 270 in = new FileInputStream( ldif ); 271 } else 272 { 273 if ( loader != null && ( in = loader.getResourceAsStream( ldif.getName() ) ) != null ) 274 { 275 return in; 276 } 277 278 // if file not on system see if something is bundled with the jar ... 279 in = getClass().getResourceAsStream( ldif.getName() ); 280 if ( in != null ) 281 { 282 return in; 283 } 284 285 in = ClassLoader.getSystemResourceAsStream( ldif.getName() ); 286 if ( in != null ) 287 { 288 return in; 289 } 290 291 throw new FileNotFoundException( I18n.err( I18n.ERR_173 ) ); 292 } 293 294 return in; 295 } 296 }