/*
 * This code is part of Project Waterloo from King's College London
 * 
 *
 * Copyright King's College London 2012-
 *
 * @author Malcolm Lidierth, King's College London  [Contact]
 *
 * Project Waterloo is free software:  you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Project Waterloo is distributed in the hope that it will  be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see .
 *
 */
package kcl.waterloo.graphics.transforms;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.*;
import java.util.regex.Pattern;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

/**
 *
 * @author Malcolm Lidierth, King's College London  [Contact]
 */
public class Services {

    private final static ArrayList clzz = getClasses();

    /**
     * Adds a user specified class to the list of available transforms. The
     * class must implement the GJDataTransformInterface or be an immediate
     * subclass of a class that does.
     *
     * Note: classes should be added before any calls to getAvailable as
     * programmer's can, and are likely to , call that just once in any JVM
     * session and maintain the result in a static final property.
     *
     * @param clz the class to add
     */
    public static void addClass(Class clz) {
        Class[] arr = clz.getInterfaces();
        boolean ok = false;
        for (Class arr1 : arr) {
            if (arr1.equals(GJDataTransformInterface.class)) {
                ok = true;
            }
        }
        if (!ok) {
            arr = clz.getSuperclass().getInterfaces();
        }
        for (Class arr1 : arr) {
            if (arr1.equals(GJDataTransformInterface.class)) {
                ok = true;
            }
        }
        if (ok) {
            clzz.add(clz);
        } else {
        }
    }

    /**
     * Returns a list of the available data transforms
     *
     * @return a list of transforms classes in the
     * kcl.waterloo.graphics.transforms package together with any transforms
     * added with a call to addTransform
     *
     */
    public static LinkedHashMap getAvailable() {
        LinkedHashMap names = new LinkedHashMap();
        if (clzz == null) {
            return names;
        }
        for (Iterator it = clzz.iterator(); it.hasNext();) {
            Class clz = it.next();
            Method m = null;
            try {
                m = clz.getMethod("getInstance");
            } catch (NoSuchMethodException ex) {
            } catch (SecurityException ex) {
                //.getLogger(Services.class.getName()).log(Level.SEVERE, null, ex);
            }
            if (m != null) {
                try {
                    GJDataTransformInterface tr;
                    tr = (GJDataTransformInterface) m.invoke(null, (Object[]) null);
                    names.put(tr.getName(), tr);
                } catch (IllegalAccessException ex) {
                    //Logger.getLogger(Services.class.getName()).log(Level.SEVERE, null, ex);
                } catch (IllegalArgumentException ex) {
                    //Logger.getLogger(Services.class.getName()).log(Level.SEVERE, null, ex);
                } catch (InvocationTargetException ex) {
                    //Logger.getLogger(Services.class.getName()).log(Level.SEVERE, null, ex);
                }

            }
        }
        return names;
    }

    /**
     * Returns an instance of the named transform
     *
     * @param name
     * @return the GJDataTransformInterface
     */
    @SuppressWarnings(value = "unchecked")
    public static GJDataTransformInterface getInstanceForName(String name) {
        for (Iterator it = clzz.iterator(); it.hasNext();) {
            Class clz = it.next();
            Method m = null;

            try {
                m = clz.getMethod("getInstance");
            } catch (NoSuchMethodException ex) {
                //Logger.getLogger(Services.class.getName()).log(Level.SEVERE, null, ex);
            } catch (SecurityException ex) {
                //Logger.getLogger(Services.class.getName()).log(Level.SEVERE, null, ex);
            }

            if (m != null) {
                GJDataTransformInterface tr = null;
                try {
                    tr = (GJDataTransformInterface) m.invoke(null, (Object[]) null);
                } catch (IllegalAccessException ex) {
                    //Logger.getLogger(Services.class.getName()).log(Level.SEVERE, null, ex);
                } catch (IllegalArgumentException ex) {
                    //Logger.getLogger(Services.class.getName()).log(Level.SEVERE, null, ex);
                } catch (InvocationTargetException ex) {
                    //Logger.getLogger(Services.class.getName()).log(Level.SEVERE, null, ex);
                }
                if (tr != null && tr.getName().equals(name)) {
                    return tr;
                }

            }
        }
        return NOPTransform.getInstance();
    }

    /**
     * Scans all classes accessible from the context class loader which belong
     * to the given package and subpackages. Adapted from
     * http://snippets.dzone.com/posts/show/4831 and extended to support use of
     * JAR files
     *
     * @return The classes
     */
    static ArrayList getClasses() {
        ArrayList classList = new ArrayList();

        try {
            Pattern regex;
            String packageName = Services.class.getPackage().getName();
            String path = packageName.replace('.', '/');
            Enumeration resources = Services.class.getClassLoader().getResources(path);
            List dirs = new ArrayList();
            while (resources.hasMoreElements()) {
                URL resource = resources.nextElement();
                dirs.add(resource.getFile());
            }
            TreeSet classes = new TreeSet();
            for (String directory : dirs) {
                TreeSet tree = findClasses(directory, packageName, null);
                classes.addAll(tree);
            }
            for (String clazz : classes) {
                try {
                    if (GJDataTransformInterface.class.isAssignableFrom(Class.forName(clazz))
                            && !Class.forName(clazz).isInterface()
                            && !Class.forName(clazz).equals(GJAbstractDataTransform.class)) {
                        classList.add(Class.forName(clazz));
                    }
                } catch (ClassNotFoundException ex) {
                    //Logger.getLogger(Services.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        } catch (IOException ex) {
            //Logger.getLogger(Services.class.getName()).log(Level.SEVERE, null, ex);
        }
        return classList;
    }

    /**
     * Recursive method used to find all classes in a given path (directory or
     * zip file url). Directories are searched recursively. (zip files are
     * Adapted from http://snippets.dzone.com/posts/show/4831 and extended to
     * support use of JAR files)
     *
     * @param path The base directory or url from which to search.
     * @param packageName The package name for classes found inside the base
     * directory
     * @param regex an optional class name pattern. e.g. .*Test
     * @return The classes
     */
    private static TreeSet findClasses(String path, String packageName, Pattern regex) {
        TreeSet classes = new TreeSet();
        ZipInputStream zip = null;
        String[] split = path.split("!");
        InputStream in = null;
        try {
            if (path.startsWith("file:") && path.contains("!")) {
                URL jar;
                try {
                    jar = new URL(split[0]);
                } catch (MalformedURLException ex) {
                    return classes;
                }
                try {
                    in = jar.openStream();
                } catch (IOException ex) {
                    return classes;
                }
                zip = new ZipInputStream(in);
                ZipEntry entry;
                try {
                    while ((entry = zip.getNextEntry()) != null) {
                        if (entry.getName().endsWith(".class")) {
                            String className = entry.getName().replaceAll("[$].*", "").replaceAll("[.]class", "").replace('/', '.');
                            if (className.startsWith(packageName) && (regex == null || regex.matcher(className).matches())) {
                                classes.add(className);
                            }
                        }
                    }
                } catch (IOException ex) {
                    return classes;
                }
            }
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException ex) {
                }
            }
            try {
                if (zip != null) {
                    zip.close();
                }
            } catch (IOException ex) {
                return classes;
            }
        }
        File dir = new File(path);
        if (!dir.exists()) {
            return classes;
        } else {
            File[] files = dir.listFiles();
            for (File file : files) {
                if (file.isDirectory()) {
                    assert !file.getName().contains(".");
                    classes.addAll(findClasses(file.getAbsolutePath(), packageName + "." + file.getName(), regex));
                } else if (file.getName().endsWith(".class")) {
                    String className = packageName + '.' + file.getName().substring(0, file.getName().length() - 6);
                    if (regex == null || regex.matcher(className).matches()) {
                        classes.add(className);
                    }
                }
            }
        }
        return classes;
    }
}

 

Ads help maintain this website.