blob: 8d4f5499956589cfd2b608fa6b9ef479c5db0455 [file] [log] [blame]
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;
}
}