blob: 57524ac6ddca6ae0b47a1ff95cbfcca792d927b1 [file] [log] [blame]
/*
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jps.incremental.resources;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.io.FileUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jps.builders.BuildOutputConsumer;
import org.jetbrains.jps.builders.DirtyFilesHolder;
import org.jetbrains.jps.builders.FileProcessor;
import org.jetbrains.jps.builders.java.ResourceRootDescriptor;
import org.jetbrains.jps.builders.java.ResourcesTargetType;
import org.jetbrains.jps.builders.storage.BuildDataCorruptedException;
import org.jetbrains.jps.incremental.CompileContext;
import org.jetbrains.jps.incremental.ProjectBuildException;
import org.jetbrains.jps.incremental.ResourcesTarget;
import org.jetbrains.jps.incremental.TargetBuilder;
import org.jetbrains.jps.incremental.messages.BuildMessage;
import org.jetbrains.jps.incremental.messages.CompilerMessage;
import org.jetbrains.jps.incremental.messages.ProgressMessage;
import org.jetbrains.jps.model.module.JpsModule;
import java.io.File;
import java.io.IOException;
import java.util.*;
/**
* @author Eugene Zhuravlev
* Date: 10/6/11
*/
public class ResourcesBuilder extends TargetBuilder<ResourceRootDescriptor, ResourcesTarget> {
private static final Logger LOG = Logger.getInstance("#org.jetbrains.jps.incremental.resourses.ResourcesBuilder");
public static final String BUILDER_NAME = "Resource Compiler";
private static final List<StandardResourceBuilderEnabler> ourEnablers = Collections.synchronizedList(new ArrayList<StandardResourceBuilderEnabler>());
public ResourcesBuilder() {
super(ResourcesTargetType.ALL_TYPES);
}
public static void registerEnabler(StandardResourceBuilderEnabler enabler) {
ourEnablers.add(enabler);
}
@Override
public void build(@NotNull ResourcesTarget target,
@NotNull DirtyFilesHolder<ResourceRootDescriptor, ResourcesTarget> holder,
@NotNull final BuildOutputConsumer outputConsumer,
@NotNull final CompileContext context) throws ProjectBuildException, IOException {
if (!isResourceProcessingEnabled(target.getModule())) {
return;
}
try {
holder.processDirtyFiles(new FileProcessor<ResourceRootDescriptor, ResourcesTarget>() {
private final Map<ResourceRootDescriptor, Boolean> mySkippedRoots = new HashMap<ResourceRootDescriptor, Boolean>();
public boolean apply(ResourcesTarget target, final File file, final ResourceRootDescriptor sourceRoot) throws IOException {
Boolean isSkipped = mySkippedRoots.get(sourceRoot);
if (isSkipped == null) {
final File outputDir = target.getOutputDir();
isSkipped = Boolean.valueOf(outputDir == null || FileUtil.filesEqual(outputDir, sourceRoot.getRootFile()));
mySkippedRoots.put(sourceRoot, isSkipped);
}
if (isSkipped.booleanValue()) {
return true;
}
try {
copyResource(context, sourceRoot, file, outputConsumer);
}
catch (IOException e) {
LOG.info(e);
context.processMessage(
new CompilerMessage(
"resources", BuildMessage.Kind.ERROR, e.getMessage(), FileUtil.toSystemIndependentName(file.getPath())
)
);
return false;
}
return !context.getCancelStatus().isCanceled();
}
});
context.checkCanceled();
context.processMessage(new ProgressMessage(""));
}
catch(BuildDataCorruptedException e) {
throw e;
}
catch(ProjectBuildException e) {
throw e;
}
catch (Exception e) {
throw new ProjectBuildException(e.getMessage(), e);
}
}
private static boolean isResourceProcessingEnabled(JpsModule module) {
synchronized (ourEnablers) {
for (StandardResourceBuilderEnabler enabler : ourEnablers) {
if (!enabler.isResourceProcessingEnabled(module)) {
return false;
}
}
}
return true;
}
private static void copyResource(CompileContext context, ResourceRootDescriptor rd, File file, BuildOutputConsumer outputConsumer) throws IOException {
final File outputRoot = rd.getTarget().getOutputDir();
if (outputRoot == null) {
return;
}
final String sourceRootPath = FileUtil.toSystemIndependentName(rd.getRootFile().getAbsolutePath());
final String relativePath = FileUtil.getRelativePath(sourceRootPath, FileUtil.toSystemIndependentName(file.getPath()), '/');
final String prefix = rd.getPackagePrefix();
final StringBuilder targetPath = new StringBuilder();
targetPath.append(FileUtil.toSystemIndependentName(outputRoot.getPath()));
if (prefix.length() > 0) {
targetPath.append('/').append(prefix.replace('.', '/'));
}
targetPath.append('/').append(relativePath);
context.processMessage(new ProgressMessage("Copying resources... [" + rd.getTarget().getModule().getName() + "]"));
final String outputPath = targetPath.toString();
final File targetFile = new File(outputPath);
FileUtil.copyContent(file, targetFile);
try {
outputConsumer.registerOutputFile(targetFile, Collections.singletonList(file.getPath()));
}
catch (Exception e) {
context.processMessage(new CompilerMessage(BUILDER_NAME, e));
}
}
@NotNull
public String getPresentableName() {
return "Resource Compiler";
}
}