org.mentawai.annotations.ApplicationManagerWithAnnotations.java Source code

Java tutorial

Introduction

Here is the source code for org.mentawai.annotations.ApplicationManagerWithAnnotations.java

Source

/*
 * Copyright (c) 2006 by UNESP - Universidade Estadual Paulista "JLIO DE MESQUITA FILHO"
 *               Faculdade de Cincias, Bauru, So Paulo, Brasil
 *               http://www.fc.unesp.br, http://www.unesp.br
 *
 *
 * Este arquivo  parte do programa DocFlow.
 *
 * DocFlow  um software livre; voc pode redistribui-lo e/ou
 * modifica-lo dentro dos termos da Licena Pblica Geral GNU como
 * publicada pela Fundao do Software Livre (FSF); na verso 2 da
 * Licena, ou (na sua opnio) qualquer verso.
 *
 * DocFlow  distribuido na esperana que possa ser util,
 * mas SEM NENHUMA GARANTIA; sem uma garantia implicita de ADEQUAO a qualquer
 * MERCADO ou APLICAO EM PARTICULAR. Veja a
 * Licena Pblica Geral GNU para maiores detalhes.
 *
 * Voc deve ter recebido uma cpia da Licena Pblica Geral GNU
 * junto com DocFlow, se no, escreva para a Fundao do Software
 * Livre(FSF) Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *
 * This file is part of DocFlow.
 *
 * DocFlow is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * DocFlow 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with DocFlow; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA *
 *
 *
 * Date:    06/03/2008 15:37:33
 *
 * Author:  Andr Penteado
 */

package org.mentawai.annotations;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Method;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.lang.StringEscapeUtils;
import org.mentawai.ajax.AjaxConsequence;
import org.mentawai.ajax.AjaxRenderer;
import org.mentawai.ajax.renderer.MapAjaxRenderer;
import org.mentawai.annotations.core.ActionClass;
import org.mentawai.annotations.core.ConsequenceOutput;
import org.mentawai.annotations.core.Consequences;
import org.mentawai.annotations.type.ConsequenceType;
import org.mentawai.core.ActionConfig;
import org.mentawai.core.ApplicationManager;
import org.mentawai.core.BaseAction;
import org.mentawai.core.Chain;
import org.mentawai.core.Consequence;
import org.mentawai.core.Forward;
import org.mentawai.core.Redirect;
import org.mentawai.core.StreamConsequence;

/**
 * @author Andre Penteado
 * @author Fernando Boaglio
 *
 * @since 06/03/2008 - 15:37:33
 */
public abstract class ApplicationManagerWithAnnotations extends ApplicationManager {

    private static String resources;

    @SuppressWarnings("rawtypes")
    private HashSet<Class> annotatedClasses = new HashSet<Class>();

    @Override
    public void loadActions() {
        super.loadActions();
        loadAnnotatedClasses();
    }

    private static Pattern getPackageTestJar() {
        return Pattern.compile(resources + "/[A-Za-z0-9/]*actions.*");
    }

    private static Pattern getPackageTest() {
        return Pattern.compile(".*[" + StringEscapeUtils.escapeJava(File.separator) + "](" + resources + "["
                + StringEscapeUtils.escapeJava(File.separator) + "][A-Za-z0-9"
                + StringEscapeUtils.escapeJava(File.separator) + "]*actions.*)");

    }

    @SuppressWarnings("rawtypes")
    private void findAnnotatedClass(File file) {
        if (file.isDirectory()) {
            for (File f : file.listFiles()) {
                findAnnotatedClass(f);
            }
        } else {
            Matcher m = getPackageTest().matcher(file.getAbsolutePath());
            if (m.matches() && file.getName().endsWith(".class")) {
                String className = m.group(1);
                className = className.replaceAll(StringEscapeUtils.escapeJava(File.separator), ".");
                className = className.substring(0, className.length() - 6);
                try {
                    Class klass = Class.forName(className);
                    if (BaseAction.class.isAssignableFrom(klass)) {
                        System.out.println("Add Annotated Class:" + className);
                        annotatedClasses.add(klass);
                    }
                } catch (Exception e) {
                    System.out.println("error! this class was not started:" + className);
                }
            }
        }
    }

    @SuppressWarnings("rawtypes")
    private void findAnnotatedClasses(String resources) throws IOException {
        ClassLoader cl = Thread.currentThread().getContextClassLoader();
        Enumeration<URL> urls = cl.getResources(resources);
        while (urls.hasMoreElements()) {
            URL url = urls.nextElement();
            if (url.getProtocol().equals("file")) {
                File file = new File(url.getFile());
                findAnnotatedClass(file);
            } else if (url.getProtocol().equals("jar")) {
                URL urlJar = new URL(url.getFile().split("\\!")[0]);
                JarFile jarFile;
                try {
                    jarFile = new JarFile(new File(urlJar.toURI().getPath()));
                } catch (URISyntaxException ex) {
                    Logger.getLogger(ApplicationManagerWithAnnotations.class.getName()).log(Level.SEVERE, null, ex);
                    continue;
                }
                Enumeration<JarEntry> entries = jarFile.entries();
                while (entries.hasMoreElements()) {
                    JarEntry entry = entries.nextElement();
                    if (getPackageTestJar().matcher(entry.getName()).matches()
                            && entry.getName().endsWith(".class")) {
                        String className = entry.getName().replace('/', '.').substring(0,
                                entry.getName().length() - 6);
                        try {
                            Class klass = Class.forName(className);
                            if (BaseAction.class.isAssignableFrom(klass)) {
                                System.out.println("Add Annotated Class:" + className);
                                annotatedClasses.add(klass);
                            }
                        } catch (Exception e) {
                            System.out.println("error! this class was not started:" + entry.getName());
                        }
                    }
                }
            }
        }
    }

    @SuppressWarnings("rawtypes")
    public void loadAnnotatedClasses() {
        ActionConfig ac;
        ArrayList<ActionConfig> acListForChains = new ArrayList<ActionConfig>();

        // Para carregamento das Chains
        ArrayList<String> actionName = new ArrayList<String>();
        ArrayList<String> innerActionName = new ArrayList<String>();
        ArrayList<String> actionChain = new ArrayList<String>();
        ArrayList<String> innerChain = new ArrayList<String>();

        if (resources == null) {
            System.out.println("NO RESOURCES DEFINED");
            return;
        }

        try {
            System.out.println("Searching for annotated classes inside package [" + resources + "]...");
            findAnnotatedClasses(resources);
        } catch (Exception e) {
            System.out.println("COULD NOT LOAD PACKAGE ANNOTATED CLASSES: ");
            e.printStackTrace();
            return;
        }
        HashSet<Class> annotatedRemove = new HashSet<Class>();
        for (Class<? extends Object> klass : annotatedClasses) {
            if (klass.getSuperclass().isAnnotationPresent(ActionClass.class)) {
                annotatedRemove.add(klass.getSuperclass());
                System.out.println("REMOVING " + klass.getSuperclass()
                        + ": this actions will be mapped by its subclass " + klass.getName() + ".");
            }
        }
        for (Class<? extends Object> klass2Remove : annotatedRemove) {
            annotatedClasses.remove(klass2Remove);
        }

        if (annotatedClasses.size() > 0) {
            for (Class<? extends Object> klass : annotatedClasses) {
                if (klass.isAnnotationPresent(ActionClass.class)) {
                    System.out.println("LOADING ANNOTATED ACTION CLASS: " + klass.getName());

                    // Mapear o prefixo da ao com a classe de ao
                    ActionClass annotation = klass.getAnnotation(ActionClass.class);
                    if (getActions().containsKey(annotation.prefix())) {
                        ac = getActions().get(annotation.prefix());
                        if (ac.getActionClass().isAssignableFrom(klass)) {
                            ac = new ActionConfig(annotation.prefix(), klass);
                        }
                    } else
                        ac = new ActionConfig(annotation.prefix(), klass);

                    // Mapear as consequencias default (sem mtodo de ao) da
                    // classe
                    ConsequenceOutput[] outputsClass = annotation.outputs();
                    if (outputsClass != null && outputsClass.length > 0) {
                        for (ConsequenceOutput output : outputsClass) {
                            if (output.type() == ConsequenceType.FORWARD) {
                                // Caso seja a consequencia padro, mapear
                                // sucesso e erro para a mesma pgina
                                if (ConsequenceOutput.SUCCESS_ERROR.equals(output.result())) {
                                    ac.addConsequence(SUCCESS, new Forward(output.page()));
                                    ac.addConsequence(ERROR, new Forward(output.page()));
                                } else
                                    ac.addConsequence(output.result(), new Forward(output.page()));
                            } else if (output.type() == ConsequenceType.REDIRECT) {
                                ac.addConsequence(output.result(),
                                        "".equals(output.page()) ? new Redirect(output.RedirectWithParameters())
                                                : new Redirect(output.page(), output.RedirectWithParameters()));
                            } else if (output.type() == ConsequenceType.STREAMCONSEQUENCE) {
                                ac.addConsequence(output.result(),
                                        "".equals(output.page()) ? new StreamConsequence()
                                                : new StreamConsequence(output.page()));
                            } else if (output.type() == ConsequenceType.AJAXCONSEQUENCE) {
                                try {
                                    AjaxRenderer ajaxRender = (AjaxRenderer) Class.forName(output.page())
                                            .newInstance();
                                    ac.addConsequence(output.result(), new AjaxConsequence(ajaxRender));
                                } catch (InstantiationException ex) {
                                    ac.addConsequence(output.result(), new AjaxConsequence(new MapAjaxRenderer()));
                                } catch (Exception ex) {
                                    System.out.println(
                                            "COULD NOT LOAD AJAX CONSEQUENCE, LOADED DEFAULT MapAjaxRenderer");
                                    ex.printStackTrace();
                                }
                            } else if (output.type() == ConsequenceType.CUSTOM) {
                                try {
                                    Consequence customObject = (Consequence) Class.forName(output.page())
                                            .newInstance();
                                    ac.addConsequence(output.result(), customObject);
                                } catch (Exception ex) {
                                    System.out.println("COULD NOT LOAD CUSTOM CONSEQUENCE: ACTION NOT LOADED: "
                                            + klass.getSimpleName());
                                    ex.printStackTrace();
                                }
                            }
                        }
                    }

                    // Mapear os mtodos de aes da classe
                    for (Method method : klass.getMethods()) {
                        if (method.isAnnotationPresent(Consequences.class)) {
                            System.out.println(
                                    "LOADING CONSEQUENCE: " + annotation.prefix() + "." + method.getName());

                            // Buscar as consequencias anotadas na classe de
                            // ao
                            ConsequenceOutput[] mapConsequences = method.getAnnotation(Consequences.class)
                                    .outputs();

                            // Mapeando as consequencias
                            if (mapConsequences != null && mapConsequences.length > 0) {
                                for (ConsequenceOutput output : mapConsequences) {
                                    if (output.type() == ConsequenceType.FORWARD) {
                                        // Caso seja a consequencia padro,
                                        // mapear sucesso e erro para a mesma
                                        // pgina
                                        if (ConsequenceOutput.SUCCESS_ERROR.equals(output.result())) {
                                            ac.addConsequence(SUCCESS, method.getName(),
                                                    new Forward(output.page()));
                                            ac.addConsequence(ERROR, method.getName(), new Forward(output.page()));
                                        } else
                                            ac.addConsequence(output.result(), method.getName(),
                                                    new Forward(output.page()));
                                    } else if (output.type() == ConsequenceType.REDIRECT) {
                                        Consequence c = null;
                                        if (output.page().equals("")) {
                                            c = new Redirect(output.RedirectWithParameters());
                                        } else {
                                            c = new Redirect(output.page(), output.RedirectWithParameters());
                                        }
                                        if (ConsequenceOutput.SUCCESS_ERROR.equals(output.result())) {
                                            ac.addConsequence(SUCCESS, method.getName(), c);
                                            ac.addConsequence(ERROR, method.getName(), c);
                                        } else {
                                            ac.addConsequence(output.result(), method.getName(), c);
                                        }
                                    } else if (output.type() == ConsequenceType.STREAMCONSEQUENCE) {
                                        ac.addConsequence(output.result(), method.getName(),
                                                "".equals(output.page()) ? new StreamConsequence()
                                                        : new StreamConsequence(output.page()));
                                    } else if (output.type() == ConsequenceType.AJAXCONSEQUENCE) {
                                        try {
                                            AjaxRenderer ajaxRender = (AjaxRenderer) Class.forName(output.page())
                                                    .newInstance();
                                            ac.addConsequence(output.result(), method.getName(),
                                                    new AjaxConsequence(ajaxRender));
                                        } catch (InstantiationException ex) {
                                            ac.addConsequence(output.result(), method.getName(),
                                                    new AjaxConsequence(new MapAjaxRenderer()));
                                        } catch (Exception ex) {
                                            System.out.println(
                                                    "COULD NOT LOAD AJAX CONSEQUENCE, LOADED DEFAULT MapAjaxRenderer");
                                            ex.printStackTrace();
                                        }
                                    } else if (output.type() == ConsequenceType.CUSTOM) {
                                        try {
                                            Consequence customObject = (Consequence) Class.forName(output.page())
                                                    .newInstance();
                                            ac.addConsequence(output.result(), method.getName(), customObject);
                                        } catch (Exception ex) {
                                            System.out.println(
                                                    "COULD NOT LOAD CUSTOM CONSEQUENCE: ACTION NOT LOADED: "
                                                            + klass.getSimpleName() + "." + method.getName());
                                            ex.printStackTrace();
                                        }
                                    } else if (output.type() == ConsequenceType.CHAIN) {
                                        String[] explodedParameter = output.page().split("\\."); // Usado
                                        // para
                                        // explodir
                                        // parameters
                                        // no
                                        // caso
                                        // de
                                        // uma
                                        // chain
                                        actionName.add(output.result());
                                        innerActionName.add(method.getName());
                                        actionChain.add(explodedParameter[0]);
                                        innerChain.add(explodedParameter.length > 1 ? explodedParameter[1] : null);
                                        acListForChains.add(ac);
                                    }
                                }
                            }
                        }
                    }
                    add(ac);
                }
            }
        }

        // Carrega as chains atrasadas porque os ActionConfigs podem ainda nao
        // ter sido carregados
        int length = actionName.size();
        Chain chain;
        for (int i = 0; i < length; i++) {
            try {
                ac = acListForChains.get(i);
                if (innerChain.get(i) == null)
                    chain = new Chain(getActionConfig(actionChain.get(i)));
                else
                    chain = new Chain(getActionConfig(actionChain.get(i)), innerChain.get(i));
                if (actionName.get(i).equals(ConsequenceOutput.SUCCESS_ERROR)) {
                    ac.addConsequence(SUCCESS, innerActionName.get(i), chain);
                    ac.addConsequence(ERROR, innerActionName.get(i), chain);
                } else {
                    ac.addConsequence(actionName.get(i), innerActionName.get(i), chain);
                }

            } catch (Exception e) {
                System.out.println("COULD NOT LOAD CHAIN CONSEQUENCE: ACTION NOT LOADED: " + actionChain.get(i)
                        + "." + innerActionName.get(i));
            }
        }
    }

    public void setResources(String resources) {
        ApplicationManagerWithAnnotations.resources = resources;
    }

}