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.1 2004-09-02 18:26:30 jsurfer 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);
86 } catch (IOException x) {
92 * @see org.eclipse.ui.texteditor.AbstractDocumentProvider#doSaveDocument(IProgressMonitor,
93 * Object, IDocument, boolean)
95 protected void doSaveDocument(IProgressMonitor monitor, Object element,
96 IDocument document, boolean overwrite) throws CoreException {
97 if (!(element instanceof IFileEditorInput)) {
98 super.doSaveDocument(monitor, element, document, overwrite);
102 IFileEditorInput input = (IFileEditorInput) element;
105 String content = document.get();
107 String encoding = getDeclaredEncoding(new ByteArrayInputStream(
108 content.getBytes("ISO-8859-1")));
110 if (encoding == null) {
111 encoding = super.getEncoding(element);
112 if (encoding == null /* || !encoding.startsWith("UTF-16") */) {
113 encoding = getDefaultEncoding();
116 setEncoding(element, encoding);
119 if (encoding.startsWith("UTF-16")) {
120 content = BOM + content;
125 stream = new ByteArrayInputStream(content.getBytes(encoding));
126 } catch (UnsupportedEncodingException e) {
127 IStatus s = new Status(
129 PlatformUI.PLUGIN_ID,
132 .getString("I18NDocumentProvider.error.encoding"),
135 throw new CoreException(s);
138 IFile file = input.getFile();
140 FileInfo info = (FileInfo) getElementInfo(element);
142 if (info != null && !overwrite) {
143 checkSynchronizationState(info.fModificationStamp, file);
146 // inform about the upcoming content change
147 fireElementStateChanging(element);
150 file.setContents(stream, overwrite, true, monitor);
151 } catch (CoreException x) {
152 // inform about failure
153 fireElementStateChangeFailed(element);
155 } catch (RuntimeException x) {
156 // inform about failure
157 fireElementStateChangeFailed(element);
161 // If here, the editor state will be flipped to "not dirty".
162 // Thus, the state changing flag will be reset.
165 ResourceMarkerAnnotationModel model = (ResourceMarkerAnnotationModel) info.fModel;
167 model.updateMarkers(info.fDocument);
169 info.fModificationStamp = computeModificationStamp(file);
173 monitor.beginTask(EditorMessages
174 .getString("I18NDocumentProvider.task.saving"), //$NON-NLS-1$
177 ContainerGenerator generator = new ContainerGenerator(file
178 .getParent().getFullPath());
180 generator.generateContainer(new SubProgressMonitor(monitor,
183 file.create(stream, false, new SubProgressMonitor(monitor,
189 } catch (IOException x) {
190 IStatus s = new Status(IStatus.ERROR, PlatformUI.PLUGIN_ID,
191 IStatus.OK, x.getMessage(), x);
193 throw new CoreException(s);
198 * @see org.eclipse.ui.editors.text.IStorageDocumentProvider#getEncoding(Object)
200 public String getEncoding(Object element) {
201 String encoding = super.getEncoding(element);
202 if (encoding != null) {
206 if (element instanceof IStorageEditorInput) {
207 IStorageEditorInput sei = (IStorageEditorInput) element;
210 InputStream in = sei.getStorage().getContents();
212 encoding = getDeclaredEncoding(in);
216 } catch (CoreException e) {
217 } catch (IOException e) {
220 if (encoding == null) {
221 encoding = getDefaultEncoding();
224 setEncoding(element, encoding);
231 * @see org.eclipse.ui.editors.text.IStorageDocumentProvider#setEncoding(Object,
234 public void setEncoding(Object element, String encoding) {
235 if (encoding == null) {
236 encoding = getDefaultEncoding();
239 super.setEncoding(element, encoding);
243 * Tries to determine encoding from contents of the stream. Returns <code>null</code>
244 * if encoding is unknown.
246 public String getDeclaredEncoding(InputStream in) throws IOException {
247 return getBOMEncoding(in);
251 * Tries to determine encoding from the byte order mark. Returns <code>null</code>
252 * if encoding is unknown.
254 private String getBOMEncoding(InputStream in) throws IOException {
255 int first = in.read();
260 int second = in.read();
265 // look for the UTF-16 Byte Order Mark (BOM)
266 if (first == 0xFE && second == 0xFF) {
270 if (first == 0xFF && second == 0xFE) {
274 int third = in.read();
279 // look for the UTF-8 BOM
280 if (first == 0xEF && second == 0xBB && third == 0xBF) {