package org.eclipse.tigerstripe.workbench.internal.core; | |
import java.io.File; | |
import java.io.IOException; | |
import java.net.URL; | |
import java.security.CodeSource; | |
import java.text.SimpleDateFormat; | |
import java.time.Year; | |
import java.util.Enumeration; | |
import java.util.GregorianCalendar; | |
import java.util.Map; | |
import java.util.TimeZone; | |
import java.util.jar.Attributes; | |
import java.util.jar.JarFile; | |
import java.util.jar.Manifest; | |
import org.apache.commons.lang.StringUtils; | |
import org.apache.log4j.Appender; | |
import org.apache.log4j.Level; | |
import org.apache.log4j.Logger; | |
import org.apache.log4j.PatternLayout; | |
import org.apache.log4j.RollingFileAppender; | |
import org.eclipse.core.runtime.Platform; | |
import org.eclipse.osgi.service.datalocation.Location; | |
import org.eclipse.tigerstripe.workbench.TigerstripeException; | |
import org.eclipse.tigerstripe.workbench.internal.api.IClasspathModuleManager; | |
import org.eclipse.tigerstripe.workbench.internal.api.IPluginManager; | |
import org.eclipse.tigerstripe.workbench.internal.api.ITigerstripeRuntime; | |
import org.eclipse.tigerstripe.workbench.internal.api.impl.NewWorkbenchProfileSession; | |
import org.eclipse.tigerstripe.workbench.internal.api.impl.TigerstripePhantomProjectHandle; | |
import org.eclipse.tigerstripe.workbench.internal.core.module.ClasspathModuleManager; | |
import org.eclipse.tigerstripe.workbench.internal.core.module.IInstalledModule; | |
import org.eclipse.tigerstripe.workbench.internal.core.plugin.PluginManager; | |
import org.eclipse.tigerstripe.workbench.internal.core.profile.PhantomTigerstripeProjectMgr; | |
import org.eclipse.tigerstripe.workbench.plugins.LogLevel; | |
import org.eclipse.tigerstripe.workbench.profile.IPhantomProjectManager; | |
import org.eclipse.tigerstripe.workbench.profile.IWorkbenchProfileBaseSession; | |
import org.eclipse.tigerstripe.workbench.project.IPhantomTigerstripeProject; | |
public class NewTigerstripeRuntime implements ITigerstripeRuntime { | |
// Version of the currently active tigerstripe feature | |
public static final String TIGERSTRIPE_FEATURE_VERSION = "tigerstripe.feature.version"; // $NON-NLS-1$ | |
public static final String CURRENT_YEAR = "tigerstripe.runtime.year"; // $NON-NLS-1$ | |
public static final String TIGERSTRIPE_HOME_DIR = "tigerstripe"; // $NON-NLS-1$ | |
public static final String TIGERSTRIPE_PLUGINS_DIR = "plugins"; // $NON-NLS-1$ | |
public static final String TIGERSTRIPE_MODULES_DIR = "modules"; // $NON-NLS-1$ | |
public static final String PRODUCT_NAME = "product.name"; // $NON-NLS-1$ | |
/** Signaling we're running as a generic Eclipse Run */ | |
public static final int ECLIPSE_GUI_RUN = 1; | |
/** Signaling we're running thru the Ant command */ | |
public static final int ANT_RUN = 2; | |
/** Signaling we're running thru the CLI */ | |
public static final int CLI_RUN = 3; | |
/** Signaling we're running thru the Eclipse Headless harness */ | |
public static final int ECLIPSE_HEADLESS_RUN = 4; | |
/** Signaling we're running thru the Eclipse Headless harness */ | |
public static final int STANDALONE_RUN = 4; | |
private static final String LOG4J_FQCN = NewTigerstripeRuntime.class.getName(); | |
private static NewTigerstripeRuntime defaultInstance; | |
private static ThreadLocal<NewTigerstripeRuntime> threadLocalInstance = new ThreadLocal<>(); | |
public static NewTigerstripeRuntime getThreadActiveRuntime() { | |
return threadLocalInstance.get() != null ? threadLocalInstance.get() : getDefaultInstance(); | |
} | |
private static synchronized NewTigerstripeRuntime getDefaultInstance() { | |
if (defaultInstance == null) { | |
defaultInstance = new NewTigerstripeRuntime(); | |
} | |
return defaultInstance; | |
} | |
public static void setThreadActiveRuntime(NewTigerstripeRuntime runtime) { | |
NewTigerstripeRuntime old = threadLocalInstance.get(); | |
if (old != null) { | |
old.dispose(); | |
} | |
threadLocalInstance.set(runtime); | |
} | |
private volatile boolean initialized = false; | |
/* | |
* the current run type. This is set once and for all Valid values are | |
* ECLIPSE_GUI_RUN, ECLIPSE_HEADLESS_RUN, ANT_RUN, CLI_RUN | |
*/ | |
private int runType = ECLIPSE_GUI_RUN; | |
private Logger tigerstripeLogger; | |
private String loggingDir = null; | |
private String loggingFile = null; | |
private Level defaultLoggingLevel = Level.ALL; | |
private int maxNumBackupLogs = 9; | |
private String logStartTime = ""; | |
private String tigerstripeRuntimeRoot; | |
private TigerstripePhantomProjectHandle phantomHandle = null; | |
private PhantomTigerstripeProjectMgr tsProjectManager; | |
private PluginManager pluginManager = null; | |
private IClasspathModuleManager classpathModuleManager = null; | |
protected IWorkbenchProfileBaseSession workbenchProfileSession; | |
private String ts_home; | |
public int getRuntype() { | |
return runType; | |
} | |
/** | |
* Sets the runtype | |
* | |
* @param runType | |
* - valid values are ECLIPSE_GUI_RUN, ECLIPSE_HEADLESS_RUN, | |
* ANT_RUN, CLI_RUN | |
*/ | |
public void setRuntype(int runType) { | |
this.runType = runType; | |
} | |
public void setLoggingDir(String logging_Dir) { | |
loggingDir = logging_Dir; | |
} | |
public String getLoggingDir() { | |
String runtimeRoot = getTigerstripeRuntimeRoot(); | |
if (loggingDir == null) { | |
return runtimeRoot; | |
} | |
return loggingDir; | |
} | |
/** | |
* Initialize any Tigerstripe Logging related logic | |
* | |
* WARNING: this can only be run once the Tigerstripe Runtime Root as been | |
* established. | |
* | |
* @param loggingDir | |
* - the absolute path to the dir where the tigerstripe log shall | |
* be created | |
*/ | |
public void initLogger() { | |
if (getLoggingDir() != null) { | |
// First check that the loggingDir exists: upon first run | |
// it would not have been created at this stage. | |
File loggingDirFile = new File(getLoggingDir()); | |
if (!loggingDirFile.exists()) { | |
loggingDirFile.mkdirs(); | |
} | |
// logger ID needs to be unique per runtime instantiation, otherwise multi-module generation end up getting access to the same logger object. | |
String tigerstripeLoggerID = NewTigerstripeRuntime.class.getCanonicalName() + getTs_home().hashCode(); | |
File outputFile = new File(loggingDirFile, "tigerstripe.log"); | |
// the current time (to the nearest millisecond) is used as a | |
// unique ID for this process's logfile entries (in case there are | |
// multiple processes using the same logfile... | |
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSZ"); | |
TimeZone tz = TimeZone.getTimeZone("GMT+0"); | |
GregorianCalendar calendar = new GregorianCalendar(tz); | |
logStartTime = sdf.format(calendar.getTime()); | |
String conversionPattern = "%-5p %C [%d{dd-MMM-yyyy HH:mm:ss.SSS}] - %m [" + logStartTime + "]%n"; | |
PatternLayout patternLayout = new PatternLayout(conversionPattern); | |
try { | |
boolean outputFileExists = false; | |
if (outputFile.exists()) | |
outputFileExists = true; | |
RollingFileAppender appender = new RollingFileAppender(patternLayout, outputFile.getAbsolutePath()); | |
appender.setMaxBackupIndex(maxNumBackupLogs); | |
appender.setImmediateFlush(true); | |
tigerstripeLogger = Logger.getLogger(tigerstripeLoggerID); | |
tigerstripeLogger.removeAllAppenders(); | |
if (outputFileExists) { | |
appender.rollOver(); | |
} | |
tigerstripeLogger.addAppender(appender); | |
tigerstripeLogger.setAdditivity(false); | |
tigerstripeLogger.setLevel(defaultLoggingLevel); | |
loggingFile = appender.getFile(); | |
} catch (IOException e) { | |
e.printStackTrace(System.err); | |
} | |
// Print info about build in the header of the log | |
logInfoMessage(" Tigerstripe(tm) CLI v" + findWorkbenchFeatureVersion()); | |
logInfoMessage("\nRuntime environment:\n"); | |
Map<String, String> systemEnv = System.getenv(); | |
for (String key : systemEnv.keySet()) { | |
logInfoMessage(" " + key + " = " + systemEnv.get(key)); | |
} | |
} | |
} | |
public void setLogLevel(LogLevel plLevel) { | |
if (tigerstripeLogger != null) { | |
tigerstripeLogger.setLevel(plLevel.toLog4j()); | |
} | |
} | |
public void logDebugMessage(String message) { | |
logDebugMessage(message, null); | |
} | |
public void logDebugMessage(String message, Throwable t) { | |
logMessage(Level.DEBUG, message, t); | |
} | |
public void logErrorMessage(String message) { | |
logErrorMessage(message, null); | |
} | |
public void logErrorMessage(String message, Throwable t) { | |
logMessage(Level.ERROR, message, t); | |
} | |
public void logFatalMessage(String message) { | |
logFatalMessage(message, null); | |
} | |
public void logFatalMessage(String message, Throwable t) { | |
logMessage(Level.FATAL, message, t); | |
} | |
public void logInfoMessage(String message) { | |
logInfoMessage(message, null); | |
} | |
public void logInfoMessage(String message, Throwable t) { | |
logMessage(Level.INFO, message, t); | |
} | |
public void logTraceMessage(String message) { | |
logTraceMessage(message, null); | |
} | |
public void logTraceMessage(String message, Throwable t) { | |
logMessage(Level.TRACE, message, t); | |
} | |
public void logWarnMessage(String message) { | |
logWarnMessage(message, null); | |
} | |
public void logWarnMessage(String message, Throwable t) { | |
logMessage(Level.WARN, message, t); | |
} | |
public void logMessageSilently(Level level, String message, Throwable t) { | |
if (tigerstripeLogger != null) { | |
tigerstripeLogger.log(LOG4J_FQCN, level, message, t); | |
} | |
} | |
public void logMessage(Level level, String message, Throwable t) { | |
if (tigerstripeLogger != null) { | |
tigerstripeLogger.log(LOG4J_FQCN, level, message, t); | |
} | |
} | |
public String getProperty(String property) { | |
if (TIGERSTRIPE_FEATURE_VERSION.equalsIgnoreCase(property)) { | |
return findWorkbenchFeatureVersion(); | |
} else if (CURRENT_YEAR.equalsIgnoreCase(property)) { | |
int year = Year.now().getValue(); | |
return String.valueOf(year); | |
} | |
return null; | |
} | |
public String getLogPath() { | |
return loggingFile; | |
} | |
protected static String findWorkbenchFeatureVersion() { | |
CodeSource src = NewTigerstripeRuntime.class.getProtectionDomain().getCodeSource(); | |
if (src != null) { | |
URL path = src.getLocation(); | |
try (JarFile jarFile = new JarFile(path.getPath());) { | |
Manifest mf = jarFile.getManifest(); | |
Attributes attrs = mf.getMainAttributes(); | |
String value = attrs.getValue("Bundle-Version"); | |
if (StringUtils.isNotEmpty(value)) { | |
return value; | |
} | |
} catch (Exception e) { | |
// ignore - just drop out | |
} | |
} | |
return "Not yet set"; | |
} | |
public String getTigerstripeRuntimeRoot() { | |
if (tigerstripeRuntimeRoot == null) { | |
try { | |
File runtimeRoot = getOrCreateTigerstripeRuntimeDir(); | |
tigerstripeRuntimeRoot = runtimeRoot.getAbsolutePath(); | |
} catch (TigerstripeException e) { | |
System.err.println("Please define TIGERSTRIPE_HOME."); | |
System.exit(-1); | |
} | |
} | |
return tigerstripeRuntimeRoot; | |
} | |
public void setTigerstripeRuntime(String tigerstripeRuntime) { | |
tigerstripeRuntimeRoot = tigerstripeRuntime; | |
} | |
public IPhantomProjectManager getPhantomTigerstripeProjectMgr() { | |
synchronized (this) { | |
if (tsProjectManager == null) { | |
tsProjectManager = new PhantomTigerstripeProjectMgr(this); | |
} | |
} | |
return tsProjectManager; | |
} | |
public IPhantomTigerstripeProject getPhantomProject() throws TigerstripeException { | |
synchronized (this) { | |
if (phantomHandle == null) { | |
phantomHandle = new TigerstripePhantomProjectHandle(this); | |
phantomHandle.init(); | |
} | |
} | |
return phantomHandle; | |
} | |
public void resetPhantomProject() { | |
synchronized (this) { | |
if (phantomHandle != null) { | |
phantomHandle.dispose(); | |
phantomHandle = null; | |
} | |
} | |
} | |
public String getGeneratorDeployLocation() { | |
if (getTigerstripeRuntimeRoot() != null) { | |
File dir = new File(new File(getTigerstripeRuntimeRoot()), TIGERSTRIPE_PLUGINS_DIR); | |
if (!dir.exists()) { | |
dir.mkdirs(); | |
} | |
return dir.getAbsolutePath(); | |
} | |
return getTigerstripeRuntimeRoot(); | |
} | |
public synchronized void init(String ts_home) { | |
if (!initialized) { | |
try { | |
setTs_home(ts_home); | |
File tigerstripeRuntimeRootFile = getOrCreateTigerstripeRuntimeDir(); | |
setTigerstripeRuntime(tigerstripeRuntimeRootFile.getAbsolutePath()); | |
getOrCreateTigerstripePluginDir(); | |
getOrCreateTigerstripeModulesDir(); | |
initLogger(); | |
classpathModuleManager = new ClasspathModuleManager(this); | |
initialized = true; | |
getPhantomTigerstripeProjectMgr().getPhantomProject(); | |
} catch (TigerstripeException e) { | |
logErrorMessage("Tigerstripe has encountered a critical error during post-startup initialization", e); | |
} | |
} | |
} | |
public void dispose() { | |
// NOTE - We do not dispose the workbench profile or plugins, as they are very | |
// expensive to reload in case this instance is re-initialized again. | |
if (classpathModuleManager != null) { | |
classpathModuleManager.dispose(); | |
classpathModuleManager = null; | |
} | |
if (phantomHandle != null) { | |
phantomHandle.dispose(); | |
phantomHandle = null; | |
} | |
if (tsProjectManager != null) { | |
tsProjectManager.dispose(); | |
tsProjectManager = null; | |
} | |
if (tigerstripeLogger != null) { | |
Enumeration<Appender> appenders = tigerstripeLogger.getAllAppenders(); | |
if (appenders != null) { | |
while (appenders.hasMoreElements()) { | |
Appender appender = appenders.nextElement(); | |
appender.close(); | |
tigerstripeLogger.removeAppender(appender); | |
} | |
} | |
tigerstripeLogger = null; | |
} | |
loggingDir = null; | |
loggingFile = null; | |
logStartTime = null; | |
tigerstripeRuntimeRoot = null; | |
ts_home = null; | |
initialized = false; | |
} | |
public String getTs_home() { | |
return ts_home; | |
} | |
public void setTs_home(String ts_home) { | |
this.ts_home = ts_home; | |
} | |
// The default here is for standalone | |
public File getOrCreateTigerstripeRuntimeDir() throws TigerstripeException { | |
if (getRuntype() != NewTigerstripeRuntime.STANDALONE_RUN) { | |
Location location = Platform.getInstallLocation(); | |
if (location != null && StringUtils.isNotEmpty(location.getURL().getPath())) { | |
File tsRuntimeDir = new File(new File(location.getURL().getPath()), | |
NewTigerstripeRuntime.TIGERSTRIPE_HOME_DIR); | |
if (!tsRuntimeDir.exists()) { | |
if (!tsRuntimeDir.mkdirs()) | |
throw new TigerstripeException( | |
"Failed to create Tigerstripe Runtime Directory at " + tsRuntimeDir.getAbsolutePath()); | |
} | |
return tsRuntimeDir; | |
} | |
} | |
// This only happens in Standalone, | |
if (getTs_home() == null || getTs_home().length() == 0) { | |
// Let's get this from the env | |
setTs_home(System.getenv("TIGERSTRIPE_HOME")); | |
} | |
if (StringUtils.isEmpty(getTs_home())) { | |
throw new TigerstripeException( | |
"When running in headless mode TIGERSTRIPE_HOME environment variable must be set."); | |
} | |
return new File(ts_home); | |
} | |
private File getOrCreateTigerstripePluginDir() throws TigerstripeException { | |
if (getRuntype() != NewTigerstripeRuntime.STANDALONE_RUN) { | |
File pluginsDir = new File(getOrCreateTigerstripeRuntimeDir(), | |
NewTigerstripeRuntime.TIGERSTRIPE_PLUGINS_DIR); | |
if (!pluginsDir.exists()) | |
if (!pluginsDir.mkdir()) | |
throw new TigerstripeException("Failed to create Tigerstripe Runtime Directory for plugins at " | |
+ pluginsDir.toURI().toString()); | |
return pluginsDir; | |
} | |
// In standalone, there is no "plugins" dir. | |
return null; | |
} | |
private File getOrCreateTigerstripeModulesDir() throws TigerstripeException { | |
if (getRuntype() != NewTigerstripeRuntime.STANDALONE_RUN) { | |
File modulesDir = new File(getOrCreateTigerstripeRuntimeDir(), | |
NewTigerstripeRuntime.TIGERSTRIPE_MODULES_DIR); | |
if (!modulesDir.exists()) | |
if (!modulesDir.mkdirs()) | |
throw new TigerstripeException("Failed to create Tigerstripe Runtime Directory for modules at " | |
+ modulesDir.toURI().toString()); | |
return modulesDir; | |
} | |
// In standalone, there is no "modules" dir. | |
return null; | |
} | |
public IPluginManager getPluginManager() { | |
if (pluginManager == null) { | |
pluginManager = new PluginManager(this); | |
} | |
return pluginManager; | |
} | |
public IInstalledModule getModule(String moduleId) { | |
if (classpathModuleManager == null) { | |
classpathModuleManager = new ClasspathModuleManager(this); | |
} | |
return classpathModuleManager.getModule(moduleId); | |
} | |
public IWorkbenchProfileBaseSession getWorkbenchProfileSession() { | |
if (workbenchProfileSession == null) { | |
workbenchProfileSession = new NewWorkbenchProfileSession(this); | |
workbenchProfileSession.reloadActiveProfile(); | |
} | |
return workbenchProfileSession; | |
} | |
} |