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.api.ldap.schemaextractor.impl;
21  
22  
23  import java.io.BufferedReader;
24  import java.io.File;
25  import java.io.IOException;
26  import java.io.InputStream;
27  import java.io.InputStreamReader;
28  import java.net.URL;
29  import java.util.Enumeration;
30  import java.util.HashMap;
31  import java.util.Map;
32  import java.util.regex.Pattern;
33  import java.util.zip.ZipEntry;
34  import java.util.zip.ZipException;
35  import java.util.zip.ZipFile;
36  
37  import org.slf4j.Logger;
38  import org.slf4j.LoggerFactory;
39  
40  
41  /**
42   * Lists LDIF resources available from the classpath.
43   *
44   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
45   */
46  public final class ResourceMap
47  {
48      /** the system property which can be used to load schema from a user specified
49       *  resource like a absolute path to a directory or jar file.
50       *  This is useful to start embedded DirectoryService in a servlet container environment
51       *
52       *  usage: -Dschema.resource.location=/tmp/schema
53       *                OR
54       *         -Dschema.resource.location=/tmp/api-ldap-schema-1.0.0-M13.jar
55       *  */
56      private static final String SCHEMA_RESOURCE_LOCATION = "schema.resource.location";
57  
58      /** The logger. */
59      private static final Logger LOG = LoggerFactory.getLogger( ResourceMap.class );
60  
61  
62      /**
63       * Private constructor.
64       */
65      private ResourceMap()
66      {
67      }
68  
69  
70      /**
71       * For all elements of java.class.path OR from the resource name set in the
72       * system property 'schema.resource.location' get a Map of resources
73       * Pattern pattern = Pattern.compile(".*").
74       * The keys represent resource names and the boolean parameter indicates
75       * whether or not the resource is in a Jar file.
76       *
77       * @param pattern the pattern to match
78       * @return the resources with markers - true if resource is in Jar
79       */
80      public static Map<String, Boolean> getResources( Pattern pattern )
81      {
82          HashMap<String, Boolean> retval = new HashMap<String, Boolean>();
83  
84          String schemaResourceLoc = System.getProperty( SCHEMA_RESOURCE_LOCATION, "" );
85  
86          if ( schemaResourceLoc.trim().length() > 0 )
87          {
88              LOG.debug( "loading from the user provider schema resource {}", schemaResourceLoc );
89  
90              File file = new File( schemaResourceLoc );
91  
92              if ( file.exists() )
93              {
94                  getResources( retval, schemaResourceLoc, pattern );
95              }
96              else
97              {
98                  LOG.error( "unable to load schema from the given resource value {}", schemaResourceLoc );
99              }
100         }
101         else
102         {
103             getResourcesFromClassloader( retval, pattern );
104         }
105 
106         return retval;
107     }
108 
109 
110     private static void getResources( HashMap<String, Boolean> map,
111         String element, Pattern pattern )
112     {
113         File file = new File( element );
114 
115         if ( !file.exists() )
116         {
117             // this may happen if the class path contains an element that doesn't exist
118             LOG.debug( "element {} does not exist", element );
119 
120             return;
121         }
122 
123         if ( file.isDirectory() )
124         {
125             getResourcesFromDirectory( map, file, pattern );
126         }
127         else
128         {
129             getResourcesFromJarFile( map, file, pattern );
130         }
131     }
132 
133 
134     private static void getResourcesFromJarFile( HashMap<String, Boolean> map,
135         File file, Pattern pattern )
136     {
137         ZipFile zf;
138 
139         try
140         {
141             zf = new ZipFile( file );
142         }
143         catch ( ZipException e )
144         {
145             throw new Error( e );
146         }
147         catch ( IOException e )
148         {
149             throw new Error( e );
150         }
151 
152         Enumeration<? extends ZipEntry> e = zf.entries();
153 
154         while ( e.hasMoreElements() )
155         {
156             ZipEntry ze = e.nextElement();
157             String fileName = ze.getName();
158             boolean accept = pattern.matcher( fileName ).matches();
159 
160             if ( accept )
161             {
162                 map.put( fileName, Boolean.TRUE );
163             }
164         }
165         try
166         {
167             zf.close();
168         }
169         catch ( IOException e1 )
170         {
171             throw new Error( e1 );
172         }
173     }
174 
175 
176     private static void getResourcesFromDirectory(
177         HashMap<String, Boolean> map, File directory, Pattern pattern )
178     {
179         File[] fileList = directory.listFiles();
180 
181         for ( File file : fileList )
182         {
183             if ( file.isDirectory() )
184             {
185                 getResourcesFromDirectory( map, file, pattern );
186             }
187             else
188             {
189                 try
190                 {
191                     String fileName = file.getCanonicalPath();
192                     boolean accept = pattern.matcher( fileName ).matches();
193 
194                     if ( accept )
195                     {
196                         map.put( fileName, Boolean.FALSE );
197                     }
198                 }
199                 catch ( IOException e )
200                 {
201                     LOG.error( "Cannot load file {} : {}", file.getAbsolutePath(), e.getMessage() );
202 
203                     // Continue...
204                 }
205             }
206         }
207     }
208 
209 
210     private static void getResourcesFromClassloader( HashMap<String, Boolean> map, Pattern pattern )
211     {
212         try
213         {
214             ClassLoader cl = ResourceMap.class.getClassLoader();
215             Enumeration<URL> indexes = cl.getResources( "META-INF/apacheds-schema.index" );
216 
217             while ( indexes.hasMoreElements() )
218             {
219                 URL index = null;
220 
221                 try
222                 {
223                     index = indexes.nextElement();
224                     InputStream in = index.openStream();
225                     BufferedReader reader = new BufferedReader( new InputStreamReader( in, "UTF-8" ) );
226                     String line = reader.readLine();
227 
228                     while ( line != null )
229                     {
230                         boolean accept = pattern.matcher( line ).matches();
231 
232                         if ( accept )
233                         {
234                             map.put( line, Boolean.TRUE );
235                         }
236 
237                         line = reader.readLine();
238                     }
239 
240                     reader.close();
241                 }
242                 catch ( IOException ioe )
243                 {
244                     LOG.debug( "Cannot load resource {} : {}", index, ioe.getMessage() );
245                     // Continue...
246                 }
247             }
248         }
249         catch ( IOException e )
250         {
251             LOG.debug( "Error while loading  resuce from class loaded : {}", e.getMessage() );
252             throw new Error( e );
253         }
254     }
255 }