/* * Copyright 2000-2009 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 com.intellij.openapi.compiler; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vfs.VfsUtilCore; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.io.IOUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.io.DataInput; import java.io.DataOutput; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.List; /** * Compiler which copies the compiled files to a different directory. */ public abstract class CopyingCompiler implements PackagingCompiler { public abstract VirtualFile[] getFilesToCopy(CompileContext context); public abstract String getDestinationPath(CompileContext context, VirtualFile sourceFile); @Override public final void processOutdatedItem(CompileContext context, File file, @Nullable ValidityState state) { if (state != null) { final String destinationPath = ((DestinationFileInfo)state).getDestinationPath(); new File(destinationPath).delete(); } } @Override @NotNull public final ProcessingItem[] getProcessingItems(final CompileContext context) { return ApplicationManager.getApplication().runReadAction((Computable<ProcessingItem[]>)() -> { final VirtualFile[] filesToCopy = getFilesToCopy(context); final ProcessingItem[] items = new ProcessingItem[filesToCopy.length]; for (int idx = 0; idx < filesToCopy.length; idx++) { final VirtualFile file = filesToCopy[idx]; items[idx] = new CopyItem(file, getDestinationPath(context, file)); } return items; }); } @Override public ProcessingItem[] process(CompileContext context, ProcessingItem[] items) { final List<ProcessingItem> successfullyProcessed = new ArrayList<ProcessingItem>(items.length); for (ProcessingItem item : items) { final CopyItem copyItem = (CopyItem)item; final String toPath = copyItem.getDestinationPath(); try { if (isDirectoryCopying()) { FileUtil.copyDir(copyItem.getFile(), new File(toPath)); } else { FileUtil.copy(copyItem.getFile(), new File(toPath)); } successfullyProcessed.add(copyItem); } catch (IOException e) { context.addMessage(CompilerMessageCategory.ERROR, CompilerBundle.message("error.copying", item.getFile().getPath(), toPath, e.getMessage()), null, -1, -1); } } return successfullyProcessed.toArray(new ProcessingItem[successfullyProcessed.size()]); } protected boolean isDirectoryCopying() { return false; } @Override @NotNull public String getDescription() { return CompilerBundle.message("file.copying.compiler.description"); } @Override public boolean validateConfiguration(CompileScope scope) { return true; } @Override public ValidityState createValidityState(DataInput in) throws IOException { return new DestinationFileInfo(IOUtil.readString(in), true); } private static class CopyItem implements FileProcessingCompiler.ProcessingItem { private final File myFile; private final DestinationFileInfo myInfo; public CopyItem(@NotNull VirtualFile file, @NotNull String destinationPath) { myFile = VfsUtilCore.virtualToIoFile(file); myInfo = new DestinationFileInfo(destinationPath, new File(destinationPath).exists()); } @Override @NotNull public File getFile() { return myFile; } @Override public ValidityState getValidityState() { return myInfo; } public String getDestinationPath() { return myInfo.getDestinationPath(); } } private static class DestinationFileInfo implements ValidityState { private final String destinationPath; private final boolean myFileExists; public DestinationFileInfo(String destinationPath, boolean fileExists) { this.destinationPath = destinationPath; myFileExists = fileExists; } @Override public boolean equalsTo(ValidityState otherState) { if (!(otherState instanceof DestinationFileInfo)) { return false; } DestinationFileInfo destinationFileInfo = (DestinationFileInfo)otherState; return (myFileExists == destinationFileInfo.myFileExists) && (destinationPath.equals(destinationFileInfo.destinationPath)); } @Override public void save(DataOutput out) throws IOException { IOUtil.writeString(destinationPath, out); } public String getDestinationPath() { return destinationPath; } } }