blob: d2846c9b38753cf64364c015a3d84078ad44aeea [file] [log] [blame]
Richard S. Hallace5ff32006-03-16 15:57:37 +00001/*
2 * $Header: /cvshome/build/org.osgi.framework/src/org/osgi/framework/AdminPermission.java,v 1.28 2006/03/14 01:21:02 hargrave Exp $
3 *
4 * Copyright (c) OSGi Alliance (2000, 2005). All Rights Reserved.
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19package org.osgi.framework;
20
21import java.lang.reflect.Constructor;
22import java.lang.reflect.InvocationTargetException;
23import java.security.*;
24
25/**
26 * Indicates the caller's authority to perform specific privileged
27 * administrative operations on or to get sensitive information about a bundle.
28 * The actions for this permission are:
29 *
30 * <pre>
31 * Action Methods
32 * class Bundle.loadClass
33 * execute Bundle.start
34 * Bundle.stop
35 * StartLevel.setBundleStartLevel
36 * extensionLifecycle BundleContext.installBundle for extension bundles
37 * Bundle.update for extension bundles
38 * Bundle.uninstall for extension bundles
39 * lifecycle BundleContext.installBundle
40 * Bundle.update
41 * Bundle.uninstall
42 * listener BundleContext.addBundleListener for SynchronousBundleListener
43 * BundleContext.removeBundleListener for SynchronousBundleListener
44 * metadata Bundle.getHeaders
45 * Bundle.getLocation
46 * resolve PackageAdmin.refreshPackages
47 * PackageAdmin.resolveBundles
48 * resource Bundle.getResource
49 * Bundle.getResources
50 * Bundle.getEntry
51 * Bundle.getEntryPaths
52 * Bundle.findEntries
53 * Bundle resource/entry URL creation
54 * startlevel StartLevel.setStartLevel
55 * StartLevel.setInitialBundleStartLevel
56 * </pre>
57 *
58 * <p>
59 * The special action "*" will represent all actions.
60 * <p>
61 * The name of this permission is a filter expression. The filter gives access
62 * to the following parameters:
63 * <ul>
64 * <li>signer - A Distinguished Name chain used to sign a bundle. Wildcards in
65 * a DN are not matched according to the filter string rules, but according to
66 * the rules defined for a DN chain.</li>
67 * <li>location - The location of a bundle.</li>
68 * <li>id - The bundle ID of the designated bundle.</li>
69 * <li>name - The symbolic name of a bundle.</li>
70 * </ul>
71 *
72 * @version $Revision: 1.28 $
73 */
74
75public final class AdminPermission extends BasicPermission {
76 static final long serialVersionUID = 307051004521261705L;
77
78 /**
79 * The action string <code>class</code> (Value is "class").
80 * @since 1.3
81 */
82 public final static String CLASS = "class";
83 /**
84 * The action string <code>execute</code> (Value is "execute").
85 * @since 1.3
86 */
87 public final static String EXECUTE = "execute";
88 /**
89 * The action string <code>extensionLifecycle</code> (Value is
90 * "extensionLifecycle").
91 * @since 1.3
92 */
93 public final static String EXTENSIONLIFECYCLE = "extensionLifecycle";
94 /**
95 * The action string <code>lifecycle</code> (Value is "lifecycle").
96 * @since 1.3
97 */
98 public final static String LIFECYCLE = "lifecycle";
99 /**
100 * The action string <code>listener</code> (Value is "listener").
101 * @since 1.3
102 */
103 public final static String LISTENER = "listener";
104 /**
105 * The action string <code>metadata</code> (Value is "metadata").
106 * @since 1.3
107 */
108 public final static String METADATA = "metadata";
109 /**
110 * The action string <code>resolve</code> (Value is "resolve").
111 * @since 1.3
112 */
113 public final static String RESOLVE = "resolve";
114 /**
115 * The action string <code>resource</code> (Value is "resource").
116 * @since 1.3
117 */
118 public final static String RESOURCE = "resource";
119 /**
120 * The action string <code>startlevel</code> (Value is "startlevel").
121 * @since 1.3
122 */
123 public final static String STARTLEVEL = "startlevel";
124
125 /*
126 * NOTE: A framework implementor may also choose to replace this class in
127 * their distribution with a class that directly interfaces with the
128 * framework implementation. This replacement class MUST NOT
129 * alter the public/protected signature of this class.
130 */
131
132 /*
133 * This class will load the AdminPermission class in the package named by
134 * the org.osgi.vendor.framework package. For each instance of this class,
135 * an instance of the vendor AdminPermission class will be created and this
136 * class will delegate method calls to the vendor AdminPermission instance.
137 */
138 private static final String packageProperty = "org.osgi.vendor.framework";
139 private static final Constructor initStringString;
140 private static final Constructor initBundleString;
141 static {
142 Constructor[] constructors = (Constructor[]) AccessController
143 .doPrivileged(new PrivilegedAction() {
144 public Object run() {
145 String packageName = System
146 .getProperty(packageProperty);
147 if (packageName == null) {
148 throw new NoClassDefFoundError(packageProperty
149 + " property not set");
150 }
151
152 Class delegateClass;
153 try {
154 delegateClass = Class.forName(packageName
155 + ".AdminPermission");
156 }
157 catch (ClassNotFoundException e) {
158 throw new NoClassDefFoundError(e.toString());
159 }
160
161 Constructor[] result = new Constructor[2];
162 try {
163 result[0] = delegateClass
164 .getConstructor(new Class[] {String.class,
165 String.class });
166 result[1] = delegateClass
167 .getConstructor(new Class[] {Bundle.class,
168 String.class });
169 }
170 catch (NoSuchMethodException e) {
171 throw new NoSuchMethodError(e.toString());
172 }
173
174 return result;
175 }
176 });
177
178 initStringString = constructors[0];
179 initBundleString = constructors[1];
180 }
181
182 /*
183 * This is the delegate permission created by the constructor.
184 */
185 private final Permission delegate;
186
187 /**
188 * Creates a new <code>AdminPermission</code> object that matches all
189 * bundles and has all actions. Equivalent to AdminPermission("*","*");
190 */
191 public AdminPermission() {
192 this("*", "*"); //$NON-NLS-1$
193 }
194
195 /**
196 * Create a new AdminPermission.
197 *
198 * This constructor must only be used to create a permission that is going
199 * to be checked.
200 * <p>
201 * Examples:
202 *
203 * <pre>
204 * (signer=\*,o=ACME,c=US)
205 * (&amp;(signer=\*,o=ACME,c=US)(name=com.acme.*)(location=http://www.acme.com/bundles/*))
206 * (id&gt;=1)
207 * </pre>
208 *
209 * <p>
210 * When a signer key is used within the filter expression the signer value
211 * must escape the special filter chars ('*', '(', ')').
212 * <p>
213 * Null arguments are equivalent to "*".
214 *
215 * @param filter A filter expression that can use signer, location, id, and
216 * name keys. A value of &quot;*&quot; or <code>null</code> matches
217 * all bundle.
218 * @param actions <code>class</code>, <code>execute</code>,
219 * <code>extensionLifecycle</code>, <code>lifecycle</code>,
220 * <code>listener</code>, <code>metadata</code>,
221 * <code>resolve</code>, <code>resource</code>, or
222 * <code>startlevel</code>. A value of "*" or <code>null</code>
223 * indicates all actions
224 */
225 public AdminPermission(String filter, String actions) {
226 // arguments will be null if called from a PermissionInfo defined with
227 // no args
228 super(filter == null ? "*" : filter);
229 try {
230 try {
231 delegate = (Permission) initStringString
232 .newInstance(new Object[] {filter, actions});
233 }
234 catch (InvocationTargetException e) {
235 throw e.getTargetException();
236 }
237 }
238 catch (Error e) {
239 throw e;
240 }
241 catch (RuntimeException e) {
242 throw e;
243 }
244 catch (Throwable e) {
245 throw new RuntimeException(e.toString());
246 }
247 }
248
249 /**
250 * Creates a new <code>AdminPermission</code> object to be used by the
251 * code that must check a <code>Permission</code> object.
252 *
253 * @param bundle A bundle
254 * @param actions <code>class</code>, <code>execute</code>,
255 * <code>extensionLifecycle</code>, <code>lifecycle</code>,
256 * <code>listener</code>, <code>metadata</code>,
257 * <code>resolve</code>, <code>resource</code>,
258 * <code>startlevel</code>
259 * @since 1.3
260 */
261 public AdminPermission(Bundle bundle, String actions) {
262 super(createName(bundle));
263 try {
264 try {
265 delegate = (Permission) initBundleString
266 .newInstance(new Object[] {bundle, actions});
267 }
268 catch (InvocationTargetException e) {
269 throw e.getTargetException();
270 }
271 }
272 catch (Error e) {
273 throw e;
274 }
275 catch (RuntimeException e) {
276 throw e;
277 }
278 catch (Throwable e) {
279 throw new RuntimeException(e.toString());
280 }
281 }
282
283 /**
284 * Create a permission name from a Bundle
285 *
286 * @param bundle Bundle to use to create permission name.
287 * @return permission name.
288 */
289 private static String createName(Bundle bundle) {
290 StringBuffer sb = new StringBuffer();
291 sb.append("(id=");
292 sb.append(bundle.getBundleId());
293 sb.append(")");
294 return sb.toString();
295 }
296
297 /**
298 * Determines the equality of two <code>AdminPermission</code> objects.
299 *
300 * @param obj The object being compared for equality with this object.
301 * @return <code>true</code> if <code>obj</code> is equivalent to this
302 * <code>AdminPermission</code>; <code>false</code> otherwise.
303 */
304 public boolean equals(Object obj) {
305 if (obj == this) {
306 return true;
307 }
308
309 if (!(obj instanceof AdminPermission)) {
310 return false;
311 }
312
313 AdminPermission p = (AdminPermission) obj;
314
315 return delegate.equals(p.delegate);
316 }
317
318 /**
319 * Returns the hash code value for this object.
320 *
321 * @return Hash code value for this object.
322 */
323 public int hashCode() {
324 return delegate.hashCode();
325 }
326
327 /**
328 * Returns the canonical string representation of the
329 * <code>AdminPermission</code> actions.
330 *
331 * <p>
332 * Always returns present <code>AdminPermission</code> actions in the
333 * following order: <code>class</code>, <code>execute</code>,
334 * <code>extensionLifecycle</code>, <code>lifecycle</code>,
335 * <code>listener</code>, <code>metadata</code>, <code>resolve</code>,
336 * <code>resource</code>, <code>startlevel</code>.
337 *
338 * @return Canonical string representation of the
339 * <code>AdminPermission</code> actions.
340 */
341 public String getActions() {
342 return delegate.getActions();
343 }
344
345 /**
346 * Determines if the specified permission is implied by this object. This
347 * method throws an exception if the specified permission was not
348 * constructed with a bundle.
349 *
350 * <p>
351 * This method returns <code>true</code> if the specified permission is an
352 * AdminPermission AND
353 * <ul>
354 * <li>this object's filter matches the specified permission's bundle ID,
355 * bundle symbolic name, bundle location and bundle signer distinguished
356 * name chain OR</li>
357 * <li>this object's filter is "*"</li>
358 * </ul>
359 * AND this object's actions include all of the specified permission's
360 * actions.
361 * <p>
362 * Special case: if the specified permission was constructed with "*"
363 * filter, then this method returns <code>true</code> if this object's
364 * filter is "*" and this object's actions include all of the specified
365 * permission's actions
366 *
367 * @param p The permission to interrogate.
368 *
369 * @return <code>true</code> if the specified permission is implied by
370 * this object; <code>false</code> otherwise.
371 * @throws RuntimeException if specified permission was not constructed with
372 * a bundle or "*"
373 */
374 public boolean implies(Permission p) {
375 if (!(p instanceof AdminPermission)) {
376 return false;
377 }
378
379 AdminPermission pp = (AdminPermission) p;
380 return delegate.implies(pp.delegate);
381 }
382
383 /**
384 * Returns a new <code>PermissionCollection</code> object suitable for
385 * storing <code>AdminPermission</code>s.
386 *
387 * @return A new <code>PermissionCollection</code> object.
388 */
389 public PermissionCollection newPermissionCollection() {
390 return delegate.newPermissionCollection();
391 }
392}