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