Package org.jenkinsci.plugins.activiti_explorer

Source Code of org.jenkinsci.plugins.activiti_explorer.ActivitiExplorer

package org.jenkinsci.plugins.activiti_explorer;

import com.cisco.step.jenkins.plugins.jenkow.JenkowBuilder.DescriptorImpl;
import com.cisco.step.jenkins.plugins.jenkow.JenkowEngine;
import com.cloudbees.vietnam4j.ProxiedWebApplication;
import hudson.Extension;
import hudson.Util;
import hudson.model.UnprotectedRootAction;
import hudson.model.User;
import jenkins.model.Jenkins;
import org.acegisecurity.Authentication;
import org.activiti.engine.ProcessEngine;
import org.apache.commons.io.IOUtils;
import org.dom4j.DocumentException;
import org.jenkinsci.plugins.activiti_explorer.dto.UserDTO;
import org.jenkinsci.plugins.jenkow.activiti.override.JenkinsProcessEngineFactory;
import org.jenkinsci.plugins.jenkow.activiti.override.ServletContextDataSource;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;

import javax.inject.Inject;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.jar.JarEntry;
import java.util.jar.JarInputStream;

/**
* Activiti Explorer web application embedded inside Jenkins.
*
* @author Kohsuke Kawaguchi
*/
@Extension
public class ActivitiExplorer implements UnprotectedRootAction {
    private ProxiedWebApplication webApp;

    @Inject
    DescriptorImpl descriptor;

    public String getIconFileName() {
        return "/plugin/jenkow-activiti-explorer/images/24x24/activiti.png";
    }

    public String getDisplayName() {
        return "Activiti Explorer";
    }

    public String getUrlName() {
        return "activiti-explorer";
    }

    public void doDynamic(StaplerRequest req, StaplerResponse rsp) throws ServletException, IOException {
        ProxiedWebApplication webApp = getProxyWebApplication(req);

        HttpSession session = req.getSession();
        HttpSession ps = webApp.getProxiedSession(session);
        UserDTO oldUser = (UserDTO)ps.getAttribute("jenkins.user");
        UserDTO newUser = createUserInfo();
        if (!mapToId(oldUser).equals(mapToId(newUser))) {
            // force a new session. AE isn't designed to anticipate the user change without invalidating a session,
            // but Jenkins does that. So when we see that the user has changed in Jenkins, force a new session
            // (but only in AE.)
            webApp.clearProxiedSession(session);
            ps = webApp.getProxiedSession(session);
        }

        ps.setAttribute("jenkins.user", newUser);


        webApp.handleRequest(req, rsp);
    }

    private String mapToId(UserDTO o) {
        return o==null ? "\u0000" : o.id;
    }

    /**
     * Creates {@link UserDTO} that represents the currently logged-in user.
     */
    private UserDTO createUserInfo() {
        Authentication a = Jenkins.getAuthentication();
        User u = User.current();

        UserDTO user = new UserDTO();
        user.id = a.getName();
        user.firstName = u != null ? u.getFullName() : a.getName();
        user.lastName = "";
        user.fullName = u != null ? u.getFullName() : a.getName();
        user.isAdmin = Jenkins.getInstance().getACL().hasPermission(a,Jenkins.ADMINISTER);
        user.isUser = true;

        return user;
    }

    /**
     * Extracts a war file into the specified directory.
     */
    private void extract(URL war, File dir) throws IOException {
        if (dir.exists())
            Util.deleteRecursive(dir);

        JarInputStream jar = new JarInputStream(war.openStream());
        try {
            JarEntry e;
            while ((e=jar.getNextJarEntry())!=null) {
                File dst = new File(dir,e.getName());
                if (e.isDirectory())
                    dst.mkdirs();
                else {
                    dst.getParentFile().mkdirs();
                    FileOutputStream out = new FileOutputStream(dst);
                    try {
                        IOUtils.copy(jar, out);
                    } finally {
                        out.close();
                    }

                    if (e.getTime()>=0)
                        dst.setLastModified(e.getTime());
                }
            }
        } finally {
            jar.close();
        }
    }

    /**
     * Patch activiti-explorer war file so that we can inject our stuff into it.
     */
    private void patch(File war) throws DocumentException, IOException {
        new XmlPatcher(new File(war,"WEB-INF/activiti-standalone-context.xml")) {
            public void patch() {
                // patch data source in
                overrideBeanTo("dataSource", ServletContextDataSource.class.getName());

                // single sign-on
                // can't load the class yet, so string
                overrideBeanTo("activitiLoginHandler", "org.jenkinsci.plugins.jenkow.activiti.override.JenkinsLoginHandler");

                // inject our own fully configured ProcessEngine
                overrideBeanTo("processEngine", JenkinsProcessEngineFactory.class.getName());

                // no more demo data generation
                removeBean("demoDataGenerator");
            }
        };
        new XmlPatcher(new File(war,"WEB-INF/activiti-ui-context.xml")) {
            public void patch() {
                // tweak the navigation bar
                overrideBeanTo("componentFactories", "org.jenkinsci.plugins.jenkow.activiti.override.JenkinsComponentFactories");

                swapClass("explorerApp","org.jenkinsci.plugins.jenkow.activiti.override.ExplorerApp2");
            }
        };
    }

    private synchronized ProxiedWebApplication getProxyWebApplication(StaplerRequest req) throws ServletException {
        if (webApp==null) {
            try {
                final ClassLoader ourLoader = getClass().getClassLoader();

                File war = new File(Jenkins.getInstance().getRootDir(), "cache/activiti-explorer");
                extract(ourLoader.getResource("activiti-explorer.war"),war);
                patch(war);
                webApp = new ProxiedWebApplication(
                        war,
                        req.getContextPath()+'/'+getUrlName());

                webApp.setParentLoaderHasPriority(true);

                webApp.addClassPath(ourLoader.getResource("activiti-explorer-override.jar"));
                // inject DataSource
                webApp.getProxiedServletContext().setAttribute(ServletContextDataSource.class.getName(),
                        descriptor.getDatabase().getDataSource());
                webApp.getProxiedServletContext().setAttribute(ProcessEngine.class.getName(),
                        JenkowEngine.getEngine());

                // pass through to the servlet container so that Activiti won't get confused
                // by what Jenkins loads (e.g., log4j version inconsistency)
                // but we do expose DTO classes to share them between two apps.
                webApp.setParentClassLoader(new URLClassLoader(new URL[0],HttpServletRequest.class.getClassLoader()) {
                    @Override
                    protected Class<?> findClass(String name) throws ClassNotFoundException {
                        if (name.startsWith("org.jenkinsci.plugins.activiti_explorer.dto.")
                         || name.startsWith("org.activiti.engine.")) {
                            return getClass().getClassLoader().loadClass(name);
                        }
                        throw new ClassNotFoundException(name);
                    }
                });

                webApp.start();
            } catch (Exception e) {
                throw new ServletException(e);
            }
        }
        return webApp;
    }
}
TOP

Related Classes of org.jenkinsci.plugins.activiti_explorer.ActivitiExplorer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.