00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 package org.knopflerfish.framework.permissions;
00036
00037 import java.io.*;
00038 import java.security.*;
00039 import java.util.ArrayList;
00040 import java.util.HashMap;
00041 import java.util.Iterator;
00042
00043 import org.osgi.service.permissionadmin.PermissionInfo;
00044 import org.knopflerfish.framework.Util;
00045
00046
00047 class PermissionInfoStorage {
00048
00049 final static String DEFAULTPERM = "(java.security.AllPermission)";
00050
00051 private PermissionInfo[] initialDefault = null;
00052
00053 private File permDir;
00054
00055 private long lastPermFile;
00056
00057 private HashMap permissions = new HashMap();
00058
00059 private PermissionInfo[] defaultPermissions;
00060
00061 private HashMap defaultInvalidateCallbacks = new HashMap();
00062
00063
00064 public PermissionInfoStorage() {
00065 initialDefault = new PermissionInfo[] { new PermissionInfo(DEFAULTPERM) };
00066 defaultPermissions = initialDefault;
00067
00068 permDir = Util.getFileStorage("perms");
00069 if (permDir == null) {
00070 System.err.println("Property org.osgi.framework.dir not set," +
00071 "permission data will not be saved between sessions");
00072 } else {
00073 load();
00074 }
00075 }
00076
00077
00084 synchronized PermissionInfo[] get(String location, PermissionsWrapper callInvalidate) {
00085 Element res = (Element) permissions.get(location);
00086 if (res != null) {
00087 if (callInvalidate != null) {
00088 if (res.invalidateCallback == null) {
00089 res.invalidateCallback = new ArrayList(2);
00090 }
00091 res.invalidateCallback.add(callInvalidate);
00092 }
00093 return res.pi;
00094 }
00095 return null;
00096 }
00097
00098
00107 synchronized PermissionInfo[] getDefault(PermissionsWrapper callInvalidate) {
00108 if (callInvalidate != null) {
00109 ArrayList cil = (ArrayList)defaultInvalidateCallbacks.get(callInvalidate.location);
00110 if (cil == null) {
00111 cil = new ArrayList(2);
00112 defaultInvalidateCallbacks.put(callInvalidate.location, cil);
00113 }
00114 cil.add(callInvalidate);
00115 }
00116 return defaultPermissions;
00117 }
00118
00119
00127 synchronized String [] getKeys() {
00128 int size = permissions.size();
00129 if (size == 0) {
00130 return null;
00131 } else {
00132 String [] res = new String [size];
00133 int ix = 0;
00134 for (Iterator i = permissions.keySet().iterator(); i.hasNext();) {
00135 res[ix++] = (String)i.next();
00136 }
00137 return res;
00138 }
00139 }
00140
00141
00151 synchronized void put(String location, PermissionInfo[] perms) {
00152 Element old = (Element)permissions.put(location, new Element(perms));
00153 save(location, perms);
00154 ArrayList vpw = old != null ? old.invalidateCallback :
00155 (ArrayList)defaultInvalidateCallbacks.remove(location);
00156 if (vpw != null) {
00157 for (Iterator i = vpw.iterator(); i.hasNext(); ) {
00158 ((PermissionsWrapper)i.next()).invalidate();
00159 }
00160 }
00161 }
00162
00163
00176 synchronized void putDefault(PermissionInfo[] permissions) {
00177 if (permissions != null) {
00178 defaultPermissions = permissions;
00179 } else {
00180 defaultPermissions = initialDefault;
00181 }
00182 save(null, defaultPermissions);
00183 for (Iterator i = defaultInvalidateCallbacks.values().iterator(); i.hasNext(); ) {
00184 for (Iterator j = ((ArrayList)i.next()).iterator(); j.hasNext(); ) {
00185 ((PermissionsWrapper)j.next()).invalidate();
00186 }
00187 }
00188 defaultInvalidateCallbacks.clear();
00189 }
00190
00191
00198 synchronized void remove(String location) {
00199 Element old = (Element)permissions.remove(location);
00200 save(location, null);
00201 if (old != null && old.invalidateCallback != null) {
00202 for (Iterator i = old.invalidateCallback.iterator(); i.hasNext(); ) {
00203 ((PermissionsWrapper)i.next()).invalidate();
00204 }
00205 }
00206 }
00207
00208
00215 synchronized void purgeCallback(PermissionCollection pc) {
00216 PermissionsWrapper pw = (PermissionsWrapper)pc;
00217 Element e = (Element)permissions.get(pw.location);
00218 if (e != null && e.invalidateCallback != null && e.invalidateCallback.remove(pw)) {
00219 if (e.invalidateCallback.isEmpty()) {
00220 e.invalidateCallback = null;
00221 }
00222 } else {
00223 ArrayList cil = (ArrayList)defaultInvalidateCallbacks.get(pw.location);
00224 if (cil != null && cil.remove(pw)) {
00225 if (cil.isEmpty()) {
00226 defaultInvalidateCallbacks.remove(pw);
00227 }
00228 }
00229 }
00230 }
00231
00232
00233
00234
00235
00239 private void save(final String location, final PermissionInfo [] perms) {
00240 if (permDir != null) {
00241 AccessController.doPrivileged(new PrivilegedAction() {
00242 public Object run() {
00243 File f;
00244 String loc;
00245 if (location != null) {
00246 if (lastPermFile % 20 == 0) {
00247 purge();
00248 }
00249 f = new File(permDir, Long.toString(++lastPermFile));
00250 loc = location;
00251 } else {
00252
00253 f = new File(permDir, "default");
00254 loc = "defaultPermissions";
00255 }
00256 BufferedWriter out = null;
00257 try {
00258 out = new BufferedWriter(new FileWriter(f));
00259 int p;
00260 while ((p = loc.indexOf('\n')) != -1) {
00261 out.write(loc.substring(0, ++p) + " ");
00262 loc = loc.substring(p);
00263 }
00264 out.write(loc + "\n\n");
00265 if (perms != null) {
00266 for (int i = 0; i < perms.length; i++) {
00267 out.write(perms[i].getEncoded() + "\n");
00268 }
00269 } else {
00270 out.write("NULL\n");
00271 }
00272 out.write("\n");
00273 out.close();
00274 } catch (IOException e) {
00275 if (out != null) {
00276 try {
00277 out.close();
00278 } catch (IOException ignore) { }
00279 f.delete();
00280 }
00281
00282 }
00283 return null;
00284 }
00285 });
00286 }
00287 }
00288
00289
00293 private void load() {
00294 File[] files = getSortedFiles();
00295 for (int i = 0; i < files.length; i++) {
00296 load(files[i]);
00297 }
00298 }
00299
00303 private void load(File fh) {
00304 BufferedReader in = null;
00305 boolean isDefault = "default".equals(fh.getName());
00306 try {
00307 in = new BufferedReader(new FileReader(fh));
00308 String loc = parseLocation(in);
00309 ArrayList piv = new ArrayList();
00310
00311 int c = in.read();
00312 while (c != -1) {
00313 StringBuffer pe = new StringBuffer();
00314 while (c != -1 && c != (int)'\n') {
00315 pe.append((char) c);
00316 c = in.read();
00317 }
00318 String line = pe.toString();
00319 if ("NULL".equals(line)) {
00320
00321 if (isDefault) {
00322 defaultPermissions = null;
00323 } else {
00324 permissions.remove(loc);
00325 }
00326 try {
00327 in.close();
00328 } catch (IOException ignore) { }
00329 return;
00330 } else if ("".equals(line)) {
00331
00332 break;
00333 }
00334 piv.add(new PermissionInfo(line));
00335 c = in.read();
00336 }
00337 if (c == -1) {
00338 throw new IOException("Premature EOF when parsing permission file: " + fh.getName());
00339 }
00340 if (in.read() != -1) {
00341 throw new IOException("Garbage at end of file when parsing permission file: " + fh.getName());
00342 }
00343 in.close();
00344 PermissionInfo[] pi = new PermissionInfo[piv.size()];
00345 piv.toArray(pi);
00346 if (isDefault) {
00347 defaultPermissions = pi;
00348 } else {
00349 permissions.put(loc, new Element(pi));
00350 }
00351 } catch (IOException e) {
00352 if (in != null) {
00353 try {
00354 in.close();
00355 } catch (IOException ignore) { }
00356 }
00357
00358 }
00359 }
00360
00364 private String parseLocation(Reader in) throws IOException {
00365 StringBuffer loc = new StringBuffer();
00366 int c;
00367
00368 while ((c = in.read()) != -1) {
00369 char cc = (char)c;
00370 if (cc == '\n') {
00371 c = in.read();
00372 if (c != (int)' ') {
00373 break;
00374 }
00375 }
00376 loc.append(cc);
00377 }
00378 return loc.toString();
00379 }
00380
00385 private void purge() {
00386 HashMap foundTwo = new HashMap();
00387 File[] files = getSortedFiles();
00388 for (int i = files.length - 1; i >= 0; i--) {
00389 String loc;
00390 BufferedReader in = null;
00391 try {
00392 in = new BufferedReader(new FileReader(files[i]));
00393 loc = parseLocation(in);
00394 } catch (IOException ignore) {
00395 files[i].delete();
00396 continue;
00397 } finally {
00398 if (in != null) {
00399 try {
00400 in.close();
00401 } catch (IOException ignore) { }
00402 }
00403 }
00404 Boolean v = (Boolean)foundTwo.get(loc);
00405 if (v != null) {
00406 if (v.booleanValue()) {
00407 files[i].delete();
00408 } else {
00409 foundTwo.put(loc, new Boolean(true));
00410 }
00411 } else {
00412 foundTwo.put(loc, new Boolean(false));
00413 }
00414 }
00415 }
00416
00421 private File[] getSortedFiles() {
00422 String[] files = permDir.list();
00423 File[] res = new File[files.length];
00424 long[] lfiles = new long[files.length];
00425 int lf = -1;
00426 int pos = 0;
00427 for (int i = 0; i < files.length; i++) {
00428 try {
00429 long fval = Long.parseLong(files[i]);
00430 int j;
00431 for (j = lf; j >= 0; j--) {
00432 if (fval > lfiles[j]) {
00433 break;
00434 }
00435 }
00436 if (j >= lf) {
00437 lfiles[++lf] = fval;
00438 } else {
00439 lf++;
00440 j++;
00441 System.arraycopy(lfiles, j, lfiles, j+1, lf-j);
00442 lfiles[j] = fval;
00443 }
00444 files[i] = null;
00445 } catch (NumberFormatException ignore) {
00446 res[pos++] = new File(permDir, files[i]);
00447 }
00448 }
00449 for (int i = 0; i <= lf; i++) {
00450 res[pos++] = new File(permDir, Long.toString(lfiles[i]));
00451 }
00452 lastPermFile = (lf >= 0) ? lfiles[lf] : -1;
00453 return res;
00454 }
00455
00456 class Element {
00457 PermissionInfo[] pi;
00458 ArrayList invalidateCallback = null;
00459
00460 Element(PermissionInfo[] pi) {
00461 this.pi = pi;
00462 }
00463 }
00464 }