io.fabric8.devops.ProjectConfigs.java Source code

Java tutorial

Introduction

Here is the source code for io.fabric8.devops.ProjectConfigs.java

Source

/**
 *  Copyright 2005-2016 Red Hat, Inc.
 *
 *  Red Hat 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.
 */
package io.fabric8.devops;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.MappingIterator;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import io.fabric8.utils.Maps;
import io.fabric8.utils.Strings;
import io.fabric8.utils.Systems;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.beans.PropertyEditor;
import java.beans.PropertyEditorManager;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * A helper class for loading and saving the {@link ProjectConfig}
 */
public class ProjectConfigs {
    private static final transient Logger LOG = LoggerFactory.getLogger(ProjectConfigs.class);

    public static final String FILE_NAME = "fabric8.yml";
    public static final String LOCAL_FLOW_FILE_NAME = "Jenkinsfile";

    public static String toYaml(Object dto) throws JsonProcessingException {
        ObjectMapper mapper = createObjectMapper();
        return mapper.writeValueAsString(dto);
    }

    /**
     * Returns the configuration from the {@link #FILE_NAME} in the given folder or returns the default configuration
     */
    public static ProjectConfig loadFromFolder(File folder) {
        File projectConfigFile = new File(folder, FILE_NAME);
        if (projectConfigFile != null && projectConfigFile.exists() && projectConfigFile.isFile()) {
            LOG.debug("Parsing fabric8 devops project configuration from: " + projectConfigFile.getName());
            try {
                return ProjectConfigs.parseProjectConfig(projectConfigFile);
            } catch (IOException e) {
                LOG.warn("Failed to parse " + projectConfigFile + ". " + e, e);
            }
        }
        return new ProjectConfig();
    }

    /**
     * Tries to find the project configuration from the current directory or a parent folder.
     *
     * If no fabric8.yml file can be found just return an empty configuration
     */
    public static ProjectConfig findFromFolder(File folder) {
        if (folder.isDirectory()) {
            File projectConfigFile = new File(folder, FILE_NAME);
            if (projectConfigFile != null && projectConfigFile.exists() && projectConfigFile.isFile()) {
                return loadFromFolder(folder);
            }
            File parentFile = folder.getParentFile();
            if (parentFile != null) {
                return findFromFolder(parentFile);
            }
        }
        return new ProjectConfig();
    }

    /**
     * Returns the project config from the given url if it exists or null
     */
    public static ProjectConfig loadFromUrl(String url) {
        if (Strings.isNotBlank(url)) {
            try {
                return loadFromUrl(new URL(url));
            } catch (MalformedURLException e) {
                LOG.warn("Failed to create URL from: " + url + ". " + e, e);
            }
        }
        return null;
    }

    /**
     * Returns the project config from the given url if it exists or null
     */
    public static ProjectConfig loadFromUrl(URL url) {
        InputStream input = null;
        try {
            input = url.openStream();
        } catch (FileNotFoundException e) {
            LOG.info("No fabric8.yml at URL: " + url);
        } catch (IOException e) {
            LOG.warn("Failed to open fabric8.yml file at URL: " + url + ". " + e, e);
        }
        if (input != null) {
            try {
                LOG.info("Parsing " + ProjectConfigs.FILE_NAME + " from " + url);
                return ProjectConfigs.parseProjectConfig(input);
            } catch (IOException e) {
                LOG.warn("Failed to parse " + ProjectConfigs.FILE_NAME + " from " + url + ". " + e, e);
            }
        }
        return null;
    }

    /**
     * Returns true if the given folder has a configuration file called {@link #FILE_NAME}
     */
    public static boolean hasConfigFile(File folder) {
        File projectConfigFile = new File(folder, FILE_NAME);
        return projectConfigFile != null && projectConfigFile.exists() && projectConfigFile.isFile();
    }

    /**
     * Creates a configured Jackson object mapper for parsing YAML
     */
    public static ObjectMapper createObjectMapper() {
        return new ObjectMapper(new YAMLFactory());
    }

    public static ProjectConfig parseProjectConfig(File file) throws IOException {
        return parseYaml(file, ProjectConfig.class);
    }

    public static ProjectConfig parseProjectConfig(InputStream input) throws IOException {
        return parseYaml(input, ProjectConfig.class);
    }

    public static ProjectConfig parseProjectConfig(String yaml) throws IOException {
        return parseYaml(yaml, ProjectConfig.class);
    }

    private static <T> T parseYaml(File file, Class<T> clazz) throws IOException {
        ObjectMapper mapper = createObjectMapper();
        return mapper.readValue(file, clazz);
    }

    static <T> List<T> parseYamlValues(File file, Class<T> clazz) throws IOException {
        ObjectMapper mapper = createObjectMapper();
        MappingIterator<T> iter = mapper.readerFor(clazz).readValues(file);
        List<T> answer = new ArrayList<>();
        while (iter.hasNext()) {
            answer.add(iter.next());
        }
        return answer;
    }

    private static <T> T parseYaml(InputStream inputStream, Class<T> clazz) throws IOException {
        ObjectMapper mapper = createObjectMapper();
        return mapper.readValue(inputStream, clazz);
    }

    private static <T> T parseYaml(String yaml, Class<T> clazz) throws IOException {
        ObjectMapper mapper = createObjectMapper();
        return mapper.readValue(yaml, clazz);
    }

    /**
     * Saves the fabric8.yml file to the given project directory
     */
    public static boolean saveToFolder(File basedir, ProjectConfig config, boolean overwriteIfExists)
            throws IOException {
        File file = new File(basedir, ProjectConfigs.FILE_NAME);
        if (file.exists()) {
            if (!overwriteIfExists) {
                LOG.warn("Not generating " + file + " as it already exists");
                return false;
            }
        }
        return saveConfig(config, file);
    }

    /**
     * Saves the configuration as YAML in the given file
     */
    public static boolean saveConfig(ProjectConfig config, File file) throws IOException {
        createObjectMapper().writeValue(file, config);
        return true;
    }

    /**
     * Configures the given {@link ProjectConfig} with a map of key value pairs from
     * something like a JBoss Forge command
     */
    public static void configureProperties(ProjectConfig config, Map map) {
        Class<? extends ProjectConfig> clazz = config.getClass();
        BeanInfo beanInfo = null;
        try {
            beanInfo = Introspector.getBeanInfo(clazz);
        } catch (IntrospectionException e) {
            LOG.warn("Could not introspect " + clazz.getName() + ". " + e, e);
        }
        if (beanInfo != null) {
            PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
            for (PropertyDescriptor descriptor : propertyDescriptors) {
                Method writeMethod = descriptor.getWriteMethod();
                if (writeMethod != null) {
                    String name = descriptor.getName();
                    Object value = map.get(name);
                    if (value != null) {
                        Object safeValue = null;
                        Class<?> propertyType = descriptor.getPropertyType();
                        if (propertyType.isInstance(value)) {
                            safeValue = value;
                        } else {
                            PropertyEditor editor = descriptor.createPropertyEditor(config);
                            if (editor == null) {
                                editor = PropertyEditorManager.findEditor(propertyType);
                            }
                            if (editor != null) {
                                String text = value.toString();
                                editor.setAsText(text);
                                safeValue = editor.getValue();
                            } else {
                                LOG.warn("Cannot update property " + name + " with value " + value + " of type "
                                        + propertyType.getName() + " on " + clazz.getName());
                            }
                        }
                        if (safeValue != null) {
                            try {
                                writeMethod.invoke(config, safeValue);
                            } catch (Exception e) {
                                LOG.warn("Failed to set property " + name + " with value " + value + " on "
                                        + clazz.getName() + " " + config + ". " + e, e);
                            }

                        }
                    }
                }
            }
        }
        String flow = null;
        Object flowValue = map.get("pipeline");
        if (flowValue == null) {
            flowValue = map.get("flow");
        }
        if (flowValue != null) {
            flow = flowValue.toString();
        }
        config.setPipeline(flow);
    }

    /**
     * If no environments have been configured lets default them from the `FABRIC8_DEFAULT_ENVIRONMENTS` environment variable
     */
    public static void defaultEnvironments(ProjectConfig config, String namespace) {
        if (config != null) {
            String buildName = config.getBuildName();
            if (Strings.isNotBlank(buildName) && Maps.isNullOrEmpty(config.getEnvironments())) {
                // lets default the environments from env var
                String defaultEnvironmentsText = Systems.getEnvVarOrSystemProperty("FABRIC8_DEFAULT_ENVIRONMENTS",
                        "Testing=${namespace}-testing,Staging=${namespace}-staging,Production=${namespace}-prod");
                String text = Strings.replaceAllWithoutRegex(defaultEnvironmentsText, "${buildName}", buildName);
                text = Strings.replaceAllWithoutRegex(text, "${namespace}", namespace);
                LinkedHashMap<String, String> environments = Maps.parseMap(text);
                config.setEnvironments(environments);
            }
        }
    }

}