001/*
002 * Copyright (c) 2012-2017 Institut National des Sciences Appliquées de Lyon (INSA-Lyon)
003 *
004 * All rights reserved. This program and the accompanying materials
005 * are made available under the terms of the Eclipse Public License v1.0
006 * which accompanies this distribution, and is available at
007 * http://www.eclipse.org/legal/epl-v10.html
008 */
009
010package org.eclipse.golo.cli.command;
011
012import com.beust.jcommander.Parameter;
013import com.beust.jcommander.Parameters;
014import com.beust.jcommander.ParametersDelegate;
015import org.eclipse.golo.cli.command.spi.CliCommand;
016import org.eclipse.golo.compiler.GoloClassLoader;
017import org.eclipse.golo.compiler.GoloCompilationException;
018
019import java.io.File;
020import java.io.FileInputStream;
021import java.io.IOException;
022import java.util.LinkedList;
023import java.util.List;
024
025import static gololang.Messages.*;
026
027@Parameters(commandNames = {"golo"}, resourceBundle = "commands", commandDescriptionKey = "golo")
028public class GoloGoloCommand implements CliCommand {
029
030  @Parameter(names = "--files", variableArity = true, descriptionKey = "golo.files", required = true)
031  List<String> files = new LinkedList<>();
032
033  @Parameter(names = "--module", descriptionKey = "main_module")
034  String module;
035
036  @Parameter(names = "--args", variableArity = true, descriptionKey = "arguments")
037  List<String> arguments = new LinkedList<>();
038
039  @ParametersDelegate
040  ClasspathOption classpath = new ClasspathOption();
041
042  @Override
043  public void execute() throws Throwable {
044    GoloClassLoader loader = classpath.initGoloClassLoader();
045    Class<?> lastClass = null;
046    for (String goloFile : this.files) {
047      lastClass = loadGoloFile(goloFile, this.module, loader);
048    }
049    if (lastClass == null && this.module != null) {
050      error(message("module_not_found", this.module));
051      return;
052    }
053    if (lastClass == null) {
054      return;
055    }
056    try {
057      callRun(lastClass, this.arguments.toArray(new String[this.arguments.size()]));
058    } catch (CliCommand.NoMainMethodException e) {
059      error(message("module_no_main", lastClass.getName()));
060    }
061  }
062
063  private Class<?> loadGoloFile(String goloFile, String module, GoloClassLoader loader) throws Throwable {
064    File file = new File(goloFile);
065    if (!file.exists()) {
066      error(message("file_not_found", file));
067    } else if (file.isDirectory()) {
068      File[] directoryFiles = file.listFiles();
069      if (directoryFiles != null) {
070        Class<?> lastClass = null;
071        for (File directoryFile : directoryFiles) {
072          Class<?> loadedClass = loadGoloFile(directoryFile.getAbsolutePath(), module, loader);
073          if (module == null || (loadedClass != null && loadedClass.getCanonicalName().equals(module))) {
074            lastClass = loadedClass;
075          }
076        }
077        return lastClass;
078      }
079    } else if (file.getName().endsWith(".golo")) {
080      try (FileInputStream in = new FileInputStream(file)) {
081        Class<?> loadedClass = loader.load(file.getName(), in);
082        if (module == null || loadedClass.getCanonicalName().equals(module)) {
083          return loadedClass;
084        }
085      } catch (IOException e) {
086        error(message("file_not_found", file.getAbsolutePath()));
087      } catch (GoloCompilationException e) {
088        handleCompilationException(e);
089      }
090    }
091    return null;
092  }
093}