blob: 9a0af4ad83a2c1fd3a224e3519fff2a68f8aad70 [file] [log] [blame]
/*
* Copyright 2000-2013 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.diff;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.diff.impl.string.DiffString;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.EditorFactory;
import com.intellij.openapi.fileEditor.OpenFileDescriptor;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.fileTypes.FileTypeManager;
import com.intellij.openapi.vfs.CharsetToolkit;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.LineSeparator;
import com.intellij.util.SystemProperties;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.*;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
/**
* Allows to compare some text not associated with file or document.
*
* @see #getText()
* @see #setReadOnly(boolean)
*/
public class SimpleContent extends DiffContent {
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.diff.SimpleContent");
private final byte[] myOriginalBytes;
private final String myOriginalText;
private final LineSeparators myLineSeparators = new LineSeparators();
private final Document myDocument;
private final FileType myType;
private Charset myCharset;
private byte[] myBOM;
/**
* Constructs content with given text and null type
*/
public SimpleContent(String text) {
this(text, null);
}
public SimpleContent(@NotNull String text, @Nullable FileType type) {
this(text, type, EditorFactory.getInstance());
}
public SimpleContent(@NotNull String text, FileType type, EditorFactory f) {
myOriginalBytes = text.getBytes();
myOriginalText = myLineSeparators.correctText(text);
myDocument = f.createDocument(myOriginalText);
setReadOnly(true);
myType = type;
}
public static SimpleContent createEmpty() {
final SimpleContent content = new SimpleContent("");
content.setIsEmpty(true);
return content;
}
/**
* Make this content editable or not. By default SimpleContent isn't editable.
*/
public void setReadOnly(boolean readOnly) {
myDocument.setReadOnly(readOnly);
}
/**
* @return modified text.
* @see #setReadOnly(boolean)
*/
public String getText() {
return myLineSeparators.restoreText(myDocument.getText());
}
@Override
public Document getDocument() {
return myDocument;
}
/**
* @return null
*/
@Override
public OpenFileDescriptor getOpenFileDescriptor(int offset) {
return null;
}
/**
* @return null
*/
@Override
public VirtualFile getFile() {
return null;
}
@Override
@Nullable
public FileType getContentType() {
return myType;
}
/**
* @return Encodes using default encoding
*/
@Override
public byte[] getBytes() {
String currentText = getText();
if (myOriginalText.equals(myDocument.getText()) && myCharset == null) {
return myOriginalBytes;
}
else if (myCharset != null) {
final ByteBuffer buffer = myCharset.encode(currentText).compact();
int bomLength = myBOM != null ? myBOM.length : 0;
final int encodedLength = buffer.position();
byte[] result = new byte[encodedLength + bomLength];
if (bomLength > 0) {
System.arraycopy(myBOM, 0, result, 0, bomLength);
}
buffer.position(0);
buffer.get(result, bomLength, encodedLength);
return result;
}
return currentText.getBytes();
}
@NotNull
@Override
public LineSeparator getLineSeparator() {
return LineSeparator.fromString(myLineSeparators.mySeparator);
}
public Charset getCharset() {
return myCharset;
}
public void setCharset(final Charset charset) {
myCharset = charset;
}
/**
* @param text text of content
* @param fileName used to determine content type
*/
public static SimpleContent forFileContent(String text, String fileName) {
FileType fileType;
if (fileName != null) {
fileType = FileTypeManager.getInstance().getFileTypeByFileName(fileName);
}
else {
fileType = null;
}
return new SimpleContent(text, fileType);
}
/**
* @param bytes binary text representaion
* @param charset name of charset. If null IDE default charset will be used
* @param fileType content type. If null file name will be used to select file type
* @return content representing bytes as text
* @throws UnsupportedEncodingException
*/
public static SimpleContent fromBytes(byte[] bytes, String charset, FileType fileType) throws UnsupportedEncodingException {
if (charset == null) charset = CharsetToolkit.getDefaultSystemCharset().name();
return new SimpleContent(new String(bytes, charset), fileType);
}
/**
* @param file should exist and not to be a directory
* @param charset name of file charset. If null IDE default charset will be used
* @param fileType content type. If null file name will be used to select file type
* @return Content representing text in file
* @throws IOException
*/
public static DiffContent fromIoFile(File file, String charset, FileType fileType) throws IOException {
if (file.isDirectory()) throw new IllegalArgumentException(file.toString());
if (fileType == null) fileType = FileTypeManager.getInstance().getFileTypeByFileName(file.getName());
BufferedInputStream stream = new BufferedInputStream(new FileInputStream(file));
try {
byte[] bytes = new byte[(int)file.length()];
int bytesRead = stream.read(bytes, 0, bytes.length);
LOG.assertTrue(file.length() == bytesRead);
return fromBytes(bytes, charset, fileType);
}
finally {
stream.close();
}
}
public void setBOM(final byte[] BOM) {
myBOM = BOM;
}
private static class LineSeparators {
private String mySeparator;
@NotNull
public String correctText(@NotNull String text) {
DiffString.LineTokenizer lineTokenizer = new DiffString.LineTokenizer(DiffString.create(text));
DiffString[] lines = lineTokenizer.execute();
mySeparator = lineTokenizer.getLineSeparator();
LOG.assertTrue(mySeparator == null || !mySeparator.isEmpty());
if (mySeparator == null) mySeparator = SystemProperties.getLineSeparator();
return DiffString.concatenate(lines).toString();
}
@NotNull
public String restoreText(@NotNull String text) {
if (mySeparator == null) throw new NullPointerException();
return text.replaceAll("\n", mySeparator);
}
}
}