org.apache.cactus.eclipse.webapp.internal.WarBuilder.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.cactus.eclipse.webapp.internal.WarBuilder.java

Source

/* 
 * ========================================================================
 * 
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * 
 * ========================================================================
 */
package org.apache.cactus.eclipse.webapp.internal;

import org.apache.cactus.eclipse.webapp.internal.ui.WebappMessages;
import org.apache.cactus.eclipse.webapp.internal.ui.WebappPlugin;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.taskdefs.War;
import org.apache.tools.ant.taskdefs.Zip;
import org.apache.tools.ant.types.FileSet;
import org.apache.tools.ant.types.ZipFileSet;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.internal.core.JavaModel;

import java.io.File;
import java.io.IOException;
import java.util.Vector;

/**
 * Helper class for creating War files.
 * 
 * @version $Id: WarBuilder.java 238816 2004-02-29 16:36:46Z vmassol $
 */
public class WarBuilder {
    /**
     * The Java project to build the war from
     */
    private IJavaProject javaProject;

    /**
     * The Webapp object that stores webapp preferences 
     */
    private Webapp webapp;

    /**
     * Name of the WEB-INF directory
     */
    public static final String WEBINF = "WEB-INF";

    /**
     * Name of the lib directory
     */
    public static final String LIB = "lib";

    /**
     * Name of the web.xml file
     */
    public static final String WEBXML = "web.xml";

    /**
     * @param theJavaProject the Java project for which the webapp will be 
     *        created
     * @throws JavaModelException if we can't get the output location
     */
    public WarBuilder(final IJavaProject theJavaProject) throws JavaModelException {
        this.javaProject = theJavaProject;
        this.webapp = new Webapp(theJavaProject);
    }

    /**
     * @param theWebFilesDir webapp directory to get the web.xml from
     * @return the web.xml file in the given webapp directory,
     *  or null if none
     */
    public static File getWebXML(final File theWebFilesDir) {
        if (theWebFilesDir == null) {
            return null;
        } else {
            String userWebXMLPath = theWebFilesDir.getAbsolutePath() + File.separator + WEBINF + File.separator
                    + WEBXML;
            return new File(userWebXMLPath);
        }
    }

    /**
     * For each IClasspathEntry transform the path in an absolute path.
     * @param theEntries array of IClasspathEntry to render asbolute
     * @return an array of absolute IClasspathEntries
     */
    private static IClasspathEntry[] getAbsoluteEntries(final IClasspathEntry[] theEntries) {
        if (theEntries == null) {
            return new IClasspathEntry[0];
        }
        Vector result = new Vector();
        for (int i = 0; i < theEntries.length; i++) {
            IClasspathEntry currentEntry = theEntries[i];
            if (currentEntry.getEntryKind() == IClasspathEntry.CPE_LIBRARY) {
                IPath path = currentEntry.getPath();
                Object target = JavaModel.getTarget(ResourcesPlugin.getWorkspace().getRoot(), path, true);
                if (target instanceof IFile) {
                    IFile file = (IFile) target;
                    IPath absolutePath = file.getLocation();
                    result.add(JavaCore.newLibraryEntry(absolutePath, null, null));
                } else if (target instanceof File) {
                    File file = (File) target;
                    result.add(JavaCore.newLibraryEntry(new Path(file.getAbsolutePath()), null, null));
                }
            }
        }
        return (IClasspathEntry[]) result.toArray(new IClasspathEntry[result.size()]);
    }

    /**
     * @param theJavaProject the java project for which we want to get the
     *        absolute output path 
     * @return the absolute project output path
     * @throws JavaModelException if we fail to get the project relative 
     *         output location
     */
    private static File getAbsoluteOutputLocation(final IJavaProject theJavaProject) throws JavaModelException {
        IPath projectPath = theJavaProject.getProject().getLocation();
        IPath outputLocation = theJavaProject.getOutputLocation();
        IPath classFilesPath = projectPath.append(outputLocation.removeFirstSegments(1));
        return classFilesPath.toFile();
    }

    /**
     * Creates the war file.
     * @param thePM a monitor that reflects the overall progress,
     *  or null if none is to be used.
     * @return File the location where the war file was created
     * @throws CoreException if we can't create the file
     */
    public final File createWar(final IProgressMonitor thePM) throws CoreException {
        IProgressMonitor progressMonitor = thePM;
        if (progressMonitor == null) {
            progressMonitor = new NullProgressMonitor();
        }

        progressMonitor.subTask(WebappMessages.getString("WarBuilder.message.createwar.monitor"));
        this.webapp.loadValues();
        File outputWar = getOutputWar();
        File userWebFilesDir = getUserWebFilesDir();
        File userWebXML = getWebXML(userWebFilesDir);
        IClasspathEntry[] jarEntries = getJarEntries();
        File userClassFilesDir = getAbsoluteOutputLocation(this.javaProject);

        outputWar.delete();
        War warTask = new War();
        progressMonitor.worked(1);
        Project antProject = new Project();
        antProject.init();
        warTask.setProject(antProject);
        warTask.setDestFile(outputWar);
        ZipFileSet classes = new ZipFileSet();
        classes.setDir(userClassFilesDir);
        warTask.addClasses(classes);
        classes = new ZipFileSet();
        classes.setDir(userClassFilesDir);
        classes.setIncludes("log4j.properties");
        warTask.addClasses(classes);
        if (userWebFilesDir != null && userWebFilesDir.exists()) {
            FileSet webFiles = new FileSet();
            webFiles.setDir(userWebFilesDir);
            webFiles.setExcludes(WEBINF);
            warTask.addFileset(webFiles);
        }
        if (userWebXML != null && userWebXML.exists()) {
            warTask.setWebxml(userWebXML);
        } else {
            // Without a webxml attribute the Ant war task
            // requires the update attribute set to true
            // That's why we actually need an existing war file.
            try {
                // A file is needed for war creation
                File voidFile = File.createTempFile("void", null);
                createZipFile(outputWar, voidFile);
                voidFile.delete();
            } catch (IOException e) {
                throw new CoreException(new Status(IStatus.ERROR, WebappPlugin.getPluginId(), IStatus.OK,
                        WebappMessages.getString("WarBuilder.message.createwar.temp"), e));
            }

            warTask.setUpdate(true);
        }

        ZipFileSet[] jarFS = getZipFileSets(jarEntries);
        for (int i = 0; i < jarFS.length; i++) {
            warTask.addLib(jarFS[i]);
        }
        warTask.execute();
        progressMonitor.worked(2);
        return outputWar;
    }

    /**
     * @param theJarEntries the jars to build ZipFileSets from
     * @return an array of ZipFileSet corresponding to the given jars
     */
    private static ZipFileSet[] getZipFileSets(final IClasspathEntry[] theJarEntries) {
        Vector result = new Vector();
        for (int i = 0; i < theJarEntries.length; i++) {

            IClasspathEntry currentEntry = theJarEntries[i];
            if (currentEntry.getEntryKind() == IClasspathEntry.CPE_LIBRARY) {
                File currentJar = currentEntry.getPath().toFile();
                ZipFileSet zipFS = new ZipFileSet();
                zipFS.setFile(currentJar);
                result.add(zipFS);
            }
        }
        return (ZipFileSet[]) result.toArray(new ZipFileSet[result.size()]);
    }

    /**
     * @return the web application folder situated in the user's project
     */
    private File getUserWebFilesDir() {
        // path to the web directory relative to the user's project
        String userWebFilesPath = this.webapp.getDir();
        if (userWebFilesPath == null || userWebFilesPath.equals("")) {
            return null;
        } else {
            IPath projectPath = this.javaProject.getProject().getLocation();

            // web application folder situated in the user's project
            return projectPath.append(userWebFilesPath).toFile();
        }
    }

    /**
     * @return the jar entries
     */
    private IClasspathEntry[] getJarEntries() {
        return getAbsoluteEntries(this.webapp.getClasspath());
    }

    /**
     * @return the output war file
     */
    private File getOutputWar() {
        return new File(this.webapp.getOutput());
    }

    /**
     * Removes the specified file or directory, and all subdirectories
     * @param theFile the file or directory to delete
     */
    public static final void delete(final File theFile) {
        if (theFile.isDirectory()) {
            File[] dir = theFile.listFiles();
            for (int i = 0; i < dir.length; i++) {
                delete(dir[i]);
            }
            theFile.delete();
        } else if (theFile.exists()) {
            theFile.delete();
        }
    }

    /**
     * Creates a zip file containing the given existing file. 
     * @param theZipFile the zip file to create
     * @param theExistingFile the file to include in the zip
     */
    private void createZipFile(final File theZipFile, final File theExistingFile) {
        Project antProject = new Project();
        antProject.init();
        Zip zip = new Zip();
        zip.setProject(antProject);
        zip.setDestFile(theZipFile);
        FileSet existingFileSet = new FileSet();
        existingFileSet.setFile(theExistingFile);
        zip.addFileset(existingFileSet);
        zip.execute();
    }

}