DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
  • Refcardz
  • Trend Reports
  • Webinars
  • Zones
  • |
    • Agile
    • AI
    • Big Data
    • Cloud
    • Database
    • DevOps
    • Integration
    • IoT
    • Java
    • Microservices
    • Open Source
    • Performance
    • Security
    • Web Dev
DZone >

Functional JarClassLoader - Warning, Really Awful

Snippets Manager user avatar by
Snippets Manager
·
Feb. 15, 07 · · Code Snippet
Like (0)
Save
Tweet
604 Views

Join the DZone community and get the full member experience.

Join For Free
Some really awful functional style Java...

Note that this depends on a bunch of other classes in the playground namespace. If you actually want to use it ask me and I'll send you the source - I didn't really feel like snippetting all the needed code. 


package playground.library.classloader;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import playground.library.functional.FunctionalUtils;
import playground.library.functional.Pair;
import playground.library.functional.iterator.FilterIterator;
import playground.library.functional.iterator.IteratorTransformer;
import playground.library.functional.Predicate;
import playground.library.functional.Transformer;
import playground.library.functional.iterator.DelegatingIterator;
import playground.library.functional.iterator.LinkingIterator;
import playground.library.jar.JarEntryIterator;
import playground.library.utils.IteratorUtils;
import playground.library.utils.IOUtils;

/**
 * ClassLoader for loading from Jar files.
 *
 * @author david
 */
public class JarClassLoader extends ClassLoader
{
    public JarClassLoader(ClassLoader parent) { super(parent); }    
    public JarClassLoader()                   { super(); }
    
    private final List     files = new ArrayList();
    
    /**
     * Provides an iterator over all pairs of (file, entry) of JarFiles associated
     * with this class loader and entries of those jar files.
     */
    private Iterator> getResources(){
        return new LinkingIterator>(
            new IteratorTransformer>>(
                new Transformer>>(){
                public Iterator> transform(JarFile file){
                    return FunctionalUtils.merge(file, new JarEntryIterator(file));}})
           .transform(JarClassLoader.this.files.iterator()));}
    
    /**
     * Searches through the available jar files to try and find a class with the given name.
     */
    @Override
    protected Class findClass(String name) throws ClassNotFoundException{
        final Iterator> resources = this.getResources();
        while (resources.hasNext()){
            final Pair resource = resources.next();
                if(resource.second.getName().equals(name)){
                    try { return this.load(resource.first.getInputStream(resource.second));}
                    catch (IOException e) { e.printStackTrace(); }}}
        throw new ClassNotFoundException();}
    
    /**
     * Loads the contents of the InputStream as a class. This doesn't validate
     * the contents, so will fail messily if you pass it something that isn't a
     * valid class file.
     */
    private Class load(final InputStream input){
        try {
            final ByteArrayOutputStream output = new ByteArrayOutputStream();
            final byte[] bytes = IOUtils.copy(input, new ByteArrayOutputStream()).toByteArray();
            return this.defineClass(null, bytes, 0, bytes.length); }
        catch (IOException e){ throw new RuntimeException(e); }
        finally{
            try{ input.close(); }
            catch (IOException e){ throw new RuntimeException(e);}}}
        
    /**
     * Provides an iterator which lazily loads the contents of the jar file as
     * classes. Will also register the jar file with the class loader's file list.
     * When the iterator is exhausted the jar file will be removed from the file list.
     */
    public Iterator> load(final JarFile file) throws IOException{
        this.files.add(file);
                
        return  
            new DelegatingIterator>(
                new IteratorTransformer>(
                    new Transformer>(){
                        public Class transform(JarEntry stream){
                            InputStream fileStream = null;

                            try{return JarClassLoader.this.load(fileStream = file.getInputStream(stream)); }
                            catch(IOException e){throw new RuntimeException(e);}
                            finally{IOUtils.close(fileStream); }}})
                .transform(
                    new FilterIterator( 
                       new Predicate(){ 
                           public boolean satisfies(JarEntry entry){
                               return entry.getName().endsWith(".class");}},
                       new JarEntryIterator(file)))){
                @Override
                public Class next(){
                    final Class clazz = super.next();
                    if (!this.hasNext()) JarClassLoader.this.files.remove(file);                    
                    return clazz;}
                
                @Override
                public boolean hasNext(){
                    final boolean hasNext = super.hasNext();
                    if (!hasNext) JarClassLoader.this.files.remove(file);
                    return hasNext;}};}

    /**
     * Loads all class files from the jar and returns a set of them.
     */
    public Set> loadAll(final JarFile file) throws IOException
    {
        return IteratorUtils.fill(new HashSet>(), this.load(file));
    }
}

Opinions expressed by DZone contributors are their own.

Popular on DZone

  • Handling Sensitive Data: A Primer
  • Waterfall Vs. Agile Methodologies: Which Is Best For Project Management?
  • Exporting and Importing Projects in Eclipse
  • Agile Coaches Without Technical Knowledge: How to Overcome the Paradox

Comments

Partner Resources

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • MVB Program
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com
  • +1 (919) 678-0300

Let's be friends:

DZone.com is powered by 

AnswerHub logo