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 */ 010package org.eclipse.golo.cli.command; 011 012import com.beust.jcommander.Parameter; 013import com.beust.jcommander.Parameters; 014import org.eclipse.golo.cli.command.spi.CliCommand; 015import org.eclipse.golo.compiler.GoloClassLoader; 016import org.eclipse.golo.compiler.GoloCompilationException; 017 018import java.io.IOException; 019import java.io.InputStream; 020import java.nio.file.*; 021import java.util.LinkedList; 022import java.util.List; 023import java.util.stream.Collectors; 024 025import static gololang.Messages.message; 026 027@Parameters(commandNames = {"shebang"}, resourceBundle = "commands", commandDescriptionKey = "golo") 028public class ShebangCommand implements CliCommand { 029 030 @Parameter(descriptionKey = "arguments", required = true) 031 List<String> arguments = new LinkedList<>(); 032 033 @Override 034 public void execute() throws Throwable { 035 Path script = Paths.get(arguments.get(0)); 036 while (Files.isSymbolicLink(script)) { 037 script = Files.readSymbolicLink(script); 038 } 039 Path basedir = dirName(script); 040 GoloClassLoader loader = ClasspathOption.initGoloClassLoader(classpath(basedir)); 041 try { 042 loadOtherGoloFiles(loader, basedir, script); 043 callRun(loadGoloFile(loader, script), this.arguments.toArray(new String[this.arguments.size()])); 044 } catch (GoloCompilationException e) { 045 handleCompilationException(e); 046 } 047 } 048 049 private static Path dirName(Path file) { 050 if (!file.isAbsolute()) { 051 return file.toAbsolutePath().getParent(); 052 } 053 return file.getParent(); 054 } 055 056 private static boolean sameFile(Path path1, Path path2) { 057 return path1.toAbsolutePath().compareTo(path2.toAbsolutePath()) == 0; 058 } 059 060 private List<String> classpath(Path basedir) throws IOException { 061 PathMatcher jarFiles = FileSystems.getDefault().getPathMatcher("glob:**/*.jar"); 062 return Files.walk(basedir) 063 .filter(jarFiles::matches) 064 .map(path -> path.toAbsolutePath().toString()) 065 .collect(Collectors.toList()); 066 } 067 068 private void loadOtherGoloFiles(GoloClassLoader loader, Path basedir, Path script) throws IOException { 069 PathMatcher goloFiles = FileSystems.getDefault().getPathMatcher("glob:**/*.golo"); 070 Files.walk(basedir) 071 .filter(path -> goloFiles.matches(path) && !sameFile(path, script)) 072 .forEach(path -> loadGoloFile(loader, path)); 073 } 074 075 private Class<?> loadGoloFile(GoloClassLoader loader, Path path) { 076 try (InputStream is = Files.newInputStream(path)) { 077 Path filename = path.getFileName(); 078 if (filename != null) { 079 return loader.load(filename.toString(), is); 080 } else { 081 throw new RuntimeException(message("not_regular_file", path)); 082 } 083 } catch (IOException e) { 084 throw new RuntimeException(e); 085 } 086 } 087 088}