Started a basic storage manager.
[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.security.*;
7 import java.security.cert.Certificate;
8 import java.util.*;
9
10 public class Store {
11     private static Map<Package, Store> interned = new WeakHashMap<Package, Store>();
12     private final Package pkg;
13     private final File base;
14     
15     private Store(Package pkg, CodeSource src, File root) {
16         this.pkg = pkg;
17         String nm = pkg.getName();
18         File base = root;
19         if(src != null) {
20             try {
21                 MessageDigest fdig = MessageDigest.getInstance("MD5");
22                 for(Certificate cert : src.getCertificates()) {
23                     MessageDigest cdig = MessageDigest.getInstance("MD5");
24                     cdig.update(cert.getEncoded());
25                     fdig.update(cdig.digest());
26                 }
27                 byte[] fp = fdig.digest();
28                 StringBuilder buf = new StringBuilder();
29                 for(byte b : fp) {
30                     buf.append(Misc.int2hex((b & 0xf0) >> 4, true));
31                     buf.append(Misc.int2hex(b & 0x0f, true));
32                 }
33                 base = new File(base, buf.toString());
34             } catch(NoSuchAlgorithmException e) {
35                 throw(new Error(e));
36             } catch(java.security.cert.CertificateEncodingException e) {
37                 throw(new Error(e));
38             }
39         }
40         int p = 0;
41         int p2;
42         while((p2 = nm.indexOf('.', p)) >= 0) {
43             base = new File(base, nm.substring(p, p2));
44             p = p2 + 1;
45         }
46         this.base = new File(base, nm.substring(p));
47     }
48     
49     private static File getstoreroot() {
50         ThreadContext ctx = ThreadContext.current();
51         if(ctx == null)
52             throw(new RuntimeException("Not running in jsvc context"));
53         String bn = ctx.server().config("jsvc.storage");
54         if(bn == null)
55             throw(new RuntimeException("No storage root has been configured"));
56         return(new File(bn));
57     }
58
59     public static Store forclass(final Class<?> cl) {
60         Package pkg = cl.getPackage();
61         File root = getstoreroot();
62         Store s;
63         synchronized(interned) {
64             s = interned.get(pkg);
65             if(s == null) {
66                 ProtectionDomain dom;
67                 dom = AccessController.doPrivileged(new PrivilegedAction<ProtectionDomain>() {
68                         public ProtectionDomain run() {
69                             try {
70                                 return(cl.getProtectionDomain());
71                             } catch(SecurityException e) {
72                                 return(null);
73                             }
74                         }
75                     });
76                 if(dom != null)
77                     s = new Store(pkg, dom.getCodeSource(), root);
78                 else
79                     s = new Store(pkg, null, root);
80                 interned.put(pkg, s);
81             }
82         }
83         return(s);
84     }
85 }