com.xebialabs.deployit.cli.ext.mustachify.DarEntryTransformerApplier.java Source code

Java tutorial

Introduction

Here is the source code for com.xebialabs.deployit.cli.ext.mustachify.DarEntryTransformerApplier.java

Source

/*
 * @(#)DarEntryTransformerApplier.java     Aug 1, 2011
 *
 * Copyright  2010 Andrew Phillips.
 *
 * ====================================================================
 * Licensed 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 com.xebialabs.deployit.cli.ext.mustachify;

import static com.google.common.collect.ImmutableList.copyOf;
import static com.google.common.collect.Iterables.concat;
import static com.google.common.collect.Iterables.transform;
import static com.google.common.collect.Lists.newLinkedList;
import static com.google.common.collect.Maps.transformValues;
import static com.xebialabs.deployit.cli.ext.mustachify.collect.Maps2.reduce;
import static org.apache.commons.io.FilenameUtils.getBaseName;
import static org.apache.commons.io.FilenameUtils.getExtension;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collection;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import javax.annotation.Nonnull;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.base.Function;
import com.google.common.collect.ImmutableSet;
import com.xebialabs.deployit.cli.ext.mustachify.dar.DarManifestParser.DarManifest.DarManifestEntry;
import com.xebialabs.deployit.cli.ext.mustachify.io.TFiles;
import com.xebialabs.deployit.cli.ext.mustachify.transform.DarEntryTransformer;

import de.schlichtherle.truezip.file.TFile;
import de.schlichtherle.truezip.file.TFileInputStream;

class DarEntryTransformerApplier {
    private static final Logger LOGGER = LoggerFactory.getLogger(DarEntryTransformerApplier.class);

    Collection<TFile> apply(Map<DarEntry, DarEntryTransformer> entriesToTransform) {
        Map<DarEntryTransformer, Iterable<TFile>> transformerWorkloads = transformValues(reduce(entriesToTransform),
                new ExpandDarEntries());

        Collection<TFile> transformedFiles = newLinkedList();
        for (Entry<DarEntryTransformer, Iterable<TFile>> transformerWorkload : transformerWorkloads.entrySet()) {
            // will force iteration of the iterable, but we're about to do that anyway
            Collection<TFile> filesToTransform = copyOf(transformerWorkload.getValue());
            try {
                apply(transformerWorkload.getKey(), filesToTransform);
                transformedFiles.addAll(filesToTransform);
            } catch (IOException exception) {
                LOGGER.warn("Unable to transform '{}' using '{}'", filesToTransform, transformerWorkload.getKey());
            }
        }
        return transformedFiles;
    }

    private static void apply(DarEntryTransformer transformer, Iterable<TFile> filesToTransform)
            throws IOException {
        for (TFile fileToTransform : filesToTransform) {
            if (LOGGER.isDebugEnabled()) {
                LOGGER.debug("About to transform '{}' using '{}'", fileToTransform, transformer);
            }
            apply(transformer, fileToTransform);
        }
    }

    // expand each DAR entry into a set of files and concatenate the results
    private static class ExpandDarEntries implements Function<Set<DarEntry>, Iterable<TFile>> {
        @Override
        public Iterable<TFile> apply(Set<DarEntry> input) {
            return concat(transform(input, new Function<DarEntry, Iterable<TFile>>() {
                @Override
                public Iterable<TFile> apply(DarEntry entry) {
                    TFile entryContents = entry.contents;
                    return entry.isFolder() ? TFiles.listTFiles(entryContents) : ImmutableSet.of(entryContents);
                }
            }));
        }
    }

    private static void apply(DarEntryTransformer transformer, TFile fileToTransform) throws IOException {
        String entryPath = fileToTransform.getInnerEntryName();
        File newContentBuffer = File.createTempFile(getBaseName(entryPath), getExtension(entryPath));
        if (LOGGER.isDebugEnabled()) {
            LOGGER.debug("Created temporary buffer '{}' for transformed content", newContentBuffer);
        }
        try {
            InputStream entryContents = new TFileInputStream(fileToTransform);
            try {
                FileOutputStream streamToBuffer = new FileOutputStream(newContentBuffer);
                try {
                    transformer.transform(entryContents, streamToBuffer);
                } finally {
                    if (LOGGER.isTraceEnabled()) {
                        LOGGER.trace("Closing output stream '{}' to temporary buffer", streamToBuffer);
                    }
                    streamToBuffer.close();
                }
            } finally {
                if (LOGGER.isTraceEnabled()) {
                    LOGGER.trace("Closing input stream '{}' from source file", entryContents);
                }
                entryContents.close();
            }
            // overwrite untransformed file in target
            if (LOGGER.isDebugEnabled()) {
                LOGGER.debug("Copying transformed content from buffer '{}' to target '{}'", newContentBuffer,
                        fileToTransform);
            }
            TFile.cp(newContentBuffer, fileToTransform);
        } finally {
            // cleanup
            if (LOGGER.isDebugEnabled()) {
                LOGGER.debug("Deleted temporary content buffer '{}'", newContentBuffer);
            }
            newContentBuffer.delete();
        }
    }

    static class DarEntry {
        public final DarManifestEntry metadata;
        public final TFile contents;

        DarEntry(@Nonnull DarManifestEntry metadata, @Nonnull TFile contents) {
            this.metadata = metadata;
            this.contents = contents;
        }

        public boolean isFolder() {
            // could add checks of the type, too
            return contents.isDirectory();
        }
    }
}