org.sourcepit.tools.shared.resources.internal.harness.SharedResourcesUtils.java Source code

Java tutorial

Introduction

Here is the source code for org.sourcepit.tools.shared.resources.internal.harness.SharedResourcesUtils.java

Source

/*
 * Copyright 2014 Bernd Vogt and others.
 * 
 * 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 org.sourcepit.tools.shared.resources.internal.harness;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.lang.reflect.Field;
import java.net.URL;
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Properties;
import java.util.Set;

import org.apache.commons.compress.archivers.ArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream;
import org.apache.commons.io.IOUtils;
import org.apache.maven.shared.filtering.FilteringUtils;
import org.codehaus.plexus.interpolation.AbstractDelegatingValueSource;
import org.codehaus.plexus.interpolation.InterpolationPostProcessor;
import org.codehaus.plexus.interpolation.PrefixAwareRecursionInterceptor;
import org.codehaus.plexus.interpolation.PrefixedValueSourceWrapper;
import org.codehaus.plexus.interpolation.RecursionInterceptor;
import org.codehaus.plexus.interpolation.SimpleRecursionInterceptor;
import org.codehaus.plexus.interpolation.ValueSource;
import org.codehaus.plexus.interpolation.multi.MultiDelimiterInterpolatorFilterReader;
import org.codehaus.plexus.interpolation.multi.MultiDelimiterStringSearchInterpolator;

/**
 * @author Bernd
 */
public final class SharedResourcesUtils {
    private SharedResourcesUtils() {
        super();
    }

    public static void copy(ClassLoader classLoader, String resourcesLocation, String resourcesPath, File targetDir,
            boolean keepArchivePaths, IFilteredCopier copier) throws FileNotFoundException, IOException {
        copy(classLoader, resourcesLocation, resourcesPath, targetDir, keepArchivePaths, copier,
                IFilterStrategy.TRUE);
    }

    public static void copy(ClassLoader classLoader, String resourcesLocation, String resourcesPath, File targetDir,
            boolean keepArchivePaths, IFilteredCopier copier, IFilterStrategy strategy)
            throws FileNotFoundException, IOException {
        final Properties resources = loadResourcesProperties(classLoader, resourcesLocation);

        String encoding = null;
        String archiveName = null;
        String path = null;

        final String _resourcesPath = normalizeResourcesPath(resourcesPath);

        final int segmentLength = _resourcesPath.indexOf('/');
        if (segmentLength > -1) {
            final String _archiveName = _resourcesPath.substring(0, segmentLength) + ".zip";
            encoding = resources.getProperty("encoding//" + _archiveName);
            if (encoding != null) {
                archiveName = _archiveName;
                path = _resourcesPath.substring(segmentLength + 1);
            }
        } else {
            encoding = resources.getProperty("encoding//" + _resourcesPath);
            if (encoding == null) {
                final String _archiveName = _resourcesPath + ".zip";
                encoding = resources.getProperty("encoding//" + _archiveName);
                if (encoding != null) {
                    archiveName = _archiveName;
                }
            } else {
                path = _resourcesPath;
            }
        }

        if (archiveName == null) {
            if (path == null) {
                throw new FileNotFoundException("Unable to resolve path: " + resourcesPath);
            }
            importFile(classLoader, createFullResourcesPath(resourcesLocation, path), path, encoding, targetDir,
                    copier, strategy);
        } else {
            importArchive(classLoader, createFullResourcesPath(resourcesLocation, archiveName), path,
                    archiveName.substring(0, archiveName.length() - 4), encoding, targetDir, keepArchivePaths,
                    copier, strategy);
        }
    }

    private static void importArchive(ClassLoader classLoader, String archivePath, String archiveEntry,
            String dirName, String encoding, File targetDir, boolean keepArchivePaths, IFilteredCopier copier,
            IFilterStrategy strategy) throws FileNotFoundException, IOException {
        final InputStream in = classLoader.getResourceAsStream(archivePath);
        if (in == null) {
            throw new FileNotFoundException(archivePath);
        }

        final String _dirName = !keepArchivePaths ? "" : dirName;
        final File outDir = new File(targetDir, _dirName);
        if (!outDir.exists()) {
            outDir.mkdirs();
        }
        final ZipArchiveInputStream zipIn = new ZipArchiveInputStream(in, encoding, true);
        try {
            importArchive(zipIn, archiveEntry, outDir, keepArchivePaths, encoding, copier, strategy);
        } finally {
            IOUtils.closeQuietly(zipIn);
        }
    }

    private static void importArchive(ZipArchiveInputStream zipIn, String archiveEntry, File outDir,
            boolean keepArchivePaths, String encoding, IFilteredCopier copier, IFilterStrategy strategy)
            throws IOException {
        boolean found = false;

        ArchiveEntry entry = zipIn.getNextEntry();
        while (entry != null) {
            final String entryName = entry.getName();

            if (archiveEntry == null || entryName.startsWith(archiveEntry + "/")
                    || entryName.equals(archiveEntry)) {
                found = true;

                boolean isDir = entry.isDirectory();

                final String fileName;
                if (archiveEntry == null || keepArchivePaths) {
                    fileName = entryName;
                } else {
                    if (entryName.startsWith(archiveEntry + "/")) {
                        fileName = entryName.substring(archiveEntry.length() + 1);
                    } else if (!isDir && entryName.equals(archiveEntry)) {
                        fileName = new File(entryName).getName();
                    } else {
                        throw new IllegalStateException();
                    }
                }

                final File file = new File(outDir, fileName);
                if (entry.isDirectory()) {
                    file.mkdir();
                } else {
                    file.createNewFile();
                    OutputStream out = new FileOutputStream(file);
                    try {
                        if (copier != null && strategy.filter(fileName)) {
                            copy(zipIn, out, encoding, copier, file);
                        } else {
                            IOUtils.copy(zipIn, out);
                        }
                    } finally {
                        IOUtils.closeQuietly(out);
                    }
                }
            }
            entry = zipIn.getNextEntry();
        }

        if (!found) {
            throw new FileNotFoundException(archiveEntry);
        }
    }

    private static void importFile(ClassLoader classLoader, String path, String fileName, String encoding,
            File targetDir, IFilteredCopier copier, IFilterStrategy strategy)
            throws FileNotFoundException, IOException {
        final InputStream in = classLoader.getResourceAsStream(path);
        if (in == null) {
            throw new FileNotFoundException(path);
        }
        try {
            final File outFile = new File(targetDir, fileName);
            if (!outFile.exists()) {
                outFile.getParentFile().mkdirs();
                outFile.createNewFile();
            }
            final OutputStream out = new FileOutputStream(outFile);
            try {
                if (copier != null && strategy.filter(fileName)) {
                    copy(in, out, encoding, copier, outFile);
                } else {
                    IOUtils.copy(in, out);
                }
            } finally {
                IOUtils.closeQuietly(out);
            }
        } finally {
            IOUtils.closeQuietly(in);
        }
    }

    private static Properties loadResourcesProperties(ClassLoader classLoader, String templatesLocation) {
        final Properties resourceProperties = new Properties();

        final String pathToResourceProperties = createFullResourcesPath(templatesLocation, "resources.properties");

        try {
            Enumeration<URL> resources = classLoader.getResources(pathToResourceProperties);
            while (resources.hasMoreElements()) {
                InputStream in = null;
                try {
                    final URL url = (URL) resources.nextElement();
                    in = url.openStream();
                    resourceProperties.load(in);
                } finally {
                    IOUtils.closeQuietly(in);
                }
            }
        } catch (IOException e) {
            throw new IllegalStateException(e);
        }

        return resourceProperties;
    }

    protected static String createFullResourcesPath(String templatesLocation, String templateResourcesPath) {
        final StringBuilder sb = new StringBuilder();
        if (templatesLocation != null) {
            sb.append(normalizeResourcesPath(templatesLocation));
        }
        if (sb.length() > 0 && sb.charAt(sb.length() - 1) != '/') {
            sb.append('/');
        }
        sb.append(normalizeResourcesPath(templateResourcesPath));
        return sb.toString();
    }

    protected static String normalizeResourcesPath(final String path) {
        if (path == null) {
            throw new IllegalArgumentException("Path must not be null.");
        }
        String result = path.replace('\\', '/');
        if (result.startsWith("/")) {
            if (result.length() == 1) {
                result = "";
            } else {
                result = result.substring(1);
            }
        }
        if (result.endsWith("/")) {
            result = result.substring(0, result.length() - 1);
        }
        return result;
    }

    private static void copy(InputStream from, OutputStream to, String encoding, IFilteredCopier copier,
            File outFile) throws IOException {
        copier.copy(from, to, encoding, outFile);
    }

    public static Reader createFilterReader(Reader reader, LinkedHashSet<String> delimiters,
            Collection<ValueSource> valueSources, String escapeString, final boolean escapeWindowsPaths,
            final InterpolationPostProcessor postProcessor) {
        final MultiDelimiterStringSearchInterpolator interpolator = new MultiDelimiterStringSearchInterpolator();
        interpolator.setDelimiterSpecs(delimiters);
        interpolator.setEscapeString(escapeString);

        interpolator.addPostProcessor(new InterpolationPostProcessor() {
            public Object execute(String expression, Object value) {
                if (escapeWindowsPaths && value instanceof String) {
                    value = FilteringUtils.escapeWindowsPath((String) value);
                }

                if (postProcessor != null) {
                    final Object newValue = postProcessor.execute(expression, value);
                    if (newValue != null) {
                        value = newValue;
                    }
                }
                return value;
            }
        });

        final Set<String> prefixes = new HashSet<String>();
        for (ValueSource valueSource : valueSources) {
            interpolator.addValueSource(valueSource);
            String[] _prefixes = SharedResourcesUtils.getPossiblePrefixes(valueSource);
            if (_prefixes != null) {
                Collections.addAll(prefixes, _prefixes);
            }
        }

        RecursionInterceptor ri = null;
        if (prefixes != null && !prefixes.isEmpty()) {
            ri = new PrefixAwareRecursionInterceptor(prefixes, true);
        } else {
            ri = new SimpleRecursionInterceptor();
        }

        MultiDelimiterInterpolatorFilterReader filterReader = new MultiDelimiterInterpolatorFilterReader(reader,
                interpolator, ri);
        filterReader.setRecursionInterceptor(ri);
        filterReader.setDelimiterSpecs(delimiters);

        filterReader.setInterpolateWithPrefixPattern(false);
        filterReader.setEscapeString(escapeString);
        return filterReader;
    }

    @SuppressWarnings("unchecked")
    protected static String[] getPossiblePrefixes(ValueSource source) {
        try {
            if (AbstractDelegatingValueSource.class.isAssignableFrom(source.getClass())) {
                Field field = AbstractDelegatingValueSource.class.getDeclaredField("delegate");
                field.setAccessible(true);

                Object delegate = field.get(source);
                if (delegate instanceof PrefixedValueSourceWrapper) {
                    PrefixedValueSourceWrapper pp = (PrefixedValueSourceWrapper) delegate;

                    field = pp.getClass().getDeclaredField("possiblePrefixes");
                    field.setAccessible(true);

                    return (String[]) field.get(pp);
                }
            }
            return null;
        } catch (Exception e) {
            throw new IllegalStateException(e);
        }
    }
}