/**
 * Copyright (C) 2014 WhiteSource Ltd.
 *
 * 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.whitesource.fs;

import ch.qos.logback.classic.Level;
import com.beust.jcommander.JCommander;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

import static org.whitesource.agent.ConfigPropertyKeys.*;

/**
 * Author: Itai Marko
 */
public class Main {

    /* --- Static members --- */

    private static final Logger logger = LoggerFactory.getLogger(Main.class);
    private static final CommandLineArgs commandLineArgs = new CommandLineArgs();
    private static final String INFO = "info";

    private static JCommander jCommander;

    /* --- Main --- */

    public static void main(String[] args) {
        jCommander = new JCommander(commandLineArgs, args);
        // validate args // TODO use jCommander validators
        // TODO add usage command

        // read configuration properties
        Properties configProps = readAndValidateConfigFile(commandLineArgs.configFilePath);

        // read log level from configuration file
        ch.qos.logback.classic.Logger root = (ch.qos.logback.classic.Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
        String logLevel = configProps.getProperty(LOG_LEVEL_KEY, INFO);
        root.setLevel(Level.toLevel(logLevel, Level.INFO));

        // read directories and files from list-file
        List<String> files = new ArrayList<String>();
        String fileListPath = commandLineArgs.fileListPath;
        if (StringUtils.isNotBlank(fileListPath)) {
            try {
                File listFile = new File(fileListPath);
                if (listFile.exists()) {
                    for (String line : FileUtils.readLines(listFile)) {
                        files.add(line);
                    }
                }
            } catch (IOException e) {
                logger.warn("Error reading list file");
            }
        }

        // read csv directory list
        files.addAll(commandLineArgs.dependencyDirs);

        // run the agent
        FileSystemAgent whitesourceAgent = new FileSystemAgent(configProps, files);
        boolean processSuccess = whitesourceAgent.sendRequest();
        int processExitCode = processSuccess == true ? 0 : -1;
        logger.info("Process finished with exit code {}", processExitCode);
        System.exit(processExitCode);
    }

    /* --- Private methods --- */

    private static Properties readAndValidateConfigFile(String configFilePath) {
        Properties configProps = new Properties();
        InputStream inputStream = null;
        boolean foundError = false;
        try {
            inputStream = new FileInputStream(configFilePath);
            configProps.load(inputStream);
            foundError = validateConfigProps(configProps, configFilePath);
        } catch (FileNotFoundException e) {
            logger.error("Failed to open " + configFilePath + " for reading", e);
            foundError = true;
        } catch (IOException e) {
            logger.error("Error occurred when reading from " + configFilePath , e);
            foundError = true;
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    logger.warn("Failed to close " + configFilePath + "InputStream", e);
                }
            }
            if (foundError) {
                System.exit(-1); // TODO this may throw SecurityException. Return null instead
            }
        }
        return configProps;
    }

    private static boolean validateConfigProps(Properties configProps, String configFilePath) {
        boolean foundError = false;
        if (StringUtils.isBlank(configProps.getProperty(ORG_TOKEN_PROPERTY_KEY))) {
            foundError = true;
            logger.error("Could not retrieve {} property from {}", ORG_TOKEN_PROPERTY_KEY, configFilePath);
        }

        String projectToken = configProps.getProperty(PROJECT_TOKEN_PROPERTY_KEY);
        String projectName = configProps.getProperty(PROJECT_NAME_PROPERTY_KEY);
        boolean noProjectToken = StringUtils.isBlank(projectToken);
        boolean noProjectName = StringUtils.isBlank(projectName);
        if (noProjectToken && noProjectName) {
            foundError = true;
            logger.error("Could not retrieve properties {} and {}  from {}",
                    PROJECT_NAME_PROPERTY_KEY, PROJECT_TOKEN_PROPERTY_KEY, configFilePath);
        } else if (!noProjectToken && !noProjectName) {
            foundError = true;
            logger.error("Please choose {} or {}", PROJECT_NAME_PROPERTY_KEY, PROJECT_TOKEN_PROPERTY_KEY);
        }

        return foundError;
    }


}

@@ -840,16 +840,65 @@
 Factory;
+%0Aimport org.whitesource.agent.ConfigPropertyKeys;
 %0A%0Aimport
@@ -1608,16 +1608,124 @@
 ommand%0A%0A
+        String productName = commandLineArgs.product;%0A        String projectName = commandLineArgs.project;%0A
         
@@ -1846,18 +1846,380 @@
 FilePath
-);
+, projectName);%0A%0A        // Check whether the user inserted project OR/AND product via command line%0A        if (productName != null) %7B%0A            configProps.put(ConfigPropertyKeys.PRODUCT_NAME_PROPERTY_KEY,productName);%0A        %7D%0A        if (projectName != null) %7B%0A            configProps.put(ConfigPropertyKeys.PROJECT_NAME_PROPERTY_KEY, projectName);%0A        %7D
 %0A%0A      
@@ -3680,32 +3680,52 @@
 g configFilePath
+, String projectName
 ) %7B%0A        Prop
@@ -4023,32 +4023,45 @@
 , configFilePath
+, projectName
 );%0A        %7D cat
@@ -4914,16 +4914,32 @@
 FilePath
+, String project
 ) %7B%0A    
@@ -5315,16 +5315,44 @@
 ctName =
+ project != null ? project :
  configP

Add project & product parameters to command line run options