KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > SOFA > SOFAnode > TR > Impl > BundleImpl


1 /**
2  * BundleImpl.java is a part of the SOFA project.
3  * This file was created by pepan on 19.3.2003.
4  */

5 package SOFA.SOFAnode.TR.Impl;
6
7 import SOFA.SOFAnode.InOut.Bundle;
8 import SOFA.SOFAnode.InOut.InOutException;
9 import SOFA.SOFAnode.TR.ComponentInfo;
10 import SOFA.Util.Tools;
11 import SOFA.Util.VMProperties;
12 import cz.cuni.sofa.lib.InputStream;
13 import cz.cuni.sofa.lib.OutputStream;
14 import cz.cuni.sofa.lib.*;
15
16 import java.io.*;
17 import java.util.*;
18 import java.util.jar.*;
19 import java.lang.Object JavaDoc;
20
21 /**
22  * A bundle wrapping a set of components into a single zipped JAR file (actually, an arbitrary
23  * stream is used). Such a bundle is intented to be sent between two SOFA nodes when exchanging
24  * components. The manifest file of such a JAR file contains a description of all components
25  * stored in the bundle. If a bundle manifest file describes a component, but the bundle does not
26  * contain the component files, the bundle is called a meta-bundle.
27  * @author Petr Panuska
28  */

29 public class BundleImpl implements Bundle, Serializable, Streamable {
30
31   /**
32    * All components wrapped in this bundle.
33    */

34   private Hashtable components;
35
36   /**
37    * The URL pointing to the local SOFA node where this bundle was created. It's used
38    * when storing the description of components only, to denote where the component
39    * can be obtained from.
40    */

41   private static String JavaDoc sofaNodeName;
42
43   /**
44    * Points to the root directory of files created just temporarily when unpacking the
45    * bundle from a stream and just before the installation to TR.
46    */

47   private File tempDir = null;
48
49   /**
50    * This instance is used by the bundle when it denotes that a particular component does not contain
51    * any single file - it is a component description only. Such a bundle is called a meta-bundle.
52    */

53   public static final ComponentFiles NO_FILES = new ComponentFiles();
54
55   /**
56    * Creates an empty bundle.
57    */

58   public BundleImpl () {
59     components = new Hashtable();
60     sofaNodeName = "sofa://" + System.getProperty(VMProperties.NODE_NAME);
61   }
62
63   /**
64    * Gets an array of all components currently stored in this bundle.
65    * @return an array of component info objects.
66    */

67   public ComponentInfo[] getComponents () {
68     Set keySet = components.keySet();
69     int size = keySet.size();
70     ComponentInfo[] comps = new ComponentInfo[size];
71     keySet.toArray(comps);
72     return comps;
73   }
74
75   /**
76    * Returns <code>true</code> if the asked component description is stored in this bundle.
77    * @param descr the specified component.
78    * @return whether the component description is contained in this bundle.
79    */

80   public boolean contains (ComponentInfo descr) {
81     return components.containsKey(descr);
82   }
83
84   /**
85    * Returns <code>true</code> if the asked component itself
86    * (not only the description) is contained withing this bundle.
87    * @param comp the specified component.
88    * @return whether the component itself is contained in this bundle.
89    */

90   public boolean containsComponent (ComponentInfo comp) {
91     ComponentFiles files = (ComponentFiles) components.get(comp);
92     return (files != null && files != NO_FILES);
93   }
94
95   /**
96    * Returns files creating the asked component. The object wrapping all these files is of
97    * type {@link ComponentFiles}.
98    * @param descr the component being asked.
99    * @return files creating the component.
100    * @throws InOutException when the asked component is not stored in this bundle.
101    */

102   public java.lang.Object JavaDoc getComponent (ComponentInfo descr) throws InOutException {
103     ComponentFiles files = (ComponentFiles) components.get(descr);
104     if (files == null)
105       throw new InOutException("Required component has not been stored in this bundle. " + descr);
106     return files;
107   }
108
109   /**
110    * Adds files pertaining a component to the internal data structure of this bundle.
111    * @param comp the component.
112    * @param files the files pertaining the component.
113    */

114   public void add (ComponentInfoImpl comp, ComponentFiles files) {
115     comp.setLocation(comp.getName() + comp.getImplementationVersion());
116     components.put(comp, files);
117   }
118
119   /**
120    * Loads this bundle from a stream. It loads all files previously stored in a zipped
121    * JAR file including the manifest file and restores all internal data structures of
122    * this bundle. It uses a temporarily created directory for storing component files.
123    * @param stream the stream this bundle is being loaded from.
124    */

125   public void loadFromJar (BundleInputStream stream) throws IOException {
126     tempDir = stream.getTempRootDirectory(); // sets the root of temporary files
127
Manifest manifest = stream.getManifest();
128
129     Map entries = manifest.getEntries();
130     // process normal components (have files stored in the stream)
131
for (BundleEntry entry = stream.getNextBundleEntry(); entry != null; entry = stream.getNextBundleEntry()) {
132       Attributes attrs = (Attributes) entries.remove(entry.getName()); // removes entries from the map
133

134       ComponentInfoImpl compInfo = getComponentInfo(attrs);
135       components.put(compInfo, entry.getFiles());
136
137     }
138     stream.close();
139     if (!entries.isEmpty()) { // process meta-components
140
Iterator iter = entries.keySet().iterator();
141       while (iter.hasNext()) {
142         String JavaDoc key = (String JavaDoc) iter.next();
143         Attributes attrs = (Attributes) entries.get(key);
144
145 // Attributes attrs = (Attributes) iter.next();
146

147         ComponentInfoImpl compInfo = getComponentInfo(attrs);
148         components.put(compInfo, NO_FILES);
149       }
150     }
151   }
152
153   /**
154    * Gets a component described by the specified attributes. These attributes are taken
155    * from the manifest file.
156    * @param attrs the specified attributes.
157    * @return the component info with no files assigned.
158    */

159   private ComponentInfoImpl getComponentInfo (Attributes attrs) {
160     String JavaDoc name = attrs.getValue("Component-Name");
161     String JavaDoc version = attrs.getValue("Implementation-Version");
162     String JavaDoc location = attrs.getValue("Component-Path");
163
164     return new ComponentInfoImpl(name, version, location);
165   }
166
167   /**
168    * Returns the content of the manifest file of this bundle.
169    * @return the manifest file of this bundle.
170    */

171   private String JavaDoc createManifest () {
172
173     StringBuffer JavaDoc manifest = new StringBuffer JavaDoc();
174     manifest.append("Manifest-Version: 1.0\n");
175     manifest.append("Created-By: ");
176     manifest.append(System.getProperty(VMProperties.NODE_NAME, "Unknown node"));
177     manifest.append("\n");
178
179     manifest.append("\n");
180
181     class MyVector extends Vector { // implements naming directories for stored components with different names (even if the components have the same name)
182
String JavaDoc getComponentPath (ComponentInfo info) {
183         String JavaDoc name = info.getName();
184         String JavaDoc shortName = name.substring(name.lastIndexOf("::") + 2); // takes the short name of a component (without modules)
185
String JavaDoc finalName = shortName;
186         for (int i = 2; this.contains(finalName); i++) { // tries to find different name
187
finalName = shortName + Integer.toString(i); // just adds a number to the original name
188
}
189         this.add(finalName); // rememeber the name for next use
190
return finalName;
191       }
192     }
193     ;
194
195     MyVector compDirs = new MyVector();
196
197     Enumeration comp = components.keys();
198     while (comp.hasMoreElements()) {
199       ComponentInfoImpl info = (ComponentInfoImpl) comp.nextElement();
200       ComponentFiles compFiles = (ComponentFiles) components.get(info); // component files
201
String JavaDoc name = compDirs.getComponentPath(info);
202       String JavaDoc location = (compFiles == NO_FILES) ? sofaNodeName : name;
203       info.setLocation(location);
204       manifest.append("Name: ");
205       manifest.append(name);
206       manifest.append("\n");
207       manifest.append("Component-Name: ");
208       manifest.append(info.getName());
209       manifest.append("\n");
210       manifest.append("Implementation-Version: ");
211       manifest.append(info.getImplementationVersion());
212       manifest.append("\n");
213       manifest.append("Component-Path: ");
214       manifest.append(location);
215       manifest.append("\n");
216       manifest.append("\n");
217       manifest.append("\n");
218     }
219
220     return manifest.toString();
221
222   }
223
224   /**
225    * Saves this bundle to the specified stream. It stores all component files to
226    * a zipped directory with a manifest file - a JAR file. The manifest file describes
227    * all components being stored.
228    * @param stream the stream where is this bundle being stored to.
229    * @throws IOException when some IO operation fails.
230    */

231   public void saveToJar (BundleOutputStream stream) throws IOException {
232     stream.putNextEntry(new BundleEntry(JarFile.MANIFEST_NAME));
233     String JavaDoc manifest = createManifest();
234     byte[] buffer = manifest.getBytes();
235     stream.write(buffer);
236
237     Enumeration comp = components.keys();
238     while (comp.hasMoreElements()) {
239       ComponentInfoImpl info = (ComponentInfoImpl) comp.nextElement(); // the component
240
ComponentFiles compFiles = (ComponentFiles) components.get(info); // component files
241
if (compFiles != NO_FILES) // don't store files belonging to a meta-component
242
stream.putNextBundleEntry(new BundleEntry(info.getLocation(), compFiles)); // location here serves as a prefix of all component file names
243
}
244
245     stream.close();
246   }
247
248   /**
249    * Reads a bundle from a stream.
250    * @param is the input stream this bundle is being read from.
251    * @throws IOException when some IO operation fails.
252    * @see #loadFromJar
253    */

254   public void _read (InputStream is) throws IOException {
255 /*
256     //todo following code is here for testing purposes only
257     FileOutputStream f = new FileOutputStream("c:\\ww\\tmp2.zip");
258     final int BUFFER_SIZE = 4096;
259     byte[] buffer = new byte[BUFFER_SIZE];
260     for (int length; // use buffer to copy the entry to the file
261          (length = is.read(buffer, 0, BUFFER_SIZE)) >= 0;
262          f.write(buffer, 0, length));
263     f.close();
264     FileInputStream is2 = new FileInputStream("c:\\ww\\tmp2.zip");
265     loadFromJar(new BundleInputStream(is2));
266 */

267     loadFromJar(new BundleInputStream(is));
268   }
269   
270   public void _read (java.io.InputStream JavaDoc is) throws IOException
271   {
272     loadFromJar(new BundleInputStream(is));
273   }
274
275   /**
276    * Writes this bundle to a stream.
277    * @param os the output stream this bundle is being stored to.
278    * @throws IOException when some IO operation fails.
279    * @see #saveToJar
280    */

281   public void _write (OutputStream os) throws IOException {
282 /* //todo following code is here for testing purposes only
283     FileOutputStream f = new FileOutputStream("x:\\tmp\\tmp3.zip");
284     saveToJar(new BundleOutputStream(f));
285     f.close();
286 */

287     saveToJar(new BundleOutputStream(os));
288   }
289   public void _write (java.io.OutputStream JavaDoc os) throws IOException
290   {
291     saveToJar(new BundleOutputStream(os));
292   }
293   
294
295   /**
296    * Deletes all temporarily created files and directories. A bundle is a structure created
297    * temporarily only. If it's going to be garbage collected, it deletes the temporary
298    * files as well.
299    */

300   protected void finalize () throws Throwable JavaDoc {
301     if (tempDir != null) // if there were some temporary files, delete these files
302
Tools.deleteSubTree(tempDir);
303     super.finalize();
304   }
305
306 }
307
Popular Tags