Untitled

 avatar
unknown
plain_text
12 days ago
5.2 kB
3
Indexable
package com.dwidasa.igate.lang;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.jar.JarFile;
import java.util.zip.ZipEntry;

import com.dwidasa.igate.service.support.Parameter;
import com.dwidasa.igate.utility.Constant;

/**
 * @author yosuawilly
 */
public class MxClassLoader extends BaseClassLoader {

	LinkedList< F1< String, byte[] > > loaders = new LinkedList<>();
	List< File > parents = new ArrayList<>();
	
	private static MxClassLoader loader;
	
	/**
	 * the constructor with parameter array of paths
	 * @param paths
	 */
	public MxClassLoader( String... paths ) {
		
		for( String path : paths ) {
			
			File file = new File( path );

			F1< String, byte[] > loader = loader( file );
			if( loader == null ) {
				
				throw new RuntimeException( "Path not exists " + path );
			}
			
			parents.add( file );
			loaders.add( loader );
		}
	}
	
	/**
	 * the constructor with parameter collection of paths
	 * @param paths
	 */
	public MxClassLoader( Collection< File > paths ) {
		
		for( File file : paths ) {
			
			F1< String, byte[] > loader = loader( file );
			if( loader == null ) {
				
				throw new RuntimeException( "Path not exists " + file.getPath() );
			}
			
			parents.add( file );
			loaders.add( loader );
		}
	}
	
	/**
	 * get instance
	 * @param newInstance
	 * @return object of MxClassLoader
	 */
	public static MxClassLoader getInstance( boolean newInstance ) {
		
		if( loader == null || newInstance ) {
			
			List< String > paths = new ArrayList<>();
			
			String appLib = Parameter.get( Constant.ApplicationLibrary );
			if( appLib != null ) {
				
				String[] libs = appLib.split( "," );
				paths.addAll( Arrays.asList( libs ) );
			}
			
			paths.add( Constant.ClassPath );
			paths.add( Constant.TempDir );
			
			loader = new MxClassLoader( paths.toArray( new String[ paths.size() ] ) );
		}
		
		return loader;
	}
	
	/**
	 * get instance
	 * @return object of MxClassLoader
	 */
	public static MxClassLoader getInstance() {
		
		return getInstance( false );
	}
	
	/**
	 * initialize loader for a File
	 * @param file directory or jar file
	 * @return the loader
	 */
	protected F1< String, byte[] > loader( File file ) {
		
		if( !file.exists() ) {
			
			return null;
		}
		else if( file.isDirectory() ) {
			
			return dirLoader( file );
		}
		else {
			
			try {

				return jarLoader( file );
			}
			catch( Exception e ) {
				
				throw new RuntimeException( e );
			}
		}
	}
	
	/**
	 * find class file in class path
	 * @param filePath
	 * @param classPath
	 * @return the File
	 */
	private static File findFile( String filePath, File classPath ) {
		
		File file = new File( classPath, filePath );
		
		return file.exists() ? file : null;
	}
	
	/**
	 * initialize directory loader
	 * @param dir directory
	 * @return the loader
	 */
	protected F1< String, byte[] > dirLoader( final File dir ) {
		
		return filePath -> {
			
			File file = findFile( filePath, dir );
			if( file == null ) {
				return null;
			}
			
			try {
				return readStream( new FileInputStream( file ) );
			}
			catch( Exception e ) {
				
				throw new RuntimeException( e );
			}
		};
	}
	
	/**
	 * initialize jar loader
	 * @param jarFile
	 * @return the loader
	 */
	protected F1< String, byte[] > jarLoader( final File file ) {
		
		return filePath -> {
			
			JarFile jarFile = null;
			
			try {
				
				jarFile = new JarFile( file );
				
				ZipEntry entry = jarFile.getJarEntry( filePath );
				if( entry == null ) {
					return null;
				}
				
				return readStream( jarFile.getInputStream( entry ) );
			}
			catch( Exception e ) {
				
				throw new RuntimeException( e );
			}
			finally {
				
				try {
					
					if( jarFile != null ) jarFile.close();
				}
				catch( Exception e ) {}
			}
		};
	}

	/**
	 * loadNewClass implementation
	 */
	protected byte[] loadNewClass( String name ) {
		
		for( F1< String, byte[] > loader : loaders ) {
			
			byte[] data = loader.e( toFilePath( name ) );
			if( data != null ) {
				return data;
			}
		}
		
		return null;
	}
	
	/**
	 * getParents implementation
	 */
	protected List<File> getParents() {
		
		return parents;
	}
	
	/**
	 * read byte of stream
	 * @param inputStream
	 * @return byte
	 * @throws Exception
	 */
	private static byte[] readStream( InputStream inputStream ) throws Exception {
        
        int read;
        byte[] buffer = new byte[8192];
        ByteArrayOutputStream boTemp = new ByteArrayOutputStream();
        
        while( ( read = inputStream.read( buffer, 0, 8192 ) ) > -1 ) {
            boTemp.write( buffer, 0, read );
        }
        
        inputStream.close();
        
        return boTemp.toByteArray();
	}
	
	/**
	 * Represent a function that accept one parameter and return value
	 * @param <A> The only parameter
	 * @param <T> The return value
	 * 
	 * @author yosuawilly
	 */
	public interface F1< A, T > {
		
	    /**
	     * Evaluate or execute the function
	     * @param obj The parameter
	     * @return Result of execution
	     */
		T e( A obj );
		
	}

}
Editor is loading...
Leave a Comment