/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF 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 org.apache.s4.tools;

import java.io.File;
import java.io.IOException;
import java.util.List;

import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.beust.jcommander.Parameter;
import com.beust.jcommander.Parameters;
import com.google.common.base.Charsets;
import com.google.common.io.Files;
import com.google.common.io.LineProcessor;
import com.google.common.io.Resources;

public class CreateApp extends S4ArgsBase {

    static Logger logger = LoggerFactory.getLogger(CreateApp.class);

    public static void main(String[] args) {

        final CreateAppArgs appArgs = new CreateAppArgs();
        Tools.parseArgs(appArgs, args);

        if (new File(appArgs.getAppDir() + "/" + appArgs.appName.get(0)).exists()) {
            System.err.println("There is already a directory called " + appArgs.appName.get(0) + " in the "
                    + appArgs.getAppDir()
                    + " directory. Please specify another name for your project or specify another parent directory");
            System.exit(1);
        }
        // create project structure
        try {
            createDir(appArgs, "/src/main/java");
            createDir(appArgs, "/src/main/resources");
            createDir(appArgs, "/src/main/java/hello");

            // copy gradlew script (redirecting to s4 gradlew)
            File gradlewTempFile = File.createTempFile("gradlew", "tmp");
            gradlewTempFile.deleteOnExit();
            Files.copy(Resources.newInputStreamSupplier(Resources.getResource("templates/gradlew")), gradlewTempFile);
            String gradlewScriptContent = Files.readLines(gradlewTempFile, Charsets.UTF_8, new PathsReplacer(appArgs));
            Files.write(gradlewScriptContent, gradlewTempFile, Charsets.UTF_8);
            Files.copy(gradlewTempFile, new File(appArgs.getAppDir() + "/gradlew"));
            new File(appArgs.getAppDir() + "/gradlew").setExecutable(true);

            // copy build file contents
            String buildFileContents = Resources.toString(Resources.getResource("templates/build.gradle"),
                    Charsets.UTF_8);
            buildFileContents = buildFileContents.replace("<s4_install_dir>",
                    "'" + new File(appArgs.s4ScriptPath).getParent() + "'");
            Files.write(buildFileContents, new File(appArgs.getAppDir() + "/build.gradle"), Charsets.UTF_8);

            // copy lib
            FileUtils.copyDirectory(new File(new File(appArgs.s4ScriptPath).getParentFile(), "lib"),
                    new File(appArgs.getAppDir() + "/lib"));

            // update app settings
            String settingsFileContents = Resources.toString(Resources.getResource("templates/settings.gradle"),
                    Charsets.UTF_8);
            settingsFileContents = settingsFileContents.replaceFirst("rootProject.name=<project-name>",
                    "rootProject.name=\"" + appArgs.appName.get(0) + "\"");
            Files.write(settingsFileContents, new File(appArgs.getAppDir() + "/settings.gradle"), Charsets.UTF_8);
            // copy hello app files
            Files.copy(Resources.newInputStreamSupplier(Resources.getResource("templates/HelloPE.java.txt")), new File(
                    appArgs.getAppDir() + "/src/main/java/hello/HelloPE.java"));
            Files.copy(Resources.newInputStreamSupplier(Resources.getResource("templates/HelloApp.java.txt")),
                    new File(appArgs.getAppDir() + "/src/main/java/hello/HelloApp.java"));
            // copy hello app adapter
            Files.copy(Resources.newInputStreamSupplier(Resources.getResource("templates/HelloInputAdapter.java.txt")),
                    new File(appArgs.getAppDir() + "/src/main/java/hello/HelloInputAdapter.java"));

            File s4TmpFile = File.createTempFile("s4Script", "template");
            s4TmpFile.deleteOnExit();
            Files.copy(Resources.newInputStreamSupplier(Resources.getResource("templates/s4")), s4TmpFile);

            // create s4
            String preparedS4Script = Files.readLines(s4TmpFile, Charsets.UTF_8, new PathsReplacer(appArgs));

            File s4Script = new File(appArgs.getAppDir() + "/s4");
            Files.write(preparedS4Script, s4Script, Charsets.UTF_8);
            s4Script.setExecutable(true);

            File readmeTmpFile = File.createTempFile("newApp", "README");
            readmeTmpFile.deleteOnExit();
            Files.copy(Resources.newInputStreamSupplier(Resources.getResource("templates/newApp.README")),
                    readmeTmpFile);
            // display contents from readme
            Files.readLines(readmeTmpFile, Charsets.UTF_8, new LineProcessor<Boolean>() {

                @Override
                public boolean processLine(String line) throws IOException {
                    System.out.println(line.replace("<appDir>", appArgs.getAppDir()));
                    return true;
                }

                @Override
                public Boolean getResult() {
                    return true;
                }

            });
        } catch (Exception e) {
            logger.error("Could not create project due to [{}]. Please check your configuration.", e.getMessage());
            logger.error("Could not create project due to [{}]. Please check your configuration.", e.getMessage());
        }
    }

    private static void createDir(CreateAppArgs appArgs, String dirName) throws Exception {
        String filePath = appArgs.getAppDir() + dirName;
        if (!new File(filePath).mkdirs()) {
            logger.error("Cannot create directory [{}], exiting.", filePath);
            throw new Exception("Cannot create directory [" + filePath + "]");
        }
    }

    private static final class PathsReplacer implements LineProcessor<String> {
        private final CreateAppArgs appArgs;
        StringBuilder sb = new StringBuilder();

        private PathsReplacer(CreateAppArgs appArgs) {
            this.appArgs = appArgs;
        }

        @Override
        public boolean processLine(String line) throws IOException {
            sb.append(line.replace("<s4_script_path>", appArgs.s4ScriptPath).replace("<s4_install_dir>",
                    new File(appArgs.s4ScriptPath).getParent())
                    + "\n");
            return true;
        }

        @Override
        public String getResult() {
            return sb.toString();
        }
    }

    @Parameters(commandNames = "newApp", separators = "=", commandDescription = "Create new application skeleton")
    static class CreateAppArgs extends S4ArgsBase {

        @Parameter(description = "name of the application", required = true, arity = 1)
        List<String> appName;

        @Parameter(names = "-parentDir", description = "parent directory of the application")
        String parentDir = System.getProperty("user.dir");

        public String getAppDir() {
            return parentDir + "/" + appName.get(0);
        }

    }
}

@@ -6043,124 +6043,8 @@
 ));%0A
-            logger.error(%22Could not create project due to %5B%7B%7D%5D. Please check your configuration.%22, e.getMessage());%0A
     
@@ -6253,86 +6253,8 @@
 ) %7B%0A
-            logger.error(%22Cannot create directory %5B%7B%7D%5D, exiting.%22, filePath);%0A
     

Remove duplicate log