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