blob: ecf138c2b7bcacdcc751dac0a40af5fa94d4bfc8 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
package org.apache.directory.api.ldap.schema.extractor.impl;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import org.apache.directory.api.i18n.I18n;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Lists LDIF resources available from the classpath.
*
* @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
*/
public final class ResourceMap
{
/** the system property which can be used to load schema from a user specified
* resource like a absolute path to a directory or jar file.
* This is useful to start embedded DirectoryService in a servlet container environment
*
* usage: -Dschema.resource.location=/tmp/schema
* OR
* -Dschema.resource.location=/tmp/api-ldap-schema-1.0.0-M13.jar
* */
private static final String SCHEMA_RESOURCE_LOCATION = "schema.resource.location";
/** The logger. */
private static final Logger LOG = LoggerFactory.getLogger( ResourceMap.class );
/**
* Private constructor.
*/
private ResourceMap()
{
}
/**
* For all elements of java.class.path OR from the resource name set in the
* system property 'schema.resource.location' get a Map of resources
* Pattern pattern = Pattern.compile(".*").
* The keys represent resource names and the boolean parameter indicates
* whether or not the resource is in a Jar file.
*
* @param pattern the pattern to match
* @return the resources with markers - true if resource is in Jar
*/
public static Map<String, Boolean> getResources( Pattern pattern )
{
HashMap<String, Boolean> retval = new HashMap<>();
String schemaResourceLoc = System.getProperty( SCHEMA_RESOURCE_LOCATION, "" );
if ( schemaResourceLoc.trim().length() > 0 )
{
if ( LOG.isDebugEnabled() )
{
LOG.debug( I18n.msg( I18n.MSG_16008_LOADING_FROM_USER_SCHEMA, schemaResourceLoc ) );
}
File file = new File( schemaResourceLoc );
if ( file.exists() )
{
getResources( retval, schemaResourceLoc, pattern );
}
else
{
LOG.error( I18n.err( I18n.ERR_16043_CANOT_LOAD_SCHEMA, schemaResourceLoc ) );
}
}
else
{
getResourcesFromClassloader( retval, pattern );
}
return retval;
}
private static void getResources( HashMap<String, Boolean> map,
String element, Pattern pattern )
{
File file = new File( element );
if ( !file.exists() )
{
// this may happen if the class path contains an element that doesn't exist
if ( LOG.isDebugEnabled() )
{
LOG.debug( I18n.msg( I18n.MSG_16009_ELEMENT_DOES_NOT_EXIST, element ) );
}
return;
}
if ( file.isDirectory() )
{
getResourcesFromDirectory( map, file, pattern );
}
else
{
getResourcesFromJarFile( map, file, pattern );
}
}
private static void getResourcesFromJarFile( HashMap<String, Boolean> map,
File file, Pattern pattern )
{
ZipFile zf;
try
{
zf = new ZipFile( file );
}
catch ( IOException e )
{
throw new Error( e );
}
Enumeration<? extends ZipEntry> e = zf.entries();
while ( e.hasMoreElements() )
{
ZipEntry ze = e.nextElement();
String fileName = ze.getName();
boolean accept = pattern.matcher( fileName ).matches();
if ( accept )
{
map.put( fileName, Boolean.TRUE );
}
}
try
{
zf.close();
}
catch ( IOException e1 )
{
throw new Error( e1 );
}
}
private static void getResourcesFromDirectory(
HashMap<String, Boolean> map, File directory, Pattern pattern )
{
File[] fileList = directory.listFiles();
if ( fileList != null )
{
for ( File file : fileList )
{
if ( file.isDirectory() )
{
getResourcesFromDirectory( map, file, pattern );
}
else
{
try
{
String fileName = file.getCanonicalPath();
boolean accept = pattern.matcher( fileName ).matches();
if ( accept )
{
map.put( fileName, Boolean.FALSE );
}
}
catch ( IOException e )
{
LOG.error( I18n.err( I18n.ERR_16044_CANNOT_LOAD_FILE, file.getAbsolutePath(), e.getMessage() ) );
// Continue...
}
}
}
}
}
private static void getResourcesFromClassloader( HashMap<String, Boolean> map, Pattern pattern )
{
try
{
ClassLoader cl = ResourceMap.class.getClassLoader();
Enumeration<URL> indexes = cl.getResources( "META-INF/apacheds-schema.index" );
while ( indexes.hasMoreElements() )
{
URL index = null;
try
{
index = indexes.nextElement();
try ( InputStream in = index.openStream() )
{
try ( BufferedReader reader = new BufferedReader( new InputStreamReader( in, StandardCharsets.UTF_8 ) ) )
{
String line = reader.readLine();
while ( line != null )
{
boolean accept = pattern.matcher( line ).matches();
if ( accept )
{
map.put( line, Boolean.TRUE );
}
line = reader.readLine();
}
}
}
}
catch ( IOException ioe )
{
LOG.error( I18n.err( I18n.ERR_16047_CANNOT_LOAD_RESOURCE, index, ioe.getMessage() ) );
// Continue...
}
}
}
catch ( IOException e )
{
LOG.error( I18n.err( I18n.ERR_16045_ERROR_LOADING_RESOURCE, e.getMessage() ) );
throw new Error( e );
}
}
}