e596c7e21ef29523f96b61751fb58299115dca62
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / corext / textmanipulation / TextBufferFactory.java
1 /*
2  * (c) Copyright IBM Corp. 2000, 2001.
3  * All Rights Reserved.
4  */
5 package net.sourceforge.phpdt.internal.corext.textmanipulation;
6
7 import java.io.BufferedInputStream;
8 import java.io.IOException;
9 import java.io.InputStream;
10 import java.io.InputStreamReader;
11 import java.util.HashMap;
12 import java.util.Map;
13
14 import net.sourceforge.phpeclipse.PHPeclipsePlugin;
15 import org.eclipse.core.resources.IFile;
16 import org.eclipse.core.resources.IWorkspaceRunnable;
17 import org.eclipse.core.resources.ResourcesPlugin;
18 import org.eclipse.core.runtime.CoreException;
19 import org.eclipse.core.runtime.IProgressMonitor;
20 import org.eclipse.core.runtime.IStatus;
21 import org.eclipse.core.runtime.Status;
22 import net.sourceforge.phpdt.internal.corext.util.IOCloser;
23 import net.sourceforge.phpdt.internal.ui.PHPStatusConstants;
24 import org.eclipse.jface.text.Document;
25 import org.eclipse.jface.text.IDocument;
26 import org.eclipse.jface.text.source.IAnnotationModel;
27 import org.eclipse.jface.util.Assert;
28 import org.eclipse.ui.part.FileEditorInput;
29 import org.eclipse.ui.texteditor.IDocumentProvider;
30
31 /* package */ class TextBufferFactory {
32
33         private IDocumentProvider fDocumentProvider;
34         private Map fFileValueMap;
35         private Map fBufferValueMap;
36         
37         private static class Value {
38                 TextBuffer buffer;
39                 FileEditorInput input;
40                 IDocument document;
41                 IAnnotationModel annotationModel;
42                 int references;
43                 public Value(TextBuffer b, FileEditorInput i, IDocument d, IAnnotationModel m) {
44                         buffer= b;
45                         input= i;
46                         document= d;
47                         annotationModel= m;
48                 }
49         }
50
51         public TextBufferFactory() {
52                 // XXX http://dev.eclipse.org/bugs/show_bug.cgi?id=5170
53                 // Need way to map a file to a document without knowing any kind of document provider.
54                 this(PHPeclipsePlugin.getDefault().getCompilationUnitDocumentProvider());
55         }
56         
57         public TextBufferFactory(IDocumentProvider provider) {
58                 fDocumentProvider= provider;
59                 Assert.isNotNull(fDocumentProvider);
60                 fFileValueMap= new HashMap(5);
61                 fBufferValueMap= new HashMap(5);
62         }
63
64         public TextBuffer acquire(IFile file) throws CoreException {
65                 FileEditorInput input= new FileEditorInput(file);       
66                 
67                 Value value= (Value)fFileValueMap.get(input);
68                 if (value != null) {
69                         value.references++;
70                         return value.buffer;
71                 }
72                 
73                 fDocumentProvider.connect(input);
74                 IDocument document= fDocumentProvider.getDocument(input);
75                 IAnnotationModel annotationModel= fDocumentProvider.getAnnotationModel(input);
76                 annotationModel.connect(document);
77                 value= new Value(new TextBuffer(document), input, document, annotationModel);
78                 fFileValueMap.put(input, value);
79                 fBufferValueMap.put(value.buffer, value);
80                 value.references++;
81                 return value.buffer;
82         }
83         
84         public void release(TextBuffer buffer) {
85                 final Value value= (Value)fBufferValueMap.get(buffer);
86                 if (value == null)
87                         return;
88                                                 
89                 value.references--;
90                 if (value.references == 0) {
91                         buffer.release();       
92                         value.annotationModel.disconnect(value.document);
93                         fDocumentProvider.disconnect(value.input);
94                         fFileValueMap.remove(value.input);
95                         fBufferValueMap.remove(buffer);
96                 }
97         }
98         
99         public void commitChanges(TextBuffer buffer, boolean force, IProgressMonitor pm) throws CoreException {
100                 final Value value= (Value)fBufferValueMap.get(buffer);
101                 if (value == null)
102                         return;
103                 
104                 boolean save= force || fDocumentProvider.mustSaveDocument(value.input);
105                 if (save) {
106                         IWorkspaceRunnable action= new IWorkspaceRunnable() {
107                                 public void run(IProgressMonitor pm) throws CoreException {
108                                         fDocumentProvider.aboutToChange(value.input);
109                                         fDocumentProvider.saveDocument(pm, value.input, value.document, true);
110                                 }
111                         };
112                         try {
113                                 ResourcesPlugin.getWorkspace().run(action, pm);
114                         } finally {
115                                 fDocumentProvider.changed(value.input);
116                         }
117                 }
118         }
119         
120         public TextBuffer create(IFile file) throws CoreException {
121                 FileEditorInput input= new FileEditorInput(file);       
122                 IDocument document= fDocumentProvider.getDocument(input);
123                 if (document != null) {
124                         return new TextBuffer(new Document(document.get()));
125                 } else {
126                         return createFromFile(file);
127                 }
128         }
129
130         private TextBuffer createFromFile(IFile file) throws CoreException {
131                 IDocument document;
132                 // Fix for http://dev.eclipse.org/bugs/show_bug.cgi?id=19319
133                 InputStream stream= file.getContents();
134                 InputStreamReader in= null;
135                 try {           
136                         document= new Document();
137                         in= new InputStreamReader(new BufferedInputStream(stream), ResourcesPlugin.getEncoding());
138                         StringBuffer buffer= new StringBuffer();
139                         char[] readBuffer= new char[2048];
140                         int n= in.read(readBuffer);
141                         while (n > 0) {
142                                 buffer.append(readBuffer, 0, n);
143                                 n= in.read(readBuffer);
144                         }
145                         document.set(buffer.toString());
146                         return new TextBuffer(document);
147                 } catch (IOException x) {
148                         IStatus s= new Status(IStatus.ERROR, PHPeclipsePlugin.getPluginId(), PHPStatusConstants.INTERNAL_ERROR, x.getMessage(), x);
149                         throw new CoreException(s);
150                 } finally {
151                         IOCloser.perform(in, stream);
152                 }
153         }
154         
155         public TextBuffer create(String content) {
156                 return new TextBuffer(new Document(content));
157         }
158         
159         public void save(TextBuffer buffer, IProgressMonitor pm) throws CoreException {
160                 Value value= (Value)fBufferValueMap.get(buffer);
161                 if (value == null)
162                         throwNotManaged();
163                 fDocumentProvider.saveDocument(pm, value.input, value.document, true);
164         }
165
166         public void aboutToChange(TextBuffer buffer) throws CoreException {
167                 Value value= (Value)fBufferValueMap.get(buffer);
168                 if (value == null)
169                         throwNotManaged();
170                 fDocumentProvider.aboutToChange(value.input);
171         }
172                 
173         public void changed(TextBuffer buffer) throws CoreException {
174                 Value value= (Value)fBufferValueMap.get(buffer);
175                 if (value == null)
176                         throwNotManaged();
177                 fDocumentProvider.changed(value.input);
178         }
179         
180         private void throwNotManaged() throws CoreException {
181                 IStatus s= new Status(IStatus.ERROR, PHPeclipsePlugin.getPluginId(), 
182                         PHPStatusConstants.INTERNAL_ERROR, TextManipulationMessages.getString("TextBufferFactory.bufferNotManaged"), null); //$NON-NLS-1$
183                 throw new CoreException(s);
184         }
185 }
186