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 * https://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 */ 020package org.apache.directory.api.ldap.schema.extractor.impl; 021 022 023import java.io.BufferedReader; 024import java.io.File; 025import java.io.IOException; 026import java.io.InputStream; 027import java.io.InputStreamReader; 028import java.net.URL; 029import java.nio.charset.StandardCharsets; 030import java.util.Enumeration; 031import java.util.HashMap; 032import java.util.Map; 033import java.util.regex.Pattern; 034import java.util.zip.ZipEntry; 035import java.util.zip.ZipFile; 036 037import org.apache.directory.api.i18n.I18n; 038import org.slf4j.Logger; 039import org.slf4j.LoggerFactory; 040 041 042/** 043 * Lists LDIF resources available from the classpath. 044 * 045 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 046 */ 047public final class ResourceMap 048{ 049 /** the system property which can be used to load schema from a user specified 050 * resource like a absolute path to a directory or jar file. 051 * This is useful to start embedded DirectoryService in a servlet container environment 052 * 053 * usage: -Dschema.resource.location=/tmp/schema 054 * OR 055 * -Dschema.resource.location=/tmp/api-ldap-schema-1.0.0-M13.jar 056 * */ 057 private static final String SCHEMA_RESOURCE_LOCATION = "schema.resource.location"; 058 059 /** The logger. */ 060 private static final Logger LOG = LoggerFactory.getLogger( ResourceMap.class ); 061 062 063 /** 064 * Private constructor. 065 */ 066 private ResourceMap() 067 { 068 } 069 070 071 /** 072 * For all elements of java.class.path OR from the resource name set in the 073 * system property 'schema.resource.location' get a Map of resources 074 * Pattern pattern = Pattern.compile(".*"). 075 * The keys represent resource names and the boolean parameter indicates 076 * whether or not the resource is in a Jar file. 077 * 078 * @param pattern the pattern to match 079 * @return the resources with markers - true if resource is in Jar 080 */ 081 public static Map<String, Boolean> getResources( Pattern pattern ) 082 { 083 HashMap<String, Boolean> retval = new HashMap<>(); 084 085 String schemaResourceLoc = System.getProperty( SCHEMA_RESOURCE_LOCATION, "" ); 086 087 if ( schemaResourceLoc.trim().length() > 0 ) 088 { 089 if ( LOG.isDebugEnabled() ) 090 { 091 LOG.debug( I18n.msg( I18n.MSG_16008_LOADING_FROM_USER_SCHEMA, schemaResourceLoc ) ); 092 } 093 094 File file = new File( schemaResourceLoc ); 095 096 if ( file.exists() ) 097 { 098 getResources( retval, schemaResourceLoc, pattern ); 099 } 100 else 101 { 102 LOG.error( I18n.err( I18n.ERR_16043_CANOT_LOAD_SCHEMA, schemaResourceLoc ) ); 103 } 104 } 105 else 106 { 107 getResourcesFromClassloader( retval, pattern ); 108 } 109 110 return retval; 111 } 112 113 114 private static void getResources( HashMap<String, Boolean> map, 115 String element, Pattern pattern ) 116 { 117 File file = new File( element ); 118 119 if ( !file.exists() ) 120 { 121 // this may happen if the class path contains an element that doesn't exist 122 if ( LOG.isDebugEnabled() ) 123 { 124 LOG.debug( I18n.msg( I18n.MSG_16009_ELEMENT_DOES_NOT_EXIST, element ) ); 125 } 126 127 return; 128 } 129 130 if ( file.isDirectory() ) 131 { 132 getResourcesFromDirectory( map, file, pattern ); 133 } 134 else 135 { 136 getResourcesFromJarFile( map, file, pattern ); 137 } 138 } 139 140 141 private static void getResourcesFromJarFile( HashMap<String, Boolean> map, 142 File file, Pattern pattern ) 143 { 144 ZipFile zf; 145 146 try 147 { 148 zf = new ZipFile( file ); 149 } 150 catch ( IOException e ) 151 { 152 throw new Error( e ); 153 } 154 155 Enumeration<? extends ZipEntry> e = zf.entries(); 156 157 while ( e.hasMoreElements() ) 158 { 159 ZipEntry ze = e.nextElement(); 160 String fileName = ze.getName(); 161 boolean accept = pattern.matcher( fileName ).matches(); 162 163 if ( accept ) 164 { 165 map.put( fileName, Boolean.TRUE ); 166 } 167 } 168 try 169 { 170 zf.close(); 171 } 172 catch ( IOException e1 ) 173 { 174 throw new Error( e1 ); 175 } 176 } 177 178 179 private static void getResourcesFromDirectory( 180 HashMap<String, Boolean> map, File directory, Pattern pattern ) 181 { 182 File[] fileList = directory.listFiles(); 183 184 if ( fileList != null ) 185 { 186 for ( File file : fileList ) 187 { 188 if ( file.isDirectory() ) 189 { 190 getResourcesFromDirectory( map, file, pattern ); 191 } 192 else 193 { 194 try 195 { 196 String fileName = file.getCanonicalPath(); 197 boolean accept = pattern.matcher( fileName ).matches(); 198 199 if ( accept ) 200 { 201 map.put( fileName, Boolean.FALSE ); 202 } 203 } 204 catch ( IOException e ) 205 { 206 LOG.error( I18n.err( I18n.ERR_16044_CANNOT_LOAD_FILE, file.getAbsolutePath(), e.getMessage() ) ); 207 208 // Continue... 209 } 210 } 211 } 212 } 213 } 214 215 216 private static void getResourcesFromClassloader( HashMap<String, Boolean> map, Pattern pattern ) 217 { 218 try 219 { 220 ClassLoader cl = ResourceMap.class.getClassLoader(); 221 Enumeration<URL> indexes = cl.getResources( "META-INF/apacheds-schema.index" ); 222 223 while ( indexes.hasMoreElements() ) 224 { 225 URL index = null; 226 227 try 228 { 229 index = indexes.nextElement(); 230 231 try ( InputStream in = index.openStream() ) 232 { 233 try ( BufferedReader reader = new BufferedReader( new InputStreamReader( in, StandardCharsets.UTF_8 ) ) ) 234 { 235 String line = reader.readLine(); 236 237 while ( line != null ) 238 { 239 boolean accept = pattern.matcher( line ).matches(); 240 241 if ( accept ) 242 { 243 map.put( line, Boolean.TRUE ); 244 } 245 246 line = reader.readLine(); 247 } 248 } 249 } 250 } 251 catch ( IOException ioe ) 252 { 253 LOG.error( I18n.err( I18n.ERR_16047_CANNOT_LOAD_RESOURCE, index, ioe.getMessage() ) ); 254 // Continue... 255 } 256 } 257 } 258 catch ( IOException e ) 259 { 260 LOG.error( I18n.err( I18n.ERR_16045_ERROR_LOADING_RESOURCE, e.getMessage() ) ); 261 throw new Error( e ); 262 } 263 } 264}