2 * Copyright 2000-2009 JetBrains s.r.o.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 package com
.intellij
.ide
.startup
.impl
;
18 import com
.intellij
.ide
.caches
.CacheUpdater
;
19 import com
.intellij
.ide
.startup
.StartupManagerEx
;
20 import com
.intellij
.openapi
.application
.Application
;
21 import com
.intellij
.openapi
.application
.ApplicationManager
;
22 import com
.intellij
.openapi
.diagnostic
.Logger
;
23 import com
.intellij
.openapi
.progress
.ProcessCanceledException
;
24 import com
.intellij
.openapi
.progress
.ProgressIndicator
;
25 import com
.intellij
.openapi
.progress
.ProgressManager
;
26 import com
.intellij
.openapi
.project
.*;
27 import com
.intellij
.openapi
.vfs
.VirtualFileManager
;
28 import com
.intellij
.util
.containers
.CollectionFactory
;
29 import com
.intellij
.util
.io
.storage
.HeavyProcessLatch
;
30 import org
.jetbrains
.annotations
.NotNull
;
31 import org
.jetbrains
.annotations
.TestOnly
;
34 import java
.util
.ArrayList
;
35 import java
.util
.Collections
;
36 import java
.util
.LinkedList
;
37 import java
.util
.List
;
39 public class StartupManagerImpl
extends StartupManagerEx
{
40 private static final Logger LOG
= Logger
.getInstance("#com.intellij.ide.startup.impl.StartupManagerImpl");
42 private final List
<Runnable
> myPreStartupActivities
= Collections
.synchronizedList(new ArrayList
<Runnable
>());
43 private final List
<Runnable
> myStartupActivities
= new ArrayList
<Runnable
>();
44 private final List
<Runnable
> myPostStartupActivities
= Collections
.synchronizedList(new ArrayList
<Runnable
>());
46 private final List
<CacheUpdater
> myCacheUpdaters
= new LinkedList
<CacheUpdater
>();
48 private volatile boolean myPreStartupActivitiesPassed
= false;
49 private volatile boolean myStartupActivitiesRunning
= false;
50 private volatile boolean myStartupActivitiesPassed
= false;
51 private volatile boolean myPostStartupActivitiesPassed
= false;
53 private final Project myProject
;
55 public StartupManagerImpl(Project project
) {
60 public void registerPreStartupActivity(@NotNull Runnable runnable
) {
61 LOG
.assertTrue(!myPreStartupActivitiesPassed
, "Registering pre startup activity that will never be run");
62 myPreStartupActivities
.add(runnable
);
66 public void registerStartupActivity(Runnable runnable
) {
67 LOG
.assertTrue(!myStartupActivitiesPassed
, "Registering startup activity that will never be run");
68 myStartupActivities
.add(runnable
);
72 public synchronized void registerPostStartupActivity(Runnable runnable
) {
73 LOG
.assertTrue(!myPostStartupActivitiesPassed
, "Registering post-startup activity that will never be run");
74 myPostStartupActivities
.add(runnable
);
78 public void registerCacheUpdater(CacheUpdater updater
) {
79 LOG
.assertTrue(!myStartupActivitiesPassed
, CacheUpdater
.class.getSimpleName() + " must be registered before startup activity finished");
80 myCacheUpdaters
.add(updater
);
84 public boolean startupActivityRunning() {
85 return myStartupActivitiesRunning
;
89 public boolean startupActivityPassed() {
90 return myStartupActivitiesPassed
;
94 public boolean postStartupActivityPassed() {
95 return myPostStartupActivitiesPassed
;
98 public void runStartupActivities() {
99 ApplicationManager
.getApplication().runReadAction(new Runnable() {
101 assert !HeavyProcessLatch
.INSTANCE
.isRunning();
102 HeavyProcessLatch
.INSTANCE
.processStarted();
104 runActivities(myPreStartupActivities
);
105 myPreStartupActivitiesPassed
= true;
107 myStartupActivitiesRunning
= true;
108 runActivities(myStartupActivities
);
110 myStartupActivitiesRunning
= false;
111 myStartupActivitiesPassed
= true;
116 HeavyProcessLatch
.INSTANCE
.processFinished();
122 public synchronized void runPostStartupActivities() {
123 Application app
= ApplicationManager
.getApplication();
124 app
.assertIsDispatchThread();
126 if (myPostStartupActivitiesPassed
) return;
128 final List
<Runnable
> dumbAware
= CollectionFactory
.arrayList();
129 final List
<Runnable
> nonDumbAware
= CollectionFactory
.arrayList();
131 for (Runnable each
: myPostStartupActivities
) {
132 if (each
instanceof DumbAware
) {
136 nonDumbAware
.add(each
);
140 runActivities(dumbAware
);
141 DumbService
.getInstance(myProject
).runWhenSmart(new Runnable() {
143 if (myProject
.isDisposed()) return;
144 runActivities(nonDumbAware
);
146 myPostStartupActivitiesPassed
= true;
147 myPostStartupActivities
.clear();
151 if (!app
.isUnitTestMode()) {
152 VirtualFileManager
.getInstance().refresh(!app
.isHeadlessEnvironment());
156 private void startCacheUpdate() {
158 DumbServiceImpl
.getInstance(myProject
).queueCacheUpdate(myCacheUpdaters
);
160 catch (ProcessCanceledException e
) {
163 catch (Throwable e
) {
168 private static void runActivities(final List
<Runnable
> activities
) {
169 final ProgressIndicator indicator
= ProgressManager
.getInstance().getProgressIndicator();
170 while (!activities
.isEmpty()) {
171 final Runnable runnable
= activities
.remove(0);
172 if (indicator
!= null) indicator
.checkCanceled();
177 catch (ProcessCanceledException e
) {
180 catch (Throwable ex
) {
186 public void runWhenProjectIsInitialized(final Runnable action
) {
187 final Runnable runnable
;
189 final Application application
= ApplicationManager
.getApplication();
190 if (action
instanceof DumbAware
) {
191 runnable
= new DumbAwareRunnable() {
193 application
.runWriteAction(action
);
198 runnable
= new Runnable() {
200 application
.runWriteAction(action
);
205 if (myProject
.isInitialized() || (application
.isUnitTestMode() && myPostStartupActivitiesPassed
)) {
206 // in tests which simulate project opening, post-startup activities could have been run already. Then we should act as if the project was initialized
207 if (application
.isDispatchThread()) {
211 SwingUtilities
.invokeLater(new Runnable() {
213 if (!myProject
.isDisposed()) {
221 registerPostStartupActivity(runnable
);
226 public void prepareForNextTest() {
227 myPreStartupActivities
.clear();
228 myStartupActivities
.clear();
229 myPostStartupActivities
.clear();
230 myCacheUpdaters
.clear();
232 myPreStartupActivitiesPassed
= false;
233 myStartupActivitiesRunning
= false;
234 myStartupActivitiesPassed
= false;
235 myPostStartupActivitiesPassed
= false;
239 public void checkCleared() {
241 assert myStartupActivities
.isEmpty() : "Activities: " + myStartupActivities
;
242 assert myPostStartupActivities
.isEmpty() : "Post Activities: " + myPostStartupActivities
;
243 assert myPreStartupActivities
.isEmpty() : "Pre Activities: " + myPreStartupActivities
;
246 prepareForNextTest();