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