KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > core > internal > registry > TableWriter


1 /*******************************************************************************
2  * Copyright (c) 2004, 2006 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.core.internal.registry;
12
13 import java.io.*;
14 import java.util.*;
15 import org.eclipse.core.runtime.*;
16 import org.eclipse.core.runtime.spi.RegistryContributor;
17
18 public class TableWriter {
19     private static final byte fileError = 0;
20
21     File mainDataFile;
22     File extraDataFile;
23     File tableFile;
24     File contributionsFile;
25     File contributorsFile;
26     File namespacesFile;
27     File orphansFile;
28
29     void setMainDataFile(File main) {
30         mainDataFile = main;
31     }
32
33     void setExtraDataFile(File extra) {
34         extraDataFile = extra;
35     }
36
37     void setTableFile(File table) {
38         tableFile = table;
39     }
40
41     void setContributionsFile(File fileName) {
42         contributionsFile = fileName;
43     }
44
45     void setContributorsFile(File fileName) {
46         contributorsFile = fileName;
47     }
48
49     void setNamespacesFile(File fileName) {
50         namespacesFile = fileName;
51     }
52
53     void setOrphansFile(File orphan) {
54         orphansFile = orphan;
55     }
56
57     DataOutputStream mainOutput;
58     DataOutputStream extraOutput;
59     FileOutputStream mainFileOutput = null;
60     FileOutputStream extraFileOutput = null;
61
62     private HashtableOfInt offsets;
63
64     private ExtensionRegistry registry;
65     private RegistryObjectManager objectManager;
66
67     public TableWriter(ExtensionRegistry registry) {
68         this.registry = registry;
69     }
70
71     private int getExtraDataPosition() {
72         return extraOutput.size();
73     }
74
75     public boolean saveCache(RegistryObjectManager objectManager, long timestamp) {
76         this.objectManager = objectManager;
77         try {
78             if (!openFiles())
79                 return false;
80             try {
81                 saveExtensionRegistry(timestamp);
82             } catch (IOException io) {
83                 log(new Status(IStatus.ERROR, RegistryMessages.OWNER_NAME, fileError, RegistryMessages.meta_registryCacheWriteProblems, io));
84                 return false;
85             }
86         } finally {
87             closeFiles();
88         }
89         return true;
90     }
91
92     private boolean openFiles() {
93         try {
94             mainFileOutput = new FileOutputStream(mainDataFile);
95             mainOutput = new DataOutputStream(new BufferedOutputStream(mainFileOutput));
96             extraFileOutput = new FileOutputStream(extraDataFile);
97             extraOutput = new DataOutputStream(new BufferedOutputStream(extraFileOutput));
98         } catch (FileNotFoundException e) {
99             if (mainFileOutput != null)
100                 try {
101                     mainFileOutput.close();
102                 } catch (IOException e1) {
103                     //Ignore
104
}
105
106             log(new Status(IStatus.ERROR, RegistryMessages.OWNER_NAME, fileError, RegistryMessages.meta_unableToCreateCache, e));
107             return false;
108         }
109         return true;
110     }
111
112     private void closeFiles() {
113         try {
114             if (mainOutput != null) {
115                 mainOutput.flush();
116                 if (mainFileOutput.getFD().valid()) {
117                     mainFileOutput.getFD().sync();
118                 }
119                 mainOutput.close();
120             }
121         } catch (IOException e) {
122             log(new Status(IStatus.ERROR, RegistryMessages.OWNER_NAME, fileError, RegistryMessages.meta_registryCacheWriteProblems, e));
123             e.printStackTrace();
124         }
125         try {
126             if (extraOutput != null) {
127                 extraOutput.flush();
128                 if (extraFileOutput.getFD().valid()) {
129                     extraFileOutput.getFD().sync();
130                 }
131                 extraOutput.close();
132             }
133         } catch (IOException e) {
134             log(new Status(IStatus.ERROR, RegistryMessages.OWNER_NAME, fileError, RegistryMessages.meta_registryCacheWriteProblems, e));
135             e.printStackTrace();
136         }
137     }
138
139     private void saveExtensionRegistry(long timestamp) throws IOException {
140         ExtensionPointHandle[] points = objectManager.getExtensionPointsHandles();
141         offsets = new HashtableOfInt(objectManager.getNextId());
142         for (int i = 0; i < points.length; i++) {
143             saveExtensionPoint(points[i]);
144         }
145         saveOrphans();
146         saveContributions(objectManager.getContributions());
147         saveContributors(objectManager.getContributors());
148         saveNamespaces(objectManager.getNamespacesIndex());
149         closeFiles(); //Close the files here so we can write the appropriate size information in the table file.
150
saveTables(timestamp); //Write the table last so if that is something went wrong we can know
151
}
152
153     private void saveContributions(KeyedHashSet[] contributions) throws IOException {
154         FileOutputStream fosNamespace = new FileOutputStream(contributionsFile);
155         DataOutputStream outputNamespace = new DataOutputStream(new BufferedOutputStream(fosNamespace));
156         KeyedElement[] newElements = contributions[0].elements();
157         KeyedElement[] formerElements = contributions[1].elements();
158
159         // get count of contributions that will be cached
160
int cacheSize = 0;
161         for (int i = 0; i < newElements.length; i++) {
162             if (((Contribution) newElements[i]).shouldPersist())
163                 cacheSize++;
164         }
165         for (int i = 0; i < formerElements.length; i++) {
166             if (((Contribution) formerElements[i]).shouldPersist())
167                 cacheSize++;
168         }
169         outputNamespace.writeInt(cacheSize);
170
171         for (int i = 0; i < newElements.length; i++) {
172             Contribution element = (Contribution) newElements[i];
173             if (element.shouldPersist()) {
174                 writeStringOrNull(element.getContributorId(), outputNamespace);
175                 saveArray(filterContributionChildren(element), outputNamespace);
176             }
177         }
178         for (int i = 0; i < formerElements.length; i++) {
179             Contribution element = (Contribution) formerElements[i];
180             if (element.shouldPersist()) {
181                 writeStringOrNull(element.getContributorId(), outputNamespace);
182                 saveArray(filterContributionChildren(element), outputNamespace);
183             }
184         }
185         outputNamespace.flush();
186         fosNamespace.getFD().sync();
187         outputNamespace.close();
188     }
189
190     // Contribution has raw children in a unique format that combines extensions and extension points.
191
// To filter, need to dis-assmeble, filter, and then re-assemble its raw children
192
private int[] filterContributionChildren(Contribution element) {
193         int[] extensionPoints = filter(element.getExtensionPoints());
194         int[] extensions = filter(element.getExtensions());
195         int[] filteredRawChildren = new int[2 + extensionPoints.length + extensions.length];
196         System.arraycopy(extensionPoints, 0, filteredRawChildren, 2, extensionPoints.length);
197         System.arraycopy(extensions, 0, filteredRawChildren, 2 + extensionPoints.length, extensions.length);
198         filteredRawChildren[Contribution.EXTENSION_POINT] = extensionPoints.length;
199         filteredRawChildren[Contribution.EXTENSION] = extensions.length;
200         return filteredRawChildren;
201     }
202
203     private void saveNamespaces(KeyedHashSet namespacesIndex) throws IOException {
204         FileOutputStream fosNamespace = new FileOutputStream(namespacesFile);
205         DataOutputStream outputNamespace = new DataOutputStream(new BufferedOutputStream(fosNamespace));
206         KeyedElement[] elements = namespacesIndex.elements();
207
208         KeyedElement[] cachedElements = new KeyedElement[elements.length];
209         int cacheSize = 0;
210         for (int i = 0; i < elements.length; i++) {
211             RegistryIndexElement element = (RegistryIndexElement) elements[i];
212             int[] extensionPoints = filter(element.getExtensionPoints());
213             int[] extensions = filter(element.getExtensions());
214             if (extensionPoints.length == 0 && extensions.length == 0)
215                 continue;
216             RegistryIndexElement cachedElement = new RegistryIndexElement((String JavaDoc) element.getKey(), extensionPoints, extensions);
217             cachedElements[cacheSize] = cachedElement;
218             cacheSize++;
219         }
220
221         outputNamespace.writeInt(cacheSize);
222         for (int i = 0; i < cacheSize; i++) {
223             RegistryIndexElement element = (RegistryIndexElement) cachedElements[i];
224             writeStringOrNull((String JavaDoc) element.getKey(), outputNamespace);
225             saveArray(element.getExtensionPoints(), outputNamespace); // it was pre-filtered as we counted the number of elements
226
saveArray(element.getExtensions(), outputNamespace); // it was pre-filtered as we counted the number of elements
227
}
228         outputNamespace.flush();
229         fosNamespace.getFD().sync();
230         outputNamespace.close();
231     }
232
233     private void saveContributors(HashMap contributors) throws IOException {
234         FileOutputStream fosContributors = new FileOutputStream(contributorsFile);
235         DataOutputStream outputContributors = new DataOutputStream(new BufferedOutputStream(fosContributors));
236
237         Collection entries = contributors.values();
238         outputContributors.writeInt(entries.size());
239
240         for (Iterator i = entries.iterator(); i.hasNext();) {
241             RegistryContributor contributor = (RegistryContributor) i.next();
242             writeStringOrNull(contributor.getActualId(), outputContributors);
243             writeStringOrNull(contributor.getActualName(), outputContributors);
244             writeStringOrNull(contributor.getId(), outputContributors);
245             writeStringOrNull(contributor.getName(), outputContributors);
246         }
247
248         outputContributors.flush();
249         fosContributors.getFD().sync();
250         outputContributors.close();
251     }
252
253     private void saveTables(long registryTimeStamp) throws IOException {
254         FileOutputStream fosTable = new FileOutputStream(tableFile);
255         DataOutputStream outputTable = new DataOutputStream(new BufferedOutputStream(fosTable));
256         writeCacheHeader(outputTable, registryTimeStamp);
257         outputTable.writeInt(objectManager.getNextId());
258         offsets.save(outputTable);
259         objectManager.getExtensionPoints().save(outputTable, objectManager); // uses writer to filter contents
260
outputTable.flush();
261         fosTable.getFD().sync();
262         outputTable.close();
263     }
264
265     private void writeCacheHeader(DataOutputStream output, long registryTimeStamp) throws IOException {
266         output.writeInt(TableReader.CACHE_VERSION);
267         output.writeLong(registry.computeState());
268         output.writeLong(registryTimeStamp);
269         output.writeLong(mainDataFile.length());
270         output.writeLong(extraDataFile.length());
271         output.writeLong(contributionsFile.length());
272         output.writeLong(contributorsFile.length());
273         output.writeLong(namespacesFile.length());
274         output.writeLong(orphansFile.length());
275         output.writeUTF(RegistryProperties.getProperty(IRegistryConstants.PROP_OS, RegistryProperties.empty));
276         output.writeUTF(RegistryProperties.getProperty(IRegistryConstants.PROP_WS, RegistryProperties.empty));
277         output.writeUTF(RegistryProperties.getProperty(IRegistryConstants.PROP_NL, RegistryProperties.empty));
278     }
279
280     private void saveArray(int[] array, DataOutputStream out) throws IOException {
281         if (array == null) {
282             out.writeInt(0);
283             return;
284         }
285         out.writeInt(array.length);
286         for (int i = 0; i < array.length; i++) {
287             out.writeInt(array[i]);
288         }
289     }
290
291     private void saveExtensionPoint(ExtensionPointHandle xpt) throws IOException {
292         if (!xpt.shouldPersist())
293             return;
294         //save the file position
295
offsets.put(xpt.getId(), mainOutput.size());
296         //save the extensionPoint
297
mainOutput.writeInt(xpt.getId());
298         saveArray(filter(xpt.getObject().getRawChildren()), mainOutput);
299         mainOutput.writeInt(getExtraDataPosition());
300         saveExtensionPointData(xpt);
301
302         saveExtensions(xpt.getExtensions(), mainOutput);
303     }
304
305     private void saveExtension(ExtensionHandle ext, DataOutputStream outputStream) throws IOException {
306         if (!ext.shouldPersist())
307             return;
308         offsets.put(ext.getId(), outputStream.size());
309         outputStream.writeInt(ext.getId());
310         writeStringOrNull(ext.getSimpleIdentifier(), outputStream);
311         writeStringOrNull(ext.getNamespaceIdentifier(), outputStream);
312         saveArray(filter(ext.getObject().getRawChildren()), outputStream);
313         outputStream.writeInt(getExtraDataPosition());
314         saveExtensionData(ext);
315     }
316
317     private void writeStringArray(String JavaDoc[] array, DataOutputStream outputStream) throws IOException {
318         outputStream.writeInt(array == null ? 0 : array.length);
319         for (int i = 0; i < (array == null ? 0 : array.length); i++) {
320             writeStringOrNull(array[i], outputStream);
321         }
322     }
323
324     //Save Configuration elements depth first
325
private void saveConfigurationElement(ConfigurationElementHandle element, DataOutputStream outputStream, DataOutputStream extraOutputStream, int depth) throws IOException {
326         if (!element.shouldPersist())
327             return;
328         DataOutputStream currentOutput = outputStream;
329         if (depth > 2)
330             currentOutput = extraOutputStream;
331
332         offsets.put(element.getId(), currentOutput.size());
333
334         currentOutput.writeInt(element.getId());
335         ConfigurationElement actualCe = (ConfigurationElement) element.getObject();
336
337         writeStringOrNull(actualCe.getContributorId(), currentOutput);
338         writeStringOrNull(actualCe.getName(), currentOutput);
339         currentOutput.writeInt(actualCe.parentId);
340         currentOutput.writeByte(actualCe.parentType);
341         currentOutput.writeInt(depth > 1 ? extraOutputStream.size() : -1);
342         writeStringArray(actualCe.getPropertiesAndValue(), currentOutput);
343         //save the children
344
saveArray(filter(actualCe.getRawChildren()), currentOutput);
345
346         ConfigurationElementHandle[] childrenCEs = (ConfigurationElementHandle[]) element.getChildren();
347         for (int i = 0; i < childrenCEs.length; i++) {
348             saveConfigurationElement(childrenCEs[i], outputStream, extraOutputStream, depth + 1);
349         }
350
351     }
352
353     private void saveExtensions(IExtension[] exts, DataOutputStream outputStream) throws IOException {
354         for (int i = 0; i < exts.length; i++) {
355             saveExtension((ExtensionHandle) exts[i], outputStream);
356         }
357
358         for (int i = 0; i < exts.length; i++) {
359             if (!((ExtensionHandle) exts[i]).shouldPersist())
360                 continue;
361             IConfigurationElement[] ces = exts[i].getConfigurationElements();
362             int countCElements = 0;
363             boolean[] save = new boolean[ces.length];
364             for (int j = 0; j < ces.length; j++) {
365                 if (((ConfigurationElementHandle) ces[j]).shouldPersist()) {
366                     save[j] = true;
367                     countCElements++;
368                 } else
369                     save[j] = false;
370             }
371             outputStream.writeInt(countCElements);
372             for (int j = 0; j < ces.length; j++) {
373                 if (save[j])
374                     saveConfigurationElement((ConfigurationElementHandle) ces[j], outputStream, extraOutput, 1);
375             }
376         }
377     }
378
379     private void saveExtensionPointData(ExtensionPointHandle xpt) throws IOException {
380         writeStringOrNull(xpt.getLabel(), extraOutput);
381         writeStringOrNull(xpt.getSchemaReference(), extraOutput);
382         writeStringOrNull(xpt.getUniqueIdentifier(), extraOutput);
383         writeStringOrNull(xpt.getNamespaceIdentifier(), extraOutput);
384         writeStringOrNull(((ExtensionPoint) xpt.getObject()).getContributorId(), extraOutput);
385     }
386
387     private void saveExtensionData(ExtensionHandle extension) throws IOException {
388         writeStringOrNull(extension.getLabel(), extraOutput);
389         writeStringOrNull(extension.getExtensionPointUniqueIdentifier(), extraOutput);
390         writeStringOrNull(extension.getContributorId(), extraOutput);
391     }
392
393     private void writeStringOrNull(String JavaDoc string, DataOutputStream out) throws IOException {
394         if (string == null)
395             out.writeByte(TableReader.NULL);
396         else {
397             out.writeByte(TableReader.OBJECT);
398             out.writeUTF(string);
399         }
400     }
401
402     private void saveOrphans() throws IOException {
403         Map orphans = objectManager.getOrphanExtensions();
404         Map filteredOrphans = new HashMap();
405         for (Iterator iter = orphans.entrySet().iterator(); iter.hasNext();) {
406             Map.Entry entry = (Map.Entry) iter.next();
407             int[] filteredValue = filter((int[]) entry.getValue());
408             if (filteredValue.length != 0)
409                 filteredOrphans.put(entry.getKey(), filteredValue);
410         }
411         FileOutputStream fosOrphan = new FileOutputStream(orphansFile);
412         DataOutputStream outputOrphan = new DataOutputStream(new BufferedOutputStream(fosOrphan));
413         outputOrphan.writeInt(filteredOrphans.size());
414         Set elements = filteredOrphans.entrySet();
415         for (Iterator iter = elements.iterator(); iter.hasNext();) {
416             Map.Entry entry = (Map.Entry) iter.next();
417             outputOrphan.writeUTF((String JavaDoc) entry.getKey());
418             saveArray((int[]) entry.getValue(), outputOrphan);
419         }
420         for (Iterator iter = elements.iterator(); iter.hasNext();) {
421             Map.Entry entry = (Map.Entry) iter.next();
422             mainOutput.writeInt(((int[]) entry.getValue()).length);
423             saveExtensions((IExtension[]) objectManager.getHandles((int[]) entry.getValue(), RegistryObjectManager.EXTENSION), mainOutput);
424         }
425         outputOrphan.flush();
426         fosOrphan.getFD().sync();
427         outputOrphan.close();
428     }
429
430     private void log(Status status) {
431         registry.log(status);
432     }
433
434     // Filters out registry objects that should not be cached
435
private int[] filter(int[] input) {
436         boolean[] save = new boolean[input.length];
437         int resultSize = 0;
438         for (int i = 0; i < input.length; i++) {
439             if (objectManager.shouldPersist(input[i])) {
440                 save[i] = true;
441                 resultSize++;
442             } else
443                 save[i] = false;
444         }
445         int[] result = new int[resultSize];
446         int pos = 0;
447         for (int i = 0; i < input.length; i++) {
448             if (save[i]) {
449                 result[pos] = input[i];
450                 pos++;
451             }
452         }
453         return result;
454     }
455 }
456
Popular Tags