org.jahia.bin.TestServlet.java Source code

Java tutorial

Introduction

Here is the source code for org.jahia.bin.TestServlet.java

Source

/**
 * This file is part of Jahia, next-generation open source CMS:
 * Jahia's next-generation, open source CMS stems from a widely acknowledged vision
 * of enterprise application convergence - web, search, document, social and portal -
 * unified by the simplicity of web content management.
 *
 * For more information, please visit http://www.jahia.com.
 *
 * Copyright (C) 2002-2012 Jahia Solutions Group SA. All rights reserved.
 *
 * This program 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.
 *
 * This program 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 this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 *
 * As a special exception to the terms and conditions of version 2.0 of
 * the GPL (or any later version), you may redistribute this Program in connection
 * with Free/Libre and Open Source Software ("FLOSS") applications as described
 * in Jahia's FLOSS exception. You should have received a copy of the text
 * describing the FLOSS exception, and it is also available here:
 * http://www.jahia.com/license
 *
 * Commercial and Supported Versions of the program (dual licensing):
 * alternatively, commercial and supported versions of the program may be used
 * in accordance with the terms and conditions contained in a separate
 * written agreement between you and Jahia Solutions Group SA.
 *
 * If you are unsure which license is appropriate for your use,
 * please contact the sales department at sales@jahia.com.
 */

package org.jahia.bin;

import org.jahia.params.ProcessingContextFactory;
import org.jahia.params.ProcessingContext;
import org.jahia.params.BasicSessionState;
import org.jahia.params.ParamBean;
import org.jahia.services.SpringContextSingleton;
import org.jahia.services.content.JCRSessionFactory;
import org.jahia.services.usermanager.JahiaUser;
import org.jahia.test.JahiaAdminUser;
import org.jahia.test.SurefireJUnitXMLResultFormatter;
import org.jahia.exceptions.JahiaException;
import org.junit.internal.requests.FilterRequest;
import org.junit.runner.Description;
import org.junit.runner.JUnitCore;
import org.junit.runner.Request;
import org.junit.runner.Result;
import org.junit.runner.manipulation.Filter;
import org.springframework.web.context.ServletContextAware;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import java.io.*;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.*;

import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;

/**
 * JUnit test runner servlet.
 * User: toto
 * Date: Feb 11, 2009
 * Time: 4:07:40 PM
 */
@SuppressWarnings("serial")
public class TestServlet extends HttpServlet implements Controller, ServletContextAware {

    private transient static Logger logger = org.slf4j.LoggerFactory.getLogger(TestServlet.class);

    private ServletContext servletContext;

    protected void handleGet(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse)
            throws ServletException, IOException {

        //    should be protected in production
        //        if (System.getProperty("org.jahia.selftest") == null) {
        //            httpServletResponse.setStatus(HttpServletResponse.SC_FORBIDDEN);
        //            return;
        //        }

        final ProcessingContextFactory pcf = (ProcessingContextFactory) SpringContextSingleton.getInstance()
                .getContext().getBean(ProcessingContextFactory.class.getName());
        ProcessingContext ctx = null;

        try {
            // should send response wrapper !
            ctx = pcf.getContext(httpServletRequest, httpServletResponse, servletContext);
        } catch (JahiaException e) {
            logger.error("Error while trying to build ProcessingContext", e);
            return;
        }

        try {
            ctx.setOperationMode(ParamBean.EDIT);
            //            ctx.setEntryLoadRequest(new EntryLoadRequest(EntryLoadRequest.STAGING_WORKFLOW_STATE, 0, ctx.getLocales()));

            JahiaUser admin = JahiaAdminUser.getAdminUser(0);
            JCRSessionFactory.getInstance().setCurrentUser(admin);
            ctx.setTheUser(admin);
        } catch (JahiaException e) {
            logger.error("Error getting user", e);
        }

        try {
            String pathInfo = StringUtils.substringAfter(httpServletRequest.getPathInfo(), "/test");
            if (StringUtils.isNotEmpty(pathInfo)) {
                final Set<String> ignoreTests = getIgnoreTests();
                // Execute one test
                String className = pathInfo.substring(pathInfo.lastIndexOf('/') + 1);
                try {
                    JUnitCore junitcore = new JUnitCore();
                    SurefireJUnitXMLResultFormatter xmlResultFormatter = new SurefireJUnitXMLResultFormatter(
                            httpServletResponse.getOutputStream());
                    junitcore.addListener(xmlResultFormatter);
                    Class testClass = Class.forName(className);
                    List<Class> classes = getTestClasses(testClass, new ArrayList<Class>());
                    if (classes.isEmpty()) {
                        Description description = Description.createSuiteDescription(testClass);
                        xmlResultFormatter.testRunStarted(description);
                        xmlResultFormatter.testRunFinished(new Result());
                    } else {
                        junitcore.run(new FilterRequest(Request.classes(classes.toArray(new Class[classes.size()])),
                                new Filter() {

                                    @Override
                                    public boolean shouldRun(Description description) {
                                        return !ignoreTests.contains(description.getDisplayName());
                                    }

                                    @Override
                                    public String describe() {
                                        return "Filter out Jahia configured methods";
                                    }
                                }));
                    }
                } catch (Exception e) {
                    logger.error("Error executing test", e);
                }
            } else {
                WebApplicationContext webApplicationContext = (WebApplicationContext) servletContext
                        .getAttribute(WebApplicationContext.class.getName() + ".jahiaModules");
                Map<String, TestBean> testBeans = webApplicationContext.getBeansOfType(TestBean.class);

                PrintWriter pw = httpServletResponse.getWriter();
                // Return the lists of available tests
                List<String> tests = new LinkedList<String>();
                SortedSet<TestBean> s = new TreeSet<TestBean>(testBeans.values());
                for (TestBean testBean : s) {
                    for (String o : testBean.getTestCases()) {
                        tests.add(o);
                    }
                }

                for (String c : tests) {
                    pw.println(c);
                }
            }
        } finally {
            try {
                ctx.setUserGuest();
            } catch (JahiaException e) {
                logger.error(e.getMessage(), e);
            }
        }

    }

    private List<Class> getTestClasses(Class testClass, List<Class> classes) {
        Method suiteMethod = null;
        try {
            // check if there is a suite method
            suiteMethod = testClass.getMethod("suite", new Class[0]);
        } catch (NoSuchMethodException e) {
            // no appropriate suite method found. We don't report any
            // error here since it might be perfectly normal.
        }

        if (suiteMethod != null) {
            // if there is a suite method available, then try
            // to extract the suite from it. If there is an error
            // here it will be caught below and reported.
            try {
                classes = getTestClasses((Test) suiteMethod.invoke(null, new Class[0]), classes);

            } catch (Exception e) {
                logger.error("Error getting classes of suite", e);
            }
        } else {
            classes.add(testClass);
        }
        return classes;
    }

    private List<Class> getTestClasses(Test test, List<Class> classes) {
        if (test instanceof TestSuite) {
            // if there is a suite method available, then try
            // to extract the suite from it. If there is an error
            // here it will be caught below and reported.
            Set<Class> tempClasses = new HashSet<Class>();
            for (Enumeration<Test> tests = ((TestSuite) test).tests(); tests.hasMoreElements();) {
                Test currentTest = tests.nextElement();
                if (currentTest instanceof TestSuite || !tempClasses.contains(currentTest.getClass())) {
                    classes = getTestClasses(currentTest, classes);
                    tempClasses.add(currentTest.getClass());
                }
            }
        } else {
            classes.add(test.getClass());
        }
        return classes;
    }

    private Set<String> getIgnoreTests() {
        WebApplicationContext webApplicationContext = (WebApplicationContext) servletContext
                .getAttribute(WebApplicationContext.class.getName() + ".jahiaModules");
        Map<String, TestBean> testBeans = webApplicationContext.getBeansOfType(TestBean.class);

        // Return the lists of available tests
        Set<String> ignoreTests = new HashSet<String>();

        SortedSet<TestBean> s = new TreeSet<TestBean>(testBeans.values());
        for (TestBean testBean : s) {
            if (testBean.getIgnoredTests() != null) {
                ignoreTests.addAll(testBean.getIgnoredTests());
            }
        }

        return ignoreTests;
    }

    private boolean isMethodAnnotationPresent(Class<?> checkedClass, Class<? extends Annotation> annotationClass) {
        boolean isPresent = false;
        for (Method method : checkedClass.getMethods()) {
            if (method.isAnnotationPresent(annotationClass)) {
                isPresent = true;
                break;
            }
        }
        return isPresent;
    }

    private Class<?> getTestClass(String line) {
        Class<?> clazz = null;
        if (StringUtils.isNotBlank(line) && !line.trim().startsWith("#") && !line.trim().startsWith("//")) {
            String clazzName = null;
            if (line.contains("/")) {
                // assume that it is a path for .class file
                clazzName = line.trim();
                clazzName = clazzName.replace('/', '.').substring(0, clazzName.lastIndexOf('.'));
            } else {
                // assume it is fully qualified class name
                clazzName = line.trim();
            }
            try {
                Class<?> c = Class.forName(clazzName);
                if (TestCase.class.isAssignableFrom(c) || isMethodAnnotationPresent(c, org.junit.Test.class)) {
                    clazz = c;
                }
            } catch (ClassNotFoundException e) {
                logger.error("Error finding class for name " + line, e);
            }
        }

        return clazz;
    }

    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
        if (request.getMethod().equalsIgnoreCase("get")) {
            handleGet(request, response);
        } else {
            response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
        }
        return null;
    }

    public void setServletContext(ServletContext servletContext) {
        this.servletContext = servletContext;
    }

    private List<String> readTests(String resource, boolean verify) {
        InputStream is = getClass().getClassLoader().getResourceAsStream(resource);
        List<String> tests = Collections.emptyList();
        try {
            if (is != null) {
                tests = new LinkedList<String>();
                @SuppressWarnings("unchecked")
                List<String> lines = IOUtils.readLines(is);
                for (String line : lines) {
                    if (verify) {
                        // check the class
                        Class<?> c = getTestClass(line);
                        if (c != null) {
                            tests.add(c.getName());
                        }
                    } else if (StringUtils.isNotBlank(line) && !line.trim().startsWith("#")
                            && !line.trim().startsWith("//")) {
                        // just add an non-empty line
                        tests.add(line);
                    }
                }
            }
        } catch (Exception e) {
            logger.warn("Unable to read class names from the resource " + resource);
        } finally {
            IOUtils.closeQuietly(is);
        }

        return tests;
    }
}