| /* |
| * 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.builders.impl; |
| |
| import com.intellij.openapi.diagnostic.Logger; |
| import com.intellij.openapi.util.io.FileUtil; |
| import gnu.trove.THashSet; |
| import org.jetbrains.annotations.NotNull; |
| import org.jetbrains.jps.builders.BuildOutputConsumer; |
| import org.jetbrains.jps.builders.BuildTarget; |
| import org.jetbrains.jps.builders.storage.SourceToOutputMapping; |
| import org.jetbrains.jps.incremental.CompileContext; |
| import org.jetbrains.jps.incremental.ModuleBuildTarget; |
| import org.jetbrains.jps.incremental.artifacts.ArtifactBuildTarget; |
| import org.jetbrains.jps.incremental.messages.FileGeneratedEvent; |
| |
| import java.io.File; |
| import java.io.IOException; |
| import java.util.Collection; |
| |
| /** |
| * @author Eugene Zhuravlev |
| * Date: 11/16/12 |
| */ |
| public class BuildOutputConsumerImpl implements BuildOutputConsumer { |
| private static final Logger LOG = Logger.getInstance(BuildOutputConsumerImpl.class); |
| private final BuildTarget<?> myTarget; |
| private final CompileContext myContext; |
| private FileGeneratedEvent myFileGeneratedEvent; |
| private Collection<File> myOutputs; |
| private THashSet<String> myRegisteredSources = new THashSet<String>(FileUtil.PATH_HASHING_STRATEGY); |
| |
| public BuildOutputConsumerImpl(BuildTarget<?> target, CompileContext context) { |
| myTarget = target; |
| myContext = context; |
| myFileGeneratedEvent = new FileGeneratedEvent(); |
| myOutputs = myTarget.getOutputRoots(context); |
| } |
| |
| private void registerOutput(final File output, boolean isDirectory, Collection<String> sourcePaths) throws IOException { |
| final String outputPath = FileUtil.toSystemIndependentName(output.getPath()); |
| for (File outputRoot : myOutputs) { |
| final String outputRootPath = FileUtil.toSystemIndependentName(outputRoot.getPath()); |
| final String relativePath = FileUtil.getRelativePath(outputRootPath, outputPath, '/'); |
| if (relativePath != null && !relativePath.startsWith("../")) { |
| // the relative path must be under the root or equal to it |
| if (isDirectory) { |
| addEventsRecursively(output, outputRootPath, relativePath); |
| } |
| else { |
| myFileGeneratedEvent.add(outputRootPath, relativePath); |
| } |
| } |
| } |
| final SourceToOutputMapping mapping = myContext.getProjectDescriptor().dataManager.getSourceToOutputMap(myTarget); |
| for (String sourcePath : sourcePaths) { |
| if (myRegisteredSources.add(FileUtil.toSystemIndependentName(sourcePath))) { |
| mapping.setOutput(sourcePath, outputPath); |
| } |
| else { |
| mapping.appendOutput(sourcePath, outputPath); |
| } |
| } |
| } |
| |
| private void addEventsRecursively(File output, String outputRootPath, String relativePath) { |
| File[] children = output.listFiles(); |
| if (children == null) { |
| myFileGeneratedEvent.add(outputRootPath, relativePath); |
| } |
| else { |
| String prefix = relativePath.isEmpty() || relativePath.equals(".") ? "" : relativePath + "/"; |
| for (File child : children) { |
| addEventsRecursively(child, outputRootPath, prefix + child.getName()); |
| } |
| } |
| } |
| |
| @Override |
| public void registerOutputFile(@NotNull final File outputFile, @NotNull Collection<String> sourcePaths) throws IOException { |
| registerOutput(outputFile, false, sourcePaths); |
| } |
| |
| @Override |
| public void registerOutputDirectory(@NotNull File outputDir, @NotNull Collection<String> sourcePaths) throws IOException { |
| LOG.assertTrue(!(myTarget instanceof ModuleBuildTarget) && !(myTarget instanceof ArtifactBuildTarget), |
| "'registerOutputDirectory' method cannot be used for target " + myTarget + ", it will break incremental compilation"); |
| registerOutput(outputDir, true, sourcePaths); |
| } |
| |
| public void fireFileGeneratedEvent() { |
| if (!myFileGeneratedEvent.getPaths().isEmpty()) { |
| myContext.processMessage(myFileGeneratedEvent); |
| } |
| } |
| } |