package jetbrains.mps.tool.environment; /*Generated by MPS */ import org.apache.log4j.Logger; import org.apache.log4j.LogManager; import jetbrains.mps.library.LibraryInitializer; import jetbrains.mps.project.PathMacrosProvider; import org.jetbrains.annotations.NotNull; import jetbrains.mps.RuntimeFlags; import jetbrains.mps.TestMode; import java.util.Map; import java.util.HashMap; import java.io.File; import jetbrains.mps.internal.collections.runtime.MapSequence; import jetbrains.mps.project.PathMacros; import jetbrains.mps.core.tool.environment.util.MapPathMacrosProvider; import jetbrains.mps.core.tool.environment.util.CanonicalPath; import java.util.List; import jetbrains.mps.library.contributor.LibraryContributor; import jetbrains.mps.internal.collections.runtime.ListSequence; import java.util.ArrayList; import jetbrains.mps.internal.collections.runtime.SetSequence; import org.jetbrains.annotations.Nullable; import jetbrains.mps.project.Project; import jetbrains.mps.InternalFlag; import java.util.Set; import jetbrains.mps.util.PathManager; /** * Base class for all environments, represents a caching environment. * The contract: only one environment must be alive, * it is being stored in the special EnvironmentContainer class. * * @see jetbrains.mps.tool.environment.EnvironmentContainer */ public abstract class EnvironmentBase implements Environment { private static final Logger LOG = LogManager.getLogger(EnvironmentBase.class); private static final String PLUGINS_PATH = "plugin.path"; private boolean myInitialized; private int myRefCount; protected final EnvironmentConfig myConfig; private LibraryInitializer myLibInitializer; private PathMacrosProvider myMacrosProvider; private final ProjectContainer myContainer = new ProjectContainer(); public static void initializeLog4j() { new Log4jInitializer().init(); LogManager.getLogger(EnvironmentBase.class).info("Initializing environment"); } public EnvironmentBase(@NotNull EnvironmentConfig config) { if (!(RuntimeFlags.isTestMode())) { RuntimeFlags.setTestMode(TestMode.USUAL); } myConfig = config; } protected void init(@NotNull LibraryInitializer libInitializer) { if (myInitialized) { throw new IllegalStateException("Double initialization " + this); } myLibInitializer = libInitializer; initMacros(); initLibraries(); EnvironmentContainer.setCurrent(this); retain(); myInitialized = true; } private PathMacrosProvider initMacros() { Map<String, String> macros = new HashMap<String, String>(); Map<String, File> macrosConfig = myConfig.getMacros(); for (String name : MapSequence.fromMap(macrosConfig).keySet()) { MapSequence.fromMap(macros).put(name, MapSequence.fromMap(macrosConfig).get(name).getAbsolutePath()); } myMacrosProvider = createMapMacrosProvider(macros); PathMacros.getInstance().addMacrosProvider(myMacrosProvider); return myMacrosProvider; } private static MapPathMacrosProvider createMapMacrosProvider(Map<String, String> macros) { Map<String, String> realMacros = new HashMap<String, String>(); for (String macroName : macros.keySet()) { String macroValue = MapSequence.fromMap(macros).get(macroName); CanonicalPath path = new CanonicalPath(macroValue); if (path.isValidDirectory()) { realMacros.put(macroName, path.getValue()); } } return new MapPathMacrosProvider(realMacros); } private List<LibraryContributor> initLibraries() { if (LOG.isInfoEnabled()) { LOG.info("Initializing libraries"); } final List<LibraryContributor> libContribs = ListSequence.fromList(new ArrayList<LibraryContributor>()); LibraryContributorHelper helper = new LibraryContributorHelper(myConfig, rootClassLoader()); if (SetSequence.fromSet(myConfig.getLibs()).isNotEmpty()) { ListSequence.fromList(libContribs).addElement(helper.createLibContributorForLibs()); } if (myConfig.getPlugins() != null && SetSequence.fromSet(myConfig.getPlugins()).isNotEmpty()) { ListSequence.fromList(libContribs).addElement(helper.createLibContributorForPlugins()); } myLibInitializer.load(libContribs); return libContribs; } /** * Root class loader: * 1. As a root class loader for libraries in LibraryInitializer * 2. As a root class loader for dumb idea plugin facet */ @Nullable protected abstract ClassLoader rootClassLoader(); @Override public synchronized void retain() { ++myRefCount; } @Override public void release() { if (myRefCount == 0) { throw new IllegalStateException("Reference counter is set to zero -- cannot release!"); } --myRefCount; if (myRefCount == 0) { doDispose(); EnvironmentContainer.clear(); } } @Override @NotNull public Project createProject(@NotNull ProjectStrategy strategy) { checkInitialized(); return strategy.create(this); } /** * Contract: * Returns null if there is no opened project with such File */ @Nullable public final Project getOpenedProject(@NotNull File projectFile) { checkInitialized(); return myContainer.getProject(projectFile); } @Override @NotNull public Project openProject(@NotNull File projectFile) { checkInitialized(); Project lastUsedProject = getOpenedProject(projectFile); if (lastUsedProject != null) { if (LOG.isInfoEnabled()) { LOG.info("Using the last created project"); } return lastUsedProject; } else { if (LOG.isInfoEnabled()) { LOG.info("Opening a new project"); } Project project = doOpenProject(projectFile); flushAllEvents(); return project; } } protected abstract void doDispose(); protected abstract Project doOpenProject(@NotNull File projectFile); @Override public final synchronized void dispose() { checkInitialized(); if (LOG.isDebugEnabled()) { LOG.debug("Disposing environment"); } myRefCount = 0; doDispose(); EnvironmentContainer.clear(); } protected static void setSystemProperties(boolean loadIdeaPlugins) { System.setProperty("idea.is.internal", InternalFlag.isInternalMode() + ""); System.setProperty("idea.no.jre.check", "true"); System.setProperty("idea.load.plugins", loadIdeaPlugins + ""); } protected static void setIdeaPluginsToLoad(EnvironmentConfig config) { if (isEmptyString(System.getProperty(PLUGINS_PATH))) { // this is always true except when running from ant setPluginPath(); setIdeaPluginsToLoad0(config); } } private static void setIdeaPluginsToLoad0(EnvironmentConfig config) { StringBuilder result = new StringBuilder(); Set<PluginDescriptor> plugins = config.getPlugins(); if (plugins == null) { return; } for (PluginDescriptor plugin : SetSequence.fromSet(plugins)) { result.append(plugin.getId()); result.append(","); } System.setProperty("idea.load.plugins.id", result.toString()); } protected static void setPluginPath() { StringBuilder pluginPath = new StringBuilder(); File pluginDir = new File(PathManager.getPreInstalledPluginsPath()); if (pluginDir.exists()) { for (File pluginFolder : pluginDir.listFiles()) { if (pluginPath.length() > 0) { pluginPath.append(File.pathSeparator); } pluginPath.append(pluginFolder.getPath()); } System.setProperty(PLUGINS_PATH, pluginPath.toString()); } } protected final void checkInitialized() { if (!(myInitialized)) { throw new EnvironmentBase.EnvironmentNotInitializedException(); } } private static class EnvironmentNotInitializedException extends IllegalStateException { public EnvironmentNotInitializedException() { super("#init() method must be called before using an environment"); } } private static boolean isEmptyString(String str) { return str == null || str.length() == 0; } }