/* * Copyright (c) 2002-2004 Widespace, OU and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://solareclipse.sourceforge.net/legal/cpl-v10.html * * Contributors: * Igor Malinin - initial contribution * * $Id: I18NDocumentProvider.java,v 1.2 2006-10-21 23:13:54 pombredanne Exp $ */ package net.sourceforge.phpeclipse.ui.editor; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; import java.io.UnsupportedEncodingException; import org.eclipse.core.resources.IFile; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.SubProgressMonitor; import org.eclipse.jface.text.IDocument; import org.eclipse.ui.IFileEditorInput; import org.eclipse.ui.IStorageEditorInput; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.dialogs.ContainerGenerator; import org.eclipse.ui.editors.text.FileDocumentProvider; import org.eclipse.ui.texteditor.ResourceMarkerAnnotationModel; /** * @author Igor Malinin */ public class I18NDocumentProvider extends FileDocumentProvider { private static final char BOM = 0xFEFF; /* * @see org.eclipse.ui.editors.text.StorageDocumentProvider#setDocumentContent(IDocument, * InputStream, String) */ protected void setDocumentContent(IDocument document, InputStream contentStream, String encoding) throws CoreException { Reader in = null; try { if (encoding == null) { encoding = getDefaultEncoding(); } in = new InputStreamReader(contentStream, encoding); StringBuffer buffer = new StringBuffer(); char[] readBuffer = new char[2048]; int n = in.read(readBuffer); while (n > 0) { buffer.append(readBuffer, 0, n); n = in.read(readBuffer); } if (buffer.length() > 0 && buffer.charAt(0) == BOM) { buffer.deleteCharAt(0); } document.set(buffer.toString()); } catch (IOException x) { String msg = x.getMessage(); if (msg == null) { msg = ""; //$NON-NLS-1$ } IStatus s = new Status(IStatus.ERROR, PlatformUI.PLUGIN_ID, IStatus.OK, msg, x); throw new CoreException(s); } finally { if (in != null) try { in.close(); } catch (IOException x) { } } } /* * @see org.eclipse.ui.texteditor.AbstractDocumentProvider#doSaveDocument(IProgressMonitor, * Object, IDocument, boolean) */ protected void doSaveDocument(IProgressMonitor monitor, Object element, IDocument document, boolean overwrite) throws CoreException { if (!(element instanceof IFileEditorInput)) { super.doSaveDocument(monitor, element, document, overwrite); return; } IFileEditorInput input = (IFileEditorInput) element; try { String content = document.get(); String encoding = getDeclaredEncoding(new ByteArrayInputStream( content.getBytes("ISO-8859-1"))); if (encoding == null) { encoding = super.getEncoding(element); if (encoding == null /* || !encoding.startsWith("UTF-16") */) { encoding = getDefaultEncoding(); } } else { setEncoding(element, encoding); } if (encoding.startsWith("UTF-16")) { content = BOM + content; } InputStream stream; try { stream = new ByteArrayInputStream(content.getBytes(encoding)); } catch (UnsupportedEncodingException e) { IStatus s = new Status( IStatus.ERROR, PlatformUI.PLUGIN_ID, IStatus.OK, EditorMessages .getString("I18NDocumentProvider.error.encoding"), e); throw new CoreException(s); } IFile file = input.getFile(); if (file.exists()) { FileInfo info = (FileInfo) getElementInfo(element); if (info != null && !overwrite) { checkSynchronizationState(info.fModificationStamp, file); } // inform about the upcoming content change fireElementStateChanging(element); try { file.setContents(stream, overwrite, true, monitor); } catch (CoreException x) { // inform about failure fireElementStateChangeFailed(element); throw x; } catch (RuntimeException x) { // inform about failure fireElementStateChangeFailed(element); throw x; } // If here, the editor state will be flipped to "not dirty". // Thus, the state changing flag will be reset. if (info != null) { ResourceMarkerAnnotationModel model = (ResourceMarkerAnnotationModel) info.fModel; model.updateMarkers(info.fDocument); info.fModificationStamp = computeModificationStamp(file); } } else { try { monitor.beginTask(EditorMessages .getString("I18NDocumentProvider.task.saving"), //$NON-NLS-1$ 2000); ContainerGenerator generator = new ContainerGenerator(file .getParent().getFullPath()); generator.generateContainer(new SubProgressMonitor(monitor, 1000)); file.create(stream, false, new SubProgressMonitor(monitor, 1000)); } finally { monitor.done(); } } } catch (IOException x) { IStatus s = new Status(IStatus.ERROR, PlatformUI.PLUGIN_ID, IStatus.OK, x.getMessage(), x); throw new CoreException(s); } } /* * @see org.eclipse.ui.editors.text.IStorageDocumentProvider#getEncoding(Object) */ public String getEncoding(Object element) { String encoding = super.getEncoding(element); if (encoding != null) { return encoding; } if (element instanceof IStorageEditorInput) { IStorageEditorInput sei = (IStorageEditorInput) element; try { InputStream in = sei.getStorage().getContents(); try { encoding = getDeclaredEncoding(in); } finally { in.close(); } } catch (CoreException e) { } catch (IOException e) { } if (encoding == null) { encoding = getDefaultEncoding(); } setEncoding(element, encoding); } return encoding; } /* * @see org.eclipse.ui.editors.text.IStorageDocumentProvider#setEncoding(Object, * String) */ public void setEncoding(Object element, String encoding) { if (encoding == null) { encoding = getDefaultEncoding(); } super.setEncoding(element, encoding); } /** * Tries to determine encoding from contents of the stream. Returns * null if encoding is unknown. */ public String getDeclaredEncoding(InputStream in) throws IOException { return getBOMEncoding(in); } /** * Tries to determine encoding from the byte order mark. Returns * null if encoding is unknown. */ private String getBOMEncoding(InputStream in) throws IOException { int first = in.read(); if (first < 0) { return null; } int second = in.read(); if (second < 0) { return null; } // look for the UTF-16 Byte Order Mark (BOM) if (first == 0xFE && second == 0xFF) { return "UTF-16BE"; } if (first == 0xFF && second == 0xFE) { return "UTF-16LE"; } int third = in.read(); if (third < 0) { return null; } // look for the UTF-8 BOM if (first == 0xEF && second == 0xBB && third == 0xBF) { return "UTF-8"; } return null; } }