atg.tools.dynunit.util.ComponentUtil.java Source code

Java tutorial

Introduction

Here is the source code for atg.tools.dynunit.util.ComponentUtil.java

Source

/*
 * Copyright 2013 Matt Sicker and Contributors
 *
 * 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 atg.tools.dynunit.util;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.jetbrains.annotations.Nullable;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Properties;

/**
 * Utility class to create component properties files. This is useful for making component files on the fly during
 * unit tests, Nucleus instantiation, etc.
 *
 * @author msicker
 * @version 1.0.0
 */
public final class ComponentUtil {

    private static final Logger logger = LogManager.getLogger();

    private ComponentUtil() {
    }

    /**
     * Creates a new component properties file in {@code parent} named {@code name} using the class
     * {@code canonicalClassName} and configured with the given {@code properties}.
     *
     * @param parent
     *         Directory to place the new component properties file.
     * @param name
     *         Name of component to create. Determines the file name.
     * @param canonicalClassName
     *         Full package-qualified class name to use for component.
     * @param properties
     *         Any properties to set in the component properties file.
     *
     * @return Newly created (or recreated) component properties file.
     *
     * @throws IOException
     *         if the properties file couldn't be written to.
     */
    public static File newComponent(final File parent, final String name, final String canonicalClassName,
            final Properties properties) throws IOException {
        logger.entry(parent, name, canonicalClassName, properties);
        makeDirectory(parent);
        final File output = getComponentPropertiesFile(parent, name);
        newComponentForFile(output, canonicalClassName, properties);
        return logger.exit(output);
    }

    /**
     * Creates a new component properties file in {@code parent} named {@code name} using the class {@code klass} and
     * configured with the given {@code properties}.
     *
     * @param parent
     *         Directory to place the new component properties file.
     * @param name
     *         Name of component to create. Determines the file name.
     * @param klass
     *         Class of component to create.
     * @param properties
     *         Any properties to set in the component properties file.
     *
     * @return Newly created (or recreated) component properties file.
     *
     * @throws IOException
     *         if the properties file couldn't be written to.
     */
    public static File newComponent(final File parent, final String name, final Class<?> klass,
            final Properties properties) throws IOException {
        logger.entry(parent, name, klass, properties);
        final File output = newComponent(parent, name, klass.getCanonicalName(), properties);
        return logger.exit(output);
    }

    public static File newComponent(final File parent, final String name, final Class<?> klass) throws IOException {
        logger.entry(parent, name, klass);
        final File output = newComponent(parent, name, klass, new Properties());
        return logger.exit(output);
    }

    /**
     * Creates a new component properties file in {@code parent} named {@code name} and configured with the given
     * {@code properties}. This particular builder does not specify a class, so unless the {@code $class} property is
     * given in the {@code properties}, then the created file will be treated as a general configuration as ATG does
     * when no class is specified. This is useful for creating {@code GLOBAL.properties} files as well as overriding
     * default components.
     *
     * @param parent
     *         Directory to place the new component properties file.
     * @param name
     *         Name of component to create. Determines the file name.
     * @param properties
     *         Any properties to set in the component properties file.
     *
     * @return Newly created (or recreated) component properties file.
     *
     * @throws IOException
     *         if the properties file couldn't be written to.
     */
    public static File newComponent(final File parent, final String name, final Properties properties)
            throws IOException {
        logger.entry(parent, name, properties);
        final File output = newComponent(parent, name, "", properties);
        return logger.exit(output);
    }

    /**
     * Creates a new component properties file in {@code parent} named the same as the class {@code klass} and
     * configured with the given {@code properties}.
     *
     * @param parent
     *         Directory to place the new component properties file.
     * @param klass
     *         Class of component to create. Determines the file name. If the class name ends with {@code Impl}, that
     *         is also stripped from the name.
     * @param properties
     *         Any properties to set in the component properties file.
     *
     * @return Newly created (or recreated) component properties file.
     *
     * @throws IOException
     *         if the properties file couldn't be written to.
     */
    public static File newComponent(final File parent, final Class<?> klass, final Properties properties)
            throws IOException {
        logger.entry(parent, klass, properties);
        final File output = newComponent(parent, getSimplifiedClassName(klass), klass.getName(), properties);
        return logger.exit(output);
    }

    /**
     * Creates a new component properties file in {@code parent} using the class {@code klass}, named the same as
     * {@code klass}, and using no additional properties.
     *
     * @param parent
     *         Directory to place the new component properties file.
     * @param klass
     *         Class of component to create. Determines the file name.
     *
     * @return Newly created (or recreated) component properties file.
     *
     * @throws IOException
     *         if the properties file couldn't be written to.
     */
    public static File newComponent(final File parent, final Class<?> klass) throws IOException {
        logger.entry(parent, klass);
        final File output = newComponent(parent, klass, new Properties());
        return logger.exit(output);
    }

    /**
     * Creates a new component properties file at {@code output} using the class {@code canonicalClassName} and
     * configured with the given {@code properties}. This method is generally useful when you have a properties file
     * already and wish to overwrite it.
     *
     * @param output
     *         The component properties file to write to.
     * @param canonicalClassName
     *         Full package-qualified class name to use for component.
     * @param properties
     *         Any properties to set in the component properties file.
     *
     * @return The provided {@code output} component properties file.
     *
     * @throws IOException
     *         if {@code output} couldn't be written to.
     */
    public static File newComponentForFile(final File output, final String canonicalClassName,
            final Properties properties) throws IOException {
        logger.entry(output, canonicalClassName, properties);
        recreateFile(output);
        writeComponentPropertiesToFile(output, canonicalClassName, properties);
        return logger.exit(output);
    }

    /**
     * Creates a new component properties file at {@code output} using the class {@code klass} and configured with the
     * given {@code properties}. This method is generally useful when you have a properties file already and wish to
     * overwrite it.
     *
     * @param output
     *         The component properties file to write to.
     * @param klass
     *         Class of component to create.
     * @param properties
     *         Any properties to set in the component properties file.
     *
     * @return The provided {@code output} component properties file.
     *
     * @throws IOException
     *         if {@code output} couldn't be written to.
     */
    public static File newComponentForFile(final File output, final Class<?> klass, final Properties properties)
            throws IOException {
        logger.entry(output, klass, properties);
        newComponentForFile(output, klass.getCanonicalName(), properties);
        return logger.exit(output);
    }

    /**
     * Creates a new component properties file at {@code output} for the class {@code klass}.
     *
     * @param output
     *         The component properties file to write to.
     * @param klass
     *         Class of component to create.
     *
     * @return The provided {@code output} file.
     *
     * @throws IOException
     *         if {@code output} couldn't be written to.
     */
    public static File newComponentForFile(final File output, final Class<?> klass) throws IOException {
        logger.entry(output, klass);
        newComponentForFile(output, klass, new Properties());
        return logger.exit(output);
    }

    private static void makeDirectory(@Nullable final File directory) throws IOException {
        logger.entry(directory);
        if (directory != null) {
            FileUtils.forceMkdir(directory);
        }
        logger.exit();
    }

    private static File getComponentPropertiesFile(final File parent, final String name)
            throws FileNotFoundException {
        logger.entry(parent, name);
        if (name == null) {
            throw logger.throwing(new FileNotFoundException("No name was given."));
        }
        return logger.exit(new File(parent, name + ".properties"));
    }

    private static void recreateFile(@Nullable final File file) throws IOException {
        logger.entry(file);
        if (file != null) {
            if (file.exists()) {
                FileUtils.forceDelete(file);
            }
            if (!file.createNewFile()) {
                throw logger.throwing(new IOException("File already exists but can't be deleted."));
            }
        }
        logger.exit();
    }

    private static void writeComponentPropertiesToFile(final File output, final String canonicalClassName,
            final Properties properties) throws IOException {
        logger.entry(output, canonicalClassName, properties);
        BufferedWriter out = null;
        try {
            out = new BufferedWriter(new FileWriter(output));
            if (StringUtils.isNotEmpty(canonicalClassName)) {
                out.write("$class=");
                out.write(canonicalClassName);
                out.newLine();
            }
            properties.store(out, canonicalClassName);
        } finally {
            if (out != null) {
                out.close();
            }
            logger.exit();
        }
    }

    private static String getSimplifiedClassName(Class<?> klass) {
        String className = klass.getSimpleName();
        if (className.endsWith("Impl")) {
            className = className.substring(0, className.lastIndexOf("Impl"));
        }
        return className;
    }

}