KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > osgi > internal > resolver > StateWriter


1 /*******************************************************************************
2  * Copyright (c) 2003, 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.osgi.internal.resolver;
12
13 import java.io.*;
14 import java.util.*;
15 import org.eclipse.osgi.service.resolver.*;
16 import org.osgi.framework.Constants;
17 import org.osgi.framework.Version;
18
19 class StateWriter {
20
21     // objectTable will be a hashmap of objects. The objects will be things
22
// like BundleDescription, ExportPackageDescription, Version etc.. The integer
23
// index value will be used in the cache to allow cross-references in the
24
// cached state.
25
private Map objectTable = new HashMap();
26     private ArrayList forcedWrite = new ArrayList();
27
28     private int addToObjectTable(Object JavaDoc object) {
29         Integer JavaDoc cur = (Integer JavaDoc) objectTable.get(object);
30         if (cur != null)
31             return cur.intValue();
32         objectTable.put(object, new Integer JavaDoc(objectTable.size()));
33         // return the index of the object just added (i.e. size - 1)
34
return (objectTable.size() - 1);
35     }
36
37     private int getFromObjectTable(Object JavaDoc object) {
38         if (objectTable != null) {
39             Object JavaDoc objectResult = objectTable.get(object);
40             if (objectResult != null) {
41                 return ((Integer JavaDoc) objectResult).intValue();
42             }
43         }
44         return -1;
45     }
46
47     private boolean writePrefix(Object JavaDoc object, DataOutputStream out) throws IOException {
48         if (writeIndex(object, out))
49             return true;
50         // add this object to the object table first
51
int index = addToObjectTable(object);
52         out.writeByte(StateReader.OBJECT);
53         out.writeInt(index);
54         return false;
55     }
56
57     private void writeStateDeprecated(StateImpl state, DataOutputStream out) throws IOException {
58         out.write(StateReader.STATE_CACHE_VERSION);
59         if (writePrefix(state, out))
60             return;
61         out.writeLong(state.getTimeStamp());
62         // write the platform property keys
63
String JavaDoc[] platformPropKeys = state.getPlatformPropertyKeys();
64         writePlatformProp(platformPropKeys, out);
65         Dictionary[] propSet = state.getPlatformProperties();
66         out.writeInt(propSet.length);
67         for (int i = 0; i < propSet.length; i++) {
68             Dictionary props = propSet[i];
69             out.writeInt(platformPropKeys.length);
70             for (int j = 0; j < platformPropKeys.length; j++)
71                 writePlatformProp(props.get(platformPropKeys[j]), out);
72         }
73         BundleDescription[] bundles = state.getBundles();
74         StateHelperImpl.getInstance().sortBundles(bundles);
75         out.writeInt(bundles.length);
76         if (bundles.length == 0)
77             return;
78         for (int i = 0; i < bundles.length; i++)
79             writeBundleDescription(bundles[i], out, false);
80         out.writeBoolean(state.isResolved());
81         // save the lazy data offset
82
out.writeInt(out.size());
83         for (int i = 0; i < bundles.length; i++)
84             writeBundleDescriptionLazyData(bundles[i], out);
85     }
86
87     public void saveState(StateImpl state, File stateFile, File lazyFile) throws IOException {
88         DataOutputStream outLazy = null;
89         DataOutputStream outState = null;
90         FileOutputStream fosLazy = null;
91         FileOutputStream fosState = null;
92         try {
93             BundleDescription[] bundles = state.getBundles();
94             StateHelperImpl.getInstance().sortBundles(bundles);
95             // need to prime the object table with all bundles
96
// this allows us to write only indexes to bundles in the lazy data
97
for (int i = 0; i < bundles.length; i++)
98                 addToObjectTable(bundles[i]);
99             // first write the lazy data to get the offsets and sizes to the lazy data
100
fosLazy = new FileOutputStream(lazyFile);
101             outLazy = new DataOutputStream(new BufferedOutputStream(fosLazy));
102             for (int i = 0; i < bundles.length; i++)
103                 writeBundleDescriptionLazyData(bundles[i], outLazy);
104             // now write the state data
105
fosState = new FileOutputStream(stateFile);
106             outState = new DataOutputStream(new BufferedOutputStream(fosState));
107             outState.write(StateReader.STATE_CACHE_VERSION);
108             if (writePrefix(state, outState))
109                 return;
110             outState.writeLong(state.getTimeStamp());
111             // write the platform property keys
112
String JavaDoc[] platformPropKeys = state.getPlatformPropertyKeys();
113             writePlatformProp(platformPropKeys, outState);
114             // write the platform property values
115
Dictionary[] propSet = state.getPlatformProperties();
116             outState.writeInt(propSet.length);
117             for (int i = 0; i < propSet.length; i++) {
118                 Dictionary props = propSet[i];
119                 outState.writeInt(platformPropKeys.length);
120                 for (int j = 0; j < platformPropKeys.length; j++)
121                     writePlatformProp(props.get(platformPropKeys[j]), outState);
122             }
123             outState.writeInt(bundles.length);
124             if (bundles.length == 0)
125                 return;
126             for (int i = 0; i < bundles.length; i++)
127                 // write out each bundle with the force flag set to make sure
128
// the data is written at least once in the non-lazy state data
129
writeBundleDescription(bundles[i], outState, true);
130             outState.writeBoolean(state.isResolved());
131         } finally {
132             if (outLazy != null) {
133                 try {
134                     outLazy.flush();
135                     fosLazy.getFD().sync();
136                 } catch (IOException e) {
137                     // do nothing, we tried
138
}
139                 try {
140                     outLazy.close();
141                 } catch (IOException e) {
142                     // do nothing
143
}
144             }
145             if (outState != null) {
146                 try {
147                     outState.flush();
148                     fosState.getFD().sync();
149                 } catch (IOException e) {
150                     // do nothing, we tried
151
}
152                 try {
153                     outState.close();
154                 } catch (IOException e) {
155                     // do nothing
156
}
157             }
158         }
159     }
160
161     private void writePlatformProp(Object JavaDoc obj, DataOutputStream out) throws IOException {
162         if (obj == null)
163             out.writeByte(StateReader.NULL);
164         else {
165             out.writeByte(StateReader.OBJECT);
166             if (obj instanceof String JavaDoc) {
167                 out.writeInt(1);
168                 writeStringOrNull((String JavaDoc) obj, out);
169             } else {
170                 String JavaDoc[] props = (String JavaDoc[]) obj;
171                 out.writeInt(props.length);
172                 for (int i = 0; i < props.length; i++)
173                     writeStringOrNull(props[i], out);
174             }
175         }
176     }
177
178     /*
179      * The force flag is used when writing the non-lazy state data. This forces the data to be
180      * written once even if the object exists in the object table.
181      * This is needed because we want to write the lazy data first but we only want
182      * to include indexes to the actual bundles in the lazy data. To do this we
183      * prime the object table with all the bundles first. Then we write the
184      * lazy data. Finally we write the non-lazy data and force a write of the
185      * bundles data once even if the bundle is in the object table.
186      */

187     private void writeBundleDescription(BundleDescription bundle, DataOutputStream out, boolean force) throws IOException {
188         if (force && !forcedWrite.contains(bundle)) {
189             int index = addToObjectTable(bundle);
190             out.writeByte(StateReader.OBJECT);
191             out.writeInt(index);
192             forcedWrite.add(bundle);
193         } else if (writePrefix(bundle, out))
194             return;
195         // first write out non-lazy loaded data
196
out.writeLong(bundle.getBundleId()); // ID must be the first thing
197
writeBaseDescription(bundle, out);
198         out.writeInt(((BundleDescriptionImpl) bundle).getLazyDataOffset());
199         out.writeInt(((BundleDescriptionImpl) bundle).getLazyDataSize());
200         out.writeBoolean(bundle.isResolved());
201         out.writeBoolean(bundle.isSingleton());
202         out.writeBoolean(bundle.hasDynamicImports());
203         out.writeBoolean(bundle.attachFragments());
204         out.writeBoolean(bundle.dynamicFragments());
205         writeHostSpec((HostSpecificationImpl) bundle.getHost(), out, force);
206
207         List dependencies = ((BundleDescriptionImpl) bundle).getBundleDependencies();
208         out.writeInt(dependencies.size());
209         for (Iterator iter = dependencies.iterator(); iter.hasNext();)
210             writeBundleDescription((BundleDescription) iter.next(), out, force);
211         // the rest is lazy loaded data
212
}
213
214     private void writeBundleDescriptionLazyData(BundleDescription bundle, DataOutputStream out) throws IOException {
215         int dataStart = out.size(); // save the offset of lazy data start
216
int index = getFromObjectTable(bundle);
217         ((BundleDescriptionImpl) bundle).setLazyDataOffset(out.size());
218         out.writeInt(index);
219
220         writeStringOrNull(bundle.getLocation(), out);
221         writeStringOrNull(bundle.getPlatformFilter(), out);
222
223         ExportPackageDescription[] exports = bundle.getExportPackages();
224         out.writeInt(exports.length);
225         for (int i = 0; i < exports.length; i++)
226             writeExportPackageDesc((ExportPackageDescriptionImpl) exports[i], out);
227
228         ImportPackageSpecification[] imports = bundle.getImportPackages();
229         out.writeInt(imports.length);
230         for (int i = 0; i < imports.length; i++)
231             writeImportPackageSpec(imports[i], out);
232
233         BundleSpecification[] requiredBundles = bundle.getRequiredBundles();
234         out.writeInt(requiredBundles.length);
235         for (int i = 0; i < requiredBundles.length; i++)
236             writeBundleSpec((BundleSpecificationImpl) requiredBundles[i], out);
237
238         ExportPackageDescription[] selectedExports = bundle.getSelectedExports();
239         if (selectedExports == null) {
240             out.writeInt(0);
241         } else {
242             out.writeInt(selectedExports.length);
243             for (int i = 0; i < selectedExports.length; i++)
244                 writeExportPackageDesc((ExportPackageDescriptionImpl) selectedExports[i], out);
245         }
246
247         ExportPackageDescription[] resolvedImports = bundle.getResolvedImports();
248         if (resolvedImports == null) {
249             out.writeInt(0);
250         } else {
251             out.writeInt(resolvedImports.length);
252             for (int i = 0; i < resolvedImports.length; i++)
253                 writeExportPackageDesc((ExportPackageDescriptionImpl) resolvedImports[i], out);
254         }
255
256         BundleDescription[] resolvedRequires = bundle.getResolvedRequires();
257         if (resolvedRequires == null) {
258             out.writeInt(0);
259         } else {
260             out.writeInt(resolvedRequires.length);
261             for (int i = 0; i < resolvedRequires.length; i++)
262                 writeBundleDescription(resolvedRequires[i], out, false);
263         }
264
265         String JavaDoc[] ees = bundle.getExecutionEnvironments();
266         out.writeInt(ees.length);
267         for (int i = 0; i < ees.length; i++)
268             writeStringOrNull(ees[i], out);
269
270         HashMap dynamicStamps = ((BundleDescriptionImpl) bundle).getDynamicStamps();
271         if (dynamicStamps == null)
272             out.writeInt(0);
273         else {
274             out.writeInt(dynamicStamps.size());
275             for (Iterator pkgs = dynamicStamps.keySet().iterator(); pkgs.hasNext();) {
276                 String JavaDoc pkg = (String JavaDoc) pkgs.next();
277                 writeStringOrNull(pkg, out);
278                 out.writeLong(((Long JavaDoc) dynamicStamps.get(pkg)).longValue());
279             }
280         }
281
282         GenericDescription[] genericCapabilities = bundle.getGenericCapabilities();
283         if (genericCapabilities == null)
284             out.writeInt(0);
285         else {
286             out.writeInt(genericCapabilities.length);
287             for (int i = 0; i < genericCapabilities.length; i++)
288                 writeGenericDescription(genericCapabilities[i], out);
289         }
290
291         GenericSpecification[] genericRequires = bundle.getGenericRequires();
292         if (genericRequires == null)
293             out.writeInt(0);
294         else {
295             out.writeInt(genericRequires.length);
296             for (int i = 0; i < genericRequires.length; i++)
297                 writeGenericSpecification(genericRequires[i], out);
298         }
299
300         // save the size of the lazy data
301
((BundleDescriptionImpl) bundle).setLazyDataSize(out.size() - dataStart);
302     }
303
304     private void writeBundleSpec(BundleSpecificationImpl bundle, DataOutputStream out) throws IOException {
305         writeVersionConstraint(bundle, out);
306         writeBundleDescription((BundleDescription) bundle.getSupplier(), out, false);
307         out.writeBoolean(bundle.isExported());
308         out.writeBoolean(bundle.isOptional());
309     }
310
311     private void writeExportPackageDesc(ExportPackageDescriptionImpl exportPackageDesc, DataOutputStream out) throws IOException {
312         if (writePrefix(exportPackageDesc, out))
313             return;
314         writeBaseDescription(exportPackageDesc, out);
315         out.writeBoolean(exportPackageDesc.isRoot());
316         writeMap(out, exportPackageDesc.getAttributes());
317         writeMap(out, exportPackageDesc.getDirectives());
318     }
319
320     private void writeGenericDescription(GenericDescription description, DataOutputStream out) throws IOException {
321         if (writePrefix(description, out))
322             return;
323         writeBaseDescription(description, out);
324         writeStringOrNull(description.getType() == GenericDescription.DEFAULT_TYPE ? null : description.getType(), out);
325         Dictionary attrs = description.getAttributes();
326         Map mapAttrs = new HashMap(attrs.size());
327         for (Enumeration keys = attrs.keys(); keys.hasMoreElements();) {
328             Object JavaDoc key = keys.nextElement();
329             if (!Constants.VERSION_ATTRIBUTE.equals(key))
330                 mapAttrs.put(key, attrs.get(key));
331         }
332         writeMap(out, mapAttrs);
333     }
334
335     private void writeGenericSpecification(GenericSpecification specification, DataOutputStream out) throws IOException {
336         writeVersionConstraint(specification, out);
337         writeStringOrNull(specification.getType() == GenericDescription.DEFAULT_TYPE ? null : specification.getType(), out);
338         GenericDescription[] suppliers = specification.getSuppliers();
339         out.writeInt(suppliers == null ? 0 : suppliers.length);
340         if (suppliers != null)
341             for (int i = 0; i < suppliers.length; i++)
342                 writeGenericDescription(suppliers[i], out);
343         out.writeInt(specification.getResolution());
344         writeStringOrNull(specification.getMatchingFilter(), out);
345     }
346
347     private void writeMap(DataOutputStream out, Map source) throws IOException {
348         if (source == null) {
349             out.writeInt(0);
350         } else {
351             out.writeInt(source.size());
352             Iterator iter = source.keySet().iterator();
353             while (iter.hasNext()) {
354                 String JavaDoc key = (String JavaDoc) iter.next();
355                 Object JavaDoc value = source.get(key);
356                 writeStringOrNull(key, out);
357                 if (value instanceof String JavaDoc) {
358                     out.writeByte(0);
359                     writeStringOrNull((String JavaDoc) value, out);
360                 } else if (value instanceof String JavaDoc[]) {
361                     out.writeByte(1);
362                     writeList(out, (String JavaDoc[]) value);
363                 } else if (value instanceof Boolean JavaDoc) {
364                     out.writeByte(2);
365                     out.writeBoolean(((Boolean JavaDoc) value).booleanValue());
366                 } else if (value instanceof Integer JavaDoc) {
367                     out.writeByte(3);
368                     out.writeInt(((Integer JavaDoc) value).intValue());
369                 } else if (value instanceof Long JavaDoc) {
370                     out.writeByte(4);
371                     out.writeLong(((Long JavaDoc) value).longValue());
372                 } else if (value instanceof Double JavaDoc) {
373                     out.writeByte(5);
374                     out.writeDouble(((Double JavaDoc) value).doubleValue());
375                 } else if (value instanceof Version) {
376                     out.writeByte(6);
377                     writeVersion((Version) value, out);
378                 } else if ("java.net.URI".equals(value.getClass().getName())) { //$NON-NLS-1$
379
out.writeByte(7);
380                     writeStringOrNull(value.toString(), out);
381                 }
382             }
383         }
384     }
385
386     private void writeList(DataOutputStream out, String JavaDoc[] list) throws IOException {
387         if (list == null) {
388             out.writeInt(0);
389         } else {
390             out.writeInt(list.length);
391             for (int i = 0; i < list.length; i++)
392                 writeStringOrNull(list[i], out);
393         }
394     }
395
396     private void writeBaseDescription(BaseDescription rootDesc, DataOutputStream out) throws IOException {
397         writeStringOrNull(rootDesc.getName(), out);
398         writeVersion(rootDesc.getVersion(), out);
399     }
400
401     private void writeImportPackageSpec(ImportPackageSpecification importPackageSpec, DataOutputStream out) throws IOException {
402         writeVersionConstraint(importPackageSpec, out);
403         // TODO this is a hack until the state dynamic loading is cleaned up
404
// we should only write the supplier if we are resolved
405
if (importPackageSpec.getBundle().isResolved())
406             writeExportPackageDesc((ExportPackageDescriptionImpl) importPackageSpec.getSupplier(), out);
407         else
408             out.writeByte(StateReader.NULL);
409
410         writeStringOrNull(importPackageSpec.getBundleSymbolicName(), out);
411         writeVersionRange(importPackageSpec.getBundleVersionRange(), out);
412         writeMap(out, importPackageSpec.getAttributes());
413         writeMap(out, importPackageSpec.getDirectives());
414     }
415
416     private void writeHostSpec(HostSpecificationImpl host, DataOutputStream out, boolean force) throws IOException {
417         if (host == null) {
418             out.writeByte(StateReader.NULL);
419             return;
420         }
421         out.writeByte(StateReader.OBJECT);
422         writeVersionConstraint(host, out);
423         BundleDescription[] hosts = host.getHosts();
424         if (hosts == null) {
425             out.writeInt(0);
426             return;
427         }
428         out.writeInt(hosts.length);
429         for (int i = 0; i < hosts.length; i++)
430             writeBundleDescription(hosts[i], out, force);
431     }
432
433     // called by writers for VersionConstraintImpl subclasses
434
private void writeVersionConstraint(VersionConstraint constraint, DataOutputStream out) throws IOException {
435         writeStringOrNull(constraint.getName(), out);
436         writeVersionRange(constraint.getVersionRange(), out);
437     }
438
439     private void writeVersion(Version version, DataOutputStream out) throws IOException {
440         if (version == null || version.equals(Version.emptyVersion)) {
441             out.writeByte(StateReader.NULL);
442             return;
443         }
444         out.writeByte(StateReader.OBJECT);
445         out.writeInt(version.getMajor());
446         out.writeInt(version.getMinor());
447         out.writeInt(version.getMicro());
448         writeQualifier(version.getQualifier(), out);
449     }
450
451     private void writeVersionRange(VersionRange versionRange, DataOutputStream out) throws IOException {
452         if (versionRange == null || versionRange.equals(VersionRange.emptyRange)) {
453             out.writeByte(StateReader.NULL);
454             return;
455         }
456         out.writeByte(StateReader.OBJECT);
457         writeVersion(versionRange.getMinimum(), out);
458         out.writeBoolean(versionRange.getIncludeMinimum());
459         writeVersion(versionRange.getMaximum(), out);
460         out.writeBoolean(versionRange.getIncludeMaximum());
461     }
462
463     private boolean writeIndex(Object JavaDoc object, DataOutputStream out) throws IOException {
464         if (object == null) {
465             out.writeByte(StateReader.NULL);
466             return true;
467         }
468         int index = getFromObjectTable(object);
469         if (index == -1)
470             return false;
471         out.writeByte(StateReader.INDEX);
472         out.writeInt(index);
473         return true;
474     }
475
476     public void saveStateDeprecated(StateImpl state, DataOutputStream output) throws IOException {
477         try {
478             writeStateDeprecated(state, output);
479         } finally {
480             output.close();
481         }
482     }
483
484     private void writeStringOrNull(String JavaDoc string, DataOutputStream out) throws IOException {
485         if (string == null)
486             out.writeByte(StateReader.NULL);
487         else {
488             out.writeByte(StateReader.OBJECT);
489             out.writeUTF(string);
490         }
491     }
492
493     private void writeQualifier(String JavaDoc string, DataOutputStream out) throws IOException {
494         if (string != null && string.length() == 0)
495             string = null;
496         writeStringOrNull(string, out);
497     }
498 }
499
Popular Tags