02ff6c99159ee02ae2ea7fa7c125aa62e2d489d1
[idea/community.git] / jps / jps-builders / src / org / jetbrains / jps / incremental / BuilderRegistry.java
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 org.jetbrains.jps.incremental;
17
18 import com.intellij.openapi.diagnostic.Logger;
19 import com.intellij.openapi.util.io.FileUtil;
20 import com.intellij.openapi.util.io.FileUtilRt;
21 import gnu.trove.THashSet;
22 import gnu.trove.TObjectLongHashMap;
23 import org.jetbrains.annotations.NotNull;
24 import org.jetbrains.jps.builders.BuildTargetType;
25 import org.jetbrains.jps.builders.java.JavaModuleBuildTargetType;
26 import org.jetbrains.jps.service.JpsServiceManager;
27
28 import java.io.FileFilter;
29 import java.util.*;
30
31 /**
32  * @author Eugene Zhuravlev
33  */
34 public class BuilderRegistry {
35   private static final Logger LOG = Logger.getInstance(BuilderRegistry.class);
36   private static class Holder {
37     static final BuilderRegistry ourInstance = new BuilderRegistry();
38   }
39   private final Map<BuilderCategory, List<ModuleLevelBuilder>> myModuleLevelBuilders = new HashMap<>();
40   private final TObjectLongHashMap<BuildTargetType<?>> myExpectedBuildTime = new TObjectLongHashMap<>();
41   private final List<TargetBuilder<?,?>> myTargetBuilders = new ArrayList<>();
42   private final FileFilter myModuleBuilderFileFilter;
43
44   public static BuilderRegistry getInstance() {
45     return Holder.ourInstance;
46   }
47
48   private BuilderRegistry() {
49     for (BuilderCategory category : BuilderCategory.values()) {
50       myModuleLevelBuilders.put(category, new ArrayList<>());
51     }
52
53     Set<String> compilableFileExtensions = new THashSet<>(FileUtil.PATH_HASHING_STRATEGY);
54     for (BuilderService service : JpsServiceManager.getInstance().getExtensions(BuilderService.class)) {
55       myTargetBuilders.addAll(service.createBuilders());
56       final List<? extends ModuleLevelBuilder> moduleLevelBuilders = service.createModuleLevelBuilders();
57       for (ModuleLevelBuilder builder : moduleLevelBuilders) {
58         try {
59           List<String> extensions = builder.getCompilableFileExtensions();
60           if (compilableFileExtensions != null) {
61             compilableFileExtensions.addAll(extensions);
62           }
63         }
64         catch (AbstractMethodError e) {
65           LOG.info(builder.getClass().getName() + " builder doesn't implement 'getCompilableFileExtensions' method so ModuleBuildTarget will process all files under source roots.");
66           compilableFileExtensions = null;
67         }
68         myModuleLevelBuilders.get(builder.getCategory()).add(builder);
69       }
70     }
71     if (compilableFileExtensions == null) {
72       myModuleBuilderFileFilter = FileUtilRt.ALL_FILES;
73     }
74     else {
75       final Set<String> finalCompilableFileExtensions = compilableFileExtensions;
76       myModuleBuilderFileFilter = file -> finalCompilableFileExtensions.contains(FileUtilRt.getExtension(file.getName()));
77     }
78
79     long moduleTargetBuildTime = 0;
80     for (ModuleLevelBuilder builder : getModuleLevelBuilders()) {
81       moduleTargetBuildTime += builder.getExpectedBuildTime();
82     }
83     myExpectedBuildTime.put(JavaModuleBuildTargetType.PRODUCTION, moduleTargetBuildTime);
84     myExpectedBuildTime.put(JavaModuleBuildTargetType.TEST, moduleTargetBuildTime);
85     
86     for (TargetBuilder<?, ?> targetBuilder : myTargetBuilders) {
87       long buildTime = targetBuilder.getExpectedBuildTime();
88       for (BuildTargetType<?> type : targetBuilder.getTargetTypes()) {
89         if (!myExpectedBuildTime.adjustValue(type, buildTime)) {
90           myExpectedBuildTime.put(type, buildTime);
91         }
92       }
93     }
94   }
95
96   @NotNull
97   public FileFilter getModuleBuilderFileFilter() {
98     return myModuleBuilderFileFilter;
99   }
100
101   public int getModuleLevelBuilderCount() {
102     int count = 0;
103     for (BuilderCategory category : BuilderCategory.values()) {
104       count += getBuilders(category).size();
105     }
106     return count;
107   }
108
109   public List<BuildTask> getBeforeTasks(){
110     return Collections.emptyList(); // todo
111   }
112
113   public List<BuildTask> getAfterTasks(){
114     return Collections.emptyList(); // todo
115   }
116
117   public List<ModuleLevelBuilder> getBuilders(BuilderCategory category){
118     return Collections.unmodifiableList(myModuleLevelBuilders.get(category));
119   }
120
121   public List<ModuleLevelBuilder> getModuleLevelBuilders() {
122     List<ModuleLevelBuilder> result = new ArrayList<>();
123     for (BuilderCategory category : BuilderCategory.values()) {
124       result.addAll(getBuilders(category));
125     }
126     return result;
127   }
128
129   public List<TargetBuilder<?,?>> getTargetBuilders() {
130     return myTargetBuilders;
131   }
132
133   /**
134    * Returns default expected build time for targets of the given {@code targetType}.
135    * @see Builder#getExpectedBuildTime()
136    */
137   public long getExpectedBuildTimeForTarget(BuildTargetType<?> targetType) {
138     long time = myExpectedBuildTime.get(targetType);
139     if (time == -1) {
140       //it may happen that there is no builders registered for a given type, so it won't be built at all.
141       return 0;
142     }
143     return time;
144   }
145 }