IDEA-133754 Maven: resources builder: support outputDirectory parameters of maven...
[idea/community.git] / plugins / maven / jps-plugin / src / org / jetbrains / jps / maven / compiler / MavenResourcesBuilder.java
1 package org.jetbrains.jps.maven.compiler;
2
3 import com.intellij.openapi.util.io.FileUtil;
4 import com.intellij.openapi.util.io.FileUtilRt;
5 import org.jetbrains.annotations.NotNull;
6 import org.jetbrains.jps.builders.BuildOutputConsumer;
7 import org.jetbrains.jps.builders.DirtyFilesHolder;
8 import org.jetbrains.jps.builders.FileProcessor;
9 import org.jetbrains.jps.builders.storage.BuildDataPaths;
10 import org.jetbrains.jps.incremental.CompileContext;
11 import org.jetbrains.jps.incremental.ProjectBuildException;
12 import org.jetbrains.jps.incremental.StopBuildException;
13 import org.jetbrains.jps.incremental.TargetBuilder;
14 import org.jetbrains.jps.incremental.messages.BuildMessage;
15 import org.jetbrains.jps.incremental.messages.CompilerMessage;
16 import org.jetbrains.jps.incremental.messages.ProgressMessage;
17 import org.jetbrains.jps.maven.model.JpsMavenExtensionService;
18 import org.jetbrains.jps.maven.model.impl.*;
19
20 import java.io.File;
21 import java.io.IOException;
22 import java.io.UnsupportedEncodingException;
23 import java.util.*;
24
25 /**
26  * @author Eugene Zhuravlev
27  *         Date: 10/6/11
28  */
29 public class MavenResourcesBuilder extends TargetBuilder<MavenResourceRootDescriptor, MavenResourcesTarget> {
30   public static final String BUILDER_NAME = "Maven Resources Compiler";
31
32   public MavenResourcesBuilder() {
33     super(Arrays.asList(MavenResourcesTargetType.PRODUCTION, MavenResourcesTargetType.TEST));
34   }
35
36   @Override
37   public void build(@NotNull final MavenResourcesTarget target, @NotNull final DirtyFilesHolder<MavenResourceRootDescriptor, MavenResourcesTarget> holder, @NotNull final BuildOutputConsumer outputConsumer, @NotNull final CompileContext context) throws ProjectBuildException, IOException {
38     final BuildDataPaths dataPaths = context.getProjectDescriptor().dataManager.getDataPaths();
39     final MavenProjectConfiguration projectConfig = JpsMavenExtensionService.getInstance().getMavenProjectConfiguration(dataPaths);
40     if (projectConfig == null) {
41       context.processMessage(new CompilerMessage(BUILDER_NAME, BuildMessage.Kind.ERROR, "Maven project configuration required for module '" + target.getModule().getName() + "' isn't available. Compilation of Maven projects is supported only if external build is started from an IDE."));
42       throw new StopBuildException();
43     }
44
45     final MavenModuleResourceConfiguration config = target.getModuleResourcesConfiguration(dataPaths);
46     if (config == null) {
47       return;
48     }
49
50     final Map<MavenResourceRootDescriptor, List<File>> files = new HashMap<MavenResourceRootDescriptor, List<File>>();
51
52     holder.processDirtyFiles(new FileProcessor<MavenResourceRootDescriptor, MavenResourcesTarget>() {
53
54       @Override
55       public boolean apply(MavenResourcesTarget t, File file, MavenResourceRootDescriptor rd) throws IOException {
56         assert target == t;
57
58         List<File> fileList = files.get(rd);
59         if (fileList == null) {
60           fileList = new ArrayList<File>();
61           files.put(rd, fileList);
62         }
63
64         fileList.add(file);
65         return true;
66       }
67     });
68
69     MavenResourceRootDescriptor[] roots = files.keySet().toArray(new MavenResourceRootDescriptor[files.keySet().size()]);
70     Arrays.sort(roots, new Comparator<MavenResourceRootDescriptor>() {
71       @Override
72       public int compare(MavenResourceRootDescriptor r1, MavenResourceRootDescriptor r2) {
73         int res = r1.getIndexInPom() - r2.getIndexInPom();
74
75         if (r1.isOverwrite()) {
76           assert r2.isOverwrite(); // 'overwrite' parameters is common for all roots in module.
77
78           return res;
79         }
80
81         if (r1.getConfiguration().isFiltered && !r2.getConfiguration().isFiltered) return 1;
82         if (!r1.getConfiguration().isFiltered && r2.getConfiguration().isFiltered) return -1;
83
84         if (!r1.getConfiguration().isFiltered) {
85           res = -res;
86         }
87
88         return res;
89       }
90     });
91
92     MavenResourceFileProcessor fileProcessor = new MavenResourceFileProcessor(projectConfig, target.getModule().getProject(), config);
93
94     for (MavenResourceRootDescriptor rd : roots) {
95       for (File file : files.get(rd)) {
96
97         String relPath = FileUtil.getRelativePath(rd.getRootFile(), file);
98         if (relPath == null) {
99           continue;
100         }
101         final String outputDirectory = target.isTests() ? config.testOutputDirectory : config.outputDirectory;
102         final File outputDir = MavenResourcesTarget.getOutputDir(target.getModuleOutputDir(), rd.getConfiguration(), outputDirectory);
103         if (outputDir == null) {
104           continue;
105         }
106         File outputFile = new File(outputDir, relPath);
107         String sourcePath = file.getPath();
108         try {
109           context.processMessage(new ProgressMessage("Copying resources... [" + target.getModule().getName() + "]"));
110
111           fileProcessor.copyFile(file, outputFile, rd.getConfiguration(), context, FileUtilRt.ALL_FILES);
112           outputConsumer.registerOutputFile(outputFile, Collections.singleton(sourcePath));
113         }
114         catch (UnsupportedEncodingException e) {
115           context.processMessage(
116             new CompilerMessage(BUILDER_NAME, BuildMessage.Kind.INFO, "Resource was not copied: " + e.getMessage(), sourcePath));
117         }
118
119         if (context.getCancelStatus().isCanceled()) {
120           return;
121         }
122       }
123     }
124
125     context.checkCanceled();
126
127     context.processMessage(new ProgressMessage(""));
128   }
129
130   @NotNull
131   public String getPresentableName() {
132     return BUILDER_NAME;
133   }
134 }