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