org.infoglue.deliver.portal.deploy.Deploy.java Source code

Java tutorial

Introduction

Here is the source code for org.infoglue.deliver.portal.deploy.Deploy.java

Source

/* ===============================================================================
 *
 * Part of the InfoGlue Content Management Platform (www.infoglue.org)
 *
 * ===============================================================================
 *
 *  Copyright (C)
 * 
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License version 2, as published by the
 * Free Software Foundation. See the file LICENSE.html for more information.
 * 
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY, including 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. / 59 Temple
 * Place, Suite 330 / Boston, MA 02111-1307 / USA.
 *
 * ===============================================================================
 */
package org.infoglue.deliver.portal.deploy;

import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.util.Enumeration;
import java.util.Vector;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.JarOutputStream;
import java.util.zip.ZipEntry;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.pluto.PortletContainerServices;
import org.apache.pluto.descriptors.services.PortletAppDescriptorService;
import org.apache.pluto.descriptors.services.WebAppDescriptorService;
import org.apache.pluto.descriptors.services.impl.AbstractWebAppDescriptorService;
import org.apache.pluto.descriptors.services.impl.StreamPortletAppDescriptorServiceImpl;
import org.apache.pluto.om.portlet.PortletApplicationDefinition;
import org.apache.pluto.portalImpl.om.portlet.impl.PortletApplicationDefinitionImpl;
import org.apache.pluto.portalImpl.services.ServiceManager;
import org.apache.xerces.parsers.DOMParser;
import org.exolab.castor.mapping.Mapping;
import org.exolab.castor.xml.Unmarshaller;
import org.infoglue.deliver.portal.ServletConfigContainer;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;

/**
 * Slightly modified version of jakarta-plutos deploy target. This utility
 * requires that portletdefinitionmapping.xml and servletdefinitionmapping.xml
 * are located somewhere in the classpath.
 */
public class Deploy {

    public static class StreamWebAppDescriptorServiceImpl extends AbstractWebAppDescriptorService {

        private InputStream in;
        private OutputStream out;

        public StreamWebAppDescriptorServiceImpl(String contextPath, InputStream in, OutputStream out) {
            super(contextPath);
            this.in = in;
            this.out = out;
        }

        protected InputStream getInputStream() throws IOException {
            return in;
        }

        protected OutputStream getOutputStream() throws IOException {
            return out;
        }
    }

    private static final Log log = LogFactory.getLog(Deploy.class);

    private static final int MAX_POLL_DEPLOY = 30;

    private static final String PORTLET_XML = "WEB-INF/portlet.xml";

    private static final String WEB_XML = "WEB-INF/web.xml";

    private static final String PORTLET_MAPPING = "portletdefinitionmapping.xml";

    /**
     * Deploy a portlet. Creates a .war-file in webapps and waits until it is
     * deployed by the servlet container (max 30 seconds).
     * 
     * @param webappsDir
     *            webapps directory
     * @param warName
     *            name of .war-file (portlet)
     * @param is
     *            stream of .war-file
     * @param containerName
     *            name of portlet container to be updated
     * @return true if portlet was deployed
     * @throws FileNotFoundException
     *             in case webapps directory not found
     * @throws IOException
     */
    public static boolean deployArchive(String webappsDir, String warName, InputStream is, String containerName)
            throws FileNotFoundException, IOException {
        File webapps = new File(webappsDir);
        if (!webapps.exists() || !webapps.isDirectory()) {
            throw new FileNotFoundException("Webapps directory not found: " + webappsDir);
        }
        String appName = warName;
        int dot = appName.lastIndexOf(".");
        if (dot > 0) {
            appName = appName.substring(0, dot);
        } else {
            warName += ".war";
        }

        // Create .war-file in webapps
        File war = new File(webapps, warName);
        if (war.exists()) {
            // .war-file already exists - skip?
            log.info(".war-file already exists: " + war.getAbsolutePath());
        } else {
            FileOutputStream os = new FileOutputStream(war);
            BufferedOutputStream bos = new BufferedOutputStream(os);
            int num = copyStream(is, bos);
            bos.close();
            os.close();
            log.info(num + " bytes written to " + war.getAbsolutePath());
        }

        // Expand .war-file into application directory (NOT necessary in Tomcat
        // 4.1. others?)
        /*
         * File appDir = new File(webapps, appName); if (appDir.exists()) { //
         * app dir already exists - skip? log.warn("Application directory
         * already exists: " + appDir.getAbsolutePath()); return false; } if
         * (!appDir.mkdirs()) { throw new IOException( "Unable to create
         * application directory: " + appDir.getAbsolutePath()); } int numFiles =
         * expandArchive(war, appDir); log.warn(numFiles + " files extracted to " +
         * appDir.getAbsolutePath());
         */

        // Wait until portlet is deployed in servlet container
        File appDir = new File(webapps, appName);
        File webInfDir = new File(appDir, "WEB-INF");
        File portletXml = new File(webInfDir, "portlet.xml");
        for (int i = 0; !portletXml.exists() && i < MAX_POLL_DEPLOY; i++) {
            log.debug("Waiting for servlet container to deploy portlet, try " + i + "/" + MAX_POLL_DEPLOY);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                log.warn("Deployment paus interrupted", e);
            }
        }
        if (!portletXml.exists()) {
            log.error("Failed to deploy portlet: " + war.getAbsolutePath());
        }

        // Update pluto service manager
        log.info("Updating pluto service manager: " + containerName);
        try {
            PortletContainerServices.prepare(containerName);
            ServiceManager.init(ServletConfigContainer.getContainer().getServletConfig());
        } catch (Exception e) {
            log.error("Error during update of pluto service manager", e);
        }
        return true;
    }

    /**
     * Prepare a portlet according to Pluto (switch web.xml)
     * 
     * @param file .war to prepare
     * @param tmp the resulting updated .war
     * @param appName name of application (context name)
     * @return the portlet application definition (portlet.xml)
     * @throws IOException
     */
    public static PortletApplicationDefinition prepareArchive(File file, File tmp, String appName)
            throws IOException {
        PortletApplicationDefinitionImpl portletApp = null;
        try {
            Mapping pdmXml = new Mapping();
            try {
                URL url = Deploy.class.getResource("/" + PORTLET_MAPPING);
                pdmXml.loadMapping(url);
            } catch (Exception e) {
                throw new IOException("Failed to load mapping file " + PORTLET_MAPPING);
            }

            // Open the jar file.
            JarFile jar = new JarFile(file);

            // Extract and parse portlet.xml
            ZipEntry portletEntry = jar.getEntry(PORTLET_XML);
            if (portletEntry == null) {
                throw new IOException("Unable to find portlet.xml");
            }

            InputStream pisDebug = jar.getInputStream(portletEntry);
            StringBuffer sb = new StringBuffer();
            int i;
            while ((i = pisDebug.read()) > -1) {
                sb.append((char) i);
            }
            pisDebug.close();

            InputSource xmlSource = new InputSource(new ByteArrayInputStream(sb.toString().getBytes("UTF-8")));
            DOMParser parser = new DOMParser();
            parser.parse(xmlSource);
            Document portletDocument = parser.getDocument();

            //InputStream pis = jar.getInputStream(portletEntry);
            //Document portletDocument = XmlParser.parsePortletXml(pis);
            //pis.close();
            InputStream pis = jar.getInputStream(portletEntry);

            ZipEntry webEntry = jar.getEntry(WEB_XML);
            InputStream wis = null;
            if (webEntry != null) {
                wis = jar.getInputStream(webEntry);
                /*  webDocument = XmlParser.parseWebXml(wis);
                wis.close();
                */
            }

            Unmarshaller unmarshaller = new Unmarshaller(pdmXml);
            unmarshaller.setWhitespacePreserve(true);
            unmarshaller.setIgnoreExtraElements(true);
            unmarshaller.setIgnoreExtraAttributes(true);

            portletApp = (PortletApplicationDefinitionImpl) unmarshaller.unmarshal(portletDocument);

            // refill structure with necessary information
            Vector structure = new Vector();
            structure.add(appName);
            structure.add(null);
            structure.add(null);
            portletApp.preBuild(structure);

            /*
            // now generate web part
            WebApplicationDefinitionImpl webApp = null;
            if (webDocument != null) {
            Unmarshaller unmarshallerWeb = new Unmarshaller(sdmXml);
                
            // modified by YCLI: START :: to ignore extra elements and
            // attributes
            unmarshallerWeb.setWhitespacePreserve(true);
            unmarshallerWeb.setIgnoreExtraElements(true);
            unmarshallerWeb.setIgnoreExtraAttributes(true);
            // modified by YCLI: END
                
            webApp = (WebApplicationDefinitionImpl) unmarshallerWeb.unmarshal(webDocument);
            } else {
            webApp = new WebApplicationDefinitionImpl();
            DisplayNameImpl dispName = new DisplayNameImpl();
            dispName.setDisplayName(appName);
            dispName.setLocale(Locale.ENGLISH);
            DisplayNameSetImpl dispSet = new DisplayNameSetImpl();
            dispSet.add(dispName);
            webApp.setDisplayNames(dispSet);
            DescriptionImpl desc = new DescriptionImpl();
            desc.setDescription("Automated generated Application Wrapper");
            desc.setLocale(Locale.ENGLISH);
            DescriptionSetImpl descSet = new DescriptionSetImpl();
            descSet.add(desc);
            webApp.setDescriptions(descSet);
            }
                
            org.apache.pluto.om.ControllerFactory controllerFactory = new org.apache.pluto.portalImpl.om.ControllerFactoryImpl();
                
            ServletDefinitionListCtrl servletDefinitionSetCtrl = (ServletDefinitionListCtrl) controllerFactory
                .get(webApp.getServletDefinitionList());
            Collection servletMappings = webApp.getServletMappings();
                
            Iterator portlets = portletApp.getPortletDefinitionList().iterator();
            while (portlets.hasNext()) {
                
            PortletDefinition portlet = (PortletDefinition) portlets.next();
                
            // check if already exists
            ServletDefinition servlet = webApp.getServletDefinitionList()
                    .get(portlet.getName());
            if (servlet != null) {
                ServletDefinitionCtrl _servletCtrl = (ServletDefinitionCtrl) controllerFactory
                        .get(servlet);
                _servletCtrl.setServletClass("org.apache.pluto.core.PortletServlet");
            } else {
                servlet = servletDefinitionSetCtrl.add(portlet.getName(),
                        "org.apache.pluto.core.PortletServlet");
            }
                
            ServletDefinitionCtrl servletCtrl = (ServletDefinitionCtrl) controllerFactory
                    .get(servlet);
                
            DisplayNameImpl dispName = new DisplayNameImpl();
            dispName.setDisplayName(portlet.getName() + " Wrapper");
            dispName.setLocale(Locale.ENGLISH);
            DisplayNameSetImpl dispSet = new DisplayNameSetImpl();
            dispSet.add(dispName);
            servletCtrl.setDisplayNames(dispSet);
            DescriptionImpl desc = new DescriptionImpl();
            desc.setDescription("Automated generated Portlet Wrapper");
            desc.setLocale(Locale.ENGLISH);
            DescriptionSetImpl descSet = new DescriptionSetImpl();
            descSet.add(desc);
            servletCtrl.setDescriptions(descSet);
            ParameterSet parameters = servlet.getInitParameterSet();
                
            ParameterSetCtrl parameterSetCtrl = (ParameterSetCtrl) controllerFactory
                    .get(parameters);
                
            Parameter parameter1 = parameters.get("portlet-class");
            if (parameter1 == null) {
                parameterSetCtrl.add("portlet-class", portlet.getClassName());
            } else {
                ParameterCtrl parameterCtrl = (ParameterCtrl) controllerFactory.get(parameter1);
                parameterCtrl.setValue(portlet.getClassName());
                
            }
            Parameter parameter2 = parameters.get("portlet-guid");
            if (parameter2 == null) {
                parameterSetCtrl.add("portlet-guid", portlet.getId().toString());
            } else {
                ParameterCtrl parameterCtrl = (ParameterCtrl) controllerFactory.get(parameter2);
                parameterCtrl.setValue(portlet.getId().toString());
                
            }
                
            boolean found = false;
            Iterator mappings = servletMappings.iterator();
            while (mappings.hasNext()) {
                ServletMappingImpl servletMapping = (ServletMappingImpl) mappings.next();
                if (servletMapping.getServletName().equals(portlet.getName())) {
                    found = true;
                    servletMapping.setUrlPattern("/" + portlet.getName().replace(' ', '_')
                            + "/*");
                }
            }
            if (!found) {
                ServletMappingImpl servletMapping = new ServletMappingImpl();
                servletMapping.setServletName(portlet.getName());
                servletMapping.setUrlPattern("/" + portlet.getName().replace(' ', '_') + "/*");
                servletMappings.add(servletMapping);
            }
                
            SecurityRoleRefSet servletSecurityRoleRefs = ((ServletDefinitionImpl) servlet)
                    .getInitSecurityRoleRefSet();
                
            SecurityRoleRefSetCtrl servletSecurityRoleRefSetCtrl = (SecurityRoleRefSetCtrl) controllerFactory
                    .get(servletSecurityRoleRefs);
                
            SecurityRoleSet webAppSecurityRoles = webApp.getSecurityRoles();
                
            SecurityRoleRefSet portletSecurityRoleRefs = portlet.getInitSecurityRoleRefSet();
                
            Iterator p = portletSecurityRoleRefs.iterator();
            while (p.hasNext()) {
                SecurityRoleRef portletSecurityRoleRef = (SecurityRoleRef) p.next();
                
                if (portletSecurityRoleRef.getRoleLink() == null
                        && webAppSecurityRoles.get(portletSecurityRoleRef.getRoleName()) == null) {
                    logger.info("Note: The web application has no security role defined which matches the role name \""
                                    + portletSecurityRoleRef.getRoleName()
                                    + "\" of the security-role-ref element defined for the wrapper-servlet with the name '"
                                    + portlet.getName() + "'.");
                    break;
                }
                SecurityRoleRef servletSecurityRoleRef = servletSecurityRoleRefs
                        .get(portletSecurityRoleRef.getRoleName());
                if (null != servletSecurityRoleRef) {
                    logger.info("Note: Replaced already existing element of type <security-role-ref> with value \""
                                    + portletSecurityRoleRef.getRoleName()
                                    + "\" for subelement of type <role-name> for the wrapper-servlet with the name '"
                                    + portlet.getName() + "'.");
                    servletSecurityRoleRefSetCtrl.remove(servletSecurityRoleRef);
                }
                servletSecurityRoleRefSetCtrl.add(portletSecurityRoleRef);
            }
                
            }
            */

            /*
             * TODO is this necessary? TagDefinitionImpl portletTagLib = new
             * TagDefinitionImpl(); Collection taglibs =
             * webApp.getCastorTagDefinitions(); taglibs.add(portletTagLib);
             */

            // Duplicate jar-file with replaced web.xml
            FileOutputStream fos = new FileOutputStream(tmp);
            JarOutputStream tempJar = new JarOutputStream(fos);
            byte[] buffer = new byte[1024];
            int bytesRead;
            for (Enumeration entries = jar.entries(); entries.hasMoreElements();) {
                JarEntry entry = (JarEntry) entries.nextElement();
                JarEntry newEntry = new JarEntry(entry.getName());
                tempJar.putNextEntry(newEntry);

                if (entry.getName().equals(WEB_XML)) {
                    // Swap web.xml
                    /*
                    log.debug("Swapping web.xml");
                    OutputFormat of = new OutputFormat();
                    of.setIndenting(true);
                    of.setIndent(4); // 2-space indention
                    of.setLineWidth(16384);
                    of.setDoctype(Constants.WEB_PORTLET_PUBLIC_ID, Constants.WEB_PORTLET_DTD);
                        
                    XMLSerializer serializer = new XMLSerializer(tempJar, of);
                    Marshaller marshaller = new Marshaller(serializer.asDocumentHandler());
                    marshaller.setMapping(sdmXml);
                    marshaller.marshal(webApp);
                    */

                    PortletAppDescriptorService portletAppDescriptorService = new StreamPortletAppDescriptorServiceImpl(
                            appName, pis, null);
                    File tmpf = File.createTempFile("infoglue-web-xml", null);
                    WebAppDescriptorService webAppDescriptorService = new StreamWebAppDescriptorServiceImpl(appName,
                            wis, new FileOutputStream(tmpf));

                    org.apache.pluto.driver.deploy.Deploy d = new org.apache.pluto.driver.deploy.Deploy(
                            webAppDescriptorService, portletAppDescriptorService);
                    d.updateDescriptors();
                    FileInputStream fis = new FileInputStream(tmpf);
                    while ((bytesRead = fis.read(buffer)) != -1) {
                        tempJar.write(buffer, 0, bytesRead);
                    }
                    tmpf.delete();
                } else {
                    InputStream entryStream = jar.getInputStream(entry);
                    if (entryStream != null) {
                        while ((bytesRead = entryStream.read(buffer)) != -1) {
                            tempJar.write(buffer, 0, bytesRead);
                        }
                    }
                }
            }
            tempJar.flush();
            tempJar.close();
            fos.flush();
            fos.close();
            /*
             * String strTo = dirDelim + "WEB-INF" + dirDelim + "tld" + dirDelim +
             * "portlet.tld"; String strFrom = "webapps" + dirDelim + strTo;
             * 
             * copy(strFrom, webAppsDir + webModule + strTo);
             */
        } catch (Exception e) {
            log.error("Failed to prepare archive", e);
            throw new IOException(e.getMessage());
        }

        return portletApp;
    }

    private static void copy(String from, String to) throws IOException {
        File f = new File(to);
        f.getParentFile().mkdirs();

        InputStream fis = new FileInputStream(from);
        FileOutputStream fos = new FileOutputStream(f);
        copyStream(fis, fos);
        fos.close();
    }

    private static int copyStream(InputStream is, OutputStream os) throws IOException {
        int total = 0;
        byte[] buffer = new byte[1024];
        int length = 0;

        while ((length = is.read(buffer)) >= 0) {
            os.write(buffer, 0, length);
            total += length;
        }
        os.flush();
        return total;
    }

    private static int expandArchive(File warFile, File destDir) throws IOException {
        int numEntries = 0;

        if (!destDir.exists()) {
            destDir.mkdirs();
        }
        JarFile jarFile = new JarFile(warFile);
        Enumeration files = jarFile.entries();
        while (files.hasMoreElements()) {
            JarEntry entry = (JarEntry) files.nextElement();
            String fileName = entry.getName();

            File file = new File(destDir, fileName);
            File dirF = new File(file.getParent());
            dirF.mkdirs();

            if (entry.isDirectory()) {
                file.mkdirs();
            } else {
                InputStream fis = jarFile.getInputStream(entry);
                FileOutputStream fos = new FileOutputStream(file);
                copyStream(fis, fos);
                fos.close();
            }
            numEntries++;
        }
        return numEntries;
    }

    public static void main(String[] args) {
        try {
            File file = new File("c:\\infoglueHome\\RssPortlet.war");
            File tmp = new File("c:\\infoglueHome\\RssPortlet2.war");
            prepareArchive(file, tmp, "test-portlet.war");
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}