Improved the store library massively and added a preliminary filesystem store.
[jsvc.git] / src / dolda / jsvc / store / Store.java
1 package dolda.jsvc.store;
2
3 import dolda.jsvc.*;
4 import dolda.jsvc.util.Misc;
5 import java.io.*;
6 import java.util.*;
7
8 public abstract class Store implements Iterable<File> {
9     private static Map<String, Factory> kinds = new TreeMap<String, Factory>();
10     private static Map<Package, Store> interned = new WeakHashMap<Package, Store>();
11     protected final Package pkg;
12     
13     protected Store(Package pkg) {
14         this.pkg = pkg;
15     }
16     
17     public abstract File get(String name);
18     
19     public static interface Factory {
20         public Store create(String root, Package pkg);
21     }
22
23     private static String getstoreroot() {
24         ThreadContext ctx = ThreadContext.current();
25         if(ctx == null)
26             throw(new RuntimeException("Not running in jsvc context"));
27         String bn = ctx.server().config("jsvc.storage");
28         if(bn == null)
29             throw(new RuntimeException("No storage root has been configured"));
30         return(bn);
31     }
32     
33     public static Store forclass(final Class<?> cl) {
34         Package pkg = cl.getPackage();
35         Store s;
36         synchronized(interned) {
37             s = interned.get(pkg);
38             if(s == null) {
39                 String root = getstoreroot();
40                 int p = root.indexOf(':');
41                 if(p < 0)
42                     throw(new RuntimeException("Invalid store specification: " + root));
43                 String kind = root.substring(0, p);
44                 root = root.substring(p + 1);
45                 Factory fac;
46                 synchronized(kinds) {
47                     fac = kinds.get(kind);
48                     if(fac == null)
49                         throw(new RuntimeException("No such store kind: " + kind));
50                 }
51                 s = fac.create(root, pkg);
52                 interned.put(pkg, s);
53             }
54         }
55         return(s);
56     }
57     
58     public static void register(String kind, Factory fac) {
59         synchronized(kinds) {
60             if(!kinds.containsKey(kind))
61                 kinds.put(kind, fac);
62             else
63                 throw(new RuntimeException("Store of type " + kind + " already exists"));
64         }
65     }
66     
67     static {
68         FileStore.register();
69     }
70 }