diff options
Diffstat (limited to 'org.eclipse.core.filebuffers')
32 files changed, 3269 insertions, 0 deletions
diff --git a/org.eclipse.core.filebuffers/.classpath b/org.eclipse.core.filebuffers/.classpath new file mode 100644 index 000000000..0b778fad9 --- /dev/null +++ b/org.eclipse.core.filebuffers/.classpath @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="UTF-8"?> +<classpath> + <classpathentry kind="src" path="src/"/> + <classpathentry kind="src" path="/org.eclipse.core.resources"/> + <classpathentry kind="src" path="/org.eclipse.core.boot"/> + <classpathentry kind="src" path="/org.eclipse.core.runtime"/> + <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/> + <classpathentry kind="src" path="/org.eclipse.text"/> + <classpathentry kind="output" path="bin"/> +</classpath> diff --git a/org.eclipse.core.filebuffers/.cvsignore b/org.eclipse.core.filebuffers/.cvsignore new file mode 100644 index 000000000..c5e82d745 --- /dev/null +++ b/org.eclipse.core.filebuffers/.cvsignore @@ -0,0 +1 @@ +bin
\ No newline at end of file diff --git a/org.eclipse.core.filebuffers/.project b/org.eclipse.core.filebuffers/.project new file mode 100644 index 000000000..2657d3f4a --- /dev/null +++ b/org.eclipse.core.filebuffers/.project @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<projectDescription> + <name>org.eclipse.core.filebuffers</name> + <comment></comment> + <projects> + <project>org.eclipse.core.boot</project> + <project>org.eclipse.core.resources</project> + <project>org.eclipse.core.runtime</project> + <project>org.eclipse.text</project> + </projects> + <buildSpec> + <buildCommand> + <name>org.eclipse.jdt.core.javabuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.pde.ManifestBuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.pde.SchemaBuilder</name> + <arguments> + </arguments> + </buildCommand> + </buildSpec> + <natures> + <nature>org.eclipse.pde.PluginNature</nature> + <nature>org.eclipse.jdt.core.javanature</nature> + </natures> +</projectDescription> diff --git a/org.eclipse.core.filebuffers/about.html b/org.eclipse.core.filebuffers/about.html new file mode 100644 index 000000000..9db411aab --- /dev/null +++ b/org.eclipse.core.filebuffers/about.html @@ -0,0 +1,30 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN"> +<html> +<head> +<title>About</title> +<meta http-equiv=Content-Type content="text/html; charset=ISO-8859-1"> +</head> +<body lang="EN-US"> +<h2>About This Content</h2> + +<p>20th June, 2002</p> +<h3>License</h3> +<p>Eclipse.org makes available all content in this plug-in ("Content"). Unless otherwise indicated below, the Content is provided to you under the terms and conditions of the +Common Public License Version 1.0 ("CPL"). A copy of the CPL is available at <a href="http://www.eclipse.org/legal/cpl-v10.html">http://www.eclipse.org/legal/cpl-v10.html</a>. +For purposes of the CPL, "Program" will mean the Content.</p> + +<h3>Contributions</h3> + +<p>If this Content is licensed to you under the terms and conditions of the CPL, any Contributions, as defined in the CPL, uploaded, submitted, or otherwise +made available to Eclipse.org, members of Eclipse.org and/or the host of Eclipse.org web site, by you that relate to such +Content are provided under the terms and conditions of the CPL and can be made available to others under the terms of the CPL.</p> + +<p>If this Content is licensed to you under license terms and conditions other than the CPL ("Other License"), any modifications, enhancements and/or +other code and/or documentation ("Modifications") uploaded, submitted, or otherwise made available to Eclipse.org, members of Eclipse.org and/or the +host of Eclipse.org, by you that relate to such Content are provided under terms and conditions of the Other License and can be made available +to others under the terms of the Other License. In addition, with regard to Modifications for which you are the copyright holder, you are also +providing the Modifications under the terms and conditions of the CPL and such Modifications can be made available to others under the terms of +the CPL.</p> + +</body> +</html>
\ No newline at end of file diff --git a/org.eclipse.core.filebuffers/build.properties b/org.eclipse.core.filebuffers/build.properties new file mode 100644 index 000000000..ee56c8858 --- /dev/null +++ b/org.eclipse.core.filebuffers/build.properties @@ -0,0 +1,15 @@ +############################################################################### +# Copyright (c) 2000, 2003 IBM Corporation 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://www.eclipse.org/legal/cpl-v10.html +# +# Contributors: +# IBM Corporation - initial API and implementation +############################################################################### +bin.includes = plugin.properties,\ + plugin.xml,\ + *.jar,\ + about.html +source.filebuffers.jar = src/
\ No newline at end of file diff --git a/org.eclipse.core.filebuffers/plugin.properties b/org.eclipse.core.filebuffers/plugin.properties new file mode 100644 index 000000000..23d210cea --- /dev/null +++ b/org.eclipse.core.filebuffers/plugin.properties @@ -0,0 +1,15 @@ +############################################################################### +# Copyright (c) 2000, 2003 IBM Corporation 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://www.eclipse.org/legal/cpl-v10.html +# +# Contributors: +# IBM Corporation - initial API and implementation +############################################################################### +pluginName= File Buffers +providerName= Eclipse.org +documentCreationPoint= Document Creation +documentSetupPoint= Document Setup +defaultDocumentFactory= Default Document Factory diff --git a/org.eclipse.core.filebuffers/plugin.xml b/org.eclipse.core.filebuffers/plugin.xml new file mode 100644 index 000000000..7e5101e63 --- /dev/null +++ b/org.eclipse.core.filebuffers/plugin.xml @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="UTF-8"?> +<plugin + id="org.eclipse.core.filebuffers" + name="%pluginName" + version="3.0" + provider-name="%providerName" + class="org.eclipse.core.internal.filebuffers.FileBuffersPlugin"> + + <runtime> + <library name="filebuffers.jar"> + <export name="*"/> + <packages prefixes="org.eclipse.core.filebuffers,org.eclipse.core.internal.filebuffers"/> + </library> + </runtime> + <requires> + <import plugin="org.eclipse.core.resources"/> + <import plugin="org.eclipse.core.runtime"/> + <import plugin="org.eclipse.text"/> + </requires> + + + <extension-point id="documentCreation" name="%documentCreationPoint" schema="schema/documentCreation.exsd"/> + <extension-point id="documentSetup" name="%documentSetupPoint" schema="schema/documentSetup.exsd"/> + + <extension + id="DefaultDocumentFactory" + name="%defaultDocumentFactory" + point="org.eclipse.core.filebuffers.documentCreation"> + <factory + extensions="*" + class="org.eclipse.core.internal.filebuffers.DefaultDocumentFactory"> + </factory> + </extension> +</plugin> diff --git a/org.eclipse.core.filebuffers/schema/documentCreation.exsd b/org.eclipse.core.filebuffers/schema/documentCreation.exsd new file mode 100644 index 000000000..bf009eb51 --- /dev/null +++ b/org.eclipse.core.filebuffers/schema/documentCreation.exsd @@ -0,0 +1,109 @@ +<?xml version='1.0' encoding='UTF-8'?>
+<!-- Schema file written by PDE -->
+<schema targetNamespace="org.eclipse.core.filebuffers">
+<annotation>
+ <appInfo>
+ <meta.schema plugin="org.eclipse.core.filebuffers" id="documentCreation" name="Document Creation"/>
+ </appInfo>
+ <documentation>
+ [Enter description of this extension point.]
+ </documentation>
+ </annotation>
+
+ <element name="extension">
+ <complexType>
+ <sequence>
+ <element ref="factory"/>
+ </sequence>
+ <attribute name="point" type="string" use="required">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="id" type="string">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="name" type="string">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ </annotation>
+ </attribute>
+ </complexType>
+ </element>
+
+ <element name="factory">
+ <complexType>
+ <attribute name="class" type="string" use="required">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ <appInfo>
+ <meta.attribute kind="java"/>
+ </appInfo>
+ </annotation>
+ </attribute>
+ <attribute name="extensions" type="string" use="required">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ </annotation>
+ </attribute>
+ </complexType>
+ </element>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="since"/>
+ </appInfo>
+ <documentation>
+ [Enter the first release in which this extension point appears.]
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="examples"/>
+ </appInfo>
+ <documentation>
+ [Enter extension point usage example here.]
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="apiInfo"/>
+ </appInfo>
+ <documentation>
+ [Enter API information here.]
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="implementation"/>
+ </appInfo>
+ <documentation>
+ [Enter information about supplied implementation of this extension point.]
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="copyright"/>
+ </appInfo>
+ <documentation>
+
+ </documentation>
+ </annotation>
+
+</schema>
diff --git a/org.eclipse.core.filebuffers/schema/documentSetup.exsd b/org.eclipse.core.filebuffers/schema/documentSetup.exsd new file mode 100644 index 000000000..0b875860b --- /dev/null +++ b/org.eclipse.core.filebuffers/schema/documentSetup.exsd @@ -0,0 +1,109 @@ +<?xml version='1.0' encoding='UTF-8'?>
+<!-- Schema file written by PDE -->
+<schema targetNamespace="org.eclipse.core.filebuffers">
+<annotation>
+ <appInfo>
+ <meta.schema plugin="org.eclipse.core.filebuffers" id="documentSetup" name="Document Setup"/>
+ </appInfo>
+ <documentation>
+ [Enter description of this extension point.]
+ </documentation>
+ </annotation>
+
+ <element name="extension">
+ <complexType>
+ <sequence>
+ <element ref="participant"/>
+ </sequence>
+ <attribute name="point" type="string" use="required">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="id" type="string">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="name" type="string">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ </annotation>
+ </attribute>
+ </complexType>
+ </element>
+
+ <element name="participant">
+ <complexType>
+ <attribute name="class" type="string" use="required">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ <appInfo>
+ <meta.attribute kind="java"/>
+ </appInfo>
+ </annotation>
+ </attribute>
+ <attribute name="extensions" type="string" use="required">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ </annotation>
+ </attribute>
+ </complexType>
+ </element>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="since"/>
+ </appInfo>
+ <documentation>
+ [Enter the first release in which this extension point appears.]
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="examples"/>
+ </appInfo>
+ <documentation>
+ [Enter extension point usage example here.]
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="apiInfo"/>
+ </appInfo>
+ <documentation>
+ [Enter API information here.]
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="implementation"/>
+ </appInfo>
+ <documentation>
+ [Enter information about supplied implementation of this extension point.]
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="copyright"/>
+ </appInfo>
+ <documentation>
+
+ </documentation>
+ </annotation>
+
+</schema>
diff --git a/org.eclipse.core.filebuffers/scripts/exportplugin.xml b/org.eclipse.core.filebuffers/scripts/exportplugin.xml new file mode 100644 index 000000000..57d44f387 --- /dev/null +++ b/org.eclipse.core.filebuffers/scripts/exportplugin.xml @@ -0,0 +1,28 @@ +<project name="Export Text" default="export" basedir=".."> + <target name="init"> + <tstamp/> + <property name="destdir" value="../../plugin-export" /> + <property name="plugin" value="org.eclipse.core.filebuffers" /> + <property name="version" value="_3.0.0" /> + <property name="dest" value="${destdir}/${plugin}${version}" /> + </target> + + <target name="build" depends="init"> + <eclipse.incrementalBuild project="${plugin}" kind="incr"/> + </target> + + <target name="export" depends="build"> + <mkdir dir="${destdir}" /> + <delete dir="${dest}" /> + <mkdir dir="${dest}" /> + <jar + jarfile="${dest}/filebuffers.jar" + basedir="bin" + /> + <copy file="plugin.xml" todir="${dest}"/> + <copy file="plugin.properties" todir="${dest}"/> + <zip zipfile="${dest}/filebufferssrc.zip"> + <fileset dir="src" /> + </zip> + </target> +</project> diff --git a/org.eclipse.core.filebuffers/src/org/eclipse/core/filebuffers/FileBuffers.java b/org.eclipse.core.filebuffers/src/org/eclipse/core/filebuffers/FileBuffers.java new file mode 100644 index 000000000..3ab9f6788 --- /dev/null +++ b/org.eclipse.core.filebuffers/src/org/eclipse/core/filebuffers/FileBuffers.java @@ -0,0 +1,26 @@ +/********************************************************************** +Copyright (c) 2000, 2003 IBM Corp. 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://www.eclipse.org/legal/cpl-v10.html + +Contributors: + IBM Corporation - Initial implementation +**********************************************************************/ +package org.eclipse.core.filebuffers; + +import org.eclipse.core.internal.filebuffers.FileBuffersPlugin; + +/** + * + */ +public final class FileBuffers { + + private FileBuffers() { + } + + public static ITextFileBufferManager getTextFileBufferManager() { + return FileBuffersPlugin.getDefault().getBufferedFileManager(); + } +} diff --git a/org.eclipse.core.filebuffers/src/org/eclipse/core/filebuffers/IDocumentFactory.java b/org.eclipse.core.filebuffers/src/org/eclipse/core/filebuffers/IDocumentFactory.java new file mode 100644 index 000000000..72496e32b --- /dev/null +++ b/org.eclipse.core.filebuffers/src/org/eclipse/core/filebuffers/IDocumentFactory.java @@ -0,0 +1,26 @@ +/********************************************************************** +Copyright (c) 2000, 2003 IBM Corp. 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://www.eclipse.org/legal/cpl-v10.html + +Contributors: + IBM Corporation - Initial implementation +**********************************************************************/ +package org.eclipse.core.filebuffers; + +import org.eclipse.jface.text.IDocument; + +/** + * Factory for documents. + */ +public interface IDocumentFactory { + + /** + * Creates and returns a new, empty document. + * + * @return a new, empty document + */ + IDocument createDocument(); +} diff --git a/org.eclipse.core.filebuffers/src/org/eclipse/core/filebuffers/IDocumentSetupParticipant.java b/org.eclipse.core.filebuffers/src/org/eclipse/core/filebuffers/IDocumentSetupParticipant.java new file mode 100644 index 000000000..9e10724d4 --- /dev/null +++ b/org.eclipse.core.filebuffers/src/org/eclipse/core/filebuffers/IDocumentSetupParticipant.java @@ -0,0 +1,27 @@ +/********************************************************************** +Copyright (c) 2000, 2003 IBM Corp. 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://www.eclipse.org/legal/cpl-v10.html + +Contributors: + IBM Corporation - Initial implementation +**********************************************************************/ +package org.eclipse.core.filebuffers; + +import org.eclipse.jface.text.IDocument; + +/** + * Participates in the setup of a document. + * @since 3.0 + */ +public interface IDocumentSetupParticipant { + + /** + * Sets up the document to be ready for usage. + * + * @param document the document to be set up + */ + void setup(IDocument document); +} diff --git a/org.eclipse.core.filebuffers/src/org/eclipse/core/filebuffers/IFileBuffer.java b/org.eclipse.core.filebuffers/src/org/eclipse/core/filebuffers/IFileBuffer.java new file mode 100644 index 000000000..b44cc693d --- /dev/null +++ b/org.eclipse.core.filebuffers/src/org/eclipse/core/filebuffers/IFileBuffer.java @@ -0,0 +1,40 @@ +/********************************************************************** +Copyright (c) 2000, 2003 IBM Corp. 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://www.eclipse.org/legal/cpl-v10.html + +Contributors: + IBM Corporation - Initial implementation +**********************************************************************/ +package org.eclipse.core.filebuffers; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; + +/** + * + */ +public interface IFileBuffer { + + IFile getUnderlyingFile(); + + void addFileBufferListener(IFileBufferListener listener); + + void removeFileBufferListener(IFileBufferListener listener); + + void revert(IProgressMonitor monitor) throws CoreException; + + void commit(IProgressMonitor monitor, boolean overwrite) throws CoreException; + + boolean isDirty(); + + void validateState(IProgressMonitor monitor, Object computationContext) throws CoreException; + + boolean isStateValidated(); + + IStatus getStatus(); +} diff --git a/org.eclipse.core.filebuffers/src/org/eclipse/core/filebuffers/IFileBufferListener.java b/org.eclipse.core.filebuffers/src/org/eclipse/core/filebuffers/IFileBufferListener.java new file mode 100644 index 000000000..fd259bf73 --- /dev/null +++ b/org.eclipse.core.filebuffers/src/org/eclipse/core/filebuffers/IFileBufferListener.java @@ -0,0 +1,35 @@ +/********************************************************************** +Copyright (c) 2000, 2003 IBM Corp. 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://www.eclipse.org/legal/cpl-v10.html + +Contributors: + IBM Corporation - Initial implementation +**********************************************************************/ +package org.eclipse.core.filebuffers; + +import org.eclipse.core.resources.IFile; + +/** + * + */ +public interface IFileBufferListener { + + void bufferContentAboutToBeReplaced(IFileBuffer buffer); + + void bufferContentReplaced(IFileBuffer buffer); + + void stateChanging(IFileBuffer buffer); + + void dirtyStateChanged(IFileBuffer buffer, boolean isDirty); + + void stateValidationChanged(IFileBuffer buffer, boolean isStateValidated); + + void underlyingFileMoved(IFileBuffer buffer, IFile target); + + void underlyingFileDeleted(IFileBuffer buffer); + + void stateChangeFailed(IFileBuffer buffer); +} diff --git a/org.eclipse.core.filebuffers/src/org/eclipse/core/filebuffers/IFileBufferManager.java b/org.eclipse.core.filebuffers/src/org/eclipse/core/filebuffers/IFileBufferManager.java new file mode 100644 index 000000000..9b843433e --- /dev/null +++ b/org.eclipse.core.filebuffers/src/org/eclipse/core/filebuffers/IFileBufferManager.java @@ -0,0 +1,23 @@ +/********************************************************************** +Copyright (c) 2000, 2003 IBM Corp. 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://www.eclipse.org/legal/cpl-v10.html + +Contributors: + IBM Corporation - Initial implementation +**********************************************************************/ + +package org.eclipse.core.filebuffers; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.runtime.CoreException; + + +public interface IFileBufferManager { + + void connect(IFile file) throws CoreException; + + void disconnect(IFile file) throws CoreException; +} diff --git a/org.eclipse.core.filebuffers/src/org/eclipse/core/filebuffers/ITextFileBuffer.java b/org.eclipse.core.filebuffers/src/org/eclipse/core/filebuffers/ITextFileBuffer.java new file mode 100644 index 000000000..9943dde38 --- /dev/null +++ b/org.eclipse.core.filebuffers/src/org/eclipse/core/filebuffers/ITextFileBuffer.java @@ -0,0 +1,24 @@ +/********************************************************************** +Copyright (c) 2000, 2003 IBM Corp. 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://www.eclipse.org/legal/cpl-v10.html + +Contributors: + IBM Corporation - Initial implementation +**********************************************************************/ +package org.eclipse.core.filebuffers; + + +import org.eclipse.jface.text.IDocument; + + +public interface ITextFileBuffer extends IFileBuffer { + + IDocument getDocument(); + + String getEncoding(); + + void setEncoding(String encoding); +} diff --git a/org.eclipse.core.filebuffers/src/org/eclipse/core/filebuffers/ITextFileBufferManager.java b/org.eclipse.core.filebuffers/src/org/eclipse/core/filebuffers/ITextFileBufferManager.java new file mode 100644 index 000000000..73a963ac0 --- /dev/null +++ b/org.eclipse.core.filebuffers/src/org/eclipse/core/filebuffers/ITextFileBufferManager.java @@ -0,0 +1,26 @@ +/********************************************************************** +Copyright (c) 2000, 2003 IBM Corp. 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://www.eclipse.org/legal/cpl-v10.html + +Contributors: + IBM Corporation - Initial implementation +**********************************************************************/ + +package org.eclipse.core.filebuffers; + +import org.eclipse.core.resources.IFile; + +import org.eclipse.jface.text.IDocument; + + +public interface ITextFileBufferManager extends IFileBufferManager { + + ITextFileBuffer getTextFileBuffer(IFile file); + + String getDefaultEncoding(); + + IDocument createEmptyDocument(IFile file); +} diff --git a/org.eclipse.core.filebuffers/src/org/eclipse/core/internal/filebuffers/AbstractDocumentProvider2.java b/org.eclipse.core.filebuffers/src/org/eclipse/core/internal/filebuffers/AbstractDocumentProvider2.java new file mode 100644 index 000000000..d3308a2a0 --- /dev/null +++ b/org.eclipse.core.filebuffers/src/org/eclipse/core/internal/filebuffers/AbstractDocumentProvider2.java @@ -0,0 +1,661 @@ +/******************************************************************************* + * Copyright (c) 2000, 2003 IBM Corporation 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://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.core.internal.filebuffers; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.core.runtime.Status; + +import org.eclipse.jface.text.Assert; +import org.eclipse.jface.text.DocumentEvent; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IDocumentListener; + + + +/** + * An abstract implementation of a shareable document provider. + * <p> + * Subclasses must implement <code>createDocument</code>, + * <code>createAnnotationModel</code>, and <code>doSaveDocument</code>. + * </p> + */ +public abstract class AbstractDocumentProvider2 implements IDocumentProvider2 { + + /** + * Collection of all information managed for a connected element. + */ + protected class ElementInfo implements IDocumentListener { + + /** The element for which the info is stored */ + public Object fElement; + /** How often the element has been connected */ + public int fReferenceCount; + /** Can the element be saved */ + public boolean fCanBeSaved; + /** The element's document */ + public IDocument fDocument; + /** Has element state been validated */ + public boolean fIsStateValidated; + /** The status of this element */ + public IStatus fStatus; + + + /** + * Creates a new element info, initialized with the given + * document and annotation model. + * + * @param document the document + */ + public ElementInfo(IDocument document) { + fDocument= document; + fReferenceCount= 0; + fCanBeSaved= false; + fIsStateValidated= false; + } + + /** + * An element info equals another object if this object is an element info + * and if the elements of the two element infos are equal. + */ + public boolean equals(Object o) { + if (o instanceof ElementInfo) { + ElementInfo e= (ElementInfo) o; + return fElement.equals(e.fElement); + } + return false; + } + + /* + * @see Object#hashCode() + */ + public int hashCode() { + return fDocument.hashCode(); + } + + /* + * @see IDocumentListener#documentChanged(DocumentEvent) + */ + public void documentChanged(DocumentEvent event) { + fCanBeSaved= true; + removeUnchangedElementListeners(fElement, this); + fireElementDirtyStateChanged(fElement, fCanBeSaved); + } + + /* + * @see IDocumentListener#documentAboutToBeChanged(DocumentEvent) + */ + public void documentAboutToBeChanged(DocumentEvent event) { + } + }; + + /** + * Constant for representing the ok status. This is considered a value object. + */ + static final protected IStatus STATUS_OK= new Status(IStatus.OK, FileBuffersPlugin.PLUGIN_ID, IStatus.OK, "AbstractDocumentProvider.ok", null); + /** + * Constant for representing the error status. This is considered a value object. + */ + static final protected IStatus STATUS_ERROR= new Status(IStatus.ERROR, FileBuffersPlugin.PLUGIN_ID, IStatus.INFO, "AbstractDocumentProvider.error", null); + + + /** Element information of all connected elements */ + private Map fElementInfoMap= new HashMap(); + /** The element state listeners */ + private List fElementStateListeners= new ArrayList(); + /** The current progress monitor */ + private IProgressMonitor fProgressMonitor; + + + /** + * Creates a new document provider. + */ + protected AbstractDocumentProvider2() { + } + + /** + * Creates the document for the given element. + * <p> + * Subclasses must implement this method.</p> + * + * @param element the element + * @return the document + * @exception CoreException if the document could not be created + */ + protected abstract IDocument createDocument(Object element) throws CoreException; + + /** + * Performs the actual work of saving the given document provided for the given element. + * <p> + * Subclasses must implement this method.</p> + * + * @param element the element + * @param document the document + * @param overwrite indicates whether an overwrite should happen if necessary + * @exception CoreException if document could not be stored to the given element + */ + protected abstract void doSaveDocument(Object element, IDocument document, boolean overwrite) throws CoreException; + + + /** + * Returns the element info object for the given element. + * + * @param element the element + * @return the element info object, or <code>null</code> if none + */ + protected ElementInfo getElementInfo(Object element) { + return (ElementInfo) fElementInfoMap.get(element); + } + + /** + * Creates a new element info object for the given element. + * <p> + * This method is called from <code>connect</code> when an element info needs + * to be created. The <code>AbstractDocumentProvider</code> implementation + * of this method returns a new element info object whose document and + * annotation model are the values of <code>createDocument(element)</code> + * and <code>createAnnotationModel(element)</code>, respectively. Subclasses + * may override.</p> + * + * @param element the element + * @return a new element info object + * @exception CoreException if the document or annotation model could not be created + */ + protected ElementInfo createElementInfo(Object element) throws CoreException { + return new ElementInfo(createDocument(element)); + } + + /** + * Disposes the given element info object. + * <p> + * This method is called when an element info is disposed. The + * <code>AbstractDocumentProvider</code> implementation of this + * method does nothing. Subclasses may reimplement.</p> + * + * @param info the element info object + */ + protected void disposeElementInfo(ElementInfo info) { + } + + /** + * Called on initial creation and when the dirty state of the element + * changes to <code>false</code>. Adds all listeners which must be + * active as long as the element is not dirty. This method is called + * before <code>fireElementDirtyStateChanged</code> or <code> + * fireElementContentReplaced</code> is called. + * Subclasses may extend. + * + * @param element the element + * @param info the element info object + */ + protected void addUnchangedElementListeners(Object element, ElementInfo info) { + if (info.fDocument != null) + info.fDocument.addDocumentListener(info); + } + + /** + * Called when the given element gets dirty. Removes all listeners + * which must be active only when the element is not dirty. This + * method is called before <code>fireElementDirtyStateChanged</code> + * or <code>fireElementContentReplaced</code> is called. + * Subclasses may extend. + * + * @param element the element + * @param info the element info object + */ + protected void removeUnchangedElementListeners(Object element, ElementInfo info) { + if (info.fDocument != null) + info.fDocument.removeDocumentListener(info); + } + + /** + * Enumerates the elements connected via this document provider. + * + * @return the list of elements (element type: <code>Object</code>) + */ + protected Iterator getConnectedElementsIterator() { + Set s= new HashSet(); + Set keys= fElementInfoMap.keySet(); + if (keys != null) + s.addAll(keys); + return s.iterator(); + } + + /* + * @see IDocumentProvider#connect(Object) + */ + public final void connect(Object element) throws CoreException { + ElementInfo info= (ElementInfo) fElementInfoMap.get(element); + if (info == null) { + + info= createElementInfo(element); + if (info == null) + info= new ElementInfo(null); + + info.fElement= element; + + addUnchangedElementListeners(element, info); + + fElementInfoMap.put(element, info); + if (fElementInfoMap.size() == 1) + connected(); + } + ++ info.fReferenceCount; + } + + /** + * This hook method is called when this provider starts managing documents for + * elements. I.e. it is called when the first element gets connected to this provider. + * Subclasses may extend. + */ + protected void connected() { + } + + /* + * @see IDocumentProvider#disconnect + */ + public final void disconnect(Object element) { + ElementInfo info= (ElementInfo) fElementInfoMap.get(element); + + if (info == null) + return; + + if (info.fReferenceCount == 1) { + + fElementInfoMap.remove(element); + removeUnchangedElementListeners(element, info); + disposeElementInfo(info); + + if (fElementInfoMap.size() == 0) + disconnected(); + + } else + -- info.fReferenceCount; + } + + /** + * This hook method is called when this provider stops managing documents for + * element. I.e. it is called when the last element gets disconnected from this provider. + * Subcalles may extend. + */ + protected void disconnected() { + } + + /* + * @see IDocumentProvider#getDocument(Object) + */ + public IDocument getDocument(Object element) { + + if (element == null) + return null; + + ElementInfo info= (ElementInfo) fElementInfoMap.get(element); + return (info != null ? info.fDocument : null); + } + + /* + * @see org.eclipse.core.buffer.text.IDocumentProvider#getElement(org.eclipse.jface.text.IDocument) + */ + public Object getElement(IDocument document) { + Iterator e= fElementInfoMap.keySet().iterator(); + while (e.hasNext()) { + Object key= e.next(); + ElementInfo info= (ElementInfo) fElementInfoMap.get(key); + if (info != null && document == info.fDocument) + return info.fElement; + } + return null; + } + + /* + * @see IDocumentProvider#mustSaveDocument(Object) + */ + public boolean mustSaveDocument(Object element) { + + if (element == null) + return false; + + ElementInfo info= (ElementInfo) fElementInfoMap.get(element); + return (info != null ? info.fReferenceCount == 1 && info.fCanBeSaved : false); + } + + /* + * @see IDocumentProvider#canSaveDocument(Object) + */ + public boolean canSaveDocument(Object element) { + + if (element == null) + return false; + + ElementInfo info= (ElementInfo) fElementInfoMap.get(element); + return (info != null ? info.fCanBeSaved : false); + } + + /* + * @see IDocumentProvider#resetDocument(Object) + */ + public void restoreDocument(Object element) throws CoreException { + if (element == null) + return; + + ElementInfo info= (ElementInfo) fElementInfoMap.get(element); + if (info != null) { + + IDocument original= null; + IStatus status= null; + + try { + original= createDocument(element); + } catch (CoreException x) { + status= x.getStatus(); + } + + info.fStatus= status; + + if (original != null) { + + String originalContents= original.get(); + boolean replaceContents= !originalContents.equals(info.fDocument.get()); + + if (replaceContents) { + fireElementContentAboutToBeReplaced(element); + info.fDocument.set(original.get()); + } + + if (info.fCanBeSaved) { + info.fCanBeSaved= false; + addUnchangedElementListeners(element, info); + } + + if (replaceContents) + fireElementContentReplaced(element); + + fireElementDirtyStateChanged(element, false); + } + } + } + + /* + * @see IDocumentProvider#saveDocument(Object, boolean) + */ + public void saveDocument(Object element, boolean overwrite) throws CoreException { + + if (element == null) + return; + + ElementInfo info= (ElementInfo) fElementInfoMap.get(element); + if (info != null && info.fCanBeSaved) { + doSaveDocument(element, info.fDocument, overwrite); + info.fCanBeSaved= false; + addUnchangedElementListeners(element, info); + fireElementDirtyStateChanged(element, false); + } + } + + /* + * @see IDocumentProvider#addElementStateListener(IElementStateListener) + */ + public void addElementStateListener(IElementStateListener2 listener) { + Assert.isNotNull(listener); + if (!fElementStateListeners.contains(listener)) + fElementStateListeners.add(listener); + } + + /* + * @see IDocumentProvider#removeElementStateListener(IElementStateListener) + */ + public void removeElementStateListener(IElementStateListener2 listener) { + Assert.isNotNull(listener); + fElementStateListeners.remove(listener); + } + + /** + * Informs all registered element state listeners about a change in the + * dirty state of the given element. + * + * @param element the element + * @param isDirty the new dirty state + * @see IElementStateListener#elementDirtyStateChanged(Object, boolean) + */ + protected void fireElementDirtyStateChanged(Object element, boolean isDirty) { + Iterator e= new ArrayList(fElementStateListeners).iterator(); + while (e.hasNext()) { + IElementStateListener2 l= (IElementStateListener2) e.next(); + l.elementDirtyStateChanged(element, isDirty); + } + } + + /** + * Informs all registered element state listeners about an impending + * replace of the given element's content. + * + * @param element the element + * @see IElementStateListener#elementContentAboutToBeReplaced(Object) + */ + protected void fireElementContentAboutToBeReplaced(Object element) { + Iterator e= new ArrayList(fElementStateListeners).iterator(); + while (e.hasNext()) { + IElementStateListener2 l= (IElementStateListener2) e.next(); + l.documentContentAboutToBeReplaced(element); + } + } + + /** + * Informs all registered element state listeners about the just-completed + * replace of the given element's content. + * + * @param element the element + * @see IElementStateListener#elementContentReplaced(Object) + */ + protected void fireElementContentReplaced(Object element) { + Iterator e= new ArrayList(fElementStateListeners).iterator(); + while (e.hasNext()) { + IElementStateListener2 l= (IElementStateListener2) e.next(); + l.documentContentReplaced(element); + } + } + + /** + * Informs all registered element state listeners about a move. + * + * @param originalElement the element before the move + * @param movedElement the element after the move + * @see IElementStateListener#elementMoved(Object, Object) + */ + protected void fireElementMoved(Object originalElement, Object movedElement) { + Iterator e= new ArrayList(fElementStateListeners).iterator(); + while (e.hasNext()) { + IElementStateListener2 l= (IElementStateListener2) e.next(); + l.elementMoved(originalElement, movedElement); + } + } + + /** + * Informs all registered element state listeners about the deletion + * of the given element. + * + * @param element the element + * @see IElementStateListener#elementDeleted(Object) + */ + protected void fireElementDeleted(Object element) { + Iterator e= new ArrayList(fElementStateListeners).iterator(); + while (e.hasNext()) { + IElementStateListener2 l= (IElementStateListener2) e.next(); + l.elementDeleted(element); + } + } + + /* + * @see org.eclipse.core.buffer.text.IDocumentProvider#isStateValidated(java.lang.Object) + */ + public boolean isStateValidated(Object element) { + ElementInfo info= (ElementInfo) fElementInfoMap.get(element); + if (info != null) + return info.fIsStateValidated; + return false; + } + + /** + * Hook method for validating the state of the given element. Must not take care of cache updating etc. + * Default implementation is empty. + * + * @param element the element + * @param computationContext the context in which validation happens + * @exception CoreException in case validation fails + */ + protected void doValidateState(Object element, Object computationContext) throws CoreException { + } + + /* + * @see org.eclipse.core.buffer.text.IDocumentProvider#validateState(java.lang.Object, java.lang.Object) + */ + public void validateState(Object element, Object computationContext) throws CoreException { + ElementInfo info= (ElementInfo) fElementInfoMap.get(element); + if (info != null && !info.fIsStateValidated) { + + doValidateState(element, computationContext); + + doUpdateStateCache(element); + info.fIsStateValidated= true; + fireElementStateValidationChanged(element, true); + } + } + + /** + * Hook method for updating the state of the given element. + * Default implementation is empty. + * + * @param element the element + * @exception CoreException in case state cache updating fails + */ + protected void doUpdateStateCache(Object element) throws CoreException { + } + +// /** +// * Returns whether the state of the element must be invalidated given its +// * previous read-only state. +// * +// * @param element the element +// * @param wasReadOnly the previous read-only state +// * @return <code>true</code> if the state of the given element must be invalidated +// * @since 2.0 +// */ +// protected boolean invalidatesState(Object element, boolean wasReadOnly) { +// boolean readOnlyChanged= (isReadOnly(element) != wasReadOnly); +// return readOnlyChanged && !canSaveDocument(element); +// } + +// final public void updateStateCache(Object element) throws CoreException { +// ElementInfo info= (ElementInfo) fElementInfoMap.get(element); +// if (info != null) { +// boolean wasReadOnly= isReadOnly(element); +// doUpdateStateCache(element); +// if (invalidatesState(element, wasReadOnly)) { +// info.fIsStateValidated= false; +// fireElementStateValidationChanged(element, false); +// } +// } +// } + + +// public void setCanSaveDocument(Object element) { +// if (element != null) { +// ElementInfo info= (ElementInfo) fElementInfoMap.get(element); +// if (info != null) { +// info.fCanBeSaved= true; +// removeUnchangedElementListeners(element, info); +// fireElementDirtyStateChanged(element, info.fCanBeSaved); +// } +// } +// } + + /** + * Informs all registered element state listeners about a change in the + * state validation of the given element. + * + * @param element the element + * @param isStateValidated + */ + protected void fireElementStateValidationChanged(Object element, boolean isStateValidated) { + Iterator e= new ArrayList(fElementStateListeners).iterator(); + while (e.hasNext()) { + IElementStateListener2 l= (IElementStateListener2) e.next(); + l.elementStateValidationChanged(element, isStateValidated); + } + } + + /** + * Informs all registered element state listeners about the current state + * change of the element + * + * @param element the element + */ + protected void fireElementStateChanging(Object element) { + Iterator e= new ArrayList(fElementStateListeners).iterator(); + while (e.hasNext()) { + IElementStateListener2 l= (IElementStateListener2) e.next(); + l.elementStateChanging(element); + } + } + + /** + * Informs all registered element state listeners about the failed + * state change of the element + * + * @param element the element + */ + protected void fireElementStateChangeFailed(Object element) { + Iterator e= new ArrayList(fElementStateListeners).iterator(); + while (e.hasNext()) { + IElementStateListener2 l= (IElementStateListener2) e.next(); + l.elementStateChangeFailed(element); + } + } + + /* + * @see org.eclipse.core.buffer.text.IDocumentProvider#getStatus(java.lang.Object) + */ + public IStatus getStatus(Object element) { + ElementInfo info= (ElementInfo) fElementInfoMap.get(element); + if (info != null) { + if (info.fStatus != null) + return info.fStatus; + return (info.fDocument == null ? STATUS_ERROR : STATUS_OK); + } + + return STATUS_ERROR; + } + + /* + * @see org.eclipse.core.buffer.text.IDocumentProvider#getProgressMonitor() + */ + public IProgressMonitor getProgressMonitor() { + return fProgressMonitor == null ? new NullProgressMonitor() : fProgressMonitor; + } + + /* + * @see org.eclipse.core.buffer.text.IDocumentProvider#setProgressMonitor(org.eclipse.core.runtime.IProgressMonitor) + */ + public void setProgressMonitor(IProgressMonitor progressMonitor) { + fProgressMonitor= progressMonitor; + } +} diff --git a/org.eclipse.core.filebuffers/src/org/eclipse/core/internal/filebuffers/ContainerGenerator.java b/org.eclipse.core.filebuffers/src/org/eclipse/core/internal/filebuffers/ContainerGenerator.java new file mode 100644 index 000000000..9661c7c2a --- /dev/null +++ b/org.eclipse.core.filebuffers/src/org/eclipse/core/internal/filebuffers/ContainerGenerator.java @@ -0,0 +1,111 @@ +/********************************************************************** +Copyright (c) 2000, 2003 IBM Corp. 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://www.eclipse.org/legal/cpl-v10.html + +Contributors: + IBM Corporation - Initial implementation +**********************************************************************/ +package org.eclipse.core.internal.filebuffers; + +import org.eclipse.core.resources.IContainer; +import org.eclipse.core.resources.IFolder; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IWorkspace; +import org.eclipse.core.resources.IWorkspaceRoot; +import org.eclipse.core.resources.IWorkspaceRunnable; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.OperationCanceledException; +import org.eclipse.core.runtime.Path; +import org.eclipse.core.runtime.SubProgressMonitor; + +public class ContainerGenerator { + + private IPath fContainerFullPath; + private IContainer fContainer; + private IWorkspace fWorkspace; + + public ContainerGenerator(IWorkspace workspace, IPath containerPath) { + fWorkspace= workspace; + fContainerFullPath = containerPath; + } + + private IFolder createFolder(IFolder folderHandle, IProgressMonitor monitor) throws CoreException { + folderHandle.create(false, true, monitor); + if (monitor.isCanceled()) + throw new OperationCanceledException(); + return folderHandle; + } + + private IFolder createFolderHandle(IContainer container, String folderName) { + return container.getFolder(new Path(folderName)); + } + + private IProject createProject(IProject projectHandle, IProgressMonitor monitor) throws CoreException { + try { + monitor.beginTask("",2000);//$NON-NLS-1$ + + projectHandle.create(new SubProgressMonitor(monitor, 1000)); + if (monitor.isCanceled()) + throw new OperationCanceledException(); + + projectHandle.open(new SubProgressMonitor(monitor, 1000)); + if (monitor.isCanceled()) + throw new OperationCanceledException(); + + } finally { + monitor.done(); + } + + return projectHandle; + } + + private IProject createProjectHandle(IWorkspaceRoot root, String projectName) { + return root.getProject(projectName); + } + + public IContainer generateContainer(IProgressMonitor monitor) throws CoreException { + IWorkspaceRunnable runnable= new IWorkspaceRunnable() { + public void run(IProgressMonitor monitor) throws CoreException { + monitor.beginTask("creating container", 1000 * fContainerFullPath.segmentCount()); + if (fContainer != null) + return; + + // Does the container exist already? + IWorkspaceRoot root= fWorkspace.getRoot(); + fContainer= (IContainer) root.findMember(fContainerFullPath); + if (fContainer != null) + return; + + // Create the container for the given path + fContainer= root; + for (int i = 0; i < fContainerFullPath.segmentCount(); i++) { + String currentSegment = fContainerFullPath.segment(i); + IResource resource = fContainer.findMember(currentSegment); + if (resource != null) { + fContainer= (IContainer) resource; + monitor.worked(1000); + } + else { + if (i == 0) { + IProject projectHandle= createProjectHandle(root, currentSegment); + fContainer= createProject(projectHandle, new SubProgressMonitor(monitor,1000)); + } + else { + IFolder folderHandle= createFolderHandle(fContainer, currentSegment); + fContainer= createFolder(folderHandle, new SubProgressMonitor(monitor,1000)); + } + } + } + } + }; + + fWorkspace.run(runnable, monitor); + return fContainer; + } +} diff --git a/org.eclipse.core.filebuffers/src/org/eclipse/core/internal/filebuffers/DefaultDocumentFactory.java b/org.eclipse.core.filebuffers/src/org/eclipse/core/internal/filebuffers/DefaultDocumentFactory.java new file mode 100644 index 000000000..0a4973ab2 --- /dev/null +++ b/org.eclipse.core.filebuffers/src/org/eclipse/core/internal/filebuffers/DefaultDocumentFactory.java @@ -0,0 +1,32 @@ +/********************************************************************** +Copyright (c) 2000, 2003 IBM Corp. 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://www.eclipse.org/legal/cpl-v10.html + +Contributors: + IBM Corporation - Initial implementation +**********************************************************************/ +package org.eclipse.core.internal.filebuffers; + +import org.eclipse.core.filebuffers.IDocumentFactory; + +import org.eclipse.jface.text.Document; +import org.eclipse.jface.text.IDocument; + +/** + * The default document factory. + */ +public class DefaultDocumentFactory implements IDocumentFactory { + + public DefaultDocumentFactory() { + } + + /* + * @see org.eclipse.core.filebuffers.IDocumentFactory#createDocument() + */ + public IDocument createDocument() { + return new Document(); + } +} diff --git a/org.eclipse.core.filebuffers/src/org/eclipse/core/internal/filebuffers/ElementStateListener.java b/org.eclipse.core.filebuffers/src/org/eclipse/core/internal/filebuffers/ElementStateListener.java new file mode 100644 index 000000000..71ee41afc --- /dev/null +++ b/org.eclipse.core.filebuffers/src/org/eclipse/core/internal/filebuffers/ElementStateListener.java @@ -0,0 +1,102 @@ +/********************************************************************** +Copyright (c) 2000, 2003 IBM Corp. 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://www.eclipse.org/legal/cpl-v10.html + +Contributors: + IBM Corporation - Initial implementation +**********************************************************************/ +package org.eclipse.core.internal.filebuffers; + +import org.eclipse.core.filebuffers.IFileBuffer; +import org.eclipse.core.filebuffers.IFileBufferListener; +import org.eclipse.core.resources.IFile; + +/** + * + */ +public class ElementStateListener implements IElementStateListener2 { + + private IFileBufferListener fListener; + private IFileBuffer fFile; + + public ElementStateListener(IFileBufferListener bufferedFileListener, IFileBuffer file) { + fListener= bufferedFileListener; + fFile= file; + } + + private boolean isAffected(Object element) { + return element == fFile.getUnderlyingFile(); + } + + /* + * @see org.eclipse.core.buffer.internal.text.IElementStateListener2#elementDirtyStateChanged(java.lang.Object, boolean) + */ + public void elementDirtyStateChanged(Object element, boolean isDirty) { + if (isAffected(element)) + fListener.dirtyStateChanged(fFile, isDirty); + } + + + /* + * @see org.eclipse.core.buffer.internal.text.IElementStateListener2#documentContentAboutToBeReplaced(java.lang.Object) + */ + public void documentContentAboutToBeReplaced(Object element) { + if (isAffected(element)) + fListener.bufferContentAboutToBeReplaced(fFile); + } + + /* + * @see org.eclipse.core.buffer.internal.text.IElementStateListener2#documentContentReplaced(java.lang.Object) + */ + public void documentContentReplaced(Object element) { + if (isAffected(element)) + fListener.bufferContentReplaced(fFile); + } + + /* + * @see org.eclipse.core.buffer.internal.text.IElementStateListener2#elementStateValidationChanged(java.lang.Object, boolean) + */ + public void elementStateValidationChanged(Object element, boolean isStateValidated) { + if (isAffected(element)) + fListener.stateValidationChanged(fFile, isStateValidated); + } + + /* + * @see org.eclipse.core.buffer.internal.text.IElementStateListener2#elementStateChanging(java.lang.Object) + */ + public void elementStateChanging(Object element) { + if (isAffected(element)) + fListener.stateChanging(fFile); + } + + /* + * @see org.eclipse.core.buffer.internal.text.IElementStateListener2#elementStateChangeFailed(java.lang.Object) + */ + public void elementStateChangeFailed(Object element) { + if (isAffected(element)) + fListener.stateChangeFailed(fFile); + } + + public IFileBufferListener getBufferedListener() { + return fListener; + } + + /* + * @see org.eclipse.core.buffer.internal.text.IElementStateListener2#elementMoved(java.lang.Object, java.lang.Object) + */ + public void elementMoved(Object originalElement, Object movedElement) { + if (isAffected(originalElement)) + fListener.underlyingFileMoved(fFile, (IFile) movedElement); + } + + /* + * @see org.eclipse.core.buffer.internal.text.IElementStateListener2#elementDeleted(java.lang.Object) + */ + public void elementDeleted(Object element) { + if (isAffected(element)) + fListener.underlyingFileDeleted(fFile); + } +} diff --git a/org.eclipse.core.filebuffers/src/org/eclipse/core/internal/filebuffers/ExtensionsRegistry.java b/org.eclipse.core.filebuffers/src/org/eclipse/core/internal/filebuffers/ExtensionsRegistry.java new file mode 100644 index 000000000..631f87e88 --- /dev/null +++ b/org.eclipse.core.filebuffers/src/org/eclipse/core/internal/filebuffers/ExtensionsRegistry.java @@ -0,0 +1,232 @@ +/******************************************************************************* + * Copyright (c) 2000, 2003 IBM Corporation 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://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.core.internal.filebuffers; + + + +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.StringTokenizer; + +import org.eclipse.core.filebuffers.IDocumentFactory; +import org.eclipse.core.filebuffers.IDocumentSetupParticipant; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.IExtensionPoint; +import org.eclipse.core.runtime.ILog; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.Status; + + +/** + * This registry manages shareable document factories. Document factories are specified + * in <code>plugin.xml</code> per file name extension. + */ +public class ExtensionsRegistry { + + private final static String WILDCARD= "*"; //$NON-NLS-1$ + + /** The mapping between name extensions and configuration elements describing document factories. */ + private Map fFactoryDescriptors= new HashMap(); + /** The mapping between configuration elements for document factories and instantiated document factories. */ + private Map fFactories= new HashMap(); + /** The mapping between name extensions and configuration elements describing document setup participants. */ + private Map fSetupParticipantDescriptors= new HashMap(); + /** The mapping between configuration elements for setup participants and instantiated setup participants. */ + private Map fSetupParticipants= new HashMap(); + + + /** + * Creates a new document factory registry and intializes it with the information + * found in the plugin registry. + */ + public ExtensionsRegistry() { + initialize("documentCreation", "extensions", fFactoryDescriptors); //$NON-NLS-1$ //$NON-NLS-2$ + initialize("documentSetup", "extensions", fSetupParticipantDescriptors); + } + + /** + * Reads the comma-separated value of the given configuration element + * for the given attribute name and remembers the configuration element + * in the given map under the individual tokens of the attribute value. + */ + private void read(String attributeName, IConfigurationElement element, Map map) { + String value= element.getAttribute(attributeName); + if (value != null) { + StringTokenizer tokenizer= new StringTokenizer(value, ","); //$NON-NLS-1$ + while (tokenizer.hasMoreTokens()) { + String token= tokenizer.nextToken().trim(); + + Set s= (Set) map.get(token); + if (s == null) { + s= new HashSet(); + map.put(token, s); + } + s.add(element); + } + } + } + + /** + * Adds an entry to the log of this plugin for the given status + * @param status the status to log + */ + private void log(IStatus status) { + ILog log= Platform.getPlugin(FileBuffersPlugin.PLUGIN_ID).getLog(); + log.log(status); + } + + /** + * Initializes this registry. It retrieves all implementers of the given + * extension point and remembers those implementers based on the + * file name extensions in the given map. + * + * @param extensionPointName the name of the extension point + * @param childElementName the name of the child elements + * @param descriptors the map to be filled + */ + private void initialize(String extensionPointName, String childElementName, Map descriptors) { + + IExtensionPoint extensionPoint= Platform.getPluginRegistry().getExtensionPoint(FileBuffersPlugin.PLUGIN_ID, extensionPointName); + if (extensionPoint == null) { + log(new Status(IStatus.ERROR, FileBuffersPlugin.PLUGIN_ID, 0, MessageFormat.format("Extension point \"{0}\" not found.", new Object[] { extensionPointName}), null)); + return; + } + + IConfigurationElement[] elements= extensionPoint.getConfigurationElements(); + for (int i= 0; i < elements.length; i++) + read(childElementName, elements[i], descriptors); + } + + /** + * Returns the executable extension for the given configuration element. + * If there is no instantiated extension remembered for this + * element, a new extension is created and put into the cache if it is of the requested type. + * + * @param entry the configuration element + * @param extensions the map of instantiated extensions + * @param extensionType the requested result type + */ + private Object getExtension(IConfigurationElement entry, Map extensions, Class extensionType) { + Object extension= extensions.get(entry); + if (extension != null) + return extension; + + try { + extension= entry.createExecutableExtension("class"); //$NON-NLS-1$ + } catch (CoreException x) { + log(x.getStatus()); + } + + if (extensionType.isInstance(extension)) { + extensions.put(entry, extension); + return extension; + } + + return null; + } + + /** + * Returns the first enumerated element of the given set. + * + * @param set the set from which to choose + */ + private IConfigurationElement selectConfigurationElement(Set set) { + if (set != null && !set.isEmpty()) { + Iterator e= set.iterator(); + return (IConfigurationElement) e.next(); + } + return null; + } + + /** + * Returns a shareable document factory for the given file name extension. + * + * @param extension the name extension to be used for lookup + * @return the shareable document factory or <code>null</code> + */ + private IDocumentFactory getDocumentFactory(String extension) { + + Set set= (Set) fFactoryDescriptors.get(extension); + if (set != null) { + IConfigurationElement entry= selectConfigurationElement(set); + return (IDocumentFactory) getExtension(entry, fFactories, IDocumentFactory.class); + } + return null; + } + + /** + * Returns the set of setup participants for the given file name. + * + * @param extension the name extension to be used for lookup + * @return the shareable set of document setup participants + */ + private List getDocumentSetupParticipants(String extension) { + + Set set= (Set) fSetupParticipantDescriptors.get(extension); + if (set == null) + return null; + + List participants= new ArrayList(); + Iterator e= set.iterator(); + while (e.hasNext()) { + IConfigurationElement entry= (IConfigurationElement) e.next(); + Object participant= getExtension(entry, fSetupParticipants, IDocumentSetupParticipant.class); + if (participant != null) + participants.add(participant); + } + + return participants; + } + + /** + * Returns the shareable document factory for the given file. + * + * @param file the file for whose type the factory is looked up + * @return the shareable document factory + */ + public IDocumentFactory getDocumentFactory(IFile file) { + IDocumentFactory factory= getDocumentFactory(file.getFileExtension()); + if (factory == null) + factory= getDocumentFactory(WILDCARD); + return factory; + } + + /** + * Returns the shareable set of document setup participants for the given file. + * + * @param file the file for which to look up the setup participants + * @return the shareable set of document setup participants + */ + public IDocumentSetupParticipant[] getDocumentSetupParticipants(IFile file) { + List participants= new ArrayList(); + + List p= getDocumentSetupParticipants(file.getFileExtension()); + if (p != null) + participants.addAll(p); + + p= getDocumentSetupParticipants(WILDCARD); + if (p != null) + participants.addAll(p); + + IDocumentSetupParticipant[] result= new IDocumentSetupParticipant[participants.size()]; + participants.toArray(result); + return result; + } +} diff --git a/org.eclipse.core.filebuffers/src/org/eclipse/core/internal/filebuffers/FileBuffer.java b/org.eclipse.core.filebuffers/src/org/eclipse/core/internal/filebuffers/FileBuffer.java new file mode 100644 index 000000000..baef6f00f --- /dev/null +++ b/org.eclipse.core.filebuffers/src/org/eclipse/core/internal/filebuffers/FileBuffer.java @@ -0,0 +1,140 @@ +/********************************************************************** +Copyright (c) 2000, 2003 IBM Corp. 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://www.eclipse.org/legal/cpl-v10.html + +Contributors: + IBM Corporation - Initial implementation +**********************************************************************/ +package org.eclipse.core.internal.filebuffers; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.eclipse.core.filebuffers.IFileBuffer; +import org.eclipse.core.filebuffers.IFileBufferListener; +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.jface.text.Assert; + +/** + * + */ +public class FileBuffer implements IFileBuffer { + + private IFile fFile; + private FileDocumentProvider2 fDocumentProvider; + private List fElementStateListeners= new ArrayList(); + + /** + * + */ + public FileBuffer(IFile file, FileDocumentProvider2 documentProvider) { + super(); + fFile= file; + fDocumentProvider= documentProvider; + } + + protected FileDocumentProvider2 getDocumentProvider() { + return fDocumentProvider; + } + + /* + * @see org.eclipse.core.buffer.text.IBufferedFile#getUnderlyingFile() + */ + public IFile getUnderlyingFile() { + return fFile; + } + + private ElementStateListener getStateListener(IFileBufferListener listener) { + Iterator e= fElementStateListeners.iterator(); + while (e.hasNext()) { + ElementStateListener s= (ElementStateListener) e.next(); + if (s.getBufferedListener() == listener) + return s; + } + return null; + } + + /* + * @see org.eclipse.core.buffer.text.IBufferedFile#addBufferedFileListener(org.eclipse.core.buffer.text.IBufferedFileListener) + */ + public void addFileBufferListener(IFileBufferListener listener) { + Assert.isNotNull(listener); + ElementStateListener stateListener= getStateListener(listener); + if (stateListener == null) { + stateListener= new ElementStateListener(listener, this); + fElementStateListeners.add(stateListener); + } + fDocumentProvider.addElementStateListener(stateListener); + } + + /* + * @see org.eclipse.core.buffer.text.IBufferedFile#removeBufferedFileListener(org.eclipse.core.buffer.text.IBufferedFileListener) + */ + public void removeFileBufferListener(IFileBufferListener listener) { + Assert.isNotNull(listener); + ElementStateListener stateListener= getStateListener(listener); + if (stateListener != null) { + fDocumentProvider.removeElementStateListener(stateListener); + fElementStateListeners.remove(stateListener); + } + } + + /* + * @see org.eclipse.core.buffer.text.IBufferedFile#revert(org.eclipse.core.runtime.IProgressMonitor) + */ + public void revert(IProgressMonitor monitor) throws CoreException { + IProgressMonitor previous= fDocumentProvider.getProgressMonitor(); + fDocumentProvider.setProgressMonitor(monitor); + fDocumentProvider.restoreDocument(fFile); + fDocumentProvider.setProgressMonitor(previous); + } + + /* + * @see org.eclipse.core.buffer.text.IBufferedFile#commit(org.eclipse.core.runtime.IProgressMonitor, boolean) + */ + public void commit(IProgressMonitor monitor, boolean overwrite) throws CoreException { + IProgressMonitor previous= fDocumentProvider.getProgressMonitor(); + fDocumentProvider.setProgressMonitor(monitor); + fDocumentProvider.saveDocument(fFile, overwrite); + fDocumentProvider.setProgressMonitor(previous); + } + + /* + * @see org.eclipse.core.buffer.text.IBufferedFile#isDirty() + */ + public boolean isDirty() { + return fDocumentProvider.canSaveDocument(fFile); + } + + /* + * @see org.eclipse.core.buffer.text.IBufferedFile#validateState(org.eclipse.core.runtime.IProgressMonitor, java.lang.Object) + */ + public void validateState(IProgressMonitor monitor, Object computationContext) throws CoreException { + IProgressMonitor previous= fDocumentProvider.getProgressMonitor(); + fDocumentProvider.setProgressMonitor(monitor); + fDocumentProvider.validateState(fFile, computationContext); + fDocumentProvider.setProgressMonitor(previous); + } + + /* + * @see org.eclipse.core.buffer.text.IBufferedFile#isStateValidated() + */ + public boolean isStateValidated() { + return fDocumentProvider.isStateValidated(fFile); + } + + /* + * @see org.eclipse.core.buffer.text.IBufferedFile#getStatus() + */ + public IStatus getStatus() { + return fDocumentProvider.getStatus(fFile); + } +} diff --git a/org.eclipse.core.filebuffers/src/org/eclipse/core/internal/filebuffers/FileBuffersPlugin.java b/org.eclipse.core.filebuffers/src/org/eclipse/core/internal/filebuffers/FileBuffersPlugin.java new file mode 100644 index 000000000..0a6443549 --- /dev/null +++ b/org.eclipse.core.filebuffers/src/org/eclipse/core/internal/filebuffers/FileBuffersPlugin.java @@ -0,0 +1,84 @@ +package org.eclipse.core.internal.filebuffers; + +import java.util.MissingResourceException; +import java.util.ResourceBundle; + +import org.eclipse.core.filebuffers.ITextFileBufferManager; +import org.eclipse.core.resources.IWorkspace; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.IPluginDescriptor; +import org.eclipse.core.runtime.Plugin; + + +/** + * The main plugin class to be used in the desktop. + */ +public class FileBuffersPlugin extends Plugin { + + public final static String PLUGIN_ID= "org.eclipse.core.filebuffers"; //$NON-NLS-1$ + + /** The shared plug-in instance */ + private static FileBuffersPlugin fgPlugin; + /** The resource bundle */ + private ResourceBundle fResourceBundle; + /** The file buffer manager */ + private ITextFileBufferManager fTextFileBufferManager; + + /** + * The constructor. + */ + public FileBuffersPlugin(IPluginDescriptor descriptor) { + super(descriptor); + fgPlugin = this; + try { + fResourceBundle= ResourceBundle.getBundle("org.eclipse.core.buffer.internal,text.TextBufferPluginResources"); //$NON-NLS-1$ + } catch (MissingResourceException x) { + fResourceBundle = null; + } + } + + /** + * Returns the shared instance. + */ + public static FileBuffersPlugin getDefault() { + return fgPlugin; + } + + /** + * Returns the workspace instance. + */ + public static IWorkspace getWorkspace() { + return ResourcesPlugin.getWorkspace(); + } + + /** + * Returns the string from the plugin's resource bundle, + * or 'key' if not found. + */ + public static String getResourceString(String key) { + ResourceBundle bundle= FileBuffersPlugin.getDefault().getResourceBundle(); + try { + return (bundle!=null ? bundle.getString(key) : key); + } catch (MissingResourceException e) { + return key; + } + } + + /** + * Returns the plugin's resource bundle, + */ + public ResourceBundle getResourceBundle() { + return fResourceBundle; + } + + /** + * Returns the text file buffer manager of this plug-in. + * + * @return the text file buffer manager of this plug-in + */ + public ITextFileBufferManager getBufferedFileManager() { + if (fTextFileBufferManager == null) + fTextFileBufferManager= new TextFileBufferManager(); + return fTextFileBufferManager; + } +} diff --git a/org.eclipse.core.filebuffers/src/org/eclipse/core/internal/filebuffers/FileDocumentProvider2.java b/org.eclipse.core.filebuffers/src/org/eclipse/core/internal/filebuffers/FileDocumentProvider2.java new file mode 100644 index 000000000..796c4e052 --- /dev/null +++ b/org.eclipse.core.filebuffers/src/org/eclipse/core/internal/filebuffers/FileDocumentProvider2.java @@ -0,0 +1,588 @@ +/******************************************************************************* + * Copyright (c) 2000, 2003 IBM Corporation 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://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.core.internal.filebuffers; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; + +import org.eclipse.core.filebuffers.IDocumentFactory; +import org.eclipse.core.filebuffers.IDocumentSetupParticipant; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IResourceChangeEvent; +import org.eclipse.core.resources.IResourceChangeListener; +import org.eclipse.core.resources.IResourceDelta; +import org.eclipse.core.resources.IResourceDeltaVisitor; +import org.eclipse.core.resources.IResourceStatus; +import org.eclipse.core.resources.IWorkspace; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.OperationCanceledException; +import org.eclipse.core.runtime.QualifiedName; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.SubProgressMonitor; + +import org.eclipse.jface.text.IDocument; + + +/** + * Shareable document provider specialized for file resources (<code>IFile</code>). + * <p> + * This class may be instantiated or be subclassed.</p> + */ +public class FileDocumentProvider2 extends StorageDocumentProvider2 { + + /** + * Qualified name for the encoding key. + */ + private static final QualifiedName ENCODING_KEY = new QualifiedName(FileBuffersPlugin.PLUGIN_ID, "encoding"); //$NON-NLS-1$ //$NON-NLS-2$ + + + /** + * Runnable encapsulating an element state change. This runnable ensures + * that a element change failed message is sent out to the element state + * listeners in case an exception occurred. + */ + protected class SafeResourceChange implements Runnable { + + /** The resource that changes. */ + private IResource fChangedResource; + + /** + * Creates a new safe runnable for the given resource. + * + * @param resource the resource that changes + */ + public SafeResourceChange(IResource resource) { + fChangedResource= resource; + } + + /** + * @return the resource + */ + public IResource getChangedResource() { + return fChangedResource; + } + + /** + * Execute the change. + * Subclass responsibility. + * + * @exception an exception in case of error + */ + protected void execute() throws Exception { + } + + /* + * @see java.lang.Runnable#run() + */ + public void run() { + + if (getElementInfo(fChangedResource) == null) { + fireElementStateChangeFailed(fChangedResource); + return; + } + + try { + execute(); + } catch (Exception x) { + fireElementStateChangeFailed(fChangedResource); + } + } + }; + + + /** + * Synchronizes the document with external resource changes. + */ + protected class ResourceSynchronizer implements IResourceChangeListener, IResourceDeltaVisitor { + + /** The resource. */ + protected IResource fSynchronizedResource; + /** A flag indicating whether this synchronizer is installed or not. */ + protected boolean fIsInstalled= false; + + /** + * Creates a new resource synchronizer. Is not yet installed on a resource. + * + * @param resource the resource with which the document is to be synchronized + */ + public ResourceSynchronizer(IResource resource) { + fSynchronizedResource= resource; + }; + + /** + * Returns the resource associated with this synchronizer. + * + * @return the resource associated with this synchronizer + */ + protected IResource getSynchronizedResource() { + return fSynchronizedResource; + } + + /** + * Installs the synchronizer on the resource. + */ + public void install() { + getSynchronizedResource().getWorkspace().addResourceChangeListener(this); + fIsInstalled= true; + } + + /** + * Uninstalls the synchronizer from the resource. + */ + public void uninstall() { + getSynchronizedResource().getWorkspace().removeResourceChangeListener(this); + fIsInstalled= false; + } + + /* + * @see IResourceChangeListener#resourceChanged(IResourceChangeEvent) + */ + public void resourceChanged(IResourceChangeEvent e) { + IResourceDelta delta= e.getDelta(); + try { + if (delta != null && fIsInstalled) + delta.accept(this); + } catch (CoreException x) { + handleCoreException(x, "FileDocumentProvider.resourceChanged"); + } + } + + /* + * @see IResourceDeltaVisitor#visit(org.eclipse.core.resources.IResourceDelta) + */ + public boolean visit(IResourceDelta delta) throws CoreException { + + if (delta != null && getSynchronizedResource().equals(delta.getResource())) { + + Runnable runnable= null; + + switch (delta.getKind()) { + case IResourceDelta.CHANGED: + if ((IResourceDelta.CONTENT & delta.getFlags()) != 0) { + ResourceInfo info= (ResourceInfo) getElementInfo(fSynchronizedResource); + if (info != null && !info.fCanBeSaved && fSynchronizedResource.isSynchronized(IResource.DEPTH_ZERO)) { + runnable= new SafeResourceChange(fSynchronizedResource) { + protected void execute() throws Exception { + IResource r= getChangedResource(); + ResourceInfo i= (ResourceInfo) getElementInfo(r); + if (i.fModificationStamp != r.getModificationStamp()) + handleElementContentChanged(getChangedResource()); + } + }; + } + } + break; + case IResourceDelta.REMOVED: + if ((IResourceDelta.MOVED_TO & delta.getFlags()) != 0) { + final IPath path= delta.getMovedToPath(); + runnable= new SafeResourceChange(fSynchronizedResource) { + protected void execute() throws Exception { + handleElementMoved(getChangedResource(), path); + } + }; + } else { + ResourceInfo info= (ResourceInfo) getElementInfo(fSynchronizedResource); + if (info != null && !info.fCanBeSaved) { + runnable= new SafeResourceChange(fSynchronizedResource) { + protected void execute() throws Exception { + handleElementDeleted(getChangedResource()); + } + }; + } + } + break; + } + + if (runnable != null) + update(runnable); + } + + return true; // because we are sitting on files anyway + } + + /** + * Posts the update code "behind" the running operation. + * + * @param runnable the update code + */ + protected void update(Runnable runnable) { + if (runnable instanceof SafeResourceChange) + fireElementStateChanging(fSynchronizedResource); + // TODO post behind operation + runnable.run(); + } + }; + + + + /** + * Bundle of all required information to allow resources as underlying document content providers. + */ + protected class ResourceInfo extends StorageInfo { + + /** The resource synchronizer. */ + public ResourceSynchronizer fResourceSynchronizer; + /** The time stamp at which this provider changed the file. */ + public long fModificationStamp= IResource.NULL_STAMP; + + /** + * Creates and returns a new resource info. + * + * @param document the document + * @param resourceSynchronizer the file synchronizer + */ + public ResourceInfo(IDocument document, ResourceSynchronizer resourceSynchronizer) { + super(document); + fResourceSynchronizer= resourceSynchronizer; + } + }; + + + /** The document factory registry for this document provider */ + private ExtensionsRegistry fRegistry; + + + /** + * Creates and returns a new document provider. + */ + public FileDocumentProvider2(ExtensionsRegistry registry) { + super(); + fRegistry= registry; + } + + /** + * Checks whether the given resource is synchronized with the the local file system. + * If the resource has been changed, a <code>CoreException</code> is thrown. + * + * @param resource the resource to check + * @exception CoreException if resource has been changed on the file system + */ + protected void checkSynchronizationState(IResource resource) throws CoreException { + if (!resource.isSynchronized(IResource.DEPTH_ZERO)) { + Status status= new Status(IStatus.ERROR, FileBuffersPlugin.PLUGIN_ID, IResourceStatus.OUT_OF_SYNC_LOCAL, "FileDocumentProvider.error.out_of_sync", null); + throw new CoreException(status); + } + } + + /* + * @see AbstractDocumentProvider#doSaveDocument(IProgressMonitor, Object, IDocument, boolean) + */ + protected void doSaveDocument(Object element, IDocument document, boolean overwrite) throws CoreException { + if (element instanceof IResource) { + + try { + + String encoding= getEncoding(element); + if (encoding == null) + encoding= getDefaultEncoding(); + InputStream stream= new ByteArrayInputStream(document.get().getBytes(encoding)); + IFile file= (IFile) element; + + if (file.exists()) { + + ResourceInfo info= (ResourceInfo) getElementInfo(element); + + if (info != null && !overwrite) + checkSynchronizationState(file); + + // inform about the upcoming content change + fireElementStateChanging(element); + try { + + // here the resource synchronizer should actually be removed and afterwards added again. However, + // we are already inside an operation, so the delta is sent AFTER we have added the listener + file.setContents(stream, overwrite, true, getProgressMonitor()); + // set modification stamp to know whether the resource synchronizer must become active + info.fModificationStamp= file.getModificationStamp(); + + } 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 and we don't have to do + // it manually + + // if there is an annotation model update it here + + } else { + IProgressMonitor monitor= getProgressMonitor(); + try { + monitor.beginTask("FileDocumentProvider.task.saving", 2000); //$NON-NLS-1$ + ContainerGenerator generator = new ContainerGenerator(file.getWorkspace(), 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, FileBuffersPlugin.PLUGIN_ID, IStatus.OK, x.getMessage(), x); + throw new CoreException(s); + } + + } else { + super.doSaveDocument(element, document, overwrite); + } + } + + /* + * @see org.eclipse.core.internal.filebuffers.StorageDocumentProvider2#createEmptyDocument(java.lang.Object) + */ + public IDocument createEmptyDocument(Object element) { + if (element instanceof IFile) { + IDocumentFactory factory= fRegistry.getDocumentFactory((IFile) element); + + IDocument document= null; + if (factory != null) + document= factory.createDocument(); + else + document= super.createEmptyDocument(element); + + IDocumentSetupParticipant[] participants= fRegistry.getDocumentSetupParticipants((IFile) element); + if (participants != null) { + for (int i= 0; i < participants.length; i++) + participants[i].setup(document); + } + + return document; + } + return super.createEmptyDocument(element); + } + + /* + * @see AbstractDocumentProvider#createElementInfo(Object) + */ + protected ElementInfo createElementInfo(Object element) throws CoreException { + if (element instanceof IResource) { + + try { + refreshResource((IResource) element); + } catch (CoreException x) { + handleCoreException(x, "FileDocumentProvider.createElementInfo"); + } + + IDocument d= null; + IStatus s= null; + + try { + d= createDocument(element); + } catch (CoreException x) { + s= x.getStatus(); + d= createEmptyDocument(element); + } + + ResourceSynchronizer f= new ResourceSynchronizer((IResource) element); + f.install(); + + ResourceInfo info= new ResourceInfo(d, f); + info.fStatus= s; + info.fEncoding= getPersistedEncoding(element); + + return info; + } + + return super.createElementInfo(element); + } + + /* + * @see AbstractDocumentProvider#disposeElementInfo(ElementInfo) + */ + protected void disposeElementInfo(ElementInfo info) { + if (info instanceof ResourceInfo) { + ResourceInfo resourceInfo= (ResourceInfo) info; + if (resourceInfo.fResourceSynchronizer != null) + resourceInfo.fResourceSynchronizer.uninstall(); + } + + super.disposeElementInfo(info); + } + + /** + * Updates the element info to a change of the file content and sends out appropriate notifications. + * + * @param object the changed object + */ + protected void handleElementContentChanged(IResource resource) { + ResourceInfo info= (ResourceInfo) getElementInfo(resource); + if (info == null) + return; + + IDocument document= createEmptyDocument(resource); + IStatus status= null; + + try { + +// Should not be neccessary. +// +// try { +// refreshResource(resource); +// } catch (CoreException x) { +// handleCoreException(x, "FileDocumentProvider.handleElementContentChanged"); //$NON-NLS-1$ +// } + + if (resource instanceof IFile) { + IFile file= (IFile) resource; + setDocumentContent(document, file.getContents(false), info.fEncoding); + } + + } catch (CoreException x) { + status= x.getStatus(); + } + + String newContent= document.get(); + + if ( !newContent.equals(info.fDocument.get())) { + + // set the new content and fire content related events + fireElementContentAboutToBeReplaced(resource); + + removeUnchangedElementListeners(resource, info); + + info.fDocument.removeDocumentListener(info); + info.fDocument.set(newContent); + info.fCanBeSaved= false; + info.fStatus= status; + + addUnchangedElementListeners(resource, info); + + fireElementContentReplaced(resource); + + } else { + + removeUnchangedElementListeners(resource, info); + + // fires only the dirty state related event + info.fCanBeSaved= false; + info.fStatus= status; + + addUnchangedElementListeners(resource, info); + + fireElementDirtyStateChanged(resource, false); + } + } + + /** + * Sends out the notification that the file serving as document input has been moved. + * + * @param resource the changed resource + * @param path the path of the new location of the file + */ + protected void handleElementMoved(IResource resource, IPath path) { + IWorkspace workspace= ResourcesPlugin.getWorkspace(); + IFile newFile= workspace.getRoot().getFile(path); + fireElementMoved(resource, newFile); + } + + /** + * Sends out the notification that the file serving as document input has been deleted. + * + * @param resource the deleted resource + */ + protected void handleElementDeleted(IResource resource) { + fireElementDeleted(resource); + } + + /* + * @see AbstractDocumentProvider#doValidateState(Object, Object) + */ + protected void doValidateState(Object element, Object computationContext) throws CoreException { + + if (element instanceof IResource) { + ResourceInfo info= (ResourceInfo) getElementInfo(element); + if (info != null) { + IResource resource= (IResource) element; + if (resource.isReadOnly() && resource instanceof IFile) { + IWorkspace workspace= resource.getWorkspace(); + workspace.validateEdit(new IFile[] { (IFile) resource }, computationContext); + } + } + } + + super.doValidateState(element, computationContext); + } + + /* + * @see IDocumentProvider#resetDocument(Object) + */ + public void restoreDocument(Object element) throws CoreException { + if (element instanceof IResource) { + try { + refreshResource((IResource) element); + } catch (CoreException x) { + handleCoreException(x, "FileDocumentProvider.resetDocument"); + } + } + super.restoreDocument(element); + } + + /** + * Refreshes the given resource. + * + * @param resource the resource to be refreshed + * @throws a CoreException if the refresh fails + */ + protected void refreshResource(IResource resource) throws CoreException { + try { + resource.refreshLocal(IResource.DEPTH_INFINITE, getProgressMonitor()); + } catch (OperationCanceledException x) { + } + } + + // --------------- Encoding support --------------- + + /** + * Returns the persited encoding for the given element. + * + * @param element the element for which to get the persisted encoding + */ + protected String getPersistedEncoding(Object element) { + if (element instanceof IResource) { + try { + IResource resource= (IResource) element; + return resource.getPersistentProperty(ENCODING_KEY); + } catch (CoreException ex) { + return null; + } + } + return super.getPersistedEncoding(element); + } + + /** + * Persists the given encoding for the given element. + * + * @param element the element for which to store the persisted encoding + * @param encoding the encoding + */ + protected void persistEncoding(Object element, String encoding) throws CoreException { + if (element instanceof IResource) { + IResource resource= (IResource) element; + resource.setPersistentProperty(ENCODING_KEY, encoding); + } else { + super.persistEncoding(element, encoding); + } + } +} diff --git a/org.eclipse.core.filebuffers/src/org/eclipse/core/internal/filebuffers/IDocumentProvider2.java b/org.eclipse.core.filebuffers/src/org/eclipse/core/internal/filebuffers/IDocumentProvider2.java new file mode 100644 index 000000000..c43a0f0a4 --- /dev/null +++ b/org.eclipse.core.filebuffers/src/org/eclipse/core/internal/filebuffers/IDocumentProvider2.java @@ -0,0 +1,200 @@ +/******************************************************************************* + * Copyright (c) 2000, 2003 IBM Corporation 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://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.core.internal.filebuffers; + + + + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; + +import org.eclipse.jface.text.IDocument; + + + +/** + * A document provider maps between domain elements and documents. + * A document provider has the following responsibilities: + * <ul> + * <li> create an annotation model of a domain model element + * <li> create and manage a textual representation, i.e., a document, of a domain model element + * <li> create and save the content of domain model elements based on given documents + * <li> update the documents this document provider manages for domain model elements + * to changes directly applied to those domain model elements + * <li> notify all element state listeners about changes directly applied to domain model + * elements this document provider manages a document for, i.e. the document + * provider must know which changes of a domain model element are to be interpreted + * as element moves, deletes, etc. + * </ul> + * Text editors use document providers to bridge the gap between their input elements and the + * documents they work on. A single document provider may be shared between multiple editors; + * the methods take the editors' input elements as a parameter. + * <p> + * This interface may be implemented by clients; or subclass the standard + * abstract base class <code>AbstractDocumentProvider</code>.</p> + * + * @see org.eclipse.jface.text.IDocument + * @see org.eclipse.ui.texteditor.AbstractDocumentProvider + */ +public interface IDocumentProvider2 { + + /** + * Adds the given element state listener to this document provider. + * Has no effect if an identical listener is already registered. + * + * @param listener the listener + */ + void addElementStateListener(IElementStateListener2 listener); + + /** + * Removes the given element state listener from this document provider. + * Has no affect if an identical listener is not registered. + * + * @param listener the listener + */ + void removeElementStateListener(IElementStateListener2 listener); + + + /** + * Connects the given element to this document provider. This tells the provider + * that caller of this method is interested to work with the document provided for + * the given domain model element. By counting the invokations of this method and + * <code>disconnect(Object)</code> this provider can assume to know the + * correct number of clients working with the document provided for that + * domain model element. <p> + * The given element must not be <code>null</code>. + * + * @param element the element + * @exception CoreException if the textual representation or the annotation model + * of the element could not be created + */ + void connect(Object element) throws CoreException; + + /** + * Disconnects the given element from this document provider. This tells the provider + * that the caller of this method is no longer interested in working with the document + * provided for the given domain model element. By counting the invokations of + * <code>connect(Object)</code> and of this method this provider can assume to + * know the correct number of clients working with the document provided for that + * domain model element. <p> + * The given element must not be <code>null</code>. + * + * @param element the element + */ + void disconnect(Object element); + + /** + * Returns the document for the given element. Usually the document contains + * a textual presentation of the content of the element, or is the element itself. + * + * @param element the element, or <code>null</code> + * @return the document, or <code>null</code> if none + */ + IDocument getDocument(Object element); + + /** + * Creates a new empty document for the given element. The document is afterwards not + * managed by this provider. + * + * @param element the element + * @return the newly created document, or <code>null</code> if this is not possible + */ + IDocument createEmptyDocument(Object element); + + /** + * Returns the element that is the origin of the given document. + * + * @param document the given document + * @return the element or <code>null</code> if none + */ + Object getElement(IDocument document); + + /** + * Resets the given element's document to its last saved state. + * Element state listeners are notified both before (<code>elementContentAboutToBeReplaced</code>) + * and after (<code>elementContentReplaced</code>) the content is changed. + * + * @param element the element, or <code>null</code> + */ + void restoreDocument(Object element) throws CoreException; + + /** + * Saves the given document provided for the given element. + * + * @param monitor a progress monitor to report progress and request cancelation + * @param element the element, or <code>null</code> + * @param document the document + * @param overwrite indicates whether overwrite should be performed + * while saving the given element if necessary + * @exception CoreException if document could not be stored to the given element + */ + void saveDocument(Object element, boolean overwrite) throws CoreException; + + /** + * Returns whether the document provided for the given element must be saved. + * + * @param element the element, or <code>null</code> + * @return <code>true</code> if the document must be saved, and + * <code>false</code> otherwise (including the element is <code>null</code>) + */ + boolean mustSaveDocument(Object element); + + /** + * Returns whether the document provided for the given element differs from + * its original state which would required that it be saved. + * + * @param element the element, or <code>null</code> + * @return <code>true</code> if the document can be saved, and + * <code>false</code> otherwise (including the element is <code>null</code>) + */ + boolean canSaveDocument(Object element); + + /** + * Validates the state of the given element. This method may change the "real" state of the + * element. If using, it also updates the internal caches, so that this method may also change + * the results returned by <code>isReadOnly</code> and <code>isModifiable</code>. If the + * given element is not connected to this document provider, the effect is undefined. + * + * @param element the element + * @param computationContext the context in which the computation is performed, e.g., a SWT shell + * @exception CoreException if validating fails + */ + void validateState(Object element, Object computationContext) throws CoreException; + + /** + * Returns whether the state of the given element has been validated. + * + * @param element the element + * @return <code>true</code> if the state has been validated + */ + boolean isStateValidated(Object element); + + /** + * Returns the status of the given element. + * + * @param element the element + * @return the status of the given element + */ + IStatus getStatus(Object element); + + /** + * Sets this providers progress monitor. + * @param progressMonitor + */ + void setProgressMonitor(IProgressMonitor progressMonitor); + + /** + * Returns this providers progress monitor. + * @return IProgressMonitor + */ + IProgressMonitor getProgressMonitor(); +} diff --git a/org.eclipse.core.filebuffers/src/org/eclipse/core/internal/filebuffers/IElementStateListener2.java b/org.eclipse.core.filebuffers/src/org/eclipse/core/internal/filebuffers/IElementStateListener2.java new file mode 100644 index 000000000..be7e1e6a3 --- /dev/null +++ b/org.eclipse.core.filebuffers/src/org/eclipse/core/internal/filebuffers/IElementStateListener2.java @@ -0,0 +1,89 @@ +/******************************************************************************* + * Copyright (c) 2000, 2003 IBM Corporation 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://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.core.internal.filebuffers; + + +/** + * Interface for parties interested in standardized element changes. These + * changes are: + * <ul> + * <li> dirty state changes + * <li> content replacements + * <li> moves + * <li> deletions + * </ul> + * The notifications sent to the element state listeners inform about those standardized, + * abstract changes. The concrete change applied might differ from the one the listeners + * are notified about, but should be interpreted as the one the listeners receive. + */ +public interface IElementStateListener2 { + + /** + * Notifies that the dirty state of the given element has changed. + * + * @param element the element + * @param isDirty the new dirty state + */ + void elementDirtyStateChanged(Object element, boolean isDirty); + + /** + * Notifies that the content of the given element is about to be replaced. + * + * @param element the element + */ + void documentContentAboutToBeReplaced(Object element); + + /** + * Notifies that the content of the given element has been replaced. + * + * @param element the element + */ + void documentContentReplaced(Object element); + + /** + * Notifies that the element has moved. If <code>movedElement</code> + * is <code>null</code> it is similar to <code>elementDeleted(originalElement)</code>. + * + * @param originalElement the element before the move + * @param movedElement the element after the move + */ + void elementMoved(Object originalElement, Object movedElement); + + /** + * Notifies that the given element has been deleted. + * + * @param element the element + */ + void elementDeleted(Object element); + + /** + * Notifies that the state validation of the given element has changed. + * + * @param element the element + * @param isStateValidated the flag indicating whether state validation is done + */ + void elementStateValidationChanged(Object element, boolean isStateValidated); + + /** + * Notifies that the given element is currently being changed. This method may + * be sent from a non-ui thread. + * + * @param element the element + */ + void elementStateChanging(Object element); + + /** + * Notifies that changing the given element has failed. + * + * @param element the element + */ + void elementStateChangeFailed(Object element); +} diff --git a/org.eclipse.core.filebuffers/src/org/eclipse/core/internal/filebuffers/IStorageDocumentProvider2.java b/org.eclipse.core.filebuffers/src/org/eclipse/core/internal/filebuffers/IStorageDocumentProvider2.java new file mode 100644 index 000000000..721ea5eb3 --- /dev/null +++ b/org.eclipse.core.filebuffers/src/org/eclipse/core/internal/filebuffers/IStorageDocumentProvider2.java @@ -0,0 +1,45 @@ +/******************************************************************************* + * Copyright (c) 2000, 2003 IBM Corporation 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://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.core.internal.filebuffers; + + +/** + * Document provider for <code>IStorage</code> based domain elements. + * Basically incorporates the concept of character encoding. + */ +public interface IStorageDocumentProvider2 { + + /** + * Returns the default character encoding used by this provider. + * + * @return the default character encoding used by this provider + */ + String getDefaultEncoding(); + + /** + * Returns the character encoding for the given element, or + * <code>null</code> if the element is not managed by this provider. + * + * @param element the element + * @return the encoding for the given element + */ + String getEncoding(Object element); + + /** + * Sets the encoding for the given element. If <code>encoding</code> + * is <code>null</code> the workbench's character encoding should be used. + * + * @param element the element + * @param encoding the encoding to be used + */ + void setEncoding(Object element, String encoding); +} diff --git a/org.eclipse.core.filebuffers/src/org/eclipse/core/internal/filebuffers/StorageDocumentProvider2.java b/org.eclipse.core.filebuffers/src/org/eclipse/core/internal/filebuffers/StorageDocumentProvider2.java new file mode 100644 index 000000000..0236cd208 --- /dev/null +++ b/org.eclipse.core.filebuffers/src/org/eclipse/core/internal/filebuffers/StorageDocumentProvider2.java @@ -0,0 +1,240 @@ +/******************************************************************************* + * Copyright (c) 2000, 2003 IBM Corporation 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://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.core.internal.filebuffers; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; + +import org.eclipse.core.resources.IStorage; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.ILog; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.Status; + +import org.eclipse.jface.text.Document; +import org.eclipse.jface.text.IDocument; + + +/** + * Shareable document provider specialized for <code>IStorage</code>s. + */ +public class StorageDocumentProvider2 extends AbstractDocumentProvider2 implements IStorageDocumentProvider2 { + + /** + * Reader chunk size. + */ + protected final static int READER_CHUNK_SIZE= 2048; + + /** + * Buffer size. + */ + protected final static int BUFFER_SIZE= 8 * READER_CHUNK_SIZE; + + + /** + * Bundle of all required information to allow <code>IStorage</code> as underlying document resources. + */ + protected class StorageInfo extends ElementInfo { + + /** The encoding used to create the document from the storage or <code>null</code> for workbench encoding. */ + public String fEncoding= null; + + /** + * Creates a new storage info. + * + * @param document the document + */ + public StorageInfo(IDocument document) { + super(document); + } + }; + + /** + * Creates a new document provider. + */ + public StorageDocumentProvider2() { + super(); + } + + /** + * Intitializes the given document with the given stream using the given encoding. + * + * @param document the document to be initialized + * @param contentStream the stream which delivers the document content + * @param encoding the character encoding for reading the given stream + * @exception CoreException if the given stream can not be read + */ + protected void setDocumentContent(IDocument document, InputStream contentStream, String encoding) throws CoreException { + + Reader in= null; + + try { + + if (encoding == null) + encoding= getDefaultEncoding(); + + in= new BufferedReader(new InputStreamReader(contentStream, encoding), BUFFER_SIZE); + StringBuffer buffer= new StringBuffer(BUFFER_SIZE); + char[] readBuffer= new char[READER_CHUNK_SIZE]; + int n= in.read(readBuffer); + while (n > 0) { + buffer.append(readBuffer, 0, n); + n= in.read(readBuffer); + } + + document.set(buffer.toString()); + + } catch (IOException x) { + String msg= x.getMessage() == null ? "" : x.getMessage(); //$NON-NLS-1$ + IStatus s= new Status(IStatus.ERROR, FileBuffersPlugin.PLUGIN_ID, IStatus.OK, msg, x); + throw new CoreException(s); + } finally { + if (in != null) { + try { + in.close(); + } catch (IOException x) { + } + } + } + } + + /* + * @see org.eclipse.core.internal.filebuffers.IDocumentProvider2#createEmptyDocument(java.lang.Object) + */ + public IDocument createEmptyDocument(Object element) { + return new Document(); + } + + /* + * @see AbstractDocumentProvider#createDocument(Object) + */ + protected IDocument createDocument(Object element) throws CoreException { + + if (element instanceof IStorage) { + IStorage storage= (IStorage) element; + IDocument document= createEmptyDocument(element); + setDocumentContent(document, storage.getContents(), getEncoding(element)); + return document; + } + + return null; + } + + /* + * @see AbstractDocumentProvider#createElementInfo(Object) + */ + protected ElementInfo createElementInfo(Object element) throws CoreException { + if (element instanceof IStorage) { + + IDocument document= null; + IStatus status= null; + + try { + document= createDocument(element); + } catch (CoreException x) { + status= x.getStatus(); + document= createEmptyDocument(element); + } + + StorageInfo info= new StorageInfo(document); + info.fStatus= status; + info.fEncoding= getPersistedEncoding(element); + + return info; + } + + return super.createElementInfo(element); + } + + /* + * @see AbstractDocumentProvider#doSaveDocument(IProgressMonitor, Object, IDocument, boolean) + */ + protected void doSaveDocument(Object element, IDocument document, boolean overwrite) throws CoreException { + } + + /** + * Defines the standard procedure to handle <code>CoreExceptions</code>. Exceptions + * are written to the plug-in log. + * + * @param exception the exception to be logged + * @param message the message to be logged + * @since 2.0 + */ + protected void handleCoreException(CoreException exception, String message) { + ILog log= Platform.getPlugin(FileBuffersPlugin.PLUGIN_ID).getLog(); + + if (message != null) + log.log(new Status(IStatus.ERROR, FileBuffersPlugin.PLUGIN_ID, 0, message, exception)); + else + log.log(exception.getStatus()); + } + + /* + * @see IStorageDocumentProvider#getDefaultEncoding() + */ + public String getDefaultEncoding() { + return ResourcesPlugin.getEncoding(); + } + + /* + * @see IStorageDocumentProvider#getEncoding(Object) + */ + public String getEncoding(Object element) { + if (element instanceof IStorage) { + StorageInfo info= (StorageInfo) getElementInfo(element); + if (info != null) + return info.fEncoding; + else + return getPersistedEncoding(element); + } + return null; + } + + /* + * @see IStorageDocumentProvider#setEncoding(Object, String) + */ + public void setEncoding(Object element, String encoding) { + if (element instanceof IStorage) { + StorageInfo info= (StorageInfo) getElementInfo(element); + if (info != null) { + info.fEncoding= encoding; + try { + persistEncoding(element, encoding); + } catch (CoreException x) { + } + } + } + } + + /** + * Returns the persited encoding for the given element. + * + * @param element the element for which to get the persisted encoding + */ + protected String getPersistedEncoding(Object element) { + return null; + } + + /** + * Persists the given encoding for the given element. + * + * @param element the element for which to store the persisted encoding + * @param encoding the encoding + */ + protected void persistEncoding(Object element, String encoding) throws CoreException { + } +} diff --git a/org.eclipse.core.filebuffers/src/org/eclipse/core/internal/filebuffers/TextFileBuffer.java b/org.eclipse.core.filebuffers/src/org/eclipse/core/internal/filebuffers/TextFileBuffer.java new file mode 100644 index 000000000..f7bfc8e0a --- /dev/null +++ b/org.eclipse.core.filebuffers/src/org/eclipse/core/internal/filebuffers/TextFileBuffer.java @@ -0,0 +1,47 @@ +/********************************************************************** +Copyright (c) 2000, 2003 IBM Corp. 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://www.eclipse.org/legal/cpl-v10.html + +Contributors: + IBM Corporation - Initial implementation +**********************************************************************/ +package org.eclipse.core.internal.filebuffers; + +import org.eclipse.core.filebuffers.ITextFileBuffer; +import org.eclipse.core.resources.IFile; + +import org.eclipse.jface.text.IDocument; + +/** + * + */ +public class TextFileBuffer extends FileBuffer implements ITextFileBuffer { + + public TextFileBuffer(IFile file, FileDocumentProvider2 documentProvider) { + super(file, documentProvider); + } + + /* + * @see org.eclipse.core.buffer.text.IBufferedTextFile#getDocument() + */ + public IDocument getDocument() { + return getDocumentProvider().getDocument(getUnderlyingFile()); + } + + /* + * @see org.eclipse.core.buffer.text.IBufferedTextFile#getEncoding() + */ + public String getEncoding() { + return getDocumentProvider().getEncoding(getUnderlyingFile()); + } + + /* + * @see org.eclipse.core.buffer.text.IBufferedTextFile#setEncoding(java.lang.String) + */ + public void setEncoding(String encoding) { + getDocumentProvider().setEncoding(getUnderlyingFile(), encoding); + } +} diff --git a/org.eclipse.core.filebuffers/src/org/eclipse/core/internal/filebuffers/TextFileBufferManager.java b/org.eclipse.core.filebuffers/src/org/eclipse/core/internal/filebuffers/TextFileBufferManager.java new file mode 100644 index 000000000..3c7bbdabb --- /dev/null +++ b/org.eclipse.core.filebuffers/src/org/eclipse/core/internal/filebuffers/TextFileBufferManager.java @@ -0,0 +1,88 @@ +/********************************************************************** +Copyright (c) 2000, 2003 IBM Corp. 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://www.eclipse.org/legal/cpl-v10.html + +Contributors: + IBM Corporation - Initial implementation +**********************************************************************/ +package org.eclipse.core.internal.filebuffers; + +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.core.filebuffers.IFileBuffer; +import org.eclipse.core.filebuffers.ITextFileBuffer; +import org.eclipse.core.filebuffers.ITextFileBufferManager; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.runtime.CoreException; + +import org.eclipse.jface.text.Assert; +import org.eclipse.jface.text.IDocument; + +/** + * + */ +public class TextFileBufferManager implements ITextFileBufferManager { + + private FileDocumentProvider2 fFileDocumentProvider; + private Map fManagedFiles= new HashMap(); + + public TextFileBufferManager() { + fFileDocumentProvider= new FileDocumentProvider2(new ExtensionsRegistry()); + } + + /* + * @see org.eclipse.core.buffer.text.IBufferedFileManager#connect(org.eclipse.core.resources.IFile) + */ + public void connect(IFile file) throws CoreException { + Assert.isNotNull(file); + IFileBuffer bufferedFile= getTextFileBuffer(file); + if (bufferedFile == null) { + bufferedFile= createBufferedFile(file); + fManagedFiles.put(file, bufferedFile); + } + fFileDocumentProvider.connect(file); + } + + protected FileBuffer createBufferedFile(IFile file) { + return isTextFile(file) ? new TextFileBuffer(file, fFileDocumentProvider) : new FileBuffer(file, fFileDocumentProvider); + } + + protected boolean isTextFile(IFile file) { + return true; + } + + /* + * @see org.eclipse.core.buffer.text.IBufferedFileManager#disconnect(org.eclipse.core.resources.IFile) + */ + public void disconnect(IFile file) throws CoreException { + Assert.isNotNull(file); + fFileDocumentProvider.disconnect(file); + if (fFileDocumentProvider.getDocument(file) == null) + fManagedFiles.remove(file); + } + + /* + * @see org.eclipse.core.buffer.text.IBufferedFileManager#getBufferedFile(org.eclipse.core.resources.IFile) + */ + public ITextFileBuffer getTextFileBuffer(IFile file) { + return (ITextFileBuffer) fManagedFiles.get(file); + } + + /* + * @see org.eclipse.core.buffer.text.IBufferedFileManager#getDefaultEncoding() + */ + public String getDefaultEncoding() { + return fFileDocumentProvider.getDefaultEncoding(); + } + + /* + * @see org.eclipse.core.filebuffers.ITextFileBufferManager#createEmptyDocument(org.eclipse.core.resources.IFile) + */ + public IDocument createEmptyDocument(IFile file) { + return fFileDocumentProvider.createEmptyDocument(file); + } +} |