2 * Copyright 2000-2015 JetBrains s.r.o.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 package com.intellij.diff;
18 import com.intellij.diff.contents.*;
19 import com.intellij.openapi.application.ApplicationManager;
20 import com.intellij.openapi.diagnostic.Logger;
21 import com.intellij.openapi.editor.Document;
22 import com.intellij.openapi.editor.EditorFactory;
23 import com.intellij.openapi.fileEditor.FileDocumentManager;
24 import com.intellij.openapi.fileTypes.FileType;
25 import com.intellij.openapi.ide.CopyPasteManager;
26 import com.intellij.openapi.project.Project;
27 import com.intellij.openapi.util.Computable;
28 import com.intellij.openapi.util.io.FileUtil;
29 import com.intellij.openapi.util.text.StringUtil;
30 import com.intellij.openapi.vcs.FilePath;
31 import com.intellij.openapi.vfs.VfsUtil;
32 import com.intellij.openapi.vfs.VirtualFile;
33 import com.intellij.testFramework.BinaryLightVirtualFile;
34 import com.intellij.util.LineSeparator;
35 import com.intellij.util.PathUtil;
36 import org.jetbrains.annotations.NotNull;
37 import org.jetbrains.annotations.Nullable;
39 import java.awt.datatransfer.DataFlavor;
41 import java.io.IOException;
42 import java.nio.charset.Charset;
44 public class DiffContentFactoryImpl extends DiffContentFactory {
45 public final Logger LOG = Logger.getInstance(DiffContentFactoryImpl.class);
48 public static DiffContentFactoryImpl getInstanceImpl() {
49 return (DiffContentFactoryImpl)DiffContentFactory.getInstance();
54 public EmptyContent createEmpty() {
55 return new EmptyContent();
60 public DocumentContent create(@NotNull String text) {
61 return create(text, (FileType)null);
66 public DocumentContent create(@NotNull String text, @Nullable FileType type) {
67 return create(text, type, true);
72 public DocumentContent create(@NotNull String text, @Nullable FileType type, boolean respectLineSeparators) {
73 return createImpl(text, type, null, null, respectLineSeparators, true);
77 public DocumentContent create(@NotNull String text, @Nullable VirtualFile highlightFile) {
78 return createImpl(text, highlightFile != null ? highlightFile.getFileType() : null, highlightFile, null, true, true);
83 public DocumentContent create(@Nullable Project project, @NotNull Document document) {
84 return create(project, document, (FileType)null);
89 public DocumentContent create(@Nullable Project project, @NotNull Document document, @Nullable FileType fileType) {
90 VirtualFile file = FileDocumentManager.getInstance().getFile(document);
91 if (file == null) return new DocumentContentImpl(document, fileType, null, null, null);
92 return create(project, document, file);
97 public DocumentContent create(@Nullable Project project, @NotNull Document document, @Nullable VirtualFile file) {
98 if (file != null) return new FileDocumentContentImpl(project, document, file);
99 return new DocumentContentImpl(document);
104 public DiffContent create(@Nullable Project project, @NotNull VirtualFile file) {
105 if (file.isDirectory()) return new DirectoryContentImpl(project, file);
106 DocumentContent content = createDocument(project, file);
107 if (content != null) return content;
108 return new FileContentImpl(project, file);
113 public DocumentContent createDocument(@Nullable Project project, @NotNull final VirtualFile file) {
114 // TODO: add notification, that file is decompiled ?
115 if (file.isDirectory()) return null;
116 Document document = ApplicationManager.getApplication().runReadAction(new Computable<Document>() {
118 public Document compute() {
119 return FileDocumentManager.getInstance().getDocument(file);
122 if (document == null) return null;
123 return new FileDocumentContentImpl(project, document, file);
128 public FileContent createFile(@Nullable Project project, @NotNull VirtualFile file) {
129 if (file.isDirectory()) return null;
130 return (FileContent)create(project, file);
135 public DiffContent createClipboardContent() {
136 return createClipboardContent(null);
141 public DocumentContent createClipboardContent(@Nullable DocumentContent mainContent) {
142 String text = CopyPasteManager.getInstance().getContents(DataFlavor.stringFlavor);
144 FileType type = mainContent != null ? mainContent.getContentType() : null;
145 VirtualFile highlightFile = mainContent != null ? mainContent.getHighlightFile() : null;
147 return createImpl(StringUtil.notNullize(text), type, highlightFile, null, true, false);
151 private static DocumentContent createImpl(@NotNull String text,
152 @Nullable FileType type,
153 @Nullable VirtualFile highlightFile,
154 @Nullable Charset charset,
155 boolean respectLineSeparators,
157 // TODO: detect invalid (different across the file) separators ?
158 LineSeparator separator = respectLineSeparators ? StringUtil.detectSeparators(text) : null;
159 Document document = EditorFactory.getInstance().createDocument(StringUtil.convertLineSeparators(text));
160 if (readOnly) document.setReadOnly(true);
161 return new DocumentContentImpl(document, type, highlightFile, separator, charset);
165 public DiffContent createFromBytes(@Nullable Project project,
166 @NotNull FilePath filePath,
167 @NotNull byte[] content) throws IOException {
168 if (filePath.getFileType().isBinary()) {
169 return DiffContentFactory.getInstance().createBinary(project, filePath.getName(), filePath.getFileType(), content);
172 return FileAwareDocumentContent.create(project, content, filePath);
177 public DiffContent createFromBytes(@Nullable Project project,
178 @NotNull VirtualFile highlightFile,
179 @NotNull byte[] content) throws IOException {
180 // TODO: check if FileType.UNKNOWN is actually a text ?
181 if (highlightFile.getFileType().isBinary()) {
182 return DiffContentFactory.getInstance().createBinary(project, highlightFile.getName(), highlightFile.getFileType(), content);
185 return FileAwareDocumentContent.create(project, content, highlightFile);
190 public DiffContent createBinary(@Nullable Project project,
191 @NotNull String name,
192 @NotNull FileType type,
193 @NotNull byte[] content) throws IOException {
194 boolean useTemporalFile = true; // TODO: workaround for Decompiler
195 //boolean useTemporalFile = type instanceof ArchiveFileType; // workaround - our JarFileSystem can't process non-local files
198 if (useTemporalFile) {
199 if (type.getDefaultExtension().isEmpty()) {
200 file = createTemporalFile(project, "tmp_", "_" + name, content);
203 file = createTemporalFile(project, name + "_", "." + type.getDefaultExtension(), content);
207 file = new BinaryLightVirtualFile(name, type, content);
210 return create(project, file);
214 public static VirtualFile createTemporalFile(@Nullable Project project,
215 @NotNull String prefix,
216 @NotNull String suffix,
217 @NotNull byte[] content) throws IOException {
218 File tempFile = FileUtil.createTempFile(PathUtil.suggestFileName(prefix + "_", true, false),
219 PathUtil.suggestFileName("_" + suffix, true, false), true);
220 if (content.length != 0) {
221 FileUtil.writeToFile(tempFile, content);
223 VirtualFile file = VfsUtil.findFileByIoFile(tempFile, true);
225 throw new IOException("Can't create temp file for revision content");
227 VfsUtil.markDirtyAndRefresh(true, true, true, file);