org.jboss.loom.utils.Utils.java Source code

Java tutorial

Introduction

Here is the source code for org.jboss.loom.utils.Utils.java

Source

/**
 * 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.jboss.loom.utils;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import org.apache.commons.io.DirectoryWalker;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.filefilter.FileFilterUtils;
import org.apache.commons.io.filefilter.IOFileFilter;
import org.apache.commons.io.filefilter.NameFileFilter;
import org.apache.commons.lang.StringUtils;
import org.jboss.loom.ex.CliScriptException;
import org.jboss.loom.ex.CopyException;
import org.jboss.loom.ex.MigrationException;
import org.jboss.loom.migrators.Origin;
import org.jboss.loom.spi.IConfigFragment;
import org.jboss.loom.tools.report.Reporter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Global utils class.
 *
 * @author Roman Jakubco
 */
public class Utils {
    private static final Logger log = LoggerFactory.getLogger(Utils.class);

    /**
     *  Prints app help.
     */
    public static void writeHelp() {
        System.out.println();
        System.out.println(" JBoss configuration migration tool for AS 5 / EAP 5 -> AS 7 / EAP 6 / WildFly 8");
        System.out.println();
        System.out.println(" Usage:");
        System.out.println();
        System.out.println("    java -jar AsMigrator.jar [<option>, ...] [as5.dir=]<as5.dir> [as7.dir=]<as7.dir>");
        System.out.println();
        System.out.println(
                "       <as5.dir>   is expected to contain path to AS 5 or EAP 5 home directory, i.e. the one with server/ subdirectory.");
        System.out.println();
        System.out.println(
                "       <as7.dir>   is expected to contain path to AS 7 or EAP 6 home directory, i.e. the one with jboss-modules.jar.");
        System.out.println();
        System.out.println(" Options:");
        System.out.println();
        System.out.println("    as5.profile=<name>");
        System.out.println("        Path to AS 5 profile.");
        System.out.println("        Default: \"default\"");
        System.out.println();
        System.out.println("    as7.confPath=<path> ");
        System.out.println("        Path to AS 7 config file.");
        System.out.println("        Default: \"standalone/configuration/standalone.xml\"");
        System.out.println();
        System.out.println("    conf.<module>.<property>=<value> := Module-specific options.");
        System.out.println("        <module> := Name of one of modules. E.g. datasource, jaas, security, ...");
        System.out.println("        <property> := Name of the property to set. Specific per module. "
                + "May occur multiple times.");
        System.out.println();
    }

    /**
     *  Searches a file of given name under given directory tree.
     *  @throws  CopyException if nothing found.
     */
    public static Collection<File> searchForFile(String fileName, File dir) throws FileNotFoundException {

        IOFileFilter nff = new NameFileFilter(fileName);
        Collection<File> found = FileUtils.listFiles(dir, nff, FileFilterUtils.trueFileFilter());
        if (found.isEmpty()) {
            throw new FileNotFoundException("File '" + fileName + "' was not found in " + dir.getAbsolutePath());
        }
        return found;
    }

    /**
     *  Searches a file of given name under given directory tree.
     *  @throws  CopyException if nothing found.
     */
    public static List<File> searchForFileOrDir(final String name, final File dir) throws IOException {

        List<File> found = new DirectoryWalker() {
            @Override
            protected boolean handleDirectory(File directory, int depth, Collection results) throws IOException {
                if (directory.getName().equals(name))
                    results.add(directory);
                return true;
            }

            @Override
            protected void handleFile(File file, int depth, Collection results) throws IOException {
                if (file.getName().equals(name))
                    results.add(file);
            }

            public List<File> search() throws IOException {
                List<File> found = new LinkedList();
                try {
                    this.walk(dir, found);
                } catch (IOException ex) {
                    throw new IOException("Failed traversing directory '" + dir.getAbsolutePath()
                            + "' when looking for '" + name + "'");
                }
                return found;
            }
        }.search();

        if (found.isEmpty()) {
            throw new FileNotFoundException("File '" + name + "' was not found in " + dir.getAbsolutePath());
        }
        return found;
    }

    /**
     * Builds up a File object with path consisting of given components.
     */
    public static File createPath(String parent, String child, String... more) {
        return createPath(new File(parent), child, more);
    }

    public static File createPath(File parent, String child, String... more) {
        File file = new File(parent, child);
        for (String component : more) {
            file = new File(file, component);
        }
        return file;
    }

    /**
     *  Missing from Commons IO's FileUtils...
     */
    public static void copyFileOrDirectory(File src, File dest) throws IOException {
        if (src.isFile())
            FileUtils.copyFile(src, dest);
        else if (src.isDirectory())
            FileUtils.copyDirectory(src, dest);
        else
            throw new UnsupportedOperationException("Can only copy file or directory. Not this: " + src.getPath());
    }

    // ======= Lang utils ====== //

    /**
     *  Finds a subclass of given class in current stacktrace.
     *  Returns null if not found.
     */
    public static <T> Class<? extends T> findSubclassInStackTrace(Class<T> parentClass) {
        // 0 - Thread.getStackTrace().
        // 1 - This method.
        // 2 - Whatever called this method.
        return findSubclassInStackTrace(parentClass, Thread.currentThread().getStackTrace(), 2);
    }

    /**
     *  Finds a subclass of given $parentClass in given $stackTrace, skipping $skip levels.
     *  Returns null if not found.
     */
    public static <T> Class<? extends T> findSubclassInStackTrace(Class<T> parentClass,
            StackTraceElement[] stackTrace, int skip) {
        //for( StackTraceElement call : stackTrace) {
        for (int i = skip; i < stackTrace.length; i++) {
            StackTraceElement call = stackTrace[i];
            try {
                Class<?> callClass = Class.forName(call.getClassName());
                if (parentClass.isAssignableFrom(callClass))
                    return (Class<? extends T>) callClass;
            } catch (ClassNotFoundException ex) {
                Reporter.log.error("Can't load class " + call.getClassName() + ":\n    " + ex.getMessage());
            }
        }
        return null;
    }

    /**
     *  Extracts all String getters properties to a map.
     *  @see also @Property.Utils.convert*()
     */
    public static Map<String, String> describeBean(IConfigFragment bean) {

        Map<String, String> ret = new LinkedHashMap();

        Method[] methods = bean.getClass().getMethods();
        for (Method method : methods) {
            boolean get = false;
            String name = method.getName();

            // Only use getters which return String.
            if (method.getParameterTypes().length != 0)
                continue;
            if (!method.getReturnType().equals(String.class))
                continue;
            if (name.startsWith("get"))
                get = true;
            if (!(get || name.startsWith("is")))
                continue;

            // Remove "get" or "is".
            name = name.substring(get ? 3 : 2);
            // Uncapitalize, unless it's getDLQJNDIName.
            if (name.length() > 1 && !Character.isUpperCase(name.charAt(2)))
                name = StringUtils.uncapitalize(name);

            try {
                ret.put(name, (String) method.invoke(bean));
            } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
                log.warn("Failed extracting property from " + bean.getClass().getSimpleName() + ":\n    "
                        + ex.getMessage(), ex);
            }
        }
        return ret;
    }

    /**
     *  Throws a formatted message (name + errMsg) if string is null or empty.
     */
    public static void throwIfBlank(String string, String errMsg, String name) throws CliScriptException {
        if ((string == null) || (string.isEmpty())) {
            throw new CliScriptException(name + errMsg);
        }
    }

    /**
     *  Returns null for empty strings.
     */
    public static String nullIfEmpty(String str) {
        return str == null ? null : (str.isEmpty() ? null : str);
    }

    public static Properties mapToProperties(Map<String, String> map) {
        Properties props = new Properties();
        Set<Map.Entry<String, String>> entries = map.entrySet();
        for (Map.Entry<String, String> entry : entries) {
            props.put(entry.getKey(), entry.getValue());
        }
        return props;
    }

    public static <T extends Object> void validate(T object) throws MigrationException {
        ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
        Validator validator = factory.getValidator();
        Set<ConstraintViolation<T>> valRes = validator.validate(object);
        if (!valRes.isEmpty()) {
            StringBuilder sb = new StringBuilder("Validation failed for: ");
            if (object instanceof Origin.Wise)
                sb.append(((Origin.Wise) object).getOrigin());
            else
                sb.append(object);

            for (ConstraintViolation<T> fail : valRes) {
                sb.append("\n      ").append(fail.getPropertyPath()).append(" ").append(fail.getMessage());
            }
            throw new MigrationException(sb.toString());
        }
    }// validate()

    public static Throwable getRootCause(Throwable ex) {
        Throwable cause;
        do {
            cause = ex.getCause();
            if (cause == null)
                return ex;
            ex = cause;
        } while (true); // Can exceptions ever create a loop?
    }

}// class