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
.openapi
.project
;
18 import com
.intellij
.ide
.caches
.CacheUpdater
;
19 import com
.intellij
.ide
.caches
.FileContent
;
20 import com
.intellij
.openapi
.application
.Application
;
21 import com
.intellij
.openapi
.application
.ApplicationAdapter
;
22 import com
.intellij
.openapi
.application
.ApplicationManager
;
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
.progress
.util
.ProgressIndicatorBase
;
27 import com
.intellij
.openapi
.vfs
.VirtualFile
;
28 import com
.intellij
.util
.Consumer
;
29 import gnu
.trove
.THashSet
;
31 import java
.util
.Collection
;
34 class CacheUpdateRunner
{
35 private final Project myProject
;
36 private final Collection
<CacheUpdater
> myUpdaters
;
37 private CacheUpdateSession mySession
;
39 CacheUpdateRunner(Project project
, Collection
<CacheUpdater
> updaters
) {
41 myUpdaters
= updaters
;
44 public int queryNeededFiles(ProgressIndicator indicator
) {
45 // can be queried twice in DumbService
46 if (mySession
== null) {
47 mySession
= new CacheUpdateSession(myUpdaters
, indicator
);
49 return mySession
.getFilesToUpdate().size();
52 public void processFiles(final ProgressIndicator indicator
, boolean processInReadAction
) {
53 FileContentQueue queue
= new FileContentQueue();
55 Collection
<VirtualFile
> files
= mySession
.getFilesToUpdate();
56 final double total
= files
.size();
57 queue
.queue(files
, indicator
);
59 Consumer
<VirtualFile
> progressUpdater
= new Consumer
<VirtualFile
>() {
60 // need set here to handle queue.pushbacks after checkCancelled() in order
61 // not to count the same file several times
62 final Set
<VirtualFile
> processed
= new THashSet
<VirtualFile
>();
64 public void consume(VirtualFile virtualFile
) {
65 indicator
.checkCanceled();
66 processed
.add(virtualFile
);
67 indicator
.setFraction(processed
.size() / total
);
68 if (virtualFile
.isValid()) {
69 indicator
.setText2(virtualFile
.getPresentableUrl());
72 indicator
.setText2("");
77 while (!myProject
.isDisposed()) {
78 indicator
.checkCanceled();
79 // todo wait for the user...
80 if (processSomeFilesWhileUserIsInactive(queue
, progressUpdater
, mySession
, processInReadAction
)) {
85 if (myProject
.isDisposed()) {
87 indicator
.checkCanceled();
90 catch (ProcessCanceledException e
) {
96 public void updatingDone() {
98 mySession
.updatingDone();
100 catch (ProcessCanceledException e
) {
101 mySession
.canceled();
106 private boolean processSomeFilesWhileUserIsInactive(final FileContentQueue queue
,
107 final Consumer
<VirtualFile
> progressUpdater
,
108 final CacheUpdateSession session
,
109 final boolean processInReadAction
) {
110 final ProgressIndicatorBase innerIndicator
= new ProgressIndicatorBase();
111 final ApplicationAdapter canceller
= new ApplicationAdapter() {
113 public void beforeWriteActionStart(Object action
) {
114 innerIndicator
.cancel();
117 final Application application
= ApplicationManager
.getApplication();
118 application
.addApplicationListener(canceller
);
120 final boolean[] isFinished
= new boolean[1];
122 ProgressManager
.getInstance().runProcess(new Runnable() {
125 if (myProject
.isDisposed()) return;
126 if (innerIndicator
.isCanceled()) return;
128 final FileContent fileContent
= queue
.take();
129 if (fileContent
== null) {
130 isFinished
[0] = true;
135 final Runnable action
= new Runnable() {
137 innerIndicator
.checkCanceled();
139 if (myProject
.isDisposed()) return;
141 final VirtualFile file
= fileContent
.getVirtualFile();
142 progressUpdater
.consume(file
);
143 session
.processFile(fileContent
);
146 if (processInReadAction
) {
147 application
.runReadAction(action
);
153 catch (ProcessCanceledException e
) {
154 queue
.pushback(fileContent
);
162 application
.removeApplicationListener(canceller
);
165 return isFinished
[0];