invoke translating compilers per-module chunk
[fedora-idea.git] / java / compiler / impl / src / com / intellij / compiler / impl / resourceCompiler / ResourceCompiler.java
blob468618c3b29680bc798c309e39865785c35bf54f
1 /*
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.
18 * @author: Eugene Zhuravlev
19 * Date: Jan 17, 2003
20 * Time: 3:48:26 PM
22 package com.intellij.compiler.impl.resourceCompiler;
24 import com.intellij.compiler.CompilerConfiguration;
25 import com.intellij.compiler.CompilerConfigurationImpl;
26 import com.intellij.compiler.impl.CompilerUtil;
27 import com.intellij.compiler.make.MakeUtil;
28 import com.intellij.openapi.application.ApplicationManager;
29 import com.intellij.openapi.compiler.*;
30 import com.intellij.openapi.compiler.ex.CompileContextEx;
31 import com.intellij.openapi.diagnostic.Logger;
32 import com.intellij.openapi.fileTypes.FileTypeManager;
33 import com.intellij.openapi.fileTypes.StdFileTypes;
34 import com.intellij.openapi.module.Module;
35 import com.intellij.openapi.project.Project;
36 import com.intellij.openapi.roots.ProjectFileIndex;
37 import com.intellij.openapi.roots.ProjectRootManager;
38 import com.intellij.openapi.util.io.FileUtil;
39 import com.intellij.openapi.vfs.VfsUtil;
40 import com.intellij.openapi.vfs.VirtualFile;
41 import com.intellij.openapi.vfs.VirtualFileManager;
42 import com.intellij.util.Chunk;
43 import org.jetbrains.annotations.NotNull;
45 import java.io.File;
46 import java.io.IOException;
47 import java.util.*;
49 public class ResourceCompiler implements TranslatingCompiler {
50 private static final Logger LOG = Logger.getInstance("#com.intellij.compiler.impl.resourceCompiler.ResourceCompiler");
51 private final Project myProject;
52 private final CompilerConfiguration myConfiguration;
53 private static final FileTypeManager FILE_TYPE_MANAGER = FileTypeManager.getInstance();
55 public ResourceCompiler(Project project, CompilerConfiguration compilerConfiguration) {
56 myProject = project;
57 myConfiguration = compilerConfiguration;
60 @NotNull
61 public String getDescription() {
62 return CompilerBundle.message("resource.compiler.description");
65 public boolean validateConfiguration(CompileScope scope) {
66 ((CompilerConfigurationImpl) CompilerConfiguration.getInstance(myProject)).convertPatterns();
67 return true;
70 public boolean isCompilableFile(VirtualFile file, CompileContext context) {
71 return !StdFileTypes.JAVA.equals(FILE_TYPE_MANAGER.getFileTypeByFile(file)) && myConfiguration.isResourceFile(file);
74 public void compile(final CompileContext context, Chunk<Module> moduleChunk, final VirtualFile[] files, OutputSink sink) {
75 context.getProgressIndicator().pushState();
76 context.getProgressIndicator().setText(CompilerBundle.message("progress.copying.resources"));
78 final Map<String, Collection<OutputItem>> processed = new HashMap<String, Collection<OutputItem>>();
79 final LinkedList<CopyCommand> copyCommands = new LinkedList<CopyCommand>();
80 final Module singleChunkModule = moduleChunk.getNodes().size() == 1? moduleChunk.getNodes().iterator().next() : null;
81 final long start = System.currentTimeMillis();
82 ApplicationManager.getApplication().runReadAction(new Runnable() {
83 public void run() {
84 final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(myProject).getFileIndex();
85 for (final VirtualFile file : files) {
86 if (context.getProgressIndicator().isCanceled()) {
87 break;
89 final Module module = singleChunkModule != null? singleChunkModule : context.getModuleByFile(file);
90 if (module == null) {
91 continue; // looks like file invalidated
93 final VirtualFile fileRoot = MakeUtil.getSourceRoot(context, module, file);
94 if (fileRoot == null) {
95 continue;
97 final String sourcePath = file.getPath();
98 final String relativePath = VfsUtil.getRelativePath(file, fileRoot, '/');
99 final boolean inTests = ((CompileContextEx)context).isInTestSourceContent(file);
100 final VirtualFile outputDir = inTests? context.getModuleOutputDirectoryForTests(module) : context.getModuleOutputDirectory(module);
101 if (outputDir == null) {
102 continue;
104 final String outputPath = outputDir.getPath();
106 final String packagePrefix = fileIndex.getPackageNameByDirectory(fileRoot);
107 final String targetPath;
108 if (packagePrefix != null && packagePrefix.length() > 0) {
109 targetPath = outputPath + "/" + packagePrefix.replace('.', '/') + "/" + relativePath;
111 else {
112 targetPath = outputPath + "/" + relativePath;
114 if (sourcePath.equals(targetPath)) {
115 addToMap(processed, outputPath, new MyOutputItem(targetPath, file));
117 else {
118 copyCommands.add(new CopyCommand(outputPath, sourcePath, targetPath, file));
124 final Set<String> rootsToRefresh = new HashSet<String>();
125 // do actual copy outside of read action to reduce the time the application is locked on it
126 int idx = 0;
127 final int total = copyCommands.size();
128 CopyCommand.ourCopyingTime = 0L;
129 while (!copyCommands.isEmpty()) {
130 final CopyCommand command = copyCommands.removeFirst();
131 if (context.getProgressIndicator().isCanceled()) {
132 break;
134 //context.getProgressIndicator().setFraction((idx++) * 1.0 / total);
135 context.getProgressIndicator().setText2("Copying " + command.getFromPath() + "...");
136 try {
137 rootsToRefresh.add(command.getOutputPath());
138 final MyOutputItem outputItem = command.copy();
139 addToMap(processed, command.getOutputPath(), outputItem);
141 catch (IOException e) {
142 context.addMessage(
143 CompilerMessageCategory.ERROR,
144 CompilerBundle.message("error.copying", command.getFromPath(), command.getToPath(), e.getMessage()),
145 command.getSourceFileUrl(), -1, -1
149 final long stop = System.currentTimeMillis();
151 CompilerUtil.logDuration("Copying resources TOTAL", stop - start);
152 CompilerUtil.logDuration("\tCopying resources (actual copying)", CopyCommand.ourCopyingTime);
154 if (!rootsToRefresh.isEmpty()) {
155 final List<File> dirs = new ArrayList<File>();
156 for (String path : rootsToRefresh) {
157 dirs.add(new File(path));
159 CompilerUtil.refreshIODirectories(dirs);
160 rootsToRefresh.clear();
163 for (Iterator<Map.Entry<String, Collection<OutputItem>>> it = processed.entrySet().iterator(); it.hasNext();) {
164 Map.Entry<String, Collection<OutputItem>> entry = it.next();
165 sink.add(entry.getKey(), entry.getValue(), VirtualFile.EMPTY_ARRAY);
166 it.remove(); // to free memory
168 context.getProgressIndicator().popState();
171 private static void addToMap(Map<String, Collection<OutputItem>> map, String outputDir, OutputItem item) {
172 Collection<OutputItem> list = map.get(outputDir);
173 if (list == null) {
174 list = new ArrayList<OutputItem>();
175 map.put(outputDir, list);
177 list.add(item);
180 private static class CopyCommand {
181 private final String myOutputPath;
182 private final String myFromPath;
183 private final String myToPath;
184 private final VirtualFile mySourceFile;
185 public static long ourCopyingTime = 0L;
187 private CopyCommand(String outputPath, String fromPath, String toPath, VirtualFile sourceFile) {
188 myOutputPath = outputPath;
189 myFromPath = fromPath;
190 myToPath = toPath;
191 mySourceFile = sourceFile;
194 public MyOutputItem copy() throws IOException {
195 if (LOG.isDebugEnabled()) {
196 LOG.debug("Copying " + myFromPath + " to " + myToPath);
198 final File targetFile = new File(myToPath);
199 final long start = System.currentTimeMillis();
200 FileUtil.copyContent(new File(myFromPath), targetFile);
201 ourCopyingTime += (System.currentTimeMillis() - start);
202 return new MyOutputItem(myToPath, mySourceFile);
205 public String getOutputPath() {
206 return myOutputPath;
209 public String getFromPath() {
210 return myFromPath;
213 public String getToPath() {
214 return myToPath;
217 public String getSourceFileUrl() {
218 // do not use mySourseFile.getUrl() directly as it requires read action
219 return VirtualFileManager.constructUrl(mySourceFile.getFileSystem().getProtocol(), myFromPath);
223 private static class MyOutputItem implements OutputItem {
224 private final String myTargetPath;
225 private final VirtualFile myFile;
227 private MyOutputItem(String targetPath, VirtualFile sourceFile) {
228 myTargetPath = targetPath;
229 myFile = sourceFile;
232 public String getOutputPath() {
233 return myTargetPath;
236 public VirtualFile getSourceFile() {
237 return myFile;