org.codehaus.mojo.jsimport.JsFileArtifactHandler.java Source code

Java tutorial

Introduction

Here is the source code for org.codehaus.mojo.jsimport.JsFileArtifactHandler.java

Source

package org.codehaus.mojo.jsimport;

/*
 * 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.    
 */

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

import org.apache.commons.io.FileUtils;
import org.apache.maven.artifact.Artifact;

/**
 * Processes an artifact and makes available one or more files depending on whether the artifact points to a js file or
 * a "-www.zip" file respectively.
 * 
 * @author Christopher Hunt
 */
public class JsFileArtifactHandler {
    private List<File> files = new ArrayList<File>();;

    private File expansionFolder;

    /**
     * @param artifact the artifact to work with. It can either be for a JS file or a zip file with a classifier of
     *            "www".
     * @param targetFolder the folder to merge non js files into.
     * @param workFolder the folder to store any meta data that will help us do things like avoiding unnecessary unzips
     *            (given that it has been done before etc.).
     * @throws IOException if something goes wrong, particularly in the course of zip file expansion.
     */
    public JsFileArtifactHandler(Artifact artifact, File targetFolder, File workFolder) throws IOException {
        if (artifact.getType().equals("js")) {
            files = new ArrayList<File>(1);
            files.add(artifact.getFile());
        } else {
            assert artifact.getType().equals("zip") && artifact.getClassifier().equals("www");
            File wwwZipFile = artifact.getFile();
            files = expandWwwZipIntoTargetFolder(artifact, wwwZipFile, targetFolder, workFolder);
        }
    }

    private List<File> expandWwwZipIntoTargetFolder(Artifact artifact, File wwwZipFile, File targetFolder,
            File workFolder) throws IOException {
        List<File> jsFiles = new ArrayList<File>();

        // FIXME: Need to consider scope here i.e. don't create a compile www-zip file for a test run.
        expansionFolder = new File(workFolder, "www-zip" + File.separator + wwwZipFile.getName());

        // Don't expand if it is already expanded.
        if (wwwZipFile.lastModified() > expansionFolder.lastModified()) {
            String gavPath = artifact.getGroupId().replace('.', File.separatorChar) + File.separator
                    + artifact.getArtifactId() + File.separator + artifact.getVersion();
            File jsExpansionFolder = new File(expansionFolder, gavPath);

            FileInputStream fis = new FileInputStream(wwwZipFile);
            try {
                ZipInputStream zis = new ZipInputStream(new BufferedInputStream(fis));
                ZipEntry entry;
                boolean firstEntryProcessed = false;
                int rootFolderPrefixPosn = 0;
                while ((entry = zis.getNextEntry()) != null) {
                    // Any non-js files are simply copied into the target folder. js files are copied to a temporary
                    // folder as something else needs to put them into the target folder (there may be processing a js
                    // file along the way). However we ignore minified files when inflating as by convention, we don't
                    // want them as part of the project - projects can minify later.

                    String entryName = entry.getName().substring(rootFolderPrefixPosn);
                    File entryFile = null;
                    if (!entryName.endsWith("js")) {
                        if (!entry.isDirectory()) {
                            entryFile = new File(targetFolder, entryName);
                        } else if (!firstEntryProcessed) {
                            // Its a directory and it is the first thing in the zip file. We don't want to bother with
                            // this directory when creating files as we're more interested in merging it into the
                            // existing target folder.
                            rootFolderPrefixPosn = entryName.length();
                        }
                    } else if (!entryName.endsWith("-min.js")) {
                        entryFile = new File(jsExpansionFolder, entryName);
                        jsFiles.add(entryFile);
                    }

                    // If we have something interesting to inflate.
                    if (entryFile != null) {
                        entryFile.getParentFile().mkdirs();
                        FileOutputStream fos = new FileOutputStream(entryFile);
                        BufferedOutputStream dest = null;
                        try {
                            int count;
                            final int bufferSize = 2048;
                            byte data[] = new byte[bufferSize];
                            dest = new BufferedOutputStream(fos, bufferSize);
                            while ((count = zis.read(data, 0, bufferSize)) != -1) {
                                dest.write(data, 0, count);
                            }
                            dest.flush();
                        } finally {
                            dest.close();
                        }
                    }

                    firstEntryProcessed = true;
                }
            } finally {
                fis.close();
            }

            // Override the directory's mod time as that will equal the time it was compressed initially. We're not
            // interested in that - we're interested to learn whether the source zip file is newer that the directory we
            // expand into.
            expansionFolder.setLastModified(wwwZipFile.lastModified());
        } else {
            // Nothing changed. Just return a list of files that were previously expanded.
            Collection<File> existingFiles = FileUtils.listFiles(expansionFolder, new String[] { "js" }, true);
            for (File file : existingFiles) {
                if (!file.getName().endsWith("-min.js")) {
                    jsFiles.add(file);
                }
            }
        }

        return jsFiles;
    }

    /**
     * @return a list of the files that were found associated with the artifact.
     */
    public List<File> getFiles() {
        return files;
    }

    /**
     * @return the location where the files have been expanded to or null otherwise.
     */
    public File getExpansionFolder() {
        return expansionFolder;
    }

}