diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/RemoveBomAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/RemoveBomAction.java new file mode 100644 index 000000000000..9d8a15e262a4 --- /dev/null +++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/RemoveBomAction.java @@ -0,0 +1,115 @@ +/* + * Copyright 2000-2011 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.editor.actions; + +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.actionSystem.PlatformDataKeys; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.project.DumbAware; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.vfs.newvfs.NewVirtualFile; +import org.jetbrains.annotations.NotNull; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +/** + * Allows to remove file's BOM (if any). + * + * @author Denis Zhdanov + * @since 3/30/11 11:14 AM + */ +public class RemoveBomAction extends AnAction implements DumbAware { + + private static final Logger LOG = Logger.getInstance("#" + RemoveBomAction.class); + + public RemoveBomAction() { + super("Remove BOM"); + } + + @Override + public void actionPerformed(AnActionEvent e) { + VirtualFile[] files = PlatformDataKeys.VIRTUAL_FILE_ARRAY.getData(e.getDataContext()); + if (files == null) { + return; + } + List filesToProcess = getFilesWithBom(files, true); + for (VirtualFile virtualFile : filesToProcess) { + byte[] bom = virtualFile.getBOM(); + assert bom != null; + if (virtualFile instanceof NewVirtualFile) { + virtualFile.setBOM(null); + NewVirtualFile file = (NewVirtualFile)virtualFile; + try { + byte[] bytes = file.contentsToByteArray(); + byte[] contentWithStrippedBom = new byte[bytes.length - bom.length]; + System.arraycopy(bytes, bom.length, contentWithStrippedBom, 0, contentWithStrippedBom.length); + file.setBinaryContent(contentWithStrippedBom); + } + catch (IOException ex) { + LOG.warn("Unexpected exception occurred on attempt to remove BOM from file " + file, ex); + } + } + } + } + + @Override + public void update(AnActionEvent e) { + VirtualFile[] files = PlatformDataKeys.VIRTUAL_FILE_ARRAY.getData(e.getDataContext()); + if (files == null) { + e.getPresentation().setEnabled(false); + return; + } + + e.getPresentation().setEnabled(!getFilesWithBom(files, false).isEmpty()); + } + + /** + * Recursively traverses contents of the given file roots (any root may be directory) and returns files that have + * {@link VirtualFile#getBOM() BOM} defined. + * + * @param roots VFS roots to traverse + * @param all flag the defines if all files with {@link VirtualFile#getBOM() BOM} should be collected or just any of them + * @return collection of detected files with defined {@link VirtualFile#getBOM() BOM} if any; empty collectio otherwise + */ + @NotNull + private static List getFilesWithBom(@NotNull VirtualFile[] roots, boolean all) { + List result = new ArrayList(); + for (VirtualFile root : roots) { + if (!all && !result.isEmpty()) { + break; + } + getFilesWithBom(root, result, all); + } + return result; + } + + private static void getFilesWithBom(@NotNull VirtualFile root, @NotNull List result, boolean all) { + if (root.isDirectory()) { + for (VirtualFile child : root.getChildren()) { + if (!all && !result.isEmpty()) { + return; + } + getFilesWithBom(child, result, all); + } + } + else if (root.getBOM() != null) { + result.add(root); + } + } +} diff --git a/platform/platform-resources/src/idea/LangActions.xml b/platform/platform-resources/src/idea/LangActions.xml index c5a7d3c54158..cb6e263ae833 100644 --- a/platform/platform-resources/src/idea/LangActions.xml +++ b/platform/platform-resources/src/idea/LangActions.xml @@ -451,6 +451,8 @@ + + diff --git a/platform/platform-resources/src/idea/PlatformActions.xml b/platform/platform-resources/src/idea/PlatformActions.xml index 7e443655072c..561dc0944cfa 100644 --- a/platform/platform-resources/src/idea/PlatformActions.xml +++ b/platform/platform-resources/src/idea/PlatformActions.xml @@ -143,6 +143,7 @@ + @@ -337,6 +338,8 @@ + +