Never been to DZone Snippets before?

Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world

« Newer Snippets
Older Snippets »
Showing 1-4 of 4 total  RSS 

Functional JarClassLoader - warning, really awful

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<JarFile>     files = new ArrayList<JarFile>();
    
    /**
     * Provides an iterator over all pairs of (file, entry) of JarFiles associated
     * with this class loader and entries of those jar files.
     */
    private Iterator<Pair<JarFile, JarEntry>> getResources(){
        return new LinkingIterator<Pair<JarFile, JarEntry>>(
            new IteratorTransformer<JarFile, Iterator<Pair<JarFile,JarEntry>>>(
                new Transformer<JarFile, Iterator<Pair<JarFile, JarEntry>>>(){
                public Iterator<Pair<JarFile, JarEntry>> 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<Pair<JarFile,JarEntry>> resources = this.getResources();
        while (resources.hasNext()){
            final Pair<JarFile, JarEntry> 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<Class<?>> load(final JarFile file) throws IOException{
        this.files.add(file);
                
        return  
            new DelegatingIterator<Class<?>>(
                new IteratorTransformer<JarEntry, Class<?>>(
                    new Transformer<JarEntry, Class<?>>(){
                        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<JarEntry>(){ 
                           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<Class<?>> loadAll(final JarFile file) throws IOException
    {
        return IteratorUtils.fill(new HashSet<Class<?>>(), this.load(file));
    }
}

#post method in tests with a different controller

I wanted a #login method in test_helper that would allow me to easily login from any of my functional tests. However, the #post method won't allow you to set a different controller than the one in the @controller instance variable that's defined in your test's #setup. Well, by looking at how the #process method works, you can see that it just grabs the controller from @controller. Redefine that, and you're good to go:
old_controller = @controller
@controller = LoginController.new
post(
  :attempt_login,
  {:user => {:name => 'joe', :password => 'password'}}
)
@controller = old_controller

If you have several login methods, such as a #login_admin and #login_regular, you could make a wrapper to reduce duplication:
def wrap_with_controller( new_controller = LoginController )
  old_controller = @controller
  @controller = new_controller.new
  yield
  @controller = old_controller
end

def login_admin
  wrap_with_controller do
    post(
      :attempt_login,
      {:user => {:name => 'root', :password => 'password'}}
    )
  end
end

def login_regular
  wrap_with_controller do
    post(
      :attempt_login,
      {:user => {:name => 'joe', :password => 'password'}}
    )
  end
end

Python curry implementation

# Generalized version of curry, works w/ keywords too... snarfed original version
# from somewhere else ages ago, much simpler / cleaner than other implementations

curry = lambda func, *args, **kw:\
            lambda *p, **n:\
                 func(*args + p, **dict(kw.items() + n.items()))

JavaScript versions of the functions described in Martin Fowler's article "CollectionClosureMethod"

See the original article at http://www.martinfowler.com/bliki/CollectionClosureMethod.html.

These implement all the methods except the sorting related ones.
Array.prototype.select = function(detect) {
    var result = [];
    for (var i = 0; i < this.length; ++i) {
        if (detect(this[i])) {
            result.push(this[i]);
        }
    }
    return result;
};

Array.prototype.reject = function(detect) {
    var result = [];
    for (var i = 0; i < this.length; ++i) {
        if (!detect(this[i])) {
            result.push(this[i]);
        }
    }
    return result;
};

Array.prototype.partition = function(detect) {
    var yeses = [];
    var nos   = [];
    for (var i = 0; i < this.length; ++i) {
        if (detect(this[i])) {
            yeses.push(this[i]);
        } else {
            nos.push(this[i]);
        }
    }
    return [yeses, nos];
};

Array.prototype.all = function(detect) {
    for (var i = 0; i < this.length; ++i) {
        if (!detect(this[i])) {
            return false;
        }
    }
    return true;
};

Array.prototype.any = function(detect) {
    for (var i = 0; i < this.length; ++i) {
        if (detect(this[i])) {
            return true;
        }
    }
    return false;
};

Array.prototype.find = function(detect, ifNone) {
    for (var i = 0; i < this.length; ++i) {
        if (detect(this[i])) {
            return this[i];
        }
    }

    if (ifNone === null) {
        return null;
    }

    return ifNone();
};

Array.prototype.map = function(mapper) {
    var result = [];
    for (var i = 0; i < this.length; ++i) {
        result.push(mapper(this[i]));
    }
    return result;
};

Array.prototype.inject = function(initial, reducer) {
    var result = initial;
    for (var i = 0; i < this.length; ++i) {
        result = reducer(result, this[i]);
    }
    return result;
};
« Newer Snippets
Older Snippets »
Showing 1-4 of 4 total  RSS