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