/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java

https://bitbucket.org/nbargnesi/idea · Java · 1508 lines · 1269 code · 209 blank · 30 comment · 166 complexity · e969d06aaffeb0a08bebe7dc2d886735 MD5 · raw file

  1. /*
  2. * Copyright 2000-2012 JetBrains s.r.o.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package com.intellij.openapi.application.impl;
  17. import com.intellij.CommonBundle;
  18. import com.intellij.diagnostic.PerformanceWatcher;
  19. import com.intellij.diagnostic.PluginException;
  20. import com.intellij.ide.*;
  21. import com.intellij.ide.plugins.IdeaPluginDescriptor;
  22. import com.intellij.ide.plugins.PluginManager;
  23. import com.intellij.idea.StartupUtil;
  24. import com.intellij.openapi.Disposable;
  25. import com.intellij.openapi.application.*;
  26. import com.intellij.openapi.application.ex.ApplicationEx;
  27. import com.intellij.openapi.command.CommandProcessor;
  28. import com.intellij.openapi.components.RoamingType;
  29. import com.intellij.openapi.components.StateStorageException;
  30. import com.intellij.openapi.components.impl.ApplicationPathMacroManager;
  31. import com.intellij.openapi.components.impl.ComponentManagerImpl;
  32. import com.intellij.openapi.components.impl.stores.*;
  33. import com.intellij.openapi.diagnostic.Logger;
  34. import com.intellij.openapi.extensions.ExtensionPoint;
  35. import com.intellij.openapi.extensions.ExtensionPointName;
  36. import com.intellij.openapi.extensions.Extensions;
  37. import com.intellij.openapi.extensions.PluginId;
  38. import com.intellij.openapi.fileEditor.FileDocumentManager;
  39. import com.intellij.openapi.progress.EmptyProgressIndicator;
  40. import com.intellij.openapi.progress.ProcessCanceledException;
  41. import com.intellij.openapi.progress.ProgressIndicator;
  42. import com.intellij.openapi.progress.ProgressManager;
  43. import com.intellij.openapi.progress.util.ProgressWindow;
  44. import com.intellij.openapi.project.Project;
  45. import com.intellij.openapi.project.ProjectManager;
  46. import com.intellij.openapi.project.ex.ProjectEx;
  47. import com.intellij.openapi.project.ex.ProjectManagerEx;
  48. import com.intellij.openapi.project.impl.ProjectManagerImpl;
  49. import com.intellij.openapi.ui.DialogWrapper;
  50. import com.intellij.openapi.ui.Messages;
  51. import com.intellij.openapi.util.*;
  52. import com.intellij.openapi.util.registry.Registry;
  53. import com.intellij.openapi.util.text.StringUtil;
  54. import com.intellij.openapi.wm.IdeFrame;
  55. import com.intellij.openapi.wm.WindowManager;
  56. import com.intellij.openapi.wm.ex.ProgressIndicatorEx;
  57. import com.intellij.openapi.wm.impl.IdeFrameImpl;
  58. import com.intellij.psi.PsiLock;
  59. import com.intellij.ui.Splash;
  60. import com.intellij.util.Consumer;
  61. import com.intellij.util.EventDispatcher;
  62. import com.intellij.util.ReflectionCache;
  63. import com.intellij.util.Restarter;
  64. import com.intellij.util.containers.Stack;
  65. import com.intellij.util.io.storage.HeavyProcessLatch;
  66. import com.intellij.util.ui.UIUtil;
  67. import org.jetbrains.annotations.NonNls;
  68. import org.jetbrains.annotations.NotNull;
  69. import org.jetbrains.annotations.Nullable;
  70. import org.jetbrains.annotations.TestOnly;
  71. import org.picocontainer.MutablePicoContainer;
  72. import javax.swing.*;
  73. import java.awt.*;
  74. import java.io.IOException;
  75. import java.io.InputStream;
  76. import java.lang.reflect.Method;
  77. import java.util.List;
  78. import java.util.concurrent.*;
  79. import java.util.concurrent.atomic.AtomicBoolean;
  80. import java.util.concurrent.atomic.AtomicInteger;
  81. import java.util.concurrent.locks.ReentrantReadWriteLock;
  82. @SuppressWarnings({"AssignmentToStaticFieldFromInstanceMethod"})
  83. public class ApplicationImpl extends ComponentManagerImpl implements ApplicationEx {
  84. private static final Logger LOG = Logger.getInstance("#com.intellij.application.impl.ApplicationImpl");
  85. private final ModalityState MODALITY_STATE_NONE = ModalityState.NON_MODAL;
  86. // about writer preference: the way the java.util.concurrent.locks.ReentrantReadWriteLock.NonfairSync is implemented, the
  87. // writer thread will be always at the queue head and therefore, java.util.concurrent.locks.ReentrantReadWriteLock.NonfairSync.readerShouldBlock()
  88. // will return true if the write action is pending, exactly as we need
  89. private final ReentrantReadWriteLock myLock = new ReentrantReadWriteLock(false);
  90. private final ModalityInvokator myInvokator = new ModalityInvokatorImpl();
  91. private final EventDispatcher<ApplicationListener> myDispatcher = EventDispatcher.create(ApplicationListener.class);
  92. private IApplicationStore myComponentStore;
  93. private boolean myTestModeFlag;
  94. private final boolean myHeadlessMode;
  95. private final boolean myCommandLineMode;
  96. private final boolean myIsInternal;
  97. private final String myName;
  98. private final Stack<Class> myWriteActionsStack = new Stack<Class>(); // accessed from EDT only, no need to sync
  99. private volatile Runnable myExceptionalThreadWithReadAccessRunnable;
  100. private int myInEditorPaintCounter = 0;
  101. private long myStartTime = 0;
  102. @Nullable
  103. private Splash mySplash;
  104. private boolean myDoNotSave;
  105. private volatile boolean myDisposeInProgress = false;
  106. private int myRestartCode = 0;
  107. private volatile int myExitCode = 0;
  108. private final Disposable myLastDisposable = Disposer.newDisposable(); // will be disposed last
  109. private boolean myHandlingInitComponentError;
  110. private final AtomicBoolean mySaveSettingsIsInProgress = new AtomicBoolean(false);
  111. @SuppressWarnings({"UseOfArchaicSystemPropertyAccessors"})
  112. private static final int ourDumpThreadsOnLongWriteActionWaiting = Integer.getInteger("dump.threads.on.long.write.action.waiting", 0);
  113. private final AtomicInteger myAliveThreads = new AtomicInteger(0);
  114. private static final int ourReasonableThreadPoolSize = Registry.intValue("core.pooled.threads");
  115. private final ExecutorService ourThreadExecutorsService = new ThreadPoolExecutor(
  116. 3,
  117. Integer.MAX_VALUE,
  118. 5 * 60L,
  119. TimeUnit.SECONDS,
  120. new SynchronousQueue<Runnable>(),
  121. new ThreadFactory() {
  122. int i;
  123. @Override
  124. public Thread newThread(Runnable r) {
  125. final int count = myAliveThreads.incrementAndGet();
  126. final Thread thread = new Thread(r, "ApplicationImpl pooled thread "+i++) {
  127. @Override
  128. public void interrupt() {
  129. if (LOG.isDebugEnabled()) {
  130. LOG.debug("Interrupted worker, will remove from pool");
  131. }
  132. super.interrupt();
  133. }
  134. @Override
  135. public void run() {
  136. try {
  137. super.run();
  138. }
  139. catch (Throwable t) {
  140. if (LOG.isDebugEnabled()) {
  141. LOG.debug("Worker exits due to exception", t);
  142. }
  143. }
  144. myAliveThreads.decrementAndGet();
  145. }
  146. };
  147. if (ApplicationInfoImpl.getShadowInstance().isEAP() && count > ourReasonableThreadPoolSize) {
  148. LOG.info("Not enough pooled threads; creating one at:", new Throwable());
  149. }
  150. thread.setPriority(Thread.NORM_PRIORITY - 1);
  151. return thread;
  152. }
  153. }
  154. );
  155. private boolean myIsFiringLoadingEvent = false;
  156. private boolean myLoaded = false;
  157. @NonNls private static final String WAS_EVER_SHOWN = "was.ever.shown";
  158. private Boolean myActive;
  159. private static final ThreadLocal<Integer> ourEdtSafe = new ThreadLocal<Integer>();
  160. @NonNls private static final ModalityState ANY = new ModalityState() {
  161. @Override
  162. public boolean dominates(@NotNull ModalityState anotherState) {
  163. return false;
  164. }
  165. @NonNls
  166. @Override
  167. public String toString() {
  168. return "ANY";
  169. }
  170. };
  171. @Override
  172. protected void bootstrapPicoContainer() {
  173. super.bootstrapPicoContainer();
  174. getPicoContainer().registerComponentImplementation(IComponentStore.class, StoresFactory.getApplicationStoreClass());
  175. getPicoContainer().registerComponentImplementation(ApplicationPathMacroManager.class);
  176. }
  177. @NotNull
  178. public synchronized IApplicationStore getStateStore() {
  179. if (myComponentStore == null) {
  180. myComponentStore = (IApplicationStore)getPicoContainer().getComponentInstance(IComponentStore.class);
  181. }
  182. return myComponentStore;
  183. }
  184. @Override
  185. public void initializeComponent(Object component, boolean service) {
  186. getStateStore().initComponent(component, service);
  187. }
  188. public ApplicationImpl(boolean isInternal,
  189. boolean isUnitTestMode,
  190. boolean isHeadless,
  191. boolean isCommandLine,
  192. @NotNull String appName,
  193. @Nullable Splash splash) {
  194. super(null);
  195. ApplicationManager.setApplication(this, myLastDisposable); // reset back to null only when all components already disposed
  196. getPicoContainer().registerComponentInstance(Application.class, this);
  197. CommonBundle.assertKeyIsFound = isUnitTestMode;
  198. AWTExceptionHandler.register(); // do not crash AWT on exceptions
  199. if ((isInternal || isUnitTestMode) && !Comparing.equal("off", System.getProperty("idea.disposer.debug"))) {
  200. Disposer.setDebugMode(true);
  201. }
  202. myStartTime = System.currentTimeMillis();
  203. mySplash = splash;
  204. myName = appName;
  205. myIsInternal = isInternal;
  206. myTestModeFlag = isUnitTestMode;
  207. myHeadlessMode = isHeadless;
  208. myCommandLineMode = isCommandLine;
  209. myDoNotSave = myTestModeFlag || myHeadlessMode;
  210. loadApplicationComponents();
  211. if (myTestModeFlag) {
  212. registerShutdownHook();
  213. }
  214. if (!isUnitTestMode && !isHeadless) {
  215. Disposer.register(this, Disposer.newDisposable(), "ui");
  216. StartupUtil.addExternalInstanceListener(new Consumer<List<String>>() {
  217. @Override
  218. public void consume(final List<String> args) {
  219. invokeLater(new Runnable() {
  220. @Override
  221. public void run() {
  222. final Project project = CommandLineProcessor.processExternalCommandLine(args);
  223. final IdeFrame frame;
  224. if (project != null) {
  225. frame = WindowManager.getInstance().getIdeFrame(project);
  226. }
  227. else {
  228. frame = WindowManager.getInstance().getAllFrames() [0];
  229. }
  230. ((IdeFrameImpl)frame).requestFocus();
  231. }
  232. });
  233. }
  234. });
  235. }
  236. myRestartCode = Restarter.getRestartCode();
  237. registerFont("/fonts/Inconsolata.ttf");
  238. }
  239. private void registerFont(@NonNls String name) {
  240. if (isHeadlessEnvironment()) return;
  241. InputStream is = null;
  242. try {
  243. is = getClass().getResourceAsStream(name);
  244. final Font font = Font.createFont(Font.TRUETYPE_FONT, is);
  245. GraphicsEnvironment.getLocalGraphicsEnvironment().registerFont(font);
  246. }
  247. catch (Exception e) {
  248. LOG.info(e);
  249. }
  250. finally {
  251. if (is != null) {
  252. try {
  253. is.close();
  254. }
  255. catch (IOException e) {
  256. LOG.error(e);
  257. }
  258. }
  259. }
  260. }
  261. private void registerShutdownHook() {
  262. ShutDownTracker.getInstance(); // Necessary to avoid creating an instance while already shutting down.
  263. ShutDownTracker.getInstance().registerShutdownTask(new Runnable() {
  264. @Override
  265. public void run() {
  266. if (isDisposed() || isDisposeInProgress()) {
  267. return;
  268. }
  269. ShutDownTracker.invokeAndWait(isUnitTestMode(), true, new Runnable() {
  270. @Override
  271. public void run() {
  272. if (ApplicationManager.getApplication() != ApplicationImpl.this) return;
  273. try {
  274. myDisposeInProgress = true;
  275. saveAll();
  276. }
  277. finally {
  278. if (!disposeSelf(true)) {
  279. myDisposeInProgress = false;
  280. }
  281. }
  282. }
  283. });
  284. }
  285. });
  286. }
  287. private boolean disposeSelf(final boolean checkCanCloseProject) {
  288. final CommandProcessor commandProcessor = CommandProcessor.getInstance();
  289. final Ref<Boolean> canClose = new Ref<Boolean>(true);
  290. for (final Project project : ProjectManagerEx.getInstanceEx().getOpenProjects()) {
  291. try {
  292. commandProcessor.executeCommand(project, new Runnable() {
  293. @Override
  294. public void run() {
  295. final ProjectManagerImpl manager = (ProjectManagerImpl)ProjectManagerEx.getInstanceEx();
  296. if (!manager.closeProject(project, true, true, checkCanCloseProject)) {
  297. canClose.set(false);
  298. }
  299. }
  300. }, ApplicationBundle.message("command.exit"), null);
  301. }
  302. catch (Throwable e) {
  303. LOG.error(e);
  304. }
  305. if (!canClose.get()) {
  306. return false;
  307. }
  308. }
  309. Disposer.dispose(this);
  310. Disposer.assertIsEmpty();
  311. return true;
  312. }
  313. @Override
  314. @NotNull
  315. public String getName() {
  316. return myName;
  317. }
  318. @Override
  319. public boolean holdsReadLock() {
  320. return myLock.getReadHoldCount() != 0;
  321. }
  322. @Override
  323. protected void handleInitComponentError(final Throwable ex, final boolean fatal, final String componentClassName) {
  324. if (myHandlingInitComponentError) {
  325. return;
  326. }
  327. myHandlingInitComponentError = true;
  328. try {
  329. if (PluginManager.isPluginClass(componentClassName)) {
  330. LOG.error(ex);
  331. PluginId pluginId = PluginManager.getPluginByClassName(componentClassName);
  332. @NonNls final String errorMessage =
  333. "Plugin " + pluginId.getIdString() + " failed to initialize and will be disabled:\n" + ex.getMessage() +
  334. "\nPlease restart " + ApplicationNamesInfo.getInstance().getFullProductName() + ".";
  335. PluginManager.disablePlugin(pluginId.getIdString());
  336. if (!myHeadlessMode) {
  337. JOptionPane.showMessageDialog(null, errorMessage);
  338. }
  339. else {
  340. //noinspection UseOfSystemOutOrSystemErr
  341. System.out.println(errorMessage);
  342. System.exit(1);
  343. }
  344. return; // do not call super
  345. }
  346. if (fatal) {
  347. LOG.error(ex);
  348. @NonNls final String errorMessage = "Fatal error initializing class " + componentClassName + ":\n" +
  349. ex.toString() +
  350. "\nComplete error stacktrace was written to " + PathManager.getLogPath() + "/idea.log";
  351. if (!myHeadlessMode) {
  352. JOptionPane.showMessageDialog(null, errorMessage);
  353. }
  354. else {
  355. //noinspection UseOfSystemOutOrSystemErr
  356. System.out.println(errorMessage);
  357. }
  358. }
  359. super.handleInitComponentError(ex, fatal, componentClassName);
  360. }
  361. finally {
  362. myHandlingInitComponentError = false;
  363. }
  364. }
  365. private void loadApplicationComponents() {
  366. PluginManager.initPlugins(mySplash);
  367. final IdeaPluginDescriptor[] plugins = PluginManager.getPlugins();
  368. for (IdeaPluginDescriptor plugin : plugins) {
  369. if (PluginManager.shouldSkipPlugin(plugin)) continue;
  370. loadComponentsConfiguration(plugin.getAppComponents(), plugin, false);
  371. }
  372. }
  373. @Override
  374. protected synchronized Object createComponent(Class componentInterface) {
  375. Object component = super.createComponent(componentInterface);
  376. if (mySplash != null) {
  377. mySplash.showProgress("", (float)(0.65f + getPercentageOfComponentsLoaded() * 0.35f));
  378. }
  379. return component;
  380. }
  381. @Override
  382. protected MutablePicoContainer createPicoContainer() {
  383. return Extensions.getRootArea().getPicoContainer();
  384. }
  385. @Override
  386. public boolean isInternal() {
  387. return myIsInternal;
  388. }
  389. @Override
  390. public boolean isUnitTestMode() {
  391. return myTestModeFlag;
  392. }
  393. public void setUnitTestMode(boolean testModeFlag) {
  394. myTestModeFlag = testModeFlag;
  395. }
  396. @Override
  397. public boolean isHeadlessEnvironment() {
  398. return myHeadlessMode;
  399. }
  400. @Override
  401. public boolean isCommandLine() {
  402. return myCommandLineMode;
  403. }
  404. @Override
  405. public Future<?> executeOnPooledThread(@NotNull final Runnable action) {
  406. return ourThreadExecutorsService.submit(new Runnable() {
  407. @Override
  408. public void run() {
  409. try {
  410. action.run();
  411. }
  412. catch (ProcessCanceledException e) {
  413. // ignore
  414. }
  415. catch (Throwable t) {
  416. LOG.error(t);
  417. }
  418. finally {
  419. //ReflectionUtil.resetThreadLocals();
  420. Thread.interrupted(); // reset interrupted status
  421. }
  422. }
  423. });
  424. }
  425. @Override
  426. public <T> Future<T> executeOnPooledThread(@NotNull final Callable<T> action) {
  427. return ourThreadExecutorsService.submit(new Callable<T>() {
  428. @Override
  429. public T call() {
  430. try {
  431. return action.call();
  432. }
  433. catch (ProcessCanceledException e) {
  434. // ignore
  435. }
  436. catch (Throwable t) {
  437. LOG.error(t);
  438. }
  439. finally {
  440. //ReflectionUtil.resetThreadLocals();
  441. Thread.interrupted(); // reset interrupted status
  442. }
  443. return null;
  444. }
  445. });
  446. }
  447. private static Thread ourDispatchThread = null;
  448. @Override
  449. public boolean isDispatchThread() {
  450. return EventQueue.isDispatchThread();
  451. }
  452. @Override
  453. @NotNull
  454. public ModalityInvokator getInvokator() {
  455. return myInvokator;
  456. }
  457. @Override
  458. public void invokeLater(@NotNull final Runnable runnable) {
  459. myInvokator.invokeLater(runnable);
  460. }
  461. @Override
  462. public void invokeLater(@NotNull final Runnable runnable, @NotNull final Condition expired) {
  463. myInvokator.invokeLater(runnable, expired);
  464. }
  465. @Override
  466. public void invokeLater(@NotNull final Runnable runnable, @NotNull final ModalityState state) {
  467. myInvokator.invokeLater(runnable, state);
  468. }
  469. @Override
  470. public void invokeLater(@NotNull final Runnable runnable, @NotNull final ModalityState state, @NotNull final Condition expired) {
  471. myInvokator.invokeLater(runnable, state, expired);
  472. }
  473. @Override
  474. public void load(String path) throws IOException, InvalidDataException {
  475. getStateStore().setOptionsPath(path);
  476. getStateStore().setConfigPath(PathManager.getConfigPath());
  477. myIsFiringLoadingEvent = true;
  478. try {
  479. fireBeforeApplicationLoaded();
  480. }
  481. finally {
  482. myIsFiringLoadingEvent = false;
  483. }
  484. loadComponentRoamingTypes();
  485. HeavyProcessLatch.INSTANCE.processStarted();
  486. try {
  487. getStateStore().load();
  488. }
  489. catch (StateStorageException e) {
  490. throw new IOException(e.getMessage());
  491. }
  492. finally {
  493. HeavyProcessLatch.INSTANCE.processFinished();
  494. }
  495. myLoaded = true;
  496. }
  497. @Override
  498. public boolean isLoaded() {
  499. return myLoaded;
  500. }
  501. @Override
  502. protected <T> T getComponentFromContainer(final Class<T> interfaceClass) {
  503. if (myIsFiringLoadingEvent) {
  504. return null;
  505. }
  506. return super.getComponentFromContainer(interfaceClass);
  507. }
  508. private static void loadComponentRoamingTypes() {
  509. ExtensionPoint<RoamingTypeExtensionPointBean> point = Extensions.getRootArea().getExtensionPoint("com.intellij.ComponentRoamingType");
  510. final RoamingTypeExtensionPointBean[] componentRoamingTypes = point.getExtensions();
  511. for (RoamingTypeExtensionPointBean object : componentRoamingTypes) {
  512. assert object.componentName != null;
  513. assert object.roamingType != null;
  514. final RoamingType type = RoamingType.valueOf(object.roamingType);
  515. assert type != null;
  516. ComponentRoamingManager.getInstance().setRoamingType(object.componentName, type);
  517. }
  518. }
  519. private void fireBeforeApplicationLoaded() {
  520. ExtensionPoint<ApplicationLoadListener> point = Extensions.getRootArea().getExtensionPoint("com.intellij.ApplicationLoadListener");
  521. final ApplicationLoadListener[] objects = point.getExtensions();
  522. for (ApplicationLoadListener object : objects) {
  523. try {
  524. object.beforeApplicationLoaded(this);
  525. }
  526. catch(Exception e) {
  527. LOG.error(e);
  528. }
  529. }
  530. }
  531. @Override
  532. public void dispose() {
  533. fireApplicationExiting();
  534. ShutDownTracker.getInstance().ensureStopperThreadsFinished();
  535. disposeComponents();
  536. ourThreadExecutorsService.shutdownNow();
  537. myComponentStore = null;
  538. super.dispose();
  539. Disposer.dispose(myLastDisposable); // dispose it last
  540. }
  541. private final Object lock = new Object();
  542. private void makeChangesVisibleToEDT() {
  543. synchronized (lock) {
  544. lock.hashCode();
  545. }
  546. }
  547. @Override
  548. public boolean runProcessWithProgressSynchronously(@NotNull final Runnable process,
  549. @NotNull String progressTitle,
  550. boolean canBeCanceled,
  551. Project project) {
  552. return runProcessWithProgressSynchronously(process, progressTitle, canBeCanceled, project, null);
  553. }
  554. @Override
  555. public boolean runProcessWithProgressSynchronously(@NotNull final Runnable process,
  556. @NotNull final String progressTitle,
  557. final boolean canBeCanceled,
  558. @Nullable final Project project,
  559. final JComponent parentComponent) {
  560. return runProcessWithProgressSynchronously(process, progressTitle, canBeCanceled, project, parentComponent, null);
  561. }
  562. @Override
  563. public boolean runProcessWithProgressSynchronously(@NotNull final Runnable process,
  564. @NotNull final String progressTitle,
  565. final boolean canBeCanceled,
  566. @Nullable final Project project,
  567. final JComponent parentComponent,
  568. final String cancelText) {
  569. assertIsDispatchThread();
  570. if (myExceptionalThreadWithReadAccessRunnable != null ||
  571. ApplicationManager.getApplication().isUnitTestMode() ||
  572. ApplicationManager.getApplication().isHeadlessEnvironment()) {
  573. try {
  574. ProgressManager.getInstance().runProcess(process, new EmptyProgressIndicator());
  575. }
  576. catch (ProcessCanceledException e) {
  577. // ok to ignore.
  578. return false;
  579. }
  580. return true;
  581. }
  582. final ProgressWindow progress = new ProgressWindow(canBeCanceled, false, project, parentComponent, cancelText);
  583. progress.setTitle(progressTitle);
  584. try {
  585. myExceptionalThreadWithReadAccessRunnable = process;
  586. final boolean[] threadStarted = {false};
  587. SwingUtilities.invokeLater(new Runnable() {
  588. @Override
  589. public void run() {
  590. if (myExceptionalThreadWithReadAccessRunnable != process) {
  591. LOG.error("myExceptionalThreadWithReadAccessRunnable != process, process = " + myExceptionalThreadWithReadAccessRunnable);
  592. }
  593. executeOnPooledThread(new Runnable() {
  594. @Override
  595. public void run() {
  596. if (myExceptionalThreadWithReadAccessRunnable != process) {
  597. LOG.error("myExceptionalThreadWithReadAccessRunnable != process, process = " + myExceptionalThreadWithReadAccessRunnable);
  598. }
  599. final boolean old = setExceptionalThreadWithReadAccessFlag(true);
  600. LOG.assertTrue(isReadAccessAllowed());
  601. try {
  602. ProgressManager.getInstance().runProcess(process, progress);
  603. }
  604. catch (ProcessCanceledException e) {
  605. progress.cancel();
  606. // ok to ignore.
  607. }
  608. catch (RuntimeException e) {
  609. progress.cancel();
  610. throw e;
  611. }
  612. finally {
  613. setExceptionalThreadWithReadAccessFlag(old);
  614. makeChangesVisibleToEDT();
  615. }
  616. }
  617. });
  618. threadStarted[0] = true;
  619. }
  620. });
  621. progress.startBlocking();
  622. LOG.assertTrue(threadStarted[0]);
  623. LOG.assertTrue(!progress.isRunning());
  624. }
  625. finally {
  626. myExceptionalThreadWithReadAccessRunnable = null;
  627. makeChangesVisibleToEDT();
  628. }
  629. return !progress.isCanceled();
  630. }
  631. @Override
  632. public boolean isInModalProgressThread() {
  633. if (myExceptionalThreadWithReadAccessRunnable == null || !isExceptionalThreadWithReadAccess()) {
  634. return false;
  635. }
  636. ProgressIndicator progressIndicator = ProgressManager.getInstance().getProgressIndicator();
  637. return progressIndicator.isModal() && ((ProgressIndicatorEx)progressIndicator).isModalityEntered();
  638. }
  639. @Override
  640. public void invokeAndWait(@NotNull Runnable runnable, @NotNull ModalityState modalityState) {
  641. if (isDispatchThread()) {
  642. LOG.error("invokeAndWait must not be called from event queue thread");
  643. runnable.run();
  644. return;
  645. }
  646. if (isExceptionalThreadWithReadAccess()) { //OK if we're in exceptional thread.
  647. LaterInvocator.invokeAndWait(runnable, modalityState);
  648. return;
  649. }
  650. if (holdsReadLock()) {
  651. LOG.error("Calling invokeAndWait from read-action leads to possible deadlock.");
  652. }
  653. LaterInvocator.invokeAndWait(runnable, modalityState);
  654. }
  655. @Override
  656. @NotNull
  657. public ModalityState getCurrentModalityState() {
  658. Object[] entities = LaterInvocator.getCurrentModalEntities();
  659. return entities.length > 0 ? new ModalityStateEx(entities) : getNoneModalityState();
  660. }
  661. @Override
  662. @NotNull
  663. public ModalityState getModalityStateForComponent(@NotNull Component c) {
  664. Window window = c instanceof Window ? (Window)c : SwingUtilities.windowForComponent(c);
  665. if (window == null) return getNoneModalityState(); //?
  666. return LaterInvocator.modalityStateForWindow(window);
  667. }
  668. @Override
  669. public ModalityState getAnyModalityState() {
  670. return ANY;
  671. }
  672. @Override
  673. @NotNull
  674. public ModalityState getDefaultModalityState() {
  675. if (EventQueue.isDispatchThread()) {
  676. return getCurrentModalityState();
  677. }
  678. else {
  679. ProgressIndicator progress = ProgressManager.getInstance().getProgressIndicator();
  680. return progress == null ? getNoneModalityState() : progress.getModalityState();
  681. }
  682. }
  683. @Override
  684. @NotNull
  685. public ModalityState getNoneModalityState() {
  686. return MODALITY_STATE_NONE;
  687. }
  688. @Override
  689. public long getStartTime() {
  690. return myStartTime;
  691. }
  692. @Override
  693. public long getIdleTime() {
  694. return IdeEventQueue.getInstance().getIdleTime();
  695. }
  696. @Override
  697. public void exit() {
  698. exit(false);
  699. }
  700. @Override
  701. public void exit(final boolean force) {
  702. exit(force, true);
  703. }
  704. public void exit(final boolean force, final boolean allowListenersToCancel) {
  705. if (!force && getDefaultModalityState() != ModalityState.NON_MODAL) {
  706. return;
  707. }
  708. Runnable runnable = new Runnable() {
  709. @Override
  710. public void run() {
  711. if (!force && !showConfirmation()) {
  712. saveAll();
  713. myExitCode = 0;
  714. return;
  715. }
  716. getMessageBus().syncPublisher(AppLifecycleListener.TOPIC).appClosing();
  717. myDisposeInProgress = true;
  718. if (!doExit(allowListenersToCancel)) {
  719. myDisposeInProgress = false;
  720. myExitCode = 0;
  721. }
  722. }
  723. };
  724. if (!isDispatchThread()) {
  725. invokeLater(runnable, ModalityState.NON_MODAL);
  726. }
  727. else {
  728. runnable.run();
  729. }
  730. }
  731. private boolean doExit(boolean allowListenersToCancel) {
  732. saveSettings();
  733. if (allowListenersToCancel && !canExit()) {
  734. return false;
  735. }
  736. final boolean success = disposeSelf(allowListenersToCancel);
  737. if (!success || isUnitTestMode()) {
  738. return false;
  739. }
  740. System.exit(myExitCode);
  741. return true;
  742. }
  743. private static boolean showConfirmation() {
  744. final boolean hasUnsafeBgTasks = ProgressManager.getInstance().hasUnsafeProgressIndicator();
  745. DialogWrapper.DoNotAskOption option = new DialogWrapper.DoNotAskOption() {
  746. @Override
  747. public boolean isToBeShown() {
  748. return GeneralSettings.getInstance().isConfirmExit();
  749. }
  750. @Override
  751. public void setToBeShown(boolean value, int exitCode) {
  752. GeneralSettings.getInstance().setConfirmExit(value);
  753. }
  754. @Override
  755. public boolean canBeHidden() {
  756. return !hasUnsafeBgTasks;
  757. }
  758. @Override
  759. public boolean shouldSaveOptionsOnCancel() {
  760. return false;
  761. }
  762. @Override
  763. public String getDoNotShowMessage() {
  764. return "Do not ask me again";
  765. }
  766. };
  767. if (hasUnsafeBgTasks || option.isToBeShown()) {
  768. String message = ApplicationBundle
  769. .message(hasUnsafeBgTasks ? "exit.confirm.prompt.tasks" : "exit.confirm.prompt",
  770. ApplicationNamesInfo.getInstance().getFullProductName());
  771. if (DialogWrapper.OK_EXIT_CODE != Messages.showYesNoDialog(message, ApplicationBundle.message("exit.confirm.title"),
  772. ApplicationBundle.message("command.exit"), "Cancel",
  773. Messages.getQuestionIcon(), option)) {
  774. return false;
  775. }
  776. }
  777. return true;
  778. }
  779. private boolean canExit() {
  780. for (ApplicationListener applicationListener : myDispatcher.getListeners()) {
  781. if (!applicationListener.canExitApplication()) {
  782. return false;
  783. }
  784. }
  785. ProjectManagerEx projectManager = (ProjectManagerEx)ProjectManager.getInstance();
  786. Project[] projects = projectManager.getOpenProjects();
  787. for (Project project : projects) {
  788. if (!projectManager.canClose(project)) {
  789. return false;
  790. }
  791. }
  792. return true;
  793. }
  794. @Override
  795. public void runReadAction(@NotNull final Runnable action) {
  796. if (isReadAccessAllowed()) {
  797. action.run();
  798. }
  799. else {
  800. assertReadActionAllowed();
  801. try {
  802. myLock.readLock().lockInterruptibly();
  803. }
  804. catch (InterruptedException e) {
  805. throw new RuntimeInterruptedException(e);
  806. }
  807. try {
  808. action.run();
  809. }
  810. finally {
  811. myLock.readLock().unlock();
  812. }
  813. }
  814. }
  815. @Override
  816. public <T> T runReadAction(@NotNull final Computable<T> computation) {
  817. if (isReadAccessAllowed()) {
  818. return computation.compute();
  819. }
  820. else {
  821. assertReadActionAllowed();
  822. try {
  823. myLock.readLock().lockInterruptibly();
  824. }
  825. catch (InterruptedException e) {
  826. throw new RuntimeInterruptedException(e);
  827. }
  828. try {
  829. return computation.compute();
  830. }
  831. finally {
  832. myLock.readLock().unlock();
  833. }
  834. }
  835. }
  836. private static final ThreadLocal<Boolean> exceptionalThreadWithReadAccessFlag = new ThreadLocal<Boolean>();
  837. private static boolean isExceptionalThreadWithReadAccess() {
  838. Boolean flag = exceptionalThreadWithReadAccessFlag.get();
  839. return flag == Boolean.TRUE;
  840. }
  841. public static boolean setExceptionalThreadWithReadAccessFlag(boolean flag) {
  842. boolean old = isExceptionalThreadWithReadAccess();
  843. if (flag) {
  844. exceptionalThreadWithReadAccessFlag.set(Boolean.TRUE);
  845. }
  846. else {
  847. exceptionalThreadWithReadAccessFlag.remove();
  848. }
  849. return old;
  850. }
  851. @Override
  852. public void runWriteAction(@NotNull final Runnable action) {
  853. final AccessToken token = acquireWriteActionLock(action.getClass());
  854. try {
  855. action.run();
  856. }
  857. finally {
  858. token.finish();
  859. }
  860. }
  861. @Override
  862. public <T> T runWriteAction(@NotNull final Computable<T> computation) {
  863. final AccessToken token = acquireWriteActionLock(computation.getClass());
  864. try {
  865. return computation.compute();
  866. }
  867. finally {
  868. token.finish();
  869. }
  870. }
  871. @Override
  872. public boolean hasWriteAction(@Nullable Class<?> actionClass) {
  873. assertCanRunWriteAction();
  874. for (int i = myWriteActionsStack.size() - 1; i >= 0; i--) {
  875. Class action = myWriteActionsStack.get(i);
  876. if (actionClass == action || action != null && actionClass != null && ReflectionCache.isAssignable(actionClass, action)) return true;
  877. }
  878. return false;
  879. }
  880. @Override
  881. public void assertReadAccessAllowed() {
  882. if (myHeadlessMode) return;
  883. if (!isReadAccessAllowed()) {
  884. LOG.error(
  885. "Read access is allowed from event dispatch thread or inside read-action only (see com.intellij.openapi.application.Application.runReadAction())",
  886. "Current thread: " + describe(Thread.currentThread()), "Our dispatch thread:" + describe(ourDispatchThread),
  887. "SystemEventQueueThread: " + describe(getEventQueueThread()));
  888. }
  889. }
  890. @NonNls
  891. private static String describe(Thread o) {
  892. if (o == null) return "null";
  893. return o.toString() + " " + System.identityHashCode(o);
  894. }
  895. @Nullable
  896. private static Thread getEventQueueThread() {
  897. EventQueue eventQueue = Toolkit.getDefaultToolkit().getSystemEventQueue();
  898. try {
  899. Method method = EventQueue.class.getDeclaredMethod("getDispatchThread");
  900. method.setAccessible(true);
  901. return (Thread)method.invoke(eventQueue);
  902. }
  903. catch (Exception e1) {
  904. // ok
  905. }
  906. return null;
  907. }
  908. @Override
  909. public boolean isReadAccessAllowed() {
  910. Thread currentThread = Thread.currentThread();
  911. return ourDispatchThread == currentThread ||
  912. isExceptionalThreadWithReadAccess() ||
  913. holdsReadLock() ||
  914. isDispatchThread();
  915. }
  916. private static void assertCanRunWriteAction() {
  917. assertIsDispatchThread("Write access is allowed from event dispatch thread only");
  918. }
  919. @Override
  920. public void assertIsDispatchThread() {
  921. if (ShutDownTracker.isShutdownHookRunning()) return;
  922. Integer safeCounter = ourEdtSafe.get();
  923. if (safeCounter != null && safeCounter > 0) return;
  924. assertIsDispatchThread("Access is allowed from event dispatch thread only.");
  925. }
  926. private static void assertIsDispatchThread(String message) {
  927. final Thread currentThread = Thread.currentThread();
  928. if (ourDispatchThread == currentThread) return;
  929. if (EventQueue.isDispatchThread()) {
  930. ourDispatchThread = currentThread;
  931. }
  932. if (ourDispatchThread == currentThread) return;
  933. LOG.error(message,
  934. "Current thread: " + describe(Thread.currentThread()),
  935. "Our dispatch thread:" + describe(ourDispatchThread),
  936. "SystemEventQueueThread: " + describe(getEventQueueThread()));
  937. }
  938. @Override
  939. public void runEdtSafeAction(@NotNull Runnable runnable) {
  940. Integer value = ourEdtSafe.get();
  941. if (value == null) {
  942. value = Integer.valueOf(0);
  943. }
  944. ourEdtSafe.set(value + 1);
  945. try {
  946. runnable.run();
  947. }
  948. finally {
  949. int newValue = ourEdtSafe.get() - 1;
  950. ourEdtSafe.set(newValue >= 1 ? newValue : null);
  951. }
  952. }
  953. @Override
  954. public void assertIsDispatchThread(@Nullable final JComponent component) {
  955. if (component == null) return;
  956. Thread curThread = Thread.currentThread();
  957. if (ourDispatchThread == curThread) {
  958. return;
  959. }
  960. if (Boolean.TRUE.equals(component.getClientProperty(WAS_EVER_SHOWN))) {
  961. assertIsDispatchThread();
  962. }
  963. else {
  964. final JRootPane root = component.getRootPane();
  965. if (root != null) {
  966. component.putClientProperty(WAS_EVER_SHOWN, Boolean.TRUE);
  967. assertIsDispatchThread();
  968. }
  969. }
  970. }
  971. @Override
  972. public void assertTimeConsuming() {
  973. if (myTestModeFlag || myHeadlessMode || ShutDownTracker.isShutdownHookRunning()) return;
  974. LOG.assertTrue(!isDispatchThread(), "This operation is time consuming and must not be called on EDT");
  975. }
  976. @Override
  977. public boolean tryRunReadAction(@NotNull Runnable action) {
  978. //if we are inside read action, do not try to acquire read lock again since it will deadlock if there is a pending writeAction
  979. boolean mustAcquire = !isReadAccessAllowed();
  980. if (mustAcquire) {
  981. LOG.assertTrue(myTestModeFlag || !Thread.holdsLock(PsiLock.LOCK), "Thread must not hold PsiLock while performing readAction");
  982. try {
  983. // timed version of tryLock() respects fairness unlike the no-args method
  984. if (!myLock.readLock().tryLock(0, TimeUnit.MILLISECONDS)) return false;
  985. }
  986. catch (InterruptedException e) {
  987. throw new RuntimeInterruptedException(e);
  988. }
  989. }
  990. try {
  991. action.run();
  992. }
  993. finally {
  994. if (mustAcquire) {
  995. myLock.readLock().unlock();
  996. }
  997. }
  998. return true;
  999. }
  1000. public boolean tryToApplyActivationState(boolean active, Window window) {
  1001. final Component frame = UIUtil.findUltimateParent(window);
  1002. if (frame instanceof IdeFrame) {
  1003. final IdeFrame ideFrame = (IdeFrame)frame;
  1004. if (isActive() != active) {
  1005. myActive = Boolean.valueOf(active);
  1006. System.setProperty("idea.active", myActive.toString());
  1007. ApplicationActivationListener publisher = getMessageBus().syncPublisher(ApplicationActivationListener.TOPIC);
  1008. if (active) {
  1009. publisher.applicationActivated(ideFrame);
  1010. }
  1011. else {
  1012. publisher.applicationDeactivated(ideFrame);
  1013. }
  1014. return true;
  1015. }
  1016. }
  1017. return false;
  1018. }
  1019. @Override
  1020. public boolean isActive() {
  1021. if (isUnitTestMode()) return true;
  1022. if (myActive == null) {
  1023. Window active = KeyboardFocusManager.getCurrentKeyboardFocusManager().getActiveWindow();
  1024. return active != null;
  1025. }
  1026. return myActive;
  1027. }
  1028. @Override
  1029. public AccessToken acquireReadActionLock() {
  1030. // if we are inside read action, do not try to acquire read lock again since it will deadlock if there is a pending writeAction
  1031. if (isReadAccessAllowed()) return AccessToken.EMPTY_ACCESS_TOKEN;
  1032. return new ReadAccessToken();
  1033. }
  1034. @Override
  1035. public AccessToken acquireWriteActionLock(Class clazz) {
  1036. return new WriteAccessToken(clazz);
  1037. }
  1038. private class WriteAccessToken extends AccessToken {
  1039. private final Class clazz;
  1040. public WriteAccessToken(Class _clazz) {
  1041. clazz = _clazz;
  1042. assertCanRunWriteAction();
  1043. ActivityTracker.getInstance().inc();
  1044. fireBeforeWriteActionStart(_clazz);
  1045. final AtomicBoolean stopped = new AtomicBoolean(false);
  1046. LOG.assertTrue(isWriteAccessAllowed() || !Thread.holdsLock(PsiLock.LOCK), "Thread must not hold PsiLock while performing writeAction");
  1047. try {
  1048. if (!myLock.writeLock().tryLock()) {
  1049. if (ourDumpThreadsOnLongWriteActionWaiting > 0) {
  1050. executeOnPooledThread(new Runnable() {
  1051. @Override
  1052. public void run() {
  1053. while (!stopped.get()) {
  1054. try {
  1055. Thread.sleep(ourDumpThreadsOnLongWriteActionWaiting);
  1056. if (!stopped.get()) {
  1057. PerformanceWatcher.getInstance().dumpThreads(true);
  1058. }
  1059. }
  1060. catch (InterruptedException ignored) {
  1061. }
  1062. }
  1063. }
  1064. });
  1065. }
  1066. myLock.writeLock().lockInterruptibly();
  1067. }
  1068. acquired();
  1069. }
  1070. catch (InterruptedException e) {
  1071. throw new RuntimeInterruptedException(e);
  1072. }
  1073. stopped.set(true);
  1074. myWriteActionsStack.push(_clazz);
  1075. fireWriteActionStarted(_clazz);
  1076. }
  1077. @Override
  1078. public void finish() {
  1079. try {
  1080. fireWriteActionFinished(clazz);
  1081. myWriteActionsStack.pop();
  1082. }
  1083. finally {
  1084. myLock.writeLock().unlock();
  1085. released();
  1086. }
  1087. }
  1088. @Override
  1089. protected void acquired() {
  1090. String id = id();
  1091. if (id != null) {
  1092. final Thread thread = Thread.currentThread();
  1093. thread.setName(thread.getName() + id);
  1094. }
  1095. }
  1096. @Override
  1097. protected void released() {
  1098. String id = id();
  1099. if (id != null) {
  1100. final Thread thread = Thread.currentThread();
  1101. String name = thread.getName();
  1102. name = StringUtil.replace(name, id, "");
  1103. thread.setName(name);
  1104. }
  1105. }
  1106. private String id() {
  1107. Class aClass = getClass();
  1108. String name = aClass.getName();
  1109. while (name == null) {
  1110. aClass = aClass.getSuperclass();
  1111. name = aClass.getName();
  1112. }
  1113. name = name.substring(name.lastIndexOf('.') + 1);
  1114. name = name.substring(name.lastIndexOf('$') + 1);
  1115. if (!name.equals("AccessToken")) {
  1116. return " [" + name+"]";
  1117. }
  1118. return null;
  1119. }
  1120. }
  1121. private class ReadAccessToken extends AccessToken {
  1122. private ReadAccessToken() {
  1123. assertReadActionAllowed();
  1124. try {
  1125. myLock.readLock().lockInterruptibly();
  1126. acquired();
  1127. }
  1128. catch (InterruptedException e) {
  1129. throw new RuntimeInterruptedException(e);
  1130. }
  1131. }
  1132. @Override
  1133. public void finish() {
  1134. myLock.readLock().unlock();
  1135. released();
  1136. }
  1137. }
  1138. private static void assertReadActionAllowed() {
  1139. LOG.assertTrue(!Thread.holdsLock(PsiLock.LOCK), "Thread must not hold PsiLock while performing readAction");
  1140. }
  1141. @Override
  1142. public void assertWriteAccessAllowed() {
  1143. LOG.assertTrue(isWriteAccessAllowed(),
  1144. "Write access is allowed inside write-action only (see com.intellij.openapi.application.Application.runWriteAction())");
  1145. }
  1146. @Override
  1147. public boolean isWriteAccessAllowed() {
  1148. return myLock.writeLock().isHeldByCurrentThread();
  1149. }
  1150. public void editorPaintStart() {
  1151. myInEditorPaintCounter++;
  1152. }
  1153. public void editorPaintFinish() {
  1154. myInEditorPaintCounter--;
  1155. LOG.assertTrue(myInEditorPaintCounter >= 0);
  1156. }
  1157. @Override
  1158. public void addApplicationListener(@NotNull ApplicationListener l) {
  1159. myDispatcher.addListener(l);
  1160. }
  1161. @Override
  1162. public void addApplicationListener(@NotNull ApplicationListener l, @NotNull Disposable parent) {
  1163. myDispatcher.addListener(l, parent);
  1164. }
  1165. @Override
  1166. public void removeApplicationListener(@NotNull ApplicationListener l) {
  1167. myDispatcher.removeListener(l);
  1168. }
  1169. private void fireApplicationExiting() {
  1170. myDispatcher.getMulticaster().applicationExiting();
  1171. }
  1172. private void fireBeforeWriteActionStart(Class action) {
  1173. myDispatcher.getMulticaster().beforeWriteActionStart(action);
  1174. }
  1175. private void fireWriteActionStarted(Class action) {
  1176. myDispatcher.getMulticaster().writeActionStarted(action);
  1177. }
  1178. private void fireWriteActionFinished(Class action) {
  1179. myDispatcher.getMulticaster().writeActionFinished(action);
  1180. }
  1181. public void _saveSettings() { // public for testing purposes
  1182. if (mySaveSettingsIsInProgress.compareAndSet(false, true)) {
  1183. try {
  1184. StoreUtil.doSave(getStateStore());
  1185. }
  1186. catch (final Throwable ex) {
  1187. if (isUnitTestMode()) {
  1188. System.out.println("Saving application settings failed");
  1189. ex.printStackTrace();
  1190. }
  1191. else {
  1192. LOG.info("Saving application settings failed", ex);
  1193. invokeLater(new Runnable() {
  1194. @Override
  1195. public void run() {
  1196. if (ex instanceof PluginException) {
  1197. final PluginException pluginException = (PluginException)ex;
  1198. PluginManager.disablePlugin(pluginException.getPluginId().getIdString());
  1199. Messages.showMessageDialog("The plugin " +
  1200. pluginException.getPluginId() +
  1201. " failed to save settings and has been disabled. Please restart " +
  1202. ApplicationNamesInfo.getInstance().getFullProductName(), CommonBundle.getErrorTitle(),
  1203. Messages.getErrorIcon());
  1204. }
  1205. else {
  1206. Messages.showMessageDialog(ApplicationBundle.message("application.save.settings.error", ex.getLocalizedMessage()),
  1207. CommonBundle.getErrorTitle(), Messages.getErrorIcon());
  1208. }
  1209. }
  1210. });
  1211. }
  1212. }
  1213. finally {
  1214. mySaveSettingsIsInProgress.set(false);
  1215. }
  1216. }
  1217. }
  1218. @Override
  1219. public void saveSettings() {
  1220. if (myDoNotSave) return;
  1221. _saveSettings();
  1222. }
  1223. @Override
  1224. public void saveAll() {
  1225. if (myDoNotSave) return;
  1226. FileDocumentManager.getInstance().saveAllDocuments();
  1227. Project[] openProjects = ProjectManager.getInstance().getOpenProjects();
  1228. for (Project openProject : openProjects) {
  1229. ProjectEx project = (ProjectEx)openProject;
  1230. project.save();
  1231. }
  1232. saveSettings();
  1233. }
  1234. @Override
  1235. public void doNotSave() {
  1236. doNotSave(true);
  1237. }
  1238. @Override
  1239. public void doNotSave(boolean value) {
  1240. myDoNotSave = value;
  1241. }
  1242. @Override
  1243. public boolean isDoNotSave() {
  1244. return myDoNotSave;
  1245. }
  1246. @Override
  1247. public <T> T[] getExtensions(final ExtensionPointName<T> extensionPointName) {
  1248. return Extensions.getRootArea().getExtensionPoint(extensionPointName).getExtensions();
  1249. }
  1250. @Override
  1251. public boolean isDisposeInProgress() {
  1252. return myDisposeInProgress || ShutDownTracker.isShutdownHookRunning();
  1253. }
  1254. @Override
  1255. public boolean isRestartCapable() {
  1256. return Restarter.isSupported() || myRestartCode > 0;
  1257. }
  1258. @Override
  1259. public void restart() {
  1260. boolean restarted = false;
  1261. try {
  1262. restarted = Restarter.restart();
  1263. }
  1264. catch (Restarter.CannotRestartException e) {
  1265. LOG.warn(e);
  1266. }
  1267. if (!restarted) {
  1268. myExitCode = myRestartCode;
  1269. }
  1270. exit(true);
  1271. }
  1272. public boolean isSaving() {
  1273. if (getStateStore().isSaving()) return true;
  1274. Project[] openProjects = ProjectManager.getInstance().getOpenProjects();
  1275. for (Project openProject : openProjects) {
  1276. ProjectEx project = (ProjectEx)openProject;
  1277. if (project.getStateStore().isSaving()) return true;
  1278. }
  1279. return false;
  1280. }
  1281. @Override
  1282. protected boolean logSlowComponents() {
  1283. return super.logSlowComponents() || ApplicationInfoImpl.getShadowInstance().isEAP();
  1284. }
  1285. @TestOnly
  1286. public void setDisposeInProgress(boolean disposeInProgress) {
  1287. myDisposeInProgress = disposeInProgress;
  1288. }
  1289. @NonNls
  1290. @Override
  1291. public String toString() {
  1292. return "Application" +
  1293. (isDisposed() ? " (Disposed)" : "") +
  1294. (isUnitTestMode() ? " (Unit test)" : "") +
  1295. (isInternal() ? " (Internal)" : "") +
  1296. (isHeadlessEnvironment() ? " (Headless)" : "") +
  1297. (isCommandLine() ? " (Command line)" : "");
  1298. }
  1299. }