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