BundleStorageImpl.java

00001 /*
00002  * Copyright (c) 2003-2006, KNOPFLERFISH project
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following
00007  * conditions are met:
00008  *
00009  * - Redistributions of source code must retain the above copyright
00010  *   notice, this list of conditions and the following disclaimer.
00011  *
00012  * - Redistributions in binary form must reproduce the above
00013  *   copyright notice, this list of conditions and the following
00014  *   disclaimer in the documentation and/or other materials
00015  *   provided with the distribution.
00016  *
00017  * - Neither the name of the KNOPFLERFISH project nor the names of its
00018  *   contributors may be used to endorse or promote products derived
00019  *   from this software without specific prior written permission.
00020  *
00021  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00022  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00023  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00024  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00025  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00026  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00027  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
00028  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00029  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
00030  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00031  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
00032  * OF THE POSSIBILITY OF SUCH DAMAGE.
00033  */
00034 
00035 package org.knopflerfish.framework.bundlestorage.file;
00036 
00037 import org.knopflerfish.framework.*;
00038 import java.io.*;
00039 import java.util.*;
00040 
00048 public class BundleStorageImpl implements BundleStorage {
00049 
00053   private FileTree bundlesDir;
00054 
00058   private long nextFreeId = 1;
00059 
00063   private ArrayList /* BundleArchive */ archives = new ArrayList();
00064 
00070   public BundleStorageImpl() {
00071     // See if we have a storage directory
00072     bundlesDir = Util.getFileStorage("bs");
00073     if (bundlesDir == null) {
00074       throw new RuntimeException("No bundle storage area available!");
00075     }
00076     // Restore all saved bundles
00077     String [] list = bundlesDir.list();
00078     for (int i = 0; list != null & i < list.length; i++) {
00079       long id;
00080       try {
00081         id = Long.parseLong(list[i]);
00082       } catch (NumberFormatException e) {
00083         continue;
00084       }
00085       if (id == 0) {
00086         System.err.println("Saved bundle with illegal id 0 is ignored.");
00087       }
00088       int pos = find(id);
00089       if (pos < archives.size() && ((BundleArchive)archives.get(pos)).getBundleId() == id) {
00090         System.err.println("There are two bundle directories with id: " + id);
00091         break;
00092       }
00093       FileTree dir = new FileTree(bundlesDir, list[i]);
00094       if (dir.isDirectory()) {
00095         try {
00096           boolean bUninstalled = BundleArchiveImpl.isUninstalled(dir);
00097           if(bUninstalled) {
00098             // silently remove any bundle marked as uninstalled
00099             dir.delete();
00100           } else {
00101             BundleArchive ba = new BundleArchiveImpl(this, dir, id);
00102             archives.add(pos, ba);
00103           }
00104           if (id >= nextFreeId) {
00105             nextFreeId = id + 1;
00106           }
00107         } catch (Exception e) {
00108           dir.delete();
00109           System.err.println("Removed corrupt bundle dir (" + e.getMessage() + "): " + dir);
00110         }
00111       }
00112     }
00113   }
00114 
00122   public BundleArchive insertBundleJar(String location, InputStream is)
00123     throws Exception
00124   {
00125     long id = nextFreeId++;
00126     FileTree dir = new FileTree(bundlesDir, String.valueOf(id));
00127     if (dir.exists()) {
00128       // remove any old garbage
00129       dir.delete();
00130     }
00131     dir.mkdir();
00132     try {
00133       BundleArchive ba = new BundleArchiveImpl(this, dir, is, location, id);
00134       archives.add(ba);
00135       return ba;
00136     } catch (Exception e) {
00137       dir.delete();
00138       throw e;
00139     }
00140   }
00141 
00142 
00152   public BundleArchive updateBundleArchive(BundleArchive old, InputStream is)
00153     throws Exception
00154   {
00155     return new BundleArchiveImpl((BundleArchiveImpl)old, is);
00156   }
00157 
00158 
00167   public void replaceBundleArchive(BundleArchive oldBA, BundleArchive newBA)
00168     throws Exception
00169   {
00170     int pos;
00171     long id = oldBA.getBundleId();
00172     synchronized (archives) {
00173       pos = find(id);
00174       if (pos >= archives.size() || archives.get(pos) != oldBA) {
00175         throw new Exception("replaceBundleJar: Old bundle archive not found, pos=" + pos);
00176       }
00177       archives.set(pos, newBA);
00178     }
00179   }
00180 
00181 
00187   public BundleArchive [] getAllBundleArchives() {
00188     synchronized (archives) {
00189       return (BundleArchive [])archives.toArray(new BundleArchive[archives.size()]);
00190     }
00191   }
00192 
00199   public List getStartOnLaunchBundles() {
00200     ArrayList res = new ArrayList();
00201     for (Iterator i = archives.iterator(); i.hasNext(); ) {
00202       BundleArchive ba = (BundleArchive)i.next();
00203       if (ba.getStartOnLaunchFlag()) {
00204         res.add(ba.getBundleLocation());
00205       }
00206     }
00207     return res;
00208   }
00209 
00210   //
00211   // Package methods
00212   //
00213 
00220   boolean removeArchive(BundleArchive ba) {
00221     synchronized (archives) {
00222       int pos = find(ba.getBundleId());
00223       if (archives.get(pos) == ba) {
00224         archives.remove(pos);
00225         return true;
00226       } else {
00227         return false;
00228       }
00229     }
00230   }
00231 
00232 
00233   //
00234   // Private methods
00235   //
00236 
00243   private int find(long id) {
00244     int lb = 0;
00245     int ub = archives.size() - 1;
00246     int x = 0;
00247     while (lb < ub) {
00248       x = (lb + ub) / 2;
00249       long xid = ((BundleArchive)archives.get(x)).getBundleId();
00250       if (id <= xid) {
00251         ub = x;
00252       } else {
00253         lb = x+1;
00254       }
00255     }
00256     if (lb < archives.size() && ((BundleArchive)archives.get(lb)).getBundleId() < id) {
00257       return lb + 1;
00258     }
00259     return lb;
00260   }
00261 
00262 }

Generated on Mon Jan 11 21:19:13 2010 for OpenMobileIS by  doxygen 1.5.4