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 gololang; 011 012import org.eclipse.golo.cli.command.spi.CliCommand; 013import org.eclipse.golo.compiler.GoloClassLoader; 014import gololang.ir.GoloModule; 015 016import java.io.InputStream; 017import java.net.URL; 018 019import static java.util.Objects.requireNonNull; 020import static gololang.IO.toURL; 021 022/** 023 * A utility module containing functions to interact with the runtime environment. 024 */ 025public final class Runtime { 026 private Runtime() { 027 // utility class 028 } 029 030 /** 031 * Get a boolean value from a system property or an environment variable. 032 * 033 * <p>Equivalent to {@code loadBoolean("true", prop, env, defaultValue)} 034 * 035 * @param prop system property to get the value from, ignored if {@code null}. 036 * @param env environment variable to get the value from, ignored if {@code null}. 037 * @param defaultValue value to return if neither the property nor the environment are defined. 038 */ 039 public static boolean loadBoolean(String prop, String env, boolean defaultValue) { 040 return loadBoolean("true", prop, env, defaultValue); 041 } 042 043 /** 044 * Get a boolean value from a system property or an environment variable. 045 * 046 * <p>Checks if the property is defined and equals to the value (case insensitive), otherwise checks the environment 047 * variable, then use the default value. 048 * 049 * @param value content of the property. 050 * @param prop system property to get the value from, ignored if {@code null}. 051 * @param env environment variable to get the value from, ignored if {@code null}. 052 * @param defaultValue value to return if neither the property nor the environment are defined. 053 * @throws NullPointerException if {@code value} is null and one of the property or environment is defined. 054 */ 055 public static boolean loadBoolean(String value, String prop, String env, boolean defaultValue) { 056 String val = null; 057 if (prop != null) { 058 val = System.getProperty(prop); 059 } 060 if (val == null && env != null) { 061 val = System.getenv(env); 062 } 063 if (val == null) { 064 return defaultValue; 065 } 066 return val.toLowerCase().equals(value.toLowerCase()); 067 } 068 069 private static boolean debug = loadBoolean("golo.debug", "GOLO_DEBUG", false); 070 private static boolean showStackTrace = loadBoolean("golo.debug.trace", "GOLO_DEBUG_TRACE", true); 071 072 /** 073 * Checks if debug mode is active. 074 * 075 * <p>The initial value is false, but can be redefined using the {@code golo.debug} system property, or the 076 * {@code GOLO_DEBUG} environment variable. 077 */ 078 public static boolean debugMode() { 079 return debug; 080 } 081 082 /** 083 * Defines debug mode. 084 */ 085 public static void debugMode(boolean v) { 086 debug = v; 087 } 088 089 /** 090 * Checks if the main golo command should print stack traces on error. 091 */ 092 public static boolean showStackTrace() { 093 return showStackTrace; 094 } 095 096 /** 097 * Defines if the main golo command should print stack traces on error. 098 */ 099 public static void showStackTrace(boolean v) { 100 showStackTrace = v; 101 } 102 103 private static CliCommand command; 104 105 /** 106 * Defines the golo command currently used. 107 * 108 * <p>This command is called at init time and should not be called in userland code. 109 */ 110 public static void command(CliCommand cmd) { 111 command = requireNonNull(cmd); 112 } 113 114 /** 115 * Returns the golo command currently used. 116 */ 117 public static CliCommand command() { 118 return command; 119 } 120 121 /** 122 * Returns the current thread class loader. 123 * <p> 124 * Possibly wrapped in a {@code GoloClassLoader} if necessary. 125 */ 126 public static GoloClassLoader classLoader() { 127 ClassLoader cl = Thread.currentThread().getContextClassLoader(); 128 if (cl instanceof GoloClassLoader) { 129 return (GoloClassLoader) cl; 130 } 131 return new GoloClassLoader(cl); 132 } 133 134 /** 135 * Load a golo file given its path or URL. 136 * 137 * <p>Equivalent to {@code load(module, true)}. 138 * 139 * @param module can be a {@code String}, a {@code java.nio.file.Path}, a {@code java.net.URL} or a {@code java.net.URI} identifying the file to load, or directly a {@link GoloModule}. 140 * @return the loaded module class. 141 * @see #load(Object, boolean) 142 */ 143 public static Class<?> load(Object module) throws Exception { 144 return load(module, true); 145 } 146 147 /** 148 * Load a golo file given its path or URL. 149 * 150 * <p>If {@code failOnException} is false, any exception is swallowed and null is return. 151 * 152 * @param module can be a {@code String}, a {@code java.nio.file.Path}, a {@code java.net.URL} or a {@code java.net.URI} identifying the file to load, or directly a {@link GoloModule}. 153 * @param failOnException re-raise exception or not 154 * @return the loaded module class, or {@code null} if an error occurred and {@code failOnException} is {@code false} 155 * @see #load(Object, boolean) 156 */ 157 public static Class<?> load(Object module, boolean failOnException) throws Exception { 158 try { 159 if (module instanceof GoloModule) { 160 GoloModule mod = (GoloModule) module; 161 return classLoader().load(mod.sourceFile(), mod); 162 } 163 URL url = toURL(module); 164 try (InputStream is = url.openStream()) { 165 return classLoader().load(module.toString(), is); 166 } 167 } catch (Exception e) { 168 if (failOnException) { 169 throw e; 170 } 171 return null; 172 } 173 } 174 175 /** 176 * Returns the current golo version. 177 */ 178 public static String version() { 179 return org.eclipse.golo.cli.command.Metadata.VERSION; 180 } 181}