View Javadoc

1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one
3    *  or more contributor license agreements.  See the NOTICE file
4    *  distributed with this work for additional information
5    *  regarding copyright ownership.  The ASF licenses this file
6    *  to you under the Apache License, Version 2.0 (the
7    *  "License"); you may not use this file except in compliance
8    *  with the License.  You may obtain a copy of the License at
9    *  
10   *    http://www.apache.org/licenses/LICENSE-2.0
11   *  
12   *  Unless required by applicable law or agreed to in writing,
13   *  software distributed under the License is distributed on an
14   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *  KIND, either express or implied.  See the License for the
16   *  specific language governing permissions and limitations
17   *  under the License. 
18   *  
19   */
20  package org.apache.directory.server.protocol.shared.store;
21  
22  
23  import java.io.BufferedReader;
24  import java.io.File;
25  import java.io.FileInputStream;
26  import java.io.FileNotFoundException;
27  import java.io.InputStream;
28  import java.io.InputStreamReader;
29  import java.util.Collections;
30  import java.util.List;
31  
32  import javax.naming.NamingException;
33  
34  import org.apache.directory.server.core.CoreSession;
35  import org.apache.directory.server.core.entry.DefaultServerEntry;
36  import org.apache.directory.shared.ldap.entry.Entry;
37  import org.apache.directory.shared.ldap.entry.Modification;
38  import org.apache.directory.shared.ldap.ldif.LdifEntry;
39  import org.apache.directory.shared.ldap.ldif.LdifReader;
40  import org.apache.directory.shared.ldap.name.LdapDN;
41  import org.slf4j.Logger;
42  import org.slf4j.LoggerFactory;
43  
44  
45  /**
46   * Support for commands to load an LDIF file into a DirContext.
47   *
48   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
49   * @version $Rev: 686082 $, $Date: 2008-08-15 01:12:09 +0200 (Fr, 15 Aug 2008) $
50   */
51  public class LdifFileLoader
52  {
53      /**
54       * the log for this class
55       */
56      private static final Logger log = LoggerFactory.getLogger( LdifFileLoader.class );
57  
58      /**
59       * a handle on the top core session
60       */
61      protected CoreSession coreSession;
62      /**
63       * the LDIF file or directory containing LDIFs to load
64       */
65      protected File ldif;
66      /**
67       * the filters to use while loading entries into the server
68       */
69      protected final List<LdifLoadFilter> filters;
70      /**
71       * the class loader to use if we cannot file the file as a path
72       */
73      protected final ClassLoader loader;
74      /**
75       * the total count of entries loaded
76       */
77      private int count;
78  
79  
80      /**
81       * Creates a new instance of LdifFileLoader.
82       *
83       * @param ctx  the context to load the entries into.
84       * @param ldif the file of LDIF entries to load.
85       */
86      public LdifFileLoader( CoreSession coreSession, String ldif )
87      {
88          this( coreSession, new File( ldif ), null );
89      }
90  
91  
92      /**
93       * Creates a new instance of LdifFileLoader.
94       *
95       * @param ctx
96       * @param ldif
97       * @param filters
98       */
99      public LdifFileLoader( CoreSession coreSession, File ldif, List<? extends LdifLoadFilter> filters )
100     {
101         this( coreSession, ldif, filters, null );
102     }
103 
104 
105     /**
106      * Creates a new instance of LdifFileLoader.
107      *
108      * @param ctx
109      * @param ldif
110      * @param filters
111      * @param loader
112      */
113     public LdifFileLoader( CoreSession coreSession, File ldif, List<? extends LdifLoadFilter> filters, ClassLoader loader )
114     {
115         this.coreSession = coreSession;
116         this.ldif = ldif;
117         this.loader = loader;
118 
119         if ( filters == null )
120         {
121             this.filters = Collections.emptyList();
122         } else
123         {
124             this.filters = Collections.unmodifiableList( filters );
125         }
126     }
127 
128 
129     /**
130      * Applies filters making sure failures in one filter do not effect another.
131      *
132      * @param dn    the DN of the entry
133      * @param entry the attributes of the entry
134      * @return true if all filters passed the entry, false otherwise
135      */
136     private boolean applyFilters( LdapDN dn, Entry entry )
137     {
138         boolean accept = true;
139         final int limit = filters.size();
140 
141         if ( limit == 0 )
142         {
143             return true;
144         } // don't waste time with loop
145 
146         for ( int ii = 0; ii < limit; ii++ )
147         {
148             try
149             {
150                 accept &= ( filters.get( ii ) ).filter( ldif, dn, entry, coreSession );
151             }
152             catch ( NamingException e )
153             {
154                 log.warn( "filter " + filters.get( ii ) + " was bypassed due to failures", e );
155             }
156 
157             // early bypass if entry is rejected
158             if ( !accept )
159             {
160                 return false;
161             }
162         }
163         return true;
164     }
165 
166 
167     /**
168      * Opens the LDIF file and loads the entries into the context.
169      *
170      * @return The count of entries created.
171      */
172     public int execute()
173     {
174         LdapDN rdn = null;
175         InputStream in = null;
176 
177         try
178         {
179             in = getLdifStream();
180 
181             for ( LdifEntry ldifEntry:new LdifReader( new BufferedReader( new InputStreamReader( in ) ) ) )
182             {
183                 LdapDN dn = ldifEntry.getDn();
184 
185                 if ( ldifEntry.isEntry() )
186                 {
187                     Entry entry = ldifEntry.getEntry();
188                     boolean filterAccepted = applyFilters( dn, entry );
189 
190                     if ( !filterAccepted )
191                     {
192                         continue;
193                     }
194 
195                     try
196                     {
197                         coreSession.lookup( dn );
198                         log.info( "Found {}, will not create.", rdn );
199                     }
200                     catch ( Exception e )
201                     {
202                         try
203                         {
204                             coreSession.add( 
205                                 new DefaultServerEntry( 
206                                     coreSession.getDirectoryService().getRegistries(), entry ) ); 
207                            count++;
208                             log.info( "Created {}.", rdn );
209                         } 
210                         catch ( NamingException e1 )
211                         {
212                             log.info( "Could not create entry " + entry, e1 );
213                         }
214                     }
215                 } else
216                 {
217                     //modify
218                     List<Modification> items = ldifEntry.getModificationItems();
219                     
220                     try
221                     {
222                         coreSession.modify( dn, items );
223                         log.info( "Modified: " + dn + " with modificationItems: " + items );
224                     }
225                     catch ( NamingException e )
226                     {
227                         log.info( "Could not modify: " + dn + " with modificationItems: " + items, e );
228                     }
229                 }
230             }
231         }
232         catch ( FileNotFoundException fnfe )
233         {
234             log.error( "LDIF file does not exist." );
235         }
236         catch ( Exception ioe )
237         {
238             log.error( "Failed to import LDIF into backing store.", ioe );
239         }
240         finally
241         {
242             if ( in != null )
243             {
244                 try
245                 {
246                     in.close();
247                 }
248                 catch ( Exception e )
249                 {
250                     log.error( "failed to close stream", e );
251                 }
252             }
253         }
254 
255         return count;
256     }
257 
258 
259     /**
260      * Tries to find an LDIF file either on the file system or packaged within a jar.
261      *
262      * @return the input stream to the ldif file.
263      * @throws FileNotFoundException if the file cannot be found.
264      */
265     private InputStream getLdifStream() throws FileNotFoundException
266     {
267         InputStream in;
268 
269         if ( ldif.exists() )
270         {
271             in = new FileInputStream( ldif );
272         } else
273         {
274             if ( loader != null && ( in = loader.getResourceAsStream( ldif.getName() ) ) != null )
275             {
276                 return in;
277             }
278 
279             // if file not on system see if something is bundled with the jar ...
280             in = getClass().getResourceAsStream( ldif.getName() );
281             if ( in != null )
282             {
283                 return in;
284             }
285 
286             in = ClassLoader.getSystemResourceAsStream( ldif.getName() );
287             if ( in != null )
288             {
289                 return in;
290             }
291 
292             throw new FileNotFoundException( "LDIF file does not exist." );
293         }
294 
295         return in;
296     }
297 }