KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > ungoverned > oscar > util > DefaultBundleCache


1 /*
2  * Oscar - An implementation of the OSGi framework.
3  * Copyright (c) 2004, Richard S. Hall
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * * Redistributions of source code must retain the above copyright
11  * notice, this list of conditions and the following disclaimer.
12  * * Redistributions in binary form must reproduce the above copyright
13  * notice, this list of conditions and the following disclaimer in
14  * the documentation and/or other materials provided with the
15  * distribution.
16  * * Neither the name of the ungoverned.org nor the names of its
17  * contributors may be used to endorse or promote products derived
18  * from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  *
32  * Contact: Richard S. Hall (heavy@ungoverned.org)
33  * Contributor(s):
34  *
35 **/

36 package org.ungoverned.oscar.util;
37
38 import java.io.BufferedInputStream JavaDoc;
39 import java.io.File JavaDoc;
40 import java.io.InputStream JavaDoc;
41
42 import org.ungoverned.oscar.*;
43
44 /**
45  * <p>
46  * This class, combined with <tt>DefaultBundleArchive</tt>, implements the
47  * default file system-based bundle cache for Oscar. It is possible to
48  * configure the default behavior of this class by setting system properties
49  * or passing properties into Oscar's constructor. The configuration
50  * properties for this class are:
51  * </p>
52  * <ul>
53  * <li><tt>oscar.cache.bufsize</tt> - Sets the buffer size to be used by
54  * the cache; the default value is 4096. The integer
55  * value of this string provides control over the size of the
56  * internal buffer of the disk cache for performance reasons.
57  * </li>
58  * <li><tt>oscar.cache.dir</tt> - Sets the directory to be used by the
59  * cache as its cache directory. The cache directory is where all
60  * profile directories are stored and a profile directory is where a
61  * set of installed bundles are stored. By default, the cache
62  * directory is <tt>.oscar</tt> in the user's home directory. If
63  * this property is specified, then its value will be used as the cache
64  * directory instead of <tt>.oscar</tt>. This directory will be created
65  * if it does not exist.
66  * </li>
67  * <li><tt>oscar.cache.profile</tt> - Sets the profile name that will be
68  * used to create a profile directory inside of the cache directory.
69  * The created directory will contained all installed bundles associated
70  * with the profile.
71  * </li>
72  * <li><tt>oscar.cache.profiledir</tt> - Sets the directory to use as the
73  * profile directory for the bundle cache; by default the profile
74  * name is used to create a directory in the <tt>.oscar</tt> cache
75  * directory. If this property is specified, then the cache directory
76  * and profile name properties are ignored. The specified value of this
77  * property is used directly as the directory to contain all cached
78  * bundles. If this property is set, it is not necessary to set the
79  * cache directory or profile name properties. This directory will be
80  * created if it does not exist.
81  * </li>
82  * </ul>
83  * <p>
84  * For specific information on how to configure Oscar using system properties,
85  * refer to the Oscar usage documentation.
86  * </p>
87  * @see org.ungoverned.oscar.util.DefaultBundleArchive
88 **/

89 public class DefaultBundleCache implements BundleCache
90 {
91     public static final String JavaDoc CACHE_BUFSIZE_PROP = "oscar.cache.bufsize";
92     public static final String JavaDoc CACHE_DIR_PROP = "oscar.cache.dir";
93     public static final String JavaDoc CACHE_PROFILE_DIR_PROP = "oscar.cache.profiledir";
94     public static final String JavaDoc CACHE_PROFILE_PROP = "oscar.cache.profile";
95
96     protected static transient int BUFSIZE = 4096;
97     protected static transient final String JavaDoc CACHE_DIR_NAME = ".oscar";
98     protected static transient final String JavaDoc BUNDLE_DIR_PREFIX = "bundle";
99
100     private Oscar m_oscar = null;
101     private File JavaDoc m_profileDir = null;
102     private BundleArchive[] m_archives = null;
103
104     public DefaultBundleCache()
105     {
106     }
107
108     public void initialize(Oscar oscar) throws Exception JavaDoc
109     {
110         // Save Oscar reference.
111
m_oscar = oscar;
112
113         // Get buffer size value.
114
try
115         {
116             String JavaDoc sBufSize =
117                 m_oscar.getConfigProperty(CACHE_BUFSIZE_PROP);
118             if (sBufSize != null)
119             {
120                 BUFSIZE = Integer.parseInt(sBufSize);
121             }
122         }
123         catch (NumberFormatException JavaDoc ne)
124         {
125             // Use the default value.
126
}
127
128         // See if the profile directory is specified.
129
String JavaDoc profileDirStr =
130             m_oscar.getConfigProperty(CACHE_PROFILE_DIR_PROP);
131         if (profileDirStr != null)
132         {
133             m_profileDir = new File JavaDoc(profileDirStr);
134         }
135         else
136         {
137             // Since no profile directory was specified, then the profile
138
// directory will be a directory in the cache directory named
139
// after the profile.
140

141             // First, determine the location of the cache directory; it
142
// can either be specified or in the default location.
143
String JavaDoc cacheDirStr =
144                 m_oscar.getConfigProperty(CACHE_DIR_PROP);
145             if (cacheDirStr == null)
146             {
147                 // Since no cache directory was specified, put it
148
// ".oscar" in the user's home by default.
149
cacheDirStr = System.getProperty("user.home");
150                 cacheDirStr = cacheDirStr.endsWith(File.separator)
151                     ? cacheDirStr : cacheDirStr + File.separator;
152                 cacheDirStr = cacheDirStr + CACHE_DIR_NAME;
153             }
154
155             // Now, get the profile name.
156
String JavaDoc profileName =
157                 m_oscar.getConfigProperty(CACHE_PROFILE_PROP);
158             if (profileName == null)
159             {
160                 throw new IllegalArgumentException JavaDoc(
161                     "No profile name or directory has been specified.");
162             }
163             // Profile name cannot contain the File.separator char.
164
else if (profileName.indexOf(File.separator) >= 0)
165             {
166                 throw new IllegalArgumentException JavaDoc(
167                     "The profile name cannot contain the file separator character.");
168             }
169
170             m_profileDir = new File JavaDoc(cacheDirStr, profileName);
171         }
172
173         // Create profile directory.
174
if (!m_profileDir.exists())
175         {
176             if (!m_profileDir.mkdirs())
177             {
178                 Oscar.error("Unable to create directory: " + m_profileDir);
179                 throw new RuntimeException JavaDoc("Unable to create profile directory.");
180             }
181         }
182
183         // Create the existing bundle archives in the profile directory,
184
// if any exist.
185
File JavaDoc[] children = m_profileDir.listFiles();
186         int count = 0;
187         for (int i = 0; (children != null) && (i < children.length); i++)
188         {
189             // Count the legitimate bundle directories.
190
if (children[i].getName().startsWith(BUNDLE_DIR_PREFIX))
191             {
192                 count++;
193             }
194         }
195         m_archives = new BundleArchive[count];
196         count = 0;
197         for (int i = 0; (children != null) && (i < children.length); i++)
198         {
199             // Ignore directories that aren't bundle directories.
200
if (children[i].getName().startsWith(BUNDLE_DIR_PREFIX))
201             {
202                 String JavaDoc id = children[i].getName().substring(BUNDLE_DIR_PREFIX.length());
203                 m_archives[count] = new DefaultBundleArchive(
204                     children[i], Long.parseLong(id));
205                 count++;
206             }
207         }
208     }
209
210     public BundleArchive[] getArchives()
211         throws Exception JavaDoc
212     {
213         return m_archives;
214     }
215
216     public BundleArchive getArchive(long id)
217         throws Exception JavaDoc
218     {
219         for (int i = 0; i < m_archives.length; i++)
220         {
221             if (m_archives[i].getId() == id)
222             {
223                 return m_archives[i];
224             }
225         }
226         return null;
227     }
228
229     public BundleArchive create(long id, String JavaDoc location, InputStream JavaDoc is)
230         throws Exception JavaDoc
231     {
232         // Define new bundle's directory.
233
File JavaDoc bundleDir = new File JavaDoc(m_profileDir, "bundle" + id);
234
235         try
236         {
237             // Buffer the input stream.
238
is = new BufferedInputStream JavaDoc(is, DefaultBundleCache.BUFSIZE);
239             // Create an archive instance for the new bundle.
240
BundleArchive ba = new DefaultBundleArchive(bundleDir, id, location, is);
241             // Add the archive instance to the list of bundle archives.
242
BundleArchive[] bas = new BundleArchive[m_archives.length + 1];
243             System.arraycopy(m_archives, 0, bas, 0, m_archives.length);
244             bas[m_archives.length] = ba;
245             m_archives = bas;
246             return ba;
247         }
248         finally
249         {
250             if (is != null) is.close();
251         }
252     }
253
254     public void update(BundleArchive ba, InputStream JavaDoc is)
255         throws Exception JavaDoc
256     {
257         try
258         {
259             // Buffer the input stream.
260
is = new BufferedInputStream JavaDoc(is, DefaultBundleCache.BUFSIZE);
261             // Do the update.
262
((DefaultBundleArchive) ba).update(is);
263         }
264         finally
265         {
266             if (is != null) is.close();
267         }
268     }
269
270     public void purge(BundleArchive ba)
271         throws Exception JavaDoc
272     {
273         ((DefaultBundleArchive) ba).purge();
274     }
275
276     public void remove(BundleArchive ba)
277         throws Exception JavaDoc
278     {
279         ((DefaultBundleArchive) ba).remove();
280     }
281 }
Popular Tags