2 * Copyright (c) 2002-2004 Widespace, OU and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Common Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://solareclipse.sourceforge.net/legal/cpl-v10.html
9 * Igor Malinin - initial contribution
11 * $Id: I18NDocumentProvider.java,v 1.2 2006-10-21 23:13:54 pombredanne Exp $
14 package net.sourceforge.phpeclipse.ui.editor;
16 import java.io.ByteArrayInputStream;
17 import java.io.IOException;
18 import java.io.InputStream;
19 import java.io.InputStreamReader;
20 import java.io.Reader;
21 import java.io.UnsupportedEncodingException;
23 import org.eclipse.core.resources.IFile;
24 import org.eclipse.core.runtime.CoreException;
25 import org.eclipse.core.runtime.IProgressMonitor;
26 import org.eclipse.core.runtime.IStatus;
27 import org.eclipse.core.runtime.Status;
28 import org.eclipse.core.runtime.SubProgressMonitor;
29 import org.eclipse.jface.text.IDocument;
30 import org.eclipse.ui.IFileEditorInput;
31 import org.eclipse.ui.IStorageEditorInput;
32 import org.eclipse.ui.PlatformUI;
33 import org.eclipse.ui.dialogs.ContainerGenerator;
34 import org.eclipse.ui.editors.text.FileDocumentProvider;
35 import org.eclipse.ui.texteditor.ResourceMarkerAnnotationModel;
38 * @author Igor Malinin
40 public class I18NDocumentProvider extends FileDocumentProvider {
42 private static final char BOM = 0xFEFF;
45 * @see org.eclipse.ui.editors.text.StorageDocumentProvider#setDocumentContent(IDocument,
46 * InputStream, String)
48 protected void setDocumentContent(IDocument document,
49 InputStream contentStream, String encoding) throws CoreException {
53 if (encoding == null) {
54 encoding = getDefaultEncoding();
57 in = new InputStreamReader(contentStream, encoding);
59 StringBuffer buffer = new StringBuffer();
61 char[] readBuffer = new char[2048];
62 int n = in.read(readBuffer);
64 buffer.append(readBuffer, 0, n);
65 n = in.read(readBuffer);
68 if (buffer.length() > 0 && buffer.charAt(0) == BOM) {
69 buffer.deleteCharAt(0);
72 document.set(buffer.toString());
73 } catch (IOException x) {
74 String msg = x.getMessage();
76 msg = ""; //$NON-NLS-1$
79 IStatus s = new Status(IStatus.ERROR, PlatformUI.PLUGIN_ID,
82 throw new CoreException(s);
87 } catch (IOException x) {
93 * @see org.eclipse.ui.texteditor.AbstractDocumentProvider#doSaveDocument(IProgressMonitor,
94 * Object, IDocument, boolean)
96 protected void doSaveDocument(IProgressMonitor monitor, Object element,
97 IDocument document, boolean overwrite) throws CoreException {
98 if (!(element instanceof IFileEditorInput)) {
99 super.doSaveDocument(monitor, element, document, overwrite);
103 IFileEditorInput input = (IFileEditorInput) element;
106 String content = document.get();
108 String encoding = getDeclaredEncoding(new ByteArrayInputStream(
109 content.getBytes("ISO-8859-1")));
111 if (encoding == null) {
112 encoding = super.getEncoding(element);
113 if (encoding == null /* || !encoding.startsWith("UTF-16") */) {
114 encoding = getDefaultEncoding();
117 setEncoding(element, encoding);
120 if (encoding.startsWith("UTF-16")) {
121 content = BOM + content;
126 stream = new ByteArrayInputStream(content.getBytes(encoding));
127 } catch (UnsupportedEncodingException e) {
128 IStatus s = new Status(
130 PlatformUI.PLUGIN_ID,
133 .getString("I18NDocumentProvider.error.encoding"),
136 throw new CoreException(s);
139 IFile file = input.getFile();
141 FileInfo info = (FileInfo) getElementInfo(element);
143 if (info != null && !overwrite) {
144 checkSynchronizationState(info.fModificationStamp, file);
147 // inform about the upcoming content change
148 fireElementStateChanging(element);
151 file.setContents(stream, overwrite, true, monitor);
152 } catch (CoreException x) {
153 // inform about failure
154 fireElementStateChangeFailed(element);
156 } catch (RuntimeException x) {
157 // inform about failure
158 fireElementStateChangeFailed(element);
162 // If here, the editor state will be flipped to "not dirty".
163 // Thus, the state changing flag will be reset.
166 ResourceMarkerAnnotationModel model = (ResourceMarkerAnnotationModel) info.fModel;
168 model.updateMarkers(info.fDocument);
170 info.fModificationStamp = computeModificationStamp(file);
174 monitor.beginTask(EditorMessages
175 .getString("I18NDocumentProvider.task.saving"), //$NON-NLS-1$
178 ContainerGenerator generator = new ContainerGenerator(file
179 .getParent().getFullPath());
181 generator.generateContainer(new SubProgressMonitor(monitor,
184 file.create(stream, false, new SubProgressMonitor(monitor,
190 } catch (IOException x) {
191 IStatus s = new Status(IStatus.ERROR, PlatformUI.PLUGIN_ID,
192 IStatus.OK, x.getMessage(), x);
194 throw new CoreException(s);
199 * @see org.eclipse.ui.editors.text.IStorageDocumentProvider#getEncoding(Object)
201 public String getEncoding(Object element) {
202 String encoding = super.getEncoding(element);
203 if (encoding != null) {
207 if (element instanceof IStorageEditorInput) {
208 IStorageEditorInput sei = (IStorageEditorInput) element;
211 InputStream in = sei.getStorage().getContents();
213 encoding = getDeclaredEncoding(in);
217 } catch (CoreException e) {
218 } catch (IOException e) {
221 if (encoding == null) {
222 encoding = getDefaultEncoding();
225 setEncoding(element, encoding);
232 * @see org.eclipse.ui.editors.text.IStorageDocumentProvider#setEncoding(Object,
235 public void setEncoding(Object element, String encoding) {
236 if (encoding == null) {
237 encoding = getDefaultEncoding();
240 super.setEncoding(element, encoding);
244 * Tries to determine encoding from contents of the stream. Returns
245 * <code>null</code> if encoding is unknown.
247 public String getDeclaredEncoding(InputStream in) throws IOException {
248 return getBOMEncoding(in);
252 * Tries to determine encoding from the byte order mark. Returns
253 * <code>null</code> if encoding is unknown.
255 private String getBOMEncoding(InputStream in) throws IOException {
256 int first = in.read();
261 int second = in.read();
266 // look for the UTF-16 Byte Order Mark (BOM)
267 if (first == 0xFE && second == 0xFF) {
271 if (first == 0xFF && second == 0xFE) {
275 int third = in.read();
280 // look for the UTF-8 BOM
281 if (first == 0xEF && second == 0xBB && third == 0xBF) {