import dolda.jsvc.*;
import dolda.jsvc.util.Misc;
import java.io.*;
-import java.security.*;
-import java.security.cert.Certificate;
import java.util.*;
-public class Store {
+public abstract class Store implements Iterable<File> {
+ private static Map<String, Factory> kinds = new TreeMap<String, Factory>();
private static Map<Package, Store> interned = new WeakHashMap<Package, Store>();
- private final Package pkg;
- private final File base;
+ protected final Package pkg;
- private Store(Package pkg, CodeSource src, File root) {
+ protected Store(Package pkg) {
this.pkg = pkg;
- String nm = pkg.getName();
- File base = root;
- if(src != null) {
- try {
- MessageDigest fdig = MessageDigest.getInstance("MD5");
- for(Certificate cert : src.getCertificates()) {
- MessageDigest cdig = MessageDigest.getInstance("MD5");
- cdig.update(cert.getEncoded());
- fdig.update(cdig.digest());
- }
- byte[] fp = fdig.digest();
- StringBuilder buf = new StringBuilder();
- for(byte b : fp) {
- buf.append(Misc.int2hex((b & 0xf0) >> 4, true));
- buf.append(Misc.int2hex(b & 0x0f, true));
- }
- base = new File(base, buf.toString());
- } catch(NoSuchAlgorithmException e) {
- throw(new Error(e));
- } catch(java.security.cert.CertificateEncodingException e) {
- throw(new Error(e));
- }
- }
- int p = 0;
- int p2;
- while((p2 = nm.indexOf('.', p)) >= 0) {
- base = new File(base, nm.substring(p, p2));
- p = p2 + 1;
- }
- this.base = new File(base, nm.substring(p));
}
- private static File getstoreroot() {
+ public abstract File get(String name);
+
+ public static interface Factory {
+ public Store create(String root, Package pkg);
+ }
+
+ private static String getstoreroot() {
ThreadContext ctx = ThreadContext.current();
if(ctx == null)
throw(new RuntimeException("Not running in jsvc context"));
- String bn = ctx.server().config("jsvc.storage");
+ String bn = ctx.server().sysconfig("jsvc.storage", null);
if(bn == null)
throw(new RuntimeException("No storage root has been configured"));
- return(new File(bn));
+ return(bn);
}
-
+
public static Store forclass(final Class<?> cl) {
Package pkg = cl.getPackage();
- File root = getstoreroot();
Store s;
synchronized(interned) {
s = interned.get(pkg);
if(s == null) {
- ProtectionDomain dom;
- dom = AccessController.doPrivileged(new PrivilegedAction<ProtectionDomain>() {
- public ProtectionDomain run() {
- try {
- return(cl.getProtectionDomain());
- } catch(SecurityException e) {
- return(null);
- }
- }
- });
- if(dom != null)
- s = new Store(pkg, dom.getCodeSource(), root);
- else
- s = new Store(pkg, null, root);
+ String root = getstoreroot();
+ int p = root.indexOf(':');
+ if(p < 0)
+ throw(new RuntimeException("Invalid store specification: " + root));
+ String kind = root.substring(0, p);
+ root = root.substring(p + 1);
+ Factory fac;
+ synchronized(kinds) {
+ fac = kinds.get(kind);
+ if(fac == null)
+ throw(new RuntimeException("No such store kind: " + kind));
+ }
+ s = fac.create(root, pkg);
interned.put(pkg, s);
}
}
return(s);
}
+
+ public static void register(String kind, Factory fac) {
+ synchronized(kinds) {
+ if(!kinds.containsKey(kind))
+ kinds.put(kind, fac);
+ else
+ throw(new RuntimeException("Store of type " + kind + " already exists"));
+ }
+ }
+
+ static {
+ FileStore.register();
+ }
}