AdminPermission.java

00001 /*
00002  * Copyright (c) 2006, KNOPFLERFISH project
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following
00007  * conditions are met:
00008  *
00009  * - Redistributions of source code must retain the above copyright
00010  *   notice, this list of conditions and the following disclaimer.
00011  *
00012  * - Redistributions in binary form must reproduce the above
00013  *   copyright notice, this list of conditions and the following
00014  *   disclaimer in the documentation and/or other materials
00015  *   provided with the distribution.
00016  *
00017  * - Neither the name of the KNOPFLERFISH project nor the names of its
00018  *   contributors may be used to endorse or promote products derived
00019  *   from this software without specific prior written permission.
00020  *
00021  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00022  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00023  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00024  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00025  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00026  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00027  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
00028  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00029  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
00030  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00031  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
00032  * OF THE POSSIBILITY OF SUCH DAMAGE.
00033  */
00034 
00040 /* 
00041  * Copyright (c) OSGi Alliance (2005). All Rights Reserved.
00042  * 
00043  * This program and the accompanying materials are made available under the
00044  * terms of the Eclipse Public License v1.0 which accompanies this 
00045  * distribution, and is available at http://www.eclipse.org/legal/epl-v10.html.
00046  * 
00047  * This copyright applies to the comments and public final static String fields only
00048  */
00049 
00050 package org.osgi.framework;
00051 
00052 
00053 
00054 import java.security.*;
00055 
00056 import org.knopflerfish.framework.*;
00057 
00058 import java.util.Enumeration;
00059 import java.util.StringTokenizer;
00060 import java.util.Hashtable;
00061 
00062 
00112 public final class AdminPermission extends Permission {
00113 
00118         public final static String                      CLASS                           = "class";
00123         public final static String                      EXECUTE                         = "execute";
00129         public final static String                      EXTENSIONLIFECYCLE      = "extensionLifecycle";
00134         public final static String                      LIFECYCLE                       = "lifecycle";
00139         public final static String                      LISTENER                        = "listener";
00144         public final static String                      METADATA                        = "metadata";
00149         public final static String                      RESOLVE                         = "resolve";
00154         public final static String                      RESOURCE                        = "resource";
00159         public final static String                      STARTLEVEL                      = "startlevel";
00160 
00161         
00162         LDAPExpr ldap;
00163         
00164         Bundle bundle;
00165         
00166         int actionMask /*= 0*/;
00167         
00168         private static final String WILDCARD = "*";
00169         
00170         private static final int CLASS_BIT               = 1;
00171         private static final int EXECUTE_BIT             = 2;
00172         private static final int EXTENSIONLIFECYCLE_BIT  = 4;
00173         private static final int LIFECYCLE_BIT           = 8;
00174         private static final int LISTENER_BIT            = 16;
00175         private static final int METADATA_BIT            = 32;
00176         private static final int RESOLVE_BIT             = 64;
00177         private static final int RESOURCE_BIT            = 128;
00178         private static final int STARTLEVEL_BIT          = 256;
00179         private static final int ALL_BITS                = CLASS_BIT  | EXECUTE_BIT  | 
00180                                                            EXTENSIONLIFECYCLE_BIT  | LIFECYCLE_BIT  | 
00181                                                            LISTENER_BIT  | METADATA_BIT  | 
00182                                                            RESOLVE_BIT  | RESOURCE_BIT  | STARTLEVEL_BIT ;
00183          
00188         public AdminPermission() {
00189                 this("*", "*"); //$NON-NLS-1$
00190         }
00191         
00222         public AdminPermission(String filter, String actions) {
00223                 super(filter == null ? (filter = WILDCARD) : filter);
00224                 //TODO implement LDAP extensions for location and signer
00225                 try{
00226                         ldap = new LDAPExpr(filter);
00227                 }
00228                 catch(InvalidSyntaxException e){
00229                         //SPECS what to do?
00230                 }
00231                 parseActions(actions);
00232                 bundle = null;
00233         }
00234 
00247         public AdminPermission(Bundle bundle, String actions) {
00248                 super("BID#" + bundle.getBundleId());
00249                 this.bundle = bundle;
00250                 parseActions(actions);
00251         }
00252         
00253         //package only
00254         AdminPermission(String filter, int actionMask){
00255                 super(filter);
00256                 this.actionMask = actionMask;
00257                 bundle = null;
00258         }
00259         
00260     //package only
00261         AdminPermission(Bundle bundle, int actionMask){
00262                 super("BID#" + bundle.getBundleId());
00263                 this.actionMask = actionMask;
00264         }
00265 
00266 
00267         private void parseActions(String actions){
00268                 StringTokenizer st = new StringTokenizer(actions, ",");
00269                 while(st.hasMoreTokens()){
00270                         String tok = st.nextToken();
00271                         if(tok.equals(CLASS)){
00272                                 actionMask |= CLASS_BIT ;
00273                         }
00274                         else if(tok.equals(EXECUTE)){
00275                                 actionMask |= EXECUTE_BIT ;
00276                         }
00277                         else if(tok.equals(EXTENSIONLIFECYCLE)){
00278                                 actionMask |= EXTENSIONLIFECYCLE_BIT ;
00279                         }
00280                         else if(tok.equals(LIFECYCLE)){
00281                                 actionMask |= LIFECYCLE_BIT ;
00282                         }
00283                         else if(tok.equals(LISTENER)){
00284                                 actionMask |= LISTENER_BIT ;
00285                         }
00286                         else if(tok.equals(METADATA)){
00287                                 actionMask |= METADATA_BIT ;
00288                         }
00289                         else if(tok.equals(RESOLVE)){
00290                                 actionMask |= RESOLVE_BIT ;
00291                         }
00292                         else if(tok.equals(RESOURCE)){
00293                                 actionMask |= RESOURCE_BIT ;
00294                         }
00295                         else if(tok.equals(STARTLEVEL)){
00296                                 actionMask |= STARTLEVEL_BIT ;
00297                         }
00298                         else if(tok.equals("*")){
00299                                 actionMask = ALL_BITS ;
00300                         }
00301                         else{
00302                                 throw new IllegalArgumentException("Unknown action " + tok);
00303                         }
00304                 }       
00305         }
00306 
00314         public boolean equals(Object obj) {
00315                 if (obj == this) {
00316                         return true;
00317                 }
00318 
00319                 if (!(obj instanceof AdminPermission)) {
00320                         return false;
00321                 }
00322 
00323                 AdminPermission ap = (AdminPermission) obj;
00324                 
00325                 if(bundle == null){
00326                         return ((actionMask == ap.actionMask) && getName().equals(ap.getName()));
00327                 }
00328                 else{
00329                         return (actionMask == ap.actionMask  && bundle == ap.bundle);
00330                 }
00331         }
00332 
00338         public int hashCode() {
00339                 if(bundle == null){
00340                         return getName().hashCode() ^ actionMask;
00341                 }
00342                 else{
00343                         return bundle.hashCode() ^ actionMask;
00344                 }       
00345         }
00346 
00361         public String getActions() {
00362                 StringBuffer sb = new StringBuffer();
00363                 
00364                 if((actionMask & CLASS_BIT ) != 0){
00365                         sb.append(CLASS);
00366                         sb.append(',');
00367                 }
00368                 if((actionMask & EXECUTE_BIT ) != 0){
00369                         sb.append(EXECUTE);
00370                         sb.append(',');
00371                 }
00372                 if((actionMask & EXTENSIONLIFECYCLE_BIT ) != 0){
00373                         sb.append(EXTENSIONLIFECYCLE);
00374                         sb.append(',');
00375                 }
00376                 if((actionMask & LIFECYCLE_BIT ) != 0){
00377                         sb.append(LIFECYCLE);
00378                         sb.append(',');
00379                 }
00380                 if((actionMask & LISTENER_BIT ) != 0){
00381                         sb.append(LISTENER);
00382                         sb.append(',');
00383                 }
00384                 if((actionMask & METADATA_BIT ) != 0){
00385                         sb.append(METADATA);
00386                         sb.append(',');
00387                 }
00388                 if((actionMask & RESOLVE_BIT ) != 0){
00389                         sb.append(RESOLVE);
00390                         sb.append(',');
00391                 }
00392                 if((actionMask & RESOURCE_BIT ) != 0){
00393                         sb.append(RESOURCE);
00394                         sb.append(',');
00395                 }
00396                 if((actionMask & STARTLEVEL_BIT ) != 0){
00397                         sb.append(STARTLEVEL);
00398                         sb.append(',');
00399                 }
00400                 
00401                 int length = sb.length();
00402                 if(length > 0){
00403                         sb.deleteCharAt(length - 1);
00404                 }
00405                 return sb.toString();
00406         }
00407 
00408         private boolean match(final AdminPermission ap){
00409             // TODO, more efficient impl?
00410             final Hashtable t = new Hashtable();
00411             AccessController.doPrivileged(new PrivilegedAction() {
00412                 public Object run() {
00413                   t.put("id", new Long(ap.bundle.getBundleId()));       
00414                   t.put("location", ap.bundle.getLocation());
00415                   t.put("name", ap.bundle.getSymbolicName());
00416                   return null;
00417                 }
00418               });
00419             //SPECS should it be case sensitive or not?
00420             return ldap.evaluate(t, false);
00421         }
00422         
00452         public boolean implies(Permission p) {
00453                 if (!(p instanceof AdminPermission)) {
00454                         return false;
00455                 }
00456                 AdminPermission ap = (AdminPermission) p;
00457                 if(ap.bundle == null && !ap.getName().equals(WILDCARD)){
00458                         throw new RuntimeException("permission not contructed with bundle or *");
00459                 }
00460 
00461                 if ((actionMask & ap.actionMask) != ap.actionMask) {
00462                     return false;
00463                 }
00464                 if (bundle != null) { 
00465                         return bundle == ap.bundle || ap.getName().equals(WILDCARD);
00466                 } else {
00467                         return getName().equals(WILDCARD) || match(ap);
00468                 }
00469         }
00470 
00477         public PermissionCollection newPermissionCollection() {
00478                 return new AdminPermissionCollection();
00479         }
00480 }
00481 
00482 
00483 
00484 final class AdminPermissionCollection extends PermissionCollection {
00485         
00486         private Hashtable permissions;
00487 
00488         private boolean addedAll;
00489         private int allMask /* = 0 */;
00490 
00491         public AdminPermissionCollection() {
00492                 permissions = new Hashtable();
00493                 addedAll = false;
00494         }
00495 
00496         public void add(Permission permission) {
00497                 if (isReadOnly())
00498                         throw new SecurityException("read only PermissionCollection");
00499                 if (!(permission instanceof AdminPermission))
00500                         throw new IllegalArgumentException("invalid permission: " + permission);
00501 
00502                 AdminPermission ap = (AdminPermission) permission;
00503                 AdminPermission existing;
00504                 String name = null;
00505                 
00506                 if(ap.bundle != null){
00507                         existing = (AdminPermission) permissions.get(ap.bundle);
00508                 }
00509                 else{
00510                         existing = (AdminPermission) permissions.get(name = ap.getName());
00511                 }
00512                 
00513                 if (existing != null) {
00514                         int oldMask = existing.actionMask;
00515                         int newMask = ap.actionMask;
00516                         if (oldMask != newMask) {
00517                                 if(ap.bundle != null){
00518                                         permissions.put(ap.bundle, new AdminPermission(ap.bundle, oldMask | newMask));
00519                                 }
00520                                 else{
00521                                         permissions.put(name, new AdminPermission(name, oldMask | newMask));
00522                                 }       
00523                         }
00524                 }
00525                 else {
00526                         if(ap.bundle != null){
00527                                 permissions.put(ap.bundle, permission);
00528                         }
00529                         else{
00530                                 permissions.put(name, permission);
00531                         }       
00532                 }
00533 
00534                 if (name != null && name.equals("*")){
00535                         addedAll = true;
00536                         allMask |= ap.actionMask;  
00537                 }               
00538         }
00539 
00540         public boolean implies(Permission permission) {
00541                 if (!(permission instanceof AdminPermission))
00542                         return (false);
00543 
00544                 AdminPermission ap = (AdminPermission)permission;
00545                 if (addedAll && ((allMask | ap.actionMask) == allMask)){
00546                     return true;
00547                 }
00548                 if(ap.bundle != null){
00549                         Permission inTable = (Permission) permissions.get(ap.bundle);
00550                         if (inTable == null)
00551                     return false;
00552                 
00553                 return inTable.implies(ap);
00554                 }
00555                 else{
00556                         Enumeration enume = permissions.keys();
00557                         while(enume.hasMoreElements()){
00558                                 if(((Permission) permissions.get(enume.nextElement())).implies(permission)){
00559                                         return true;
00560                                 }
00561                         }
00562                         return false;
00563                 }         
00564         }
00565 
00566         public Enumeration elements() {
00567                 return (permissions.elements());
00568         }
00569 }
00570 
00571 

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