BundlePermission.java

00001 /*
00002  * $Header: /cvshome/build/org.osgi.framework/src/org/osgi/framework/BundlePermission.java,v 1.15 2006/06/16 16:31:18 hargrave Exp $
00003  *
00004  * Copyright (c) OSGi Alliance (2004, 2006). All Rights Reserved.
00005  * 
00006  * Licensed under the Apache License, Version 2.0 (the "License");
00007  * you may not use this file except in compliance with the License.
00008  * You may obtain a copy of the License at
00009  *
00010  *      http://www.apache.org/licenses/LICENSE-2.0
00011  *
00012  * Unless required by applicable law or agreed to in writing, software
00013  * distributed under the License is distributed on an "AS IS" BASIS,
00014  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00015  * See the License for the specific language governing permissions and
00016  * limitations under the License.
00017  */
00018 
00019 package org.osgi.framework;
00020 
00021 import java.io.IOException;
00022 import java.security.*;
00023 import java.util.Enumeration;
00024 import java.util.Hashtable;
00025 
00049 public final class BundlePermission extends BasicPermission {
00050 
00051         private static final long       serialVersionUID        = 3257846601685873716L;
00052 
00056         public final static String      PROVIDE                         = "provide";
00057 
00061         public final static String      REQUIRE                         = "require";
00062 
00066         public final static String      HOST                            = "host";
00067 
00071         public final static String      FRAGMENT                        = "fragment";
00072 
00073         private final static int        ACTION_PROVIDE          = 0x00000001;
00074         private final static int        ACTION_REQUIRE          = 0x00000002;
00075         private final static int        ACTION_HOST                     = 0x00000004;
00076         private final static int        ACTION_FRAGMENT         = 0x00000008;
00077         private final static int        ACTION_ALL                      = ACTION_PROVIDE
00078                                                                                                                         | ACTION_REQUIRE
00079                                                                                                                         | ACTION_HOST
00080                                                                                                                         | ACTION_FRAGMENT;
00081         private final static int        ACTION_NONE                     = 0;
00085         private transient int           action_mask                     = ACTION_NONE;
00086 
00092         private String                          actions                         = null;
00093 
00111         public BundlePermission(String symbolicName, String actions) {
00112                 this(symbolicName, getMask(actions));
00113         }
00114 
00121         BundlePermission(String symbolicName, int mask) {
00122                 super(symbolicName);
00123                 init(mask);
00124         }
00125 
00131         private void init(int mask) {
00132                 if ((mask == ACTION_NONE) || ((mask & ACTION_ALL) != mask)) {
00133                         throw new IllegalArgumentException("invalid action string");
00134                 }
00135 
00136                 action_mask = mask;
00137         }
00138 
00145         private static int getMask(String actions) {
00146                 boolean seencomma = false;
00147 
00148                 int mask = ACTION_NONE;
00149 
00150                 if (actions == null) {
00151                         return (mask);
00152                 }
00153 
00154                 char[] a = actions.toCharArray();
00155 
00156                 int i = a.length - 1;
00157                 if (i < 0)
00158                         return (mask);
00159 
00160                 while (i != -1) {
00161                         char c;
00162 
00163                         // skip whitespace
00164                         while ((i != -1)
00165                                         && ((c = a[i]) == ' ' || c == '\r' || c == '\n'
00166                                                         || c == '\f' || c == '\t'))
00167                                 i--;
00168 
00169                         // check for the known strings
00170                         int matchlen;
00171 
00172                         if (i >= 6 && (a[i - 6] == 'p' || a[i - 6] == 'P')
00173                                         && (a[i - 5] == 'r' || a[i - 5] == 'R')
00174                                         && (a[i - 4] == 'o' || a[i - 4] == 'O')
00175                                         && (a[i - 3] == 'v' || a[i - 3] == 'V')
00176                                         && (a[i - 2] == 'i' || a[i - 2] == 'I')
00177                                         && (a[i - 1] == 'd' || a[i - 1] == 'D')
00178                                         && (a[i] == 'e' || a[i] == 'E')) {
00179                                 matchlen = 7;
00180                                 mask |= ACTION_PROVIDE | ACTION_REQUIRE;
00181                         }
00182                         else
00183                                 if (i >= 6 && (a[i - 6] == 'r' || a[i - 6] == 'R')
00184                                                 && (a[i - 5] == 'e' || a[i - 5] == 'E')
00185                                                 && (a[i - 4] == 'q' || a[i - 4] == 'Q')
00186                                                 && (a[i - 3] == 'u' || a[i - 3] == 'U')
00187                                                 && (a[i - 2] == 'i' || a[i - 2] == 'I')
00188                                                 && (a[i - 1] == 'r' || a[i - 1] == 'R')
00189                                                 && (a[i] == 'e' || a[i] == 'E')) {
00190                                         matchlen = 7;
00191                                         mask |= ACTION_REQUIRE;
00192                                 }
00193                                 else
00194                                         if (i >= 3 && (a[i - 3] == 'h' || a[i - 3] == 'H')
00195                                                         && (a[i - 2] == 'o' || a[i - 2] == 'O')
00196                                                         && (a[i - 1] == 's' || a[i - 1] == 'S')
00197                                                         && (a[i] == 't' || a[i] == 'T')) {
00198                                                 matchlen = 4;
00199                                                 mask |= ACTION_HOST;
00200                                         }
00201                                         else
00202                                                 if (i >= 7 && (a[i - 7] == 'f' || a[i - 7] == 'F')
00203                                                                 && (a[i - 6] == 'r' || a[i - 6] == 'R')
00204                                                                 && (a[i - 5] == 'a' || a[i - 5] == 'A')
00205                                                                 && (a[i - 4] == 'g' || a[i - 4] == 'G')
00206                                                                 && (a[i - 3] == 'm' || a[i - 3] == 'M')
00207                                                                 && (a[i - 2] == 'e' || a[i - 2] == 'E')
00208                                                                 && (a[i - 1] == 'n' || a[i - 1] == 'N')
00209                                                                 && (a[i] == 't' || a[i] == 'T')) {
00210                                                         matchlen = 8;
00211                                                         mask |= ACTION_FRAGMENT;
00212                                                 }
00213                                                 else {
00214                                                         // parse error
00215                                                         throw new IllegalArgumentException(
00216                                                                         "invalid permission: " + actions);
00217                                                 }
00218 
00219                         // make sure we didn't just match the tail of a word
00220                         // like "ackbarfrequire". Also, skip to the comma.
00221                         seencomma = false;
00222                         while (i >= matchlen && !seencomma) {
00223                                 switch (a[i - matchlen]) {
00224                                         case ',' :
00225                                                 seencomma = true;
00226                                         /* FALLTHROUGH */
00227                                         case ' ' :
00228                                         case '\r' :
00229                                         case '\n' :
00230                                         case '\f' :
00231                                         case '\t' :
00232                                                 break;
00233                                         default :
00234                                                 throw new IllegalArgumentException(
00235                                                                 "invalid permission: " + actions);
00236                                 }
00237                                 i--;
00238                         }
00239 
00240                         // point i at the location of the comma minus one (or -1).
00241                         i -= matchlen;
00242                 }
00243 
00244                 if (seencomma) {
00245                         throw new IllegalArgumentException("invalid permission: " + actions);
00246                 }
00247 
00248                 return (mask);
00249         }
00250 
00276         public boolean implies(Permission p) {
00277                 if (p instanceof BundlePermission) {
00278                         BundlePermission target = (BundlePermission) p;
00279 
00280                         return (((action_mask & target.action_mask) == target.action_mask) && super
00281                                         .implies(p));
00282                 }
00283 
00284                 return (false);
00285         }
00286 
00298         public String getActions() {
00299                 if (actions == null) {
00300                         StringBuffer sb = new StringBuffer();
00301                         boolean comma = false;
00302 
00303                         if ((action_mask & ACTION_PROVIDE) == ACTION_PROVIDE) {
00304                                 sb.append(PROVIDE);
00305                                 comma = true;
00306                         }
00307 
00308                         if ((action_mask & ACTION_REQUIRE) == ACTION_REQUIRE) {
00309                                 if (comma)
00310                                         sb.append(',');
00311                                 sb.append(REQUIRE);
00312                                 comma = true;
00313                         }
00314 
00315                         if ((action_mask & ACTION_HOST) == ACTION_HOST) {
00316                                 if (comma)
00317                                         sb.append(',');
00318                                 sb.append(HOST);
00319                                 comma = true;
00320                         }
00321 
00322                         if ((action_mask & ACTION_FRAGMENT) == ACTION_FRAGMENT) {
00323                                 if (comma)
00324                                         sb.append(',');
00325                                 sb.append(FRAGMENT);
00326                         }
00327 
00328                         actions = sb.toString();
00329                 }
00330 
00331                 return (actions);
00332         }
00333 
00340         public PermissionCollection newPermissionCollection() {
00341                 return (new BundlePermissionCollection());
00342         }
00343 
00358         public boolean equals(Object obj) {
00359                 if (obj == this) {
00360                         return (true);
00361                 }
00362 
00363                 if (!(obj instanceof BundlePermission)) {
00364                         return (false);
00365                 }
00366 
00367                 BundlePermission p = (BundlePermission) obj;
00368 
00369                 return ((action_mask == p.action_mask) && getName().equals(p.getName()));
00370         }
00371 
00378         public int hashCode() {
00379                 return (getName().hashCode() ^ getActions().hashCode());
00380         }
00381 
00389         int getMask() {
00390                 return (action_mask);
00391         }
00392 
00399         private synchronized void writeObject(java.io.ObjectOutputStream s)
00400                         throws IOException {
00401                 // Write out the actions. The superclass takes care of the name
00402                 // call getActions to make sure actions field is initialized
00403                 if (actions == null)
00404                         getActions();
00405                 s.defaultWriteObject();
00406         }
00407 
00412         private synchronized void readObject(java.io.ObjectInputStream s)
00413                         throws IOException, ClassNotFoundException {
00414                 // Read in the action, then initialize the rest
00415                 s.defaultReadObject();
00416                 init(getMask(actions));
00417         }
00418 }
00419 
00428 final class BundlePermissionCollection extends PermissionCollection {
00429 
00433         private static final long       serialVersionUID        = 3258407326846433079L;
00434 
00440         private Hashtable                       permissions;
00441 
00447         private boolean                         all_allowed;
00448 
00454         public BundlePermissionCollection() {
00455                 permissions = new Hashtable();
00456                 all_allowed = false;
00457         }
00458 
00471         public void add(Permission permission) {
00472                 if (!(permission instanceof BundlePermission))
00473                         throw new IllegalArgumentException("invalid permission: "
00474                                         + permission);
00475                 if (isReadOnly())
00476                         throw new SecurityException("attempt to add a Permission to a "
00477                                         + "readonly PermissionCollection");
00478 
00479                 BundlePermission bp = (BundlePermission) permission;
00480                 String name = bp.getName();
00481 
00482                 BundlePermission existing = (BundlePermission) permissions.get(name);
00483 
00484                 if (existing != null) {
00485                         int oldMask = existing.getMask();
00486                         int newMask = bp.getMask();
00487                         if (oldMask != newMask) {
00488                                 permissions.put(name, new BundlePermission(name, oldMask
00489                                                 | newMask));
00490 
00491                         }
00492                 }
00493                 else {
00494                         permissions.put(name, permission);
00495                 }
00496 
00497                 if (!all_allowed) {
00498                         if (name.equals("*"))
00499                                 all_allowed = true;
00500                 }
00501         }
00502 
00515         public boolean implies(Permission permission) {
00516                 if (!(permission instanceof BundlePermission))
00517                         return (false);
00518 
00519                 BundlePermission bp = (BundlePermission) permission;
00520                 BundlePermission x;
00521 
00522                 int desired = bp.getMask();
00523                 int effective = 0;
00524 
00525                 // short circuit if the "*" Permission was added
00526                 if (all_allowed) {
00527                         x = (BundlePermission) permissions.get("*");
00528                         if (x != null) {
00529                                 effective |= x.getMask();
00530                                 if ((effective & desired) == desired)
00531                                         return (true);
00532                         }
00533                 }
00534 
00535                 // strategy:
00536                 // Check for full match first. Then work our way up the
00537                 // name looking for matches on a.b.*
00538 
00539                 String name = bp.getName();
00540 
00541                 x = (BundlePermission) permissions.get(name);
00542 
00543                 if (x != null) {
00544                         // we have a direct hit!
00545                         effective |= x.getMask();
00546                         if ((effective & desired) == desired)
00547                                 return (true);
00548                 }
00549 
00550                 // work our way up the tree...
00551                 int last, offset;
00552 
00553                 offset = name.length() - 1;
00554 
00555                 while ((last = name.lastIndexOf(".", offset)) != -1) {
00556 
00557                         name = name.substring(0, last + 1) + "*";
00558                         x = (BundlePermission) permissions.get(name);
00559 
00560                         if (x != null) {
00561                                 effective |= x.getMask();
00562                                 if ((effective & desired) == desired)
00563                                         return (true);
00564                         }
00565                         offset = last - 1;
00566                 }
00567 
00568                 // we don't have to check for "*" as it was already checked
00569                 // at the top (all_allowed), so we just return false
00570                 return (false);
00571         }
00572 
00580         public Enumeration elements() {
00581                 return (permissions.elements());
00582         }
00583 }

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