From f819bc2dbdf7b352eddc35bc2381ee6db0bab86d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Paul=20R=C3=BCtter?=
Date: Mon, 14 Jul 2025 16:33:12 +0200
Subject: [PATCH 01/26] FELIX-6759-Java-25-LTS - Try-out building framework and
HTTP subprojects against java 25 to see what will break
---
.github/workflows/maven-ci.yml | 2 +-
framework/pom.xml | 2 +-
http/pom.xml | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/.github/workflows/maven-ci.yml b/.github/workflows/maven-ci.yml
index febb6fe2ff..c246082eba 100644
--- a/.github/workflows/maven-ci.yml
+++ b/.github/workflows/maven-ci.yml
@@ -31,7 +31,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- java: [17,21,23]
+ java: [17,21,23,25]
steps:
- uses: actions/checkout@v4
- name: Set up JDK ${{ matrix.java }}
diff --git a/framework/pom.xml b/framework/pom.xml
index 4f214cc6e1..106b99c21f 100644
--- a/framework/pom.xml
+++ b/framework/pom.xml
@@ -25,7 +25,7 @@
4.0.0bundle
- Apache Felix Framework
+ Apache Felix Framework TODO remove this changeorg.apache.felix.framework7.1.0-SNAPSHOT
diff --git a/http/pom.xml b/http/pom.xml
index 39f83277a7..150c619294 100644
--- a/http/pom.xml
+++ b/http/pom.xml
@@ -26,7 +26,7 @@
../pom/pom.xml
- Apache Felix Http Reactor
+ Apache Felix Http Reactor TODO remove this changeorg.apache.felixorg.apache.felix.http7-SNAPSHOT
From b40faf7ad10878b5378448c7883ef30c7600c2e9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Paul=20R=C3=BCtter?=
Date: Mon, 14 Jul 2025 16:35:48 +0200
Subject: [PATCH 02/26] FELIX-6759-Java-25-LTS - Use 25-ea (Early access)
---
.github/workflows/maven-ci.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/maven-ci.yml b/.github/workflows/maven-ci.yml
index c246082eba..adb1b638f9 100644
--- a/.github/workflows/maven-ci.yml
+++ b/.github/workflows/maven-ci.yml
@@ -31,7 +31,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- java: [17,21,23,25]
+ java: [17,21,23,25-ea]
steps:
- uses: actions/checkout@v4
- name: Set up JDK ${{ matrix.java }}
From 43302ea2c591eb90b92639e77188a32274555dc8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Paul=20R=C3=BCtter?=
Date: Mon, 14 Jul 2025 16:41:23 +0200
Subject: [PATCH 03/26] FELIX-6759-Java-25-LTS - Update mockito-core to a
version that has jdk 25 support via byte-buddy
---
framework/pom.xml | 2 +-
http/base/pom.xml | 2 +-
http/jetty/pom.xml | 2 +-
http/jetty12/pom.xml | 2 +-
http/sslfilter/pom.xml | 2 +-
http/wrappers/pom.xml | 2 +-
webconsole/pom.xml | 2 +-
7 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/framework/pom.xml b/framework/pom.xml
index 106b99c21f..9e6db65c04 100644
--- a/framework/pom.xml
+++ b/framework/pom.xml
@@ -234,7 +234,7 @@
org.mockitomockito-core
- 5.17.0
+ 5.18.0test
diff --git a/http/base/pom.xml b/http/base/pom.xml
index ff70022597..64a42f707f 100644
--- a/http/base/pom.xml
+++ b/http/base/pom.xml
@@ -155,7 +155,7 @@
org.mockitomockito-core
- 5.17.0
+ 5.18.0test
diff --git a/http/jetty/pom.xml b/http/jetty/pom.xml
index 517c87e902..91995e89fb 100644
--- a/http/jetty/pom.xml
+++ b/http/jetty/pom.xml
@@ -526,7 +526,7 @@
org.mockitomockito-core
- 5.17.0
+ 5.18.0test
diff --git a/http/jetty12/pom.xml b/http/jetty12/pom.xml
index 7fb3195cf9..353000a39c 100644
--- a/http/jetty12/pom.xml
+++ b/http/jetty12/pom.xml
@@ -755,7 +755,7 @@
org.mockitomockito-core
- 5.17.0
+ 5.18.0test
diff --git a/http/sslfilter/pom.xml b/http/sslfilter/pom.xml
index c38d16e97d..e7901f0c51 100644
--- a/http/sslfilter/pom.xml
+++ b/http/sslfilter/pom.xml
@@ -132,7 +132,7 @@
org.mockitomockito-core
- 5.17.0
+ 5.18.0test
diff --git a/http/wrappers/pom.xml b/http/wrappers/pom.xml
index 131f392049..70f133e42c 100644
--- a/http/wrappers/pom.xml
+++ b/http/wrappers/pom.xml
@@ -109,7 +109,7 @@
org.mockitomockito-core
- 5.17.0
+ 5.18.0test
diff --git a/webconsole/pom.xml b/webconsole/pom.xml
index 0cc719bd63..68266e84a3 100644
--- a/webconsole/pom.xml
+++ b/webconsole/pom.xml
@@ -318,7 +318,7 @@
org.mockitomockito-core
- 5.17.0
+ 5.18.0test
From 71cf3567d682908946d43c1f90a7f3fd06d22445 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Paul=20R=C3=BCtter?=
Date: Mon, 14 Jul 2025 16:44:22 +0200
Subject: [PATCH 04/26] FELIX-6759-Java-25-LTS - Update awaitility
---
http/jetty/pom.xml | 2 +-
http/jetty12/pom.xml | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/http/jetty/pom.xml b/http/jetty/pom.xml
index 91995e89fb..4a11aad5bc 100644
--- a/http/jetty/pom.xml
+++ b/http/jetty/pom.xml
@@ -597,7 +597,7 @@
org.awaitilityawaitility
- 4.2.1
+ 4.3.0test
diff --git a/http/jetty12/pom.xml b/http/jetty12/pom.xml
index 353000a39c..5ab613f196 100644
--- a/http/jetty12/pom.xml
+++ b/http/jetty12/pom.xml
@@ -826,7 +826,7 @@
org.awaitilityawaitility
- 4.2.1
+ 4.3.0test
From 4dfa16292c8d3a312db2a8f4f2614fba809c4cd1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Paul=20R=C3=BCtter?=
Date: Mon, 14 Jul 2025 16:48:04 +0200
Subject: [PATCH 05/26] FELIX-6759-Java-25-LTS - Disable jetty bundle
---
http/pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/http/pom.xml b/http/pom.xml
index 150c619294..6c6a856a67 100644
--- a/http/pom.xml
+++ b/http/pom.xml
@@ -44,7 +44,7 @@
inventoryprinteritestwrappers
- jetty
+
jetty12proxysamples/whiteboard
From d88a64cf0dadde65c6f14b1cb2941f36d421f87d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Paul=20R=C3=BCtter?=
Date: Mon, 14 Jul 2025 16:50:02 +0200
Subject: [PATCH 06/26] FELIX-6759-Java-25-LTS - Don't rely on snapshot build
for jetty
---
http/itest/pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/http/itest/pom.xml b/http/itest/pom.xml
index df93733d2e..288407aa3d 100644
--- a/http/itest/pom.xml
+++ b/http/itest/pom.xml
@@ -33,7 +33,7 @@
116.1.0
- 5.1.35-SNAPSHOT
+ 5.1.34org.apache.felix.http.jetty4.13.32.6.14
From a15676bb3794c7ba95d73ad60111f98934ea0c65 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Paul=20R=C3=BCtter?=
Date: Tue, 15 Jul 2025 09:18:10 +0200
Subject: [PATCH 07/26] FELIX-6759-Java-25-LTS - continue-on-error: true to
allow building other modules after a failed one - Change SCR to trigger CI
---
.github/workflows/maven-ci.yml | 3 +++
scr/pom.xml | 2 +-
2 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/.github/workflows/maven-ci.yml b/.github/workflows/maven-ci.yml
index adb1b638f9..cdc1145054 100644
--- a/.github/workflows/maven-ci.yml
+++ b/.github/workflows/maven-ci.yml
@@ -69,12 +69,14 @@ jobs:
- name: Felix SCR
if: steps.changes.outputs.scr == 'true'
run: mvn -B -V -Dstyle.color=always --file scr/pom.xml clean verify
+ continue-on-error: true
- name: Felix Log
if: steps.changes.outputs.log == 'true'
run: mvn -B -V -Dstyle.color=always --file log/pom.xml clean verify
- name: Felix HTTP
if: steps.changes.outputs.http == 'true'
run: mvn -B -V -Dstyle.color=always "-Dit.test=!MissingWebsocketDependenciesIT" --file http/pom.xml clean install verify
+ continue-on-error: true
- name: Felix Maven bundle plugin
if: steps.changes.outputs.maven-bundle-plugin == 'true'
run: mvn -B -V -Dstyle.color=always --file tools/maven-bundle-plugin/pom.xml clean install verify
@@ -87,6 +89,7 @@ jobs:
- name: Felix Framework
if: steps.changes.outputs.framework == 'true'
run: mvn -B -V -Dstyle.color=always --file framework/pom.xml clean verify
+ continue-on-error: true
- name: OSGi-TCK Framework
if: steps.changes.outputs.framework == 'true'
run: mvn -B -V -Dstyle.color=always --file framework.tck/pom.xml clean verify
diff --git a/scr/pom.xml b/scr/pom.xml
index a96be0e2ea..f2e8dae3da 100644
--- a/scr/pom.xml
+++ b/scr/pom.xml
@@ -25,7 +25,7 @@
4.0.0bundle
- Apache Felix Declarative Services
+ Apache Felix Declarative Services TODO remove this change
Implementation of the Declarative Services specification 1.5
From a801def1f500fa870b5e15b5bbbad72aa387372b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Paul=20R=C3=BCtter?=
Date: Sat, 29 Aug 2026 20:38:36 +0200
Subject: [PATCH 08/26] FELIX-6759-Java-25-LTS - Remove SecurityManager usage
for JDK 25
Java SE 24 permanently disabled the Security Manager (JEP 486), so
System.getSecurityManager() always returns null and none of the permission
enforcement in Felix could ever run. Passing -Djava.security.manager=allow is
now a fatal VM startup error, which prevented the framework tests from running
on JDK 25 at all.
The OSGi API types are kept (AdminPermission, ServicePermission,
PackagePermission, BundlePermission, CapabilityPermission, AdaptPermission,
Bundle.hasPermission, ProtectionDomain, BundleProtectionDomain and
ext.SecurityProvider), so bundles referencing them still compile and link. Only
the enforcement is removed.
framework:
- Felix.init() no longer installs a SecurityManager. Setting
org.osgi.framework.security now fails fast instead of silently launching
without the security the launcher asked for.
- SecureAction: all 65 doPrivileged wrappers collapsed to their direct calls and
the Actions dispatch class dropped (2113 -> 656 lines).
- SecurityManagerEx no longer extends SecurityManager; it uses StackWalker,
the supported replacement for getClassContext(), which yields frames in the
same order. This raises felix.java.version to 9, the lowest level the module
still builds at.
- Permission checks removed from BundleImpl, BundleContextImpl,
BundleWiringImpl, EventDispatcher, WovenClassImpl, StatefulResolver,
ExtensionManager, ServiceRegistrationImpl, FrameworkStartLevelImpl,
FrameworkWiringImpl, URLHandlersBundleStreamHandler and
BundleProtectionDomain. Every removed branch was already unreachable without
a SecurityManager, so behaviour is unchanged.
- Dropped the two URLHandlersTest SecurityManager tests; without a
SecurityManager they duplicated the two tests they wrapped.
- asm-all 5.2 cannot read class files newer than Java 8 and broke the weaving
hook tests; replaced with asm/asm-tree 9.8.
framework.security: removed. The module existed only to implement the
SecurityManager based SecurityProvider (PermissionAdmin,
ConditionalPermissionAdmin). configadmin depends on the released 2.8.3 artifact,
not on this module.
scr, webconsole, gogo: removed the remaining getSecurityManager() gates and
doPrivileged wrappers. Bumped gogo to mockito-core 5.18.0, as 5.17.0 ships a
byte-buddy that cannot mock on JVM 25.
CI: build on JDK 25 rather than 25-ea.
Verified on JDK 25 against a JDK 21 control run on the same tree: framework,
scr (170 tests), webconsole (23 tests) and gogo now have the same results on
both JDKs. The residual failures are pre-existing Windows-only issues
(a fixture filename containing invalid NTFS characters, and deleteDir file
locking) that fail identically on JDK 21.
Co-Authored-By: Claude Opus 4.8
---
framework.security/doc/changelog.txt | 97 -
framework.security/pom.xml | 103 --
.../appended-resources/META-INF/DEPENDENCIES | 16 -
.../main/appended-resources/META-INF/LICENSE | 202 --
.../main/appended-resources/META-INF/NOTICE | 4 -
.../apache/felix/framework/FakeBundle.java | 197 --
.../felix/framework/SecurityActivator.java | 268 ---
.../felix/framework/SecurityProviderImpl.java | 135 --
.../framework/security/SecurityConstants.java | 46 -
.../ConditionalPermissionAdminImpl.java | 946 ----------
.../ConditionalPermissionInfoImpl.java | 486 -----
.../security/condpermadmin/DomainGripper.java | 134 --
.../permissionadmin/PermissionAdminImpl.java | 296 ---
.../security/util/BundleInputStream.java | 227 ---
.../framework/security/util/Conditions.java | 404 ----
.../security/util/LocalPermissions.java | 139 --
.../framework/security/util/Permissions.java | 634 -------
.../security/util/PropertiesCache.java | 242 ---
.../framework/security/util/TrustManager.java | 193 --
.../security/verifier/BundleDNParser.java | 550 ------
framework/pom.xml | 26 +-
.../felix/framework/BundleContextImpl.java | 93 +-
.../apache/felix/framework/BundleImpl.java | 233 +--
.../framework/BundleProtectionDomain.java | 19 +-
.../felix/framework/BundleWiringImpl.java | 81 +-
.../felix/framework/EventDispatcher.java | 146 +-
.../felix/framework/ExtensionManager.java | 26 +-
.../org/apache/felix/framework/Felix.java | 136 +-
.../framework/FrameworkStartLevelImpl.java | 24 -
.../felix/framework/FrameworkWiringImpl.java | 16 -
.../framework/ServiceRegistrationImpl.java | 72 +-
.../felix/framework/StatefulResolver.java | 71 -
.../URLHandlersBundleStreamHandler.java | 71 +-
.../felix/framework/WovenClassImpl.java | 89 -
.../felix/framework/util/SecureAction.java | 1635 +----------------
.../framework/util/SecurityManagerEx.java | 27 +-
.../felix/framework/URLHandlersTest.java | 40 +-
gogo/gogo-parent/pom.xml | 3 +-
.../felix/gogo/runtime/ThreadUtils.java | 3 +-
http/pom.xml | 2 +-
.../scr/impl/inject/field/FieldUtils.java | 12 +-
.../scr/impl/inject/methods/BaseMethod.java | 12 +-
.../manager/AbstractComponentManager.java | 32 +-
.../scr/impl/manager/DependencyManager.java | 132 +-
.../manager/RegionConfigurationSupport.java | 53 +-
.../webconsole/AbstractWebConsolePlugin.java | 28 +-
.../servlet/ConfigurationSupport.java | 34 +-
.../internal/servlet/OsgiManager.java | 42 +-
48 files changed, 230 insertions(+), 8247 deletions(-)
delete mode 100644 framework.security/doc/changelog.txt
delete mode 100644 framework.security/pom.xml
delete mode 100644 framework.security/src/main/appended-resources/META-INF/DEPENDENCIES
delete mode 100644 framework.security/src/main/appended-resources/META-INF/LICENSE
delete mode 100644 framework.security/src/main/appended-resources/META-INF/NOTICE
delete mode 100644 framework.security/src/main/java/org/apache/felix/framework/FakeBundle.java
delete mode 100644 framework.security/src/main/java/org/apache/felix/framework/SecurityActivator.java
delete mode 100644 framework.security/src/main/java/org/apache/felix/framework/SecurityProviderImpl.java
delete mode 100644 framework.security/src/main/java/org/apache/felix/framework/security/SecurityConstants.java
delete mode 100644 framework.security/src/main/java/org/apache/felix/framework/security/condpermadmin/ConditionalPermissionAdminImpl.java
delete mode 100644 framework.security/src/main/java/org/apache/felix/framework/security/condpermadmin/ConditionalPermissionInfoImpl.java
delete mode 100644 framework.security/src/main/java/org/apache/felix/framework/security/condpermadmin/DomainGripper.java
delete mode 100644 framework.security/src/main/java/org/apache/felix/framework/security/permissionadmin/PermissionAdminImpl.java
delete mode 100644 framework.security/src/main/java/org/apache/felix/framework/security/util/BundleInputStream.java
delete mode 100644 framework.security/src/main/java/org/apache/felix/framework/security/util/Conditions.java
delete mode 100644 framework.security/src/main/java/org/apache/felix/framework/security/util/LocalPermissions.java
delete mode 100644 framework.security/src/main/java/org/apache/felix/framework/security/util/Permissions.java
delete mode 100644 framework.security/src/main/java/org/apache/felix/framework/security/util/PropertiesCache.java
delete mode 100644 framework.security/src/main/java/org/apache/felix/framework/security/util/TrustManager.java
delete mode 100644 framework.security/src/main/java/org/apache/felix/framework/security/verifier/BundleDNParser.java
diff --git a/framework.security/doc/changelog.txt b/framework.security/doc/changelog.txt
deleted file mode 100644
index 75b33f0303..0000000000
--- a/framework.security/doc/changelog.txt
+++ /dev/null
@@ -1,97 +0,0 @@
-Changes from 2.8.3 to 2.8.4
----------------------------
-
-** Bug
- * [FELIX-6591] - Fix a memory leak in Felix Framework Security extension
-
-Changes from 2.8.1 to 2.8.3
----------------------------
-
-** Bug
- * [FELIX-3351] - Permissions.createPermission(String name, String action, Class target) Fails for action == null
- * [FELIX-6467] - `AllPermission` not checked when updating `ConditionalPermissionAdmin`
-
-Changes from 2.8.0 to 2.8.1
----------------------------
-
-** Improvement
- * [FELIX-6398] - Update packages to osgi.core 8
-
-Changes from 2.6.1 to 2.8.0
----------------------------
-
-** Improvement
- * [FELIX-6369] - Implement R8 core spec
-
-Changes from 2.6.0 to 2.6.1
----------------------------
-
-** Bug
- * [FELIX-5906] - Installing Manifest only bundles causes ArrayIndexOutOfBoundsException
-
-Changes from 2.4.0 to 2.6.0
----------------------------
-
-** Improvement
- * Update to latest framework version 5.6.0
-
-Changes from 2.2.0 to 2.4.0
----------------------------
-** Improvement
- * Update to latest framework version 4.4.0
-
-Changes form 2.0.1 to 2.2.0
----------------------------
-** Bug
- * [FELIX-3498] - BundleInputStream is not able to handle bundles that only have a MANIFEST.MF entry
- * [FELIX-3603] - Resources in META-INF/xxx/ fodlers in a signed bundle should be checked
- * [FELIX-3604] - No error log if the certificate is not valid
- * [FELIX-3893] - Bundle in cache doesn't pass security check anymore.
-
-Changes from 2.0.0 to 2.0.1
----------------------------
-
-** Bug
- * [FELIX-3196] - Security Problem: Getting full file access within the cache directory from one Bundle
- * [FELIX-3221] - NPE when uninstall a bundle on enabled OSGi security
-
-Changes from 1.4.2 to 2.0.0
----------------------------
-** Bug
- * [FELIX-2648] - Incompatible security provider state when switching from 2.0.4 to 3.0.3
- * [FELIX-2922] - ArrayIndexOutOfBoundsException when specifying no name
- * [FELIX-3004] - felix.security does not work with exploded jars
- * [FELIX-3101] - ClassCastException in Permissions class
-
-** Improvement
- * Update to latest framework version 4.0.0
-
-Changes from 1.4.1 to 1.4.2
----------------------------
-
-** Improvement
- * Update to latest framework version 3.2.0
-
-Changes from 1.4.0 to 1.4.1
----------------------------
-
-** Bug
- * [FELIX-2739] - [Security] Recent framework changes have broken the security provider.
-
-Changes from 1.2.0 to 1.4.0
----------------------------
-
-** Improvement
- * [FELIX-2547] - Implement conditionalpermissioninfo encoding/decoding to match the spec.
-
-
-Changes from 1.0.0 to 1.2.0
----------------------------
-
-** Task
- * [FELIX-2294] - Patch Framework Security for compatibility
-
-1.0.0
------
-
-** Initial Release
diff --git a/framework.security/pom.xml b/framework.security/pom.xml
deleted file mode 100644
index 14555e06be..0000000000
--- a/framework.security/pom.xml
+++ /dev/null
@@ -1,103 +0,0 @@
-
-
-
- org.apache.felix
- felix-parent
- 6
- ../pom/pom.xml
-
- 4.0.0
- bundle
- Apache Felix Security Provider
- org.apache.felix.framework.security
- 2.9.0-SNAPSHOT
-
- This bundle provides an implementation of the OSGi security for Apache Felix.
-
-
- scm:git:https://github.com/apache/felix-dev.git
- scm:git:https://github.com/apache/felix-dev.git
- https://gitbox.apache.org/repos/asf?p=felix-dev.git
- HEAD
-
-
-
- org.osgi
- osgi.core
- 8.0.0
-
-
- ${pom.groupId}
- org.apache.felix.framework
- 7.1.0-SNAPSHOT
-
-
-
-
-
- org.apache.maven.plugins
- maven-compiler-plugin
-
- 1.3
- 1.3
-
-
-
- org.apache.felix
- maven-bundle-plugin
- 5.1.2
- true
-
-
- ${pom.artifactId}
- The Apache Software Foundation
- org.osgi.service.permissionadmin, org.osgi.service.condpermadmin
- org.apache.felix.framework.*
- !*
- system.bundle; extension:=framework
- org.apache.felix.framework.SecurityActivator
-
-
- org.apache.felix.framework
-
-
-
-
- org.apache.maven.plugins
- maven-javadoc-plugin
-
- false
-
-
-
- org.apache.maven.plugins
- maven-source-plugin
-
-
- attach-sources
-
- jar
-
-
-
-
-
-
-
diff --git a/framework.security/src/main/appended-resources/META-INF/DEPENDENCIES b/framework.security/src/main/appended-resources/META-INF/DEPENDENCIES
deleted file mode 100644
index cce7c0b20e..0000000000
--- a/framework.security/src/main/appended-resources/META-INF/DEPENDENCIES
+++ /dev/null
@@ -1,16 +0,0 @@
-I. Included Third-Party Software
-
-This product includes software developed at
-The OSGi Alliance (http://www.osgi.org/).
-Copyright (c) OSGi Alliance (2000, 2009).
-Licensed under the Apache License 2.0.
-
-II. Used Third-Party Software
-
-This product uses software developed at
-The OSGi Alliance (http://www.osgi.org/).
-Copyright (c) OSGi Alliance (2000, 2009).
-Licensed under the Apache License 2.0.
-
-III. License Summary
-- Apache License 2.0
diff --git a/framework.security/src/main/appended-resources/META-INF/LICENSE b/framework.security/src/main/appended-resources/META-INF/LICENSE
deleted file mode 100644
index d645695673..0000000000
--- a/framework.security/src/main/appended-resources/META-INF/LICENSE
+++ /dev/null
@@ -1,202 +0,0 @@
-
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
- APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
- Copyright [yyyy] [name of copyright owner]
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
diff --git a/framework.security/src/main/appended-resources/META-INF/NOTICE b/framework.security/src/main/appended-resources/META-INF/NOTICE
deleted file mode 100644
index 3db2e431ed..0000000000
--- a/framework.security/src/main/appended-resources/META-INF/NOTICE
+++ /dev/null
@@ -1,4 +0,0 @@
-This product includes software developed at
-The OSGi Alliance (http://www.osgi.org/).
-Copyright (c) OSGi Alliance (2000, 2009).
-Licensed under the Apache License 2.0.
diff --git a/framework.security/src/main/java/org/apache/felix/framework/FakeBundle.java b/framework.security/src/main/java/org/apache/felix/framework/FakeBundle.java
deleted file mode 100644
index 19a050675a..0000000000
--- a/framework.security/src/main/java/org/apache/felix/framework/FakeBundle.java
+++ /dev/null
@@ -1,197 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.felix.framework;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URL;
-import java.util.Collections;
-import java.util.Dictionary;
-import java.util.Enumeration;
-import java.util.Hashtable;
-import java.util.Map;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.BundleException;
-import org.osgi.framework.ServiceReference;
-import org.osgi.framework.Version;
-
-/**
- *
- */
-public class FakeBundle extends BundleImpl implements Bundle
-{
- private final Map m_certs;
-
- public FakeBundle(Map certs)
- {
- m_certs = Collections.unmodifiableMap(certs);
- }
-
- public Enumeration findEntries(String arg0, String arg1, boolean arg2)
- {
- return null;
- }
-
- public BundleContext getBundleContext()
- {
- return null;
- }
-
- public long getBundleId()
- {
- return -1;
- }
-
- public URL getEntry(String arg0)
- {
- return null;
- }
-
- public Enumeration getEntryPaths(String arg0)
- {
- return null;
- }
-
- public Dictionary getHeaders()
- {
- return new Hashtable();
- }
-
- public Dictionary getHeaders(String arg0)
- {
- return new Hashtable();
- }
-
- public long getLastModified()
- {
- return 0;
- }
-
- public String getLocation()
- {
- return "";
- }
-
- public ServiceReference[] getRegisteredServices()
- {
- return null;
- }
-
- public URL getResource(String arg0)
- {
- return null;
- }
-
- public Enumeration getResources(String arg0) throws IOException
- {
- return null;
- }
-
- public ServiceReference[] getServicesInUse()
- {
- return null;
- }
-
- public Map getSignerCertificates(int arg0)
- {
- return m_certs;
- }
-
- public int getState()
- {
- return Bundle.UNINSTALLED;
- }
-
- public String getSymbolicName()
- {
- return null;
- }
-
- public Version getVersion()
- {
- return Version.emptyVersion;
- }
-
- public boolean hasPermission(Object arg0)
- {
- return false;
- }
-
- public Class loadClass(String arg0) throws ClassNotFoundException
- {
- return null;
- }
-
- public void start() throws BundleException
- {
- throw new IllegalStateException();
- }
-
- public void start(int arg0) throws BundleException
- {
- throw new IllegalStateException();
- }
-
- public void stop() throws BundleException
- {
- throw new IllegalStateException();
- }
-
- public void stop(int arg0) throws BundleException
- {
- throw new IllegalStateException();
- }
-
- public void uninstall() throws BundleException
- {
- throw new IllegalStateException();
- }
-
- public void update() throws BundleException
- {
- throw new IllegalStateException();
- }
-
- public void update(InputStream arg0) throws BundleException
- {
- throw new IllegalStateException();
- }
-
- public boolean equals(Object o)
- {
- return this == o;
- }
-
- public int hashCode()
- {
- return System.identityHashCode(this);
- }
-
- public Object adapt(Class arg0) {
- // TODO Auto-generated method stub
- return null;
- }
-
- public File getDataFile(String arg0) {
- // TODO Auto-generated method stub
- return null;
- }
-}
diff --git a/framework.security/src/main/java/org/apache/felix/framework/SecurityActivator.java b/framework.security/src/main/java/org/apache/felix/framework/SecurityActivator.java
deleted file mode 100644
index fd762644bd..0000000000
--- a/framework.security/src/main/java/org/apache/felix/framework/SecurityActivator.java
+++ /dev/null
@@ -1,268 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.felix.framework;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.Iterator;
-import java.util.List;
-import java.util.StringTokenizer;
-
-import org.apache.felix.framework.ext.SecurityProvider;
-import org.apache.felix.framework.security.SecurityConstants;
-import org.apache.felix.framework.security.condpermadmin.ConditionalPermissionAdminImpl;
-import org.apache.felix.framework.security.permissionadmin.PermissionAdminImpl;
-import org.apache.felix.framework.security.util.Conditions;
-import org.apache.felix.framework.security.util.LocalPermissions;
-import org.apache.felix.framework.security.util.Permissions;
-import org.apache.felix.framework.security.util.PropertiesCache;
-import org.apache.felix.framework.util.SecureAction;
-import org.osgi.framework.BundleActivator;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.BundleEvent;
-import org.osgi.framework.BundleException;
-import org.osgi.framework.BundleListener;
-import org.osgi.framework.Constants;
-import org.osgi.framework.wiring.BundleRevisions;
-import org.osgi.service.condpermadmin.ConditionalPermissionAdmin;
-import org.osgi.service.permissionadmin.PermissionAdmin;
-
-/**
- *
- * This Felix specific activator installs a security provider with the Felix
- * framework. The security settings can be changed via the
- * {@link PermissionAdmin} and/or the {@link ConditionalPermissionAdmin}
- * services that may be published by this class.
- *
- *
- * Permission informations as well as caching data will be stored in several
- * files in a directory called security obtained by a call to
- * {@link BundleContext#getDataFile(String))}.
- *
- *
- * The following properties are recognized:
- *
- * {@link SecurityConstants#ENABLE_PERMISSIONADMIN_PROP} - Whether or not (
- * true|false) to publish a{@link ConditionalPermissionAdmin}
- * service. The default is
- * {@link SecurityConstants#ENABLE_PERMISSIONADMIN_VALUE}.
- *
- *
- * {@link SecurityConstants#ENABLE_CONDPERMADMIN_PROP} - Whether or not (
- * true|false) to publish a{@link ConditionalPermissionAdmin}
- * service. The default is {@link SecurityConstants#ENABLE_CONDPERMADMIN_VALUE}.
- *
- *
- * {@link SecurityConstants#KEYSTORE_FILE_PROP} - The keystore URL(s) to use as
- * trusted CA stores. The urls must be separated by a guard (i.e., |).
- * The default is {@link SecurityConstants#KEYSTORE_FILE_VALUE}.
- *
- *
- * {@link SecurityConstants#KEYSTORE_PASS_PROP} - The keystore password(s) to
- * use for the given keystores. The passwords must be separated by a guard
- * (i.e., |).The default is
- * {@link SecurityConstants#KEYSTORE_PASS_VALUE}.
- *
- *
- * {@link SecurityConstants#KEYSTORE_TYPE_PROP} - The keystore type(s) to use
- * for the given keystores. The types must be separated by a guard (i.e.,
- * |).The default is {@link SecurityConstants#KEYSTORE_TYPE_VALUE}.
- *
- *
- * {@link SecurityConstants#CRL_FILE_PROP} - The CRL URL(s) to use for revoked
- * certificates. The urls must be separated by a guard (i.e., |). The
- * default is {@link SecurityConstants#CRL_FILE_VALUE}.
- *
- *
- */
-/*
- * TODO: using a string for passwords is bad. We need to investigate
- * alternatives.
- *
- * TODO: we might want to allow for the recognized properties to change without
- * a restart. This is trick because we can not publish a managed service due to
- * not being able to import as we are an extension bundle.
- */
-public final class SecurityActivator implements BundleActivator
-{
- public synchronized void start(BundleContext context) throws Exception
- {
- PermissionAdminImpl pai = null;
-
- SecureAction action = new SecureAction();
-
- Permissions permissions = new Permissions(context, action);
-
- File tmp = context.getDataFile("security" + File.separator + "tmp");
- if ((tmp == null) || (!tmp.isDirectory() && !tmp.mkdirs()))
- {
- throw new IOException("Can't create tmp dir.");
- }
- // TODO: log something if we can not clean-up the tmp dir
- File[] old = tmp.listFiles();
- if (old != null)
- {
- for (int i = 0; i < old.length; i++)
- {
- old[i].delete();
- }
- }
-
- if ("TRUE".equalsIgnoreCase(getProperty(context,
- SecurityConstants.ENABLE_PERMISSIONADMIN_PROP,
- SecurityConstants.ENABLE_PERMISSIONADMIN_VALUE)))
- {
- File cache = context.getDataFile("security" + File.separator
- + "pa.txt");
- if ((cache == null) || (!cache.isFile() && !cache.createNewFile()))
- {
- throw new IOException("Can't create cache file");
- }
- pai = new PermissionAdminImpl(permissions, new PropertiesCache(
- cache, tmp, action));
- }
-
- ConditionalPermissionAdminImpl cpai = null;
-
- if ("TRUE".equalsIgnoreCase(getProperty(context,
- SecurityConstants.ENABLE_CONDPERMADMIN_PROP,
- SecurityConstants.ENABLE_CONDPERMADMIN_VALUE)))
- {
- File cpaCache = context.getDataFile("security" + File.separator
- + "cpa.txt");
- if ((cpaCache == null)
- || (!cpaCache.isFile() && !cpaCache.createNewFile()))
- {
- throw new IOException("Can't create cache file");
- }
-
- LocalPermissions localPermissions = new LocalPermissions(
- permissions);
-
- final Conditions conditions = new Conditions(action);
- cpai = new ConditionalPermissionAdminImpl(permissions,
- conditions, localPermissions, new PropertiesCache(
- cpaCache, tmp, action), pai);
-
- context.addBundleListener(new UninstallListener(conditions));
- }
-
- if ((pai != null) || (cpai != null))
- {
- String crlList = getProperty(context,
- SecurityConstants.CRL_FILE_PROP,
- SecurityConstants.CRL_FILE_VALUE);
- String storeList = getProperty(context,
- SecurityConstants.KEYSTORE_FILE_PROP,
- SecurityConstants.KEYSTORE_FILE_VALUE);
- String passwdList = getProperty(context,
- SecurityConstants.KEYSTORE_PASS_PROP,
- SecurityConstants.KEYSTORE_PASS_VALUE);
- String typeList = getProperty(context,
- SecurityConstants.KEYSTORE_TYPE_PROP,
- SecurityConstants.KEYSTORE_TYPE_VALUE);
- String osgi_keystores = getProperty(context,
- Constants.FRAMEWORK_TRUST_REPOSITORIES, null);
- if (osgi_keystores != null)
- {
- StringTokenizer tok = new StringTokenizer(osgi_keystores,
- File.pathSeparator);
-
- if (storeList.length() == 0)
- {
- storeList += "file:" + tok.nextToken();
- passwdList += " ";
- typeList += "JKS";
- }
- while (tok.hasMoreTokens())
- {
- storeList += "|file:" + tok.nextToken();
- passwdList += "| ";
- typeList += "|JKS";
- }
- }
-
- StringTokenizer storeTok = new StringTokenizer(storeList, "|");
- StringTokenizer passwdTok = new StringTokenizer(passwdList, "|");
- StringTokenizer typeTok = new StringTokenizer(typeList, "|");
-
- if ((storeTok.countTokens() != typeTok.countTokens())
- || (passwdTok.countTokens() != storeTok.countTokens()))
- {
- throw new BundleException(
- "Each CACerts keystore must have one type and one passwd entry and vice versa.");
- }
-
- SecurityProvider provider = new SecurityProviderImpl(crlList,
- typeList, passwdList, storeList, pai, cpai, action, ((Felix) context.getBundle(0)).getLogger());
-
- ((Felix) context.getBundle(0)).setSecurityProvider(provider);
- }
-
- if (pai != null)
- {
- context.registerService(PermissionAdmin.class.getName(), pai, null);
- }
-
- if (cpai != null)
- {
- context.registerService(ConditionalPermissionAdmin.class.getName(),
- cpai, null);
- }
- }
-
- public synchronized void stop(BundleContext context) throws Exception
- {
- ((Felix) context.getBundle(0)).setSecurityProvider(null);
- }
-
- private String getProperty(BundleContext context, String key,
- String defaultValue)
- {
- String result = context.getProperty(key);
-
- return (result != null) ? result : defaultValue;
- }
-
- private static final class UninstallListener implements BundleListener
- {
- private final Conditions conditions;
-
- UninstallListener(Conditions conditions)
- {
- this.conditions = conditions;
- }
-
- public void bundleChanged(BundleEvent event)
- {
- if (event.getType() == BundleEvent.UNINSTALLED)
- {
- List revisions = ((BundleRevisions)event.getBundle().adapt(BundleRevisions.class)).getRevisions();
- if (revisions != null)
- {
- Iterator iter = revisions.iterator();
- while (iter.hasNext())
- {
- conditions.remove((BundleRevisionImpl) iter.next());
- }
- }
- }
- }
- }
-}
diff --git a/framework.security/src/main/java/org/apache/felix/framework/SecurityProviderImpl.java b/framework.security/src/main/java/org/apache/felix/framework/SecurityProviderImpl.java
deleted file mode 100644
index 405f9092f8..0000000000
--- a/framework.security/src/main/java/org/apache/felix/framework/SecurityProviderImpl.java
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.felix.framework;
-
-import java.security.Permission;
-import java.security.ProtectionDomain;
-
-import org.apache.felix.framework.Logger;
-import org.apache.felix.framework.ext.SecurityProvider;
-import org.apache.felix.framework.security.condpermadmin.ConditionalPermissionAdminImpl;
-import org.apache.felix.framework.security.permissionadmin.PermissionAdminImpl;
-import org.apache.felix.framework.security.util.TrustManager;
-import org.apache.felix.framework.security.verifier.BundleDNParser;
-import org.apache.felix.framework.util.SecureAction;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.wiring.BundleRevision;
-
-/**
- * This class is the entry point to the security. It is used to determine
- * whether a given bundle is signed correctely and has permissions based on
- * PermissionAdmin or ConditionalPermissionAdmin.
- */
-public final class SecurityProviderImpl implements SecurityProvider
-{
- private final BundleDNParser m_parser;
- private final PermissionAdminImpl m_pai;
- private final ConditionalPermissionAdminImpl m_cpai;
- private final SecureAction m_action;
-
- SecurityProviderImpl(String crlList, String typeList, String passwdList,
- String storeList, PermissionAdminImpl pai,
- ConditionalPermissionAdminImpl cpai, SecureAction action, Logger logger)
- {
- m_pai = pai;
- m_cpai = cpai;
- m_action = action;
- m_parser = new BundleDNParser(new TrustManager(crlList, typeList,
- passwdList, storeList, m_action), logger);
- }
-
- /**
- * If the given bundle is signed but can not be verified (e.g., missing
- * files) then throw an exception.
- */
- public void checkBundle(Bundle bundle) throws Exception
- {
- BundleRevisionImpl module = (BundleRevisionImpl) bundle.adapt(BundleRevisionImpl.class);
- m_parser.checkDNChains(module, module.getContent(),
- Bundle.SIGNERS_TRUSTED);
- }
-
- /**
- * Get a signer matcher that can be used to match digital signed bundles.
- */
- public Object getSignerMatcher(final Bundle bundle, int signersType)
- {
- BundleRevisionImpl module = (BundleRevisionImpl) bundle.adapt(BundleRevisionImpl.class);
- return m_parser.getDNChains(module, module.getContent(), signersType);
- }
-
- /**
- * If we have a permissionadmin then ask that one first and have it decide
- * in case there is a location bound. If not then either use its default
- * permission in case there is no conditional permission admin or else ask
- * that one.
- */
- public boolean hasBundlePermission(ProtectionDomain bundleProtectionDomain,
- Permission permission, boolean direct)
- {
- BundleProtectionDomain pd = (BundleProtectionDomain) bundleProtectionDomain;
- BundleImpl bundle = pd.getBundle();
- BundleRevisionImpl module = (BundleRevisionImpl) pd.getRevision();
-
- if (bundle.getBundleId() == 0)
- {
- return true;
- }
-
- // System.out.println(info.getBundleId() + " - " + permission);
- // TODO: using true, false, or null seems a bit awkward. Improve this.
- Boolean result = null;
- if (m_pai != null)
- {
- result = m_pai.hasPermission(bundle._getLocation(), pd.getBundle(),
- permission, m_cpai, pd, module.getContent());
- }
-
- if (result != null)
- {
- if ((m_cpai != null) && !direct)
- {
- boolean allow = result.booleanValue();
- if (!allow)
- {
- m_cpai.clearPD();
- return false;
- }
- return m_cpai.handlePAHandle(pd);
- }
- return result.booleanValue();
- }
-
- if (m_cpai != null)
- {
- try
- {
- return m_cpai.hasPermission(module, module.getContent(), pd,
- permission, direct, m_pai);
- }
- catch (Exception e)
- {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
-
- return false;
- }
-}
diff --git a/framework.security/src/main/java/org/apache/felix/framework/security/SecurityConstants.java b/framework.security/src/main/java/org/apache/felix/framework/security/SecurityConstants.java
deleted file mode 100644
index 790e1852d4..0000000000
--- a/framework.security/src/main/java/org/apache/felix/framework/security/SecurityConstants.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.felix.framework.security;
-
-public interface SecurityConstants
-{
- public static final String KEYSTORE_FILE_PROP = "felix.keystore";
-
- public static final String KEYSTORE_FILE_VALUE = "";
-
- public static final String KEYSTORE_TYPE_PROP = "felix.keystore.type";
-
- public static final String KEYSTORE_TYPE_VALUE = "";
-
- public static final String KEYSTORE_PASS_PROP = "felix.keystore.pass";
-
- public static final String KEYSTORE_PASS_VALUE = "";
-
- public static final String CRL_FILE_PROP = "felix.crl";
-
- public static final String CRL_FILE_VALUE = "";
-
- public static final String ENABLE_CONDPERMADMIN_PROP = "felix.security.conpermadmin";
-
- public static final String ENABLE_CONDPERMADMIN_VALUE = "true";
-
- public static final String ENABLE_PERMISSIONADMIN_PROP = "felix.security.permissionadmin";
-
- public static final String ENABLE_PERMISSIONADMIN_VALUE = "true";
-}
diff --git a/framework.security/src/main/java/org/apache/felix/framework/security/condpermadmin/ConditionalPermissionAdminImpl.java b/framework.security/src/main/java/org/apache/felix/framework/security/condpermadmin/ConditionalPermissionAdminImpl.java
deleted file mode 100644
index ba6c50fb12..0000000000
--- a/framework.security/src/main/java/org/apache/felix/framework/security/condpermadmin/ConditionalPermissionAdminImpl.java
+++ /dev/null
@@ -1,946 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.felix.framework.security.condpermadmin;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.math.BigInteger;
-import java.net.URL;
-import java.security.AccessControlContext;
-import java.security.InvalidKeyException;
-import java.security.NoSuchAlgorithmException;
-import java.security.NoSuchProviderException;
-import java.security.Permission;
-import java.security.Principal;
-import java.security.ProtectionDomain;
-import java.security.PublicKey;
-import java.security.SignatureException;
-import java.security.cert.X509Certificate;
-import java.util.AbstractSet;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Date;
-import java.util.Dictionary;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.Hashtable;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.StringTokenizer;
-import java.util.Map.Entry;
-
-import org.apache.felix.framework.BundleProtectionDomain;
-import org.apache.felix.framework.BundleRevisionImpl;
-import org.apache.felix.framework.FakeBundle;
-import org.apache.felix.framework.security.permissionadmin.PermissionAdminImpl;
-import org.apache.felix.framework.security.util.Conditions;
-import org.apache.felix.framework.security.util.LocalPermissions;
-import org.apache.felix.framework.security.util.Permissions;
-import org.apache.felix.framework.security.util.PropertiesCache;
-import org.apache.felix.framework.util.manifestparser.NativeLibrary;
-
-/*
-import org.apache.felix.moduleloader.ICapability;
-import org.apache.felix.moduleloader.IContent;
-import org.apache.felix.moduleloader.IModule;
-import org.apache.felix.moduleloader.IRequirement;
-import org.apache.felix.moduleloader.IWire;
-*/
-import org.apache.felix.framework.cache.Content;
-
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.BundleException;
-import org.osgi.framework.ServiceReference;
-import org.osgi.framework.Version;
-import org.osgi.service.condpermadmin.ConditionInfo;
-import org.osgi.service.condpermadmin.ConditionalPermissionAdmin;
-import org.osgi.service.condpermadmin.ConditionalPermissionInfo;
-import org.osgi.service.condpermadmin.ConditionalPermissionUpdate;
-import org.osgi.service.permissionadmin.PermissionInfo;
-
-/**
- * An implementation of the ConditionalPermissionAdmin service that doesn't need
- * to have a framework specific security manager set. It use the DomainGripper
- * to know what bundleprotectiondomains are expected.
- */
-public final class ConditionalPermissionAdminImpl implements
- ConditionalPermissionAdmin
-{
- private static class OrderedHashMap extends HashMap
- {
- private final List m_order = new ArrayList();
-
- public Object put(Object key, Object value)
- {
- Object result = super.put(key, value);
- if (result != value)
- {
- m_order.remove(key);
- m_order.add(key);
- }
- return result;
- };
-
- public void putAll(Map map)
- {
- for (Iterator iter = map.entrySet().iterator(); iter.hasNext();)
- {
- Entry entry = (Entry) iter.next();
- put(entry.getKey(), entry.getValue());
- }
- };
-
- public Set keySet()
- {
- return new AbstractSet()
- {
- public Iterator iterator()
- {
- return m_order.iterator();
- }
-
- public int size()
- {
- return m_order.size();
- }
-
- };
- };
-
- public Set entrySet()
- {
- return new AbstractSet()
- {
-
- public Iterator iterator()
- {
- return new Iterator()
- {
- Iterator m_iter = m_order.iterator();
-
- public boolean hasNext()
- {
- return m_iter.hasNext();
- }
-
- public Object next()
- {
- final Object key = m_iter.next();
- return new Entry()
- {
-
- public Object getKey()
- {
- return key;
- }
-
- public Object getValue()
- {
- return get(key);
- }
-
- public Object setValue(Object arg0)
- {
- throw new IllegalStateException(
- "Not Implemented");
- }
- };
- }
-
- public void remove()
- {
- throw new IllegalStateException("Not Implemented");
- }
-
- };
- }
-
- public int size()
- {
- return m_order.size();
- }
-
- };
- };
-
- public Collection values()
- {
- List result = new ArrayList();
- for (Iterator iter = m_order.iterator(); iter.hasNext();)
- {
- result.add(super.get(iter.next()));
- }
- return result;
- };
-
- public Object remove(Object key)
- {
- Object result = super.remove(key);
- if (result != null)
- {
- m_order.remove(key);
- }
- return result;
- };
-
- public void clear()
- {
- super.clear();
- m_order.clear();
- };
- };
-
- private static final ConditionInfo[] EMPTY_CONDITION_INFO = new ConditionInfo[0];
- private static final PermissionInfo[] EMPTY_PERMISSION_INFO = new PermissionInfo[0];
- private final Map m_condPermInfos = new OrderedHashMap();
- private final PropertiesCache m_propertiesCache;
- private final Permissions m_permissions;
- private final Conditions m_conditions;
- private final LocalPermissions m_localPermissions;
- private final PermissionAdminImpl m_pai;
-
- public ConditionalPermissionAdminImpl(Permissions permissions,
- Conditions condtions, LocalPermissions localPermissions,
- PropertiesCache cache, PermissionAdminImpl pai) throws IOException
- {
- m_propertiesCache = cache;
- m_permissions = permissions;
- m_conditions = condtions;
- m_localPermissions = localPermissions;
- Map old = new OrderedHashMap();
- // Now try to restore the cache.
- m_propertiesCache.read(ConditionalPermissionInfoImpl.class, old);
- for (Iterator iter = old.entrySet().iterator(); iter.hasNext();)
- {
- Entry entry = (Entry) iter.next();
- String name = (String) entry.getKey();
- ConditionalPermissionInfoImpl cpi = ((ConditionalPermissionInfoImpl) entry
- .getValue());
- m_condPermInfos.put(name, new ConditionalPermissionInfoImpl(name,
- cpi._getConditionInfos(), cpi._getPermissionInfos(), this, cpi
- .isAllow()));
- }
- m_pai = pai;
- }
-
- public ConditionalPermissionInfo addConditionalPermissionInfo(
- ConditionInfo[] conditions, PermissionInfo[] permissions)
- {
- Object sm = System.getSecurityManager();
- if (sm != null)
- {
- ((SecurityManager) sm).checkPermission(Permissions.ALL_PERMISSION);
- }
- ConditionalPermissionInfoImpl result = new ConditionalPermissionInfoImpl(
- notNull(conditions), notNull(permissions), this, true);
-
- return write(result.getName(), result);
- }
-
- ConditionalPermissionInfoImpl write(String name,
- ConditionalPermissionInfoImpl cpi)
- {
- synchronized (m_propertiesCache)
- {
- Map tmp = null;
-
- synchronized (m_condPermInfos)
- {
- tmp = new OrderedHashMap();
- tmp.putAll(m_condPermInfos);
-
- if ((name != null) && (cpi != null))
- {
- m_condPermInfos.put(name, cpi);
- }
- else if (name != null)
- {
- m_condPermInfos.remove(name);
- }
- else
- {
- tmp = null;
- }
- }
-
- try
- {
- m_propertiesCache.write(m_condPermInfos);
- }
- catch (IOException ex)
- {
- synchronized (m_condPermInfos)
- {
- if (tmp != null)
- {
- m_condPermInfos.clear();
- m_condPermInfos.putAll(tmp);
- }
- }
- ex.printStackTrace();
- throw new IllegalStateException(ex.getMessage());
- }
- }
- synchronized (m_condPermInfos)
- {
- return (ConditionalPermissionInfoImpl) m_condPermInfos.get(name);
- }
- }
-
- private static class FakeCert extends X509Certificate
- {
- private final Principal m_principal;
-
- public FakeCert(final String principal)
- {
- m_principal = new Principal()
- {
- public String getName()
- {
- return principal;
- }
- };
- }
-
- public void checkValidity()
- throws java.security.cert.CertificateExpiredException,
- java.security.cert.CertificateNotYetValidException
- {
-
- }
-
- public void checkValidity(Date date)
- throws java.security.cert.CertificateExpiredException,
- java.security.cert.CertificateNotYetValidException
- {
- }
-
- public int getBasicConstraints()
- {
- return 0;
- }
-
- public Principal getIssuerDN()
- {
- return null;
- }
-
- public boolean[] getIssuerUniqueID()
- {
- return null;
- }
-
- public boolean[] getKeyUsage()
- {
- return null;
- }
-
- public Date getNotAfter()
- {
- return null;
- }
-
- public Date getNotBefore()
- {
- return null;
- }
-
- public BigInteger getSerialNumber()
- {
- return null;
- }
-
- public String getSigAlgName()
- {
- return null;
- }
-
- public String getSigAlgOID()
- {
- return null;
- }
-
- public byte[] getSigAlgParams()
- {
- return null;
- }
-
- public byte[] getSignature()
- {
- return null;
- }
-
- public Principal getSubjectDN()
- {
- return m_principal;
- }
-
- public boolean[] getSubjectUniqueID()
- {
- return null;
- }
-
- public byte[] getTBSCertificate()
- throws java.security.cert.CertificateEncodingException
- {
- return null;
- }
-
- public int getVersion()
- {
- return 0;
- }
-
- public byte[] getEncoded()
- throws java.security.cert.CertificateEncodingException
- {
- return null;
- }
-
- public PublicKey getPublicKey()
- {
- return null;
- }
-
- public String toString()
- {
- return m_principal.getName();
- }
-
- public void verify(PublicKey key)
- throws java.security.cert.CertificateException,
- NoSuchAlgorithmException, InvalidKeyException,
- NoSuchProviderException, SignatureException
- {
-
- }
-
- public void verify(PublicKey key, String sigProvider)
- throws java.security.cert.CertificateException,
- NoSuchAlgorithmException, InvalidKeyException,
- NoSuchProviderException, SignatureException
- {
-
- }
-
- public Set getCriticalExtensionOIDs()
- {
- return null;
- }
-
- public byte[] getExtensionValue(String arg0)
- {
- return null;
- }
-
- public Set getNonCriticalExtensionOIDs()
- {
- return null;
- }
-
- public boolean hasUnsupportedCriticalExtension()
- {
- return false;
- }
-
- public boolean equals(Object o)
- {
- return this == o;
- }
-
- public int hashCode()
- {
- return System.identityHashCode(this);
- }
-
- }
-
- public AccessControlContext getAccessControlContext(final String[] signers)
- {
- Map certificates = new HashMap();
- for (int i = 0; i < signers.length; i++)
- {
- StringTokenizer tok = new StringTokenizer(signers[i], ";");
- List certsList = new ArrayList();
- while (tok.hasMoreTokens())
- {
- certsList.add(tok.nextToken());
- }
- String[] certs = (String[]) certsList.toArray(new String[certsList
- .size()]);
-
- X509Certificate key = new FakeCert(certs[0]);
- List certList = new ArrayList();
- certificates.put(key, certList);
- certList.add(key);
- for (int j = 1; j < certs.length; j++)
- {
- certList.add(new FakeCert(certs[j]));
- }
- }
- final FakeBundle fake = new FakeBundle(certificates);
- ProtectionDomain domain = new ProtectionDomain(null, null)
- {
- public boolean implies(Permission permission)
- {
- List posts = new ArrayList();
- Boolean result = m_pai.hasPermission("", fake, permission,
- ConditionalPermissionAdminImpl.this, this, null);
- if (result != null)
- {
- return result.booleanValue();
- }
- if (eval(posts, new BundleRevisionImpl(fake, Long.toString(fake.getBundleId())), permission, m_pai))
- {
- if (!posts.isEmpty())
- {
- return m_conditions.evalRecursive(posts);
- }
- return true;
- }
- return false;
- }
- };
- return new AccessControlContext(new ProtectionDomain[] { domain });
- }
-
- public ConditionalPermissionInfo getConditionalPermissionInfo(String name)
- {
- if (name == null)
- {
- throw new IllegalArgumentException("Name may not be null");
- }
- ConditionalPermissionInfoImpl result = null;
-
- synchronized (m_condPermInfos)
- {
- result = (ConditionalPermissionInfoImpl) m_condPermInfos.get(name);
- }
-
- if (result == null)
- {
- result = new ConditionalPermissionInfoImpl(this, name, true);
-
- result = write(result.getName(), result);
- }
-
- return result;
- }
-
- public Enumeration getConditionalPermissionInfos()
- {
- synchronized (m_condPermInfos)
- {
- return Collections.enumeration(new ArrayList(m_condPermInfos
- .values()));
- }
- }
-
- public ConditionalPermissionInfo setConditionalPermissionInfo(String name,
- ConditionInfo[] conditions, PermissionInfo[] permissions)
- {
- Object sm = System.getSecurityManager();
- if (sm != null)
- {
- ((SecurityManager) sm).checkPermission(Permissions.ALL_PERMISSION);
- }
-
- ConditionalPermissionInfoImpl result = null;
- conditions = notNull(conditions);
- permissions = notNull(permissions);
-
- if (name != null)
- {
- synchronized (m_condPermInfos)
- {
- result = (ConditionalPermissionInfoImpl) m_condPermInfos
- .get(name);
-
- if (result == null)
- {
- result = new ConditionalPermissionInfoImpl(name,
- conditions, permissions, this, true);
- }
- else
- {
- result.setConditionsAndPermissions(conditions, permissions);
- }
- }
- }
- else
- {
- result = new ConditionalPermissionInfoImpl(conditions, permissions,
- this, true);
- }
-
- return write(result.getName(), result);
- }
-
- private PermissionInfo[] notNull(PermissionInfo[] permissions)
- {
- if (permissions == null)
- {
- return ConditionalPermissionInfoImpl.PERMISSION_INFO;
- }
- return (PermissionInfo[]) notNull((Object[]) permissions).toArray(
- EMPTY_PERMISSION_INFO);
- }
-
- private ConditionInfo[] notNull(ConditionInfo[] conditions)
- {
- if (conditions == null)
- {
- return ConditionalPermissionInfoImpl.CONDITION_INFO;
- }
- return (ConditionInfo[]) notNull((Object[]) conditions).toArray(
- EMPTY_CONDITION_INFO);
- }
-
- private List notNull(Object[] elements)
- {
- List result = new ArrayList();
-
- for (int i = 0; i < elements.length; i++)
- {
- if (elements[i] != null)
- {
- result.add(elements[i]);
- }
- }
-
- return result;
- }
-
- // The thread local stack used to keep track of bundle protection domains we
- // still expect to see.
- private final ThreadLocal m_stack = new ThreadLocal();
-
- /**
- * This method does the actual permission check. If it is not a direct check
- * it will try to determine the other bundle domains that will follow
- * automatically in case this is the first check in one permission check. If
- * not then it will keep track of which domains we have already see. While
- * it keeps track it builds up a list of postponed tuples which it will
- * evaluate at the last domain. See the core spec 9.5.1 and following for a
- * general description.
- *
- * @param felixBundle
- * the bundle in question.
- * @param loader
- * the content loader of the bundle to get access to the jar to
- * check for local permissions.
- * @param root
- * the bundle id.
- * @param signers
- * the signers (this is to support the ACC based on signers)
- * @param pd
- * the bundle protection domain
- * @param permission
- * the permission currently checked
- * @param direct
- * whether this is a direct check or not. direct check will not
- * expect any further bundle domains on the stack
- * @return true in case the permission is granted or there are postponed
- * tuples false if not. Again, see the spec for more explanations.
- */
- public boolean hasPermission(BundleRevisionImpl module, Content content,
- ProtectionDomain pd, Permission permission, boolean direct, Object admin)
- {
- // System.out.println(felixBundle + "-" + permission);
- List domains = null;
- List tuples = null;
- Object[] entry = null;
- // first see whether this is the normal case (the special case is for
- // the ACC based on signers).
- // In case of a direct call we don't need to look for other pds
- if (direct)
- {
- domains = new ArrayList();
- tuples = new ArrayList();
- domains.add(pd);
- }
- else
- {
- // Get the other pds from the stck
- entry = (Object[]) m_stack.get();
-
- // if there are none then get them from the gripper
- if (entry == null)
- {
- entry = new Object[] { new ArrayList(DomainGripper.grab()),
- new ArrayList() };
- }
- else
- {
- m_stack.set(null);
- }
-
- domains = (List) entry[0];
- tuples = (List) entry[1];
- if (!domains.contains(pd))
- {
- // We have been called directly without the direct flag
- domains.clear();
- domains.add(pd);
- }
- }
-
- // check the local permissions. they need to all the permission if there
- // are any
- if (!impliesLocal(module.getBundle(), content, permission))
- {
- return false;
- }
-
- List posts = new ArrayList();
-
- boolean result = eval(posts, module, permission, admin);
-
- domains.remove(pd);
-
- // We postponed tuples
- if (!posts.isEmpty())
- {
- tuples.add(posts);
- }
-
- // Are we at the end or this was a direct call?
- if (domains.isEmpty())
- {
- m_stack.set(null);
- // Now eval the postponed tupels. if the previous eval did return
- // false
- // tuples will be empty so we don't return from here.
- if (!tuples.isEmpty())
- {
- return m_conditions.evalRecursive(tuples);
- }
- }
- else
- {
- // this is to support recursive permission checks. In case we
- // trigger
- // a permission check while eval the stack is null until this point
- m_stack.set(entry);
- }
-
- return result;
- }
-
- public boolean impliesLocal(Bundle felixBundle, Content content,
- Permission permission)
- {
- return m_localPermissions.implies(content, felixBundle, permission);
- }
-
- public boolean isEmpty()
- {
- synchronized (m_condPermInfos)
- {
- return m_condPermInfos.isEmpty();
- }
- }
-
- // we need to find all conditions that apply and then check whether they
- // de note the permission in question unless the conditions are postponed
- // then we make sure their permissions imply the permission and add them
- // to the list of posts. Return true in case we pass or have posts
- // else falls and clear the posts first.
- private boolean eval(List posts, BundleRevisionImpl module, Permission permission,
- Object admin)
- {
- List condPermInfos = null;
-
- synchronized (m_condPermInfos)
- {
- if (isEmpty() && (admin == null))
- {
- return true;
- }
- condPermInfos = new ArrayList(m_condPermInfos.values());
- }
-
- // Check for implicit permissions like access to file area
- if (m_permissions.getPermissions(
- m_permissions.getImplicit(module.getBundle())).implies(permission,
- module.getBundle()))
- {
- return true;
- }
- List pls = new ArrayList();
- // now do the real thing
- for (Iterator iter = condPermInfos.iterator(); iter.hasNext();)
- {
- ConditionalPermissionInfoImpl cpi = (ConditionalPermissionInfoImpl) iter
- .next();
-
- ConditionInfo[] conditions = cpi._getConditionInfos();
-
- List currentPosts = new ArrayList();
-
- Conditions conds = m_conditions.getConditions(module, conditions);
- if (!conds.isSatisfied(currentPosts, m_permissions
- .getPermissions(cpi._getPermissionInfos()), permission))
- {
- continue;
- }
-
- if (!m_permissions.getPermissions(cpi._getPermissionInfos())
- .implies(permission, null))
- {
- continue;
- }
-
- if (currentPosts.isEmpty())
- {
- pls.add(new Object[] { cpi, null });
- break;
- }
- pls.add(new Object[] { cpi, currentPosts, conds });
- }
- while (pls.size() > 1)
- {
- if (!((ConditionalPermissionInfoImpl) ((Object[]) pls.get(pls
- .size() - 1))[0]).isAllow())
- {
- pls.remove(pls.size() - 1);
- }
- else
- {
- break;
- }
- }
- if (pls.size() == 1)
- {
- if (((Object[]) pls.get(0))[1] != null)
- {
- posts.add(pls.get(0));
- }
- return ((ConditionalPermissionInfoImpl) ((Object[]) pls.get(0))[0])
- .isAllow();
- }
- for (Iterator iter = pls.iterator(); iter.hasNext();)
- {
- posts.add(iter.next());
- }
- return !posts.isEmpty();
- }
-
- public ConditionalPermissionInfo newConditionalPermissionInfo(
- String encodedConditionalPermissionInfo)
- {
- return new ConditionalPermissionInfoImpl(
- encodedConditionalPermissionInfo);
- }
-
- public ConditionalPermissionInfo newConditionalPermissionInfo(String name,
- ConditionInfo[] conditions, PermissionInfo[] permissions, String access)
- {
- return new ConditionalPermissionInfoImpl(name, conditions, permissions,
- ConditionalPermissionAdminImpl.this, access
- .equals(ConditionalPermissionInfo.ALLOW));
- }
-
- public ConditionalPermissionUpdate newConditionalPermissionUpdate()
- {
- return new ConditionalPermissionUpdate()
- {
- List current = null;
- List out = null;
- {
- synchronized (m_condPermInfos)
- {
- current = new ArrayList(m_condPermInfos.values());
- out = new ArrayList(m_condPermInfos.values());
- }
- }
-
- public boolean commit()
- {
- Object sm = System.getSecurityManager();
- if (sm != null)
- {
- ((SecurityManager) sm).checkPermission(Permissions.ALL_PERMISSION);
- }
-
- synchronized (m_condPermInfos)
- {
- if (current.equals(new ArrayList(m_condPermInfos.values())))
- {
- m_condPermInfos.clear();
- write(null, null);
- for (Iterator iter = out.iterator(); iter.hasNext();)
- {
- ConditionalPermissionInfoImpl cpii = (ConditionalPermissionInfoImpl) iter
- .next();
- write(cpii.getName(), cpii);
- }
- }
- else
- {
- return false;
- }
- }
- return true;
- }
-
- public List getConditionalPermissionInfos()
- {
- return out;
- }
- };
- }
-
- public boolean handlePAHandle(BundleProtectionDomain pd)
- {
- Object[] entry = (Object[]) m_stack.get();
-
- if (entry == null)
- {
- entry = new Object[] { new ArrayList(DomainGripper.grab()),
- new ArrayList() };
- }
-
- ((List) entry[0]).remove(pd);
- if (((List) entry[0]).isEmpty())
- {
- m_stack.set(null);
- if (!((List) entry[1]).isEmpty())
- {
- return m_conditions.evalRecursive(((List) entry[1]));
- }
- }
- else
- {
- m_stack.set(entry);
- }
-
- return true;
- }
-
- public void clearPD()
- {
- m_stack.set(null);
- }
-}
diff --git a/framework.security/src/main/java/org/apache/felix/framework/security/condpermadmin/ConditionalPermissionInfoImpl.java b/framework.security/src/main/java/org/apache/felix/framework/security/condpermadmin/ConditionalPermissionInfoImpl.java
deleted file mode 100644
index 102ace18a1..0000000000
--- a/framework.security/src/main/java/org/apache/felix/framework/security/condpermadmin/ConditionalPermissionInfoImpl.java
+++ /dev/null
@@ -1,486 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.felix.framework.security.condpermadmin;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Random;
-import java.util.StringTokenizer;
-
-import org.apache.felix.framework.security.util.Permissions;
-import org.osgi.service.condpermadmin.ConditionInfo;
-import org.osgi.service.condpermadmin.ConditionalPermissionInfo;
-import org.osgi.service.permissionadmin.PermissionInfo;
-
-/**
- * Simple storage class for condperminfos. Additionally, this class can be used
- * to encode and decode infos.
- */
-public final class ConditionalPermissionInfoImpl implements
- ConditionalPermissionInfo
-{
- private static final Random RANDOM = new Random();
- static final ConditionInfo[] CONDITION_INFO = new ConditionInfo[0];
- static final PermissionInfo[] PERMISSION_INFO = new PermissionInfo[0];
- private final Object m_lock = new Object();
- private final String m_name;
- private final boolean m_allow;
- private volatile ConditionalPermissionAdminImpl m_cpai;
- private ConditionInfo[] m_conditions;
- private PermissionInfo[] m_permissions;
-
- private int parseConditionInfo(char[] encoded, int idx, List conditions) {
- String type;
- String[] args;
- try {
- int pos = idx;
-
- /* skip whitespace */
- while (Character.isWhitespace(encoded[pos])) {
- pos++;
- }
-
- /* the first character must be '[' */
- if (encoded[pos] != '[') {
- throw new IllegalArgumentException("expecting open bracket");
- }
- pos++;
-
- /* skip whitespace */
- while (Character.isWhitespace(encoded[pos])) {
- pos++;
- }
-
- /* type is not quoted or encoded */
- int begin = pos;
- while (!Character.isWhitespace(encoded[pos])
- && (encoded[pos] != ']')) {
- pos++;
- }
- if (pos == begin || encoded[begin] == '"') {
- throw new IllegalArgumentException("expecting type");
- }
- type = new String(encoded, begin, pos - begin);
-
- /* skip whitespace */
- while (Character.isWhitespace(encoded[pos])) {
- pos++;
- }
-
- /* type may be followed by args which are quoted and encoded */
- ArrayList argsList = new ArrayList();
- while (encoded[pos] == '"') {
- pos++;
- begin = pos;
- while (encoded[pos] != '"') {
- if (encoded[pos] == '\\') {
- pos++;
- }
- pos++;
- }
- argsList.add(unescapeString(encoded, begin, pos));
- pos++;
-
- if (Character.isWhitespace(encoded[pos])) {
- /* skip whitespace */
- while (Character.isWhitespace(encoded[pos])) {
- pos++;
- }
- }
- }
- args = (String[]) argsList
- .toArray(new String[argsList.size()]);
-
- /* the final character must be ']' */
- char c = encoded[pos++];
- if (c != ']') {
- throw new IllegalArgumentException("expecting close bracket");
- }
- conditions.add(new ConditionInfo(type, args));
- return pos;
- }
- catch (ArrayIndexOutOfBoundsException e) {
- throw new IllegalArgumentException("parsing terminated abruptly");
- }
- }
-
- private int parsePermissionInfo(char[] encoded, int idx, List permissions)
- {
- String parsedType = null;
- String parsedName = null;
- String parsedActions = null;
- try {
- int pos = idx;
-
- /* skip whitespace */
- while (Character.isWhitespace(encoded[pos])) {
- pos++;
- }
-
- /* the first character must be '(' */
- if (encoded[pos] != '(') {
- throw new IllegalArgumentException("expecting open parenthesis");
- }
- pos++;
-
- /* skip whitespace */
- while (Character.isWhitespace(encoded[pos])) {
- pos++;
- }
-
- /* type is not quoted or encoded */
- int begin = pos;
- while (!Character.isWhitespace(encoded[pos])
- && (encoded[pos] != ')')) {
- pos++;
- }
- if (pos == begin || encoded[begin] == '"') {
- throw new IllegalArgumentException("expecting type");
- }
- parsedType = new String(encoded, begin, pos - begin);
-
- /* skip whitespace */
- while (Character.isWhitespace(encoded[pos])) {
- pos++;
- }
-
- /* type may be followed by name which is quoted and encoded */
- if (encoded[pos] == '"') {
- pos++;
- begin = pos;
- while (encoded[pos] != '"') {
- if (encoded[pos] == '\\') {
- pos++;
- }
- pos++;
- }
- parsedName = unescapeString(encoded, begin, pos);
- pos++;
-
- if (Character.isWhitespace(encoded[pos])) {
- /* skip whitespace */
- while (Character.isWhitespace(encoded[pos])) {
- pos++;
- }
-
- /*
- * name may be followed by actions which is quoted and
- * encoded
- */
- if (encoded[pos] == '"') {
- pos++;
- begin = pos;
- while (encoded[pos] != '"') {
- if (encoded[pos] == '\\') {
- pos++;
- }
- pos++;
- }
- parsedActions = unescapeString(encoded, begin, pos);
- pos++;
-
- /* skip whitespace */
- while (Character.isWhitespace(encoded[pos])) {
- pos++;
- }
- }
- }
- }
-
- /* the final character must be ')' */
- char c = encoded[pos++];
- if (c != ')') {
- throw new IllegalArgumentException(
- "expecting close parenthesis");
- }
- permissions.add(new PermissionInfo(parsedType,parsedName, parsedActions));
- return pos;
- }
- catch (ArrayIndexOutOfBoundsException e) {
- throw new IllegalArgumentException("parsing terminated abruptly");
- }
- }
- /**
- * Takes an encoded character array and decodes it into a new String.
- */
- private static String unescapeString(char[] str, int begin, int end) {
- StringBuffer output = new StringBuffer(end - begin);
- for (int i = begin; i < end; i++) {
- char c = str[i];
- if (c == '\\') {
- i++;
- if (i < end) {
- c = str[i];
- switch (c) {
- case '"' :
- case '\\' :
- break;
- case 'r' :
- c = '\r';
- break;
- case 'n' :
- c = '\n';
- break;
- default :
- c = '\\';
- i--;
- break;
- }
- }
- }
- output.append(c);
- }
-
- return output.toString();
- }
-
- public ConditionalPermissionInfoImpl(String encoded)
- {
- encoded = encoded.trim();
- String toUpper = encoded.toUpperCase();
- if (!(toUpper.startsWith("ALLOW {") || toUpper.startsWith("DENY {")))
- {
- throw new IllegalArgumentException();
- }
- m_allow = toUpper.startsWith("ALLOW {");
- m_cpai = null;
- List conditions = new ArrayList();
- List permissions = new ArrayList();
- try {
- char[] chars = encoded.substring((m_allow ? "ALLOW {".length() : "DENY {".length())).toCharArray();
- int idx = 0;
- while (idx < chars.length)
- {
- if (Character.isWhitespace(chars[idx])) {
- idx++;
- }
- else if (chars[idx] == '[')
- {
- idx = parseConditionInfo(chars, idx, conditions);
- }
- else if (chars[idx] == '(')
- {
- idx = parsePermissionInfo(chars, idx, permissions);
- }
- else
- {
- if (chars[idx] != '}')
- {
- throw new IllegalArgumentException("Expected } but was: " + chars[idx]);
- }
- idx++;
- break;
- }
- }
- while (Character.isWhitespace(chars[idx])) {
- idx++;
- }
- if (chars[idx] == '"') {
- idx++;
- int begin = idx;
- while (chars[idx] != '"') {
- if (chars[idx] == '\\') {
- idx++;
- }
- idx++;
- }
- m_name = unescapeString(chars, begin, idx);
- }
- else {
- m_name = Long.toString(RANDOM.nextLong() ^ System.currentTimeMillis());
- }
- } catch (ArrayIndexOutOfBoundsException ex) {
- ex.printStackTrace();
- throw new IllegalArgumentException("Unable to parse conditional permission info: " + ex.getMessage());
- }
- m_conditions = conditions.isEmpty() ? CONDITION_INFO
- : (ConditionInfo[]) conditions.toArray(new ConditionInfo[conditions
- .size()]);
- m_permissions = permissions.isEmpty() ? PERMISSION_INFO
- : (PermissionInfo[]) permissions
- .toArray(new PermissionInfo[permissions.size()]);
- }
-
- public ConditionalPermissionInfoImpl(ConditionalPermissionAdminImpl cpai,
- String name, boolean access)
- {
- m_allow = access;
- m_name = name;
- m_cpai = cpai;
- m_conditions = CONDITION_INFO;
- m_permissions = PERMISSION_INFO;
- }
-
- public ConditionalPermissionInfoImpl(ConditionInfo[] conditions,
- PermissionInfo[] permisions, ConditionalPermissionAdminImpl cpai,
- boolean access)
- {
- m_allow = access;
- m_name = Long.toString(RANDOM.nextLong() ^ System.currentTimeMillis());
- m_cpai = cpai;
- m_conditions = conditions == null ? CONDITION_INFO : conditions;
- m_permissions = permisions == null ? PERMISSION_INFO : permisions;
- }
-
- public ConditionalPermissionInfoImpl(String name,
- ConditionInfo[] conditions, PermissionInfo[] permisions,
- ConditionalPermissionAdminImpl cpai, boolean access)
- {
- m_allow = access;
- m_name = (name != null) ? name : Long.toString(RANDOM.nextLong()
- ^ System.currentTimeMillis());
- m_conditions = conditions == null ? CONDITION_INFO : conditions;
- m_permissions = permisions == null ? PERMISSION_INFO : permisions;
- m_cpai = cpai;
- }
-
- public void delete()
- {
- Object sm = System.getSecurityManager();
- if (sm != null)
- {
- ((SecurityManager) sm).checkPermission(Permissions.ALL_PERMISSION);
- }
-
- synchronized (m_lock)
- {
- m_cpai.write(m_name, null);
- m_conditions = CONDITION_INFO;
- m_permissions = PERMISSION_INFO;
- }
- }
-
- public ConditionInfo[] getConditionInfos()
- {
- synchronized (m_lock)
- {
- return (ConditionInfo[]) m_conditions.clone();
- }
- }
-
- ConditionInfo[] _getConditionInfos()
- {
- synchronized (m_lock)
- {
- return m_conditions;
- }
- }
-
- void setConditionsAndPermissions(ConditionInfo[] conditions,
- PermissionInfo[] permissions)
- {
- synchronized (m_lock)
- {
- m_conditions = conditions;
- m_permissions = permissions;
- }
- }
-
- public String getName()
- {
- return m_name;
- }
-
- public PermissionInfo[] getPermissionInfos()
- {
- synchronized (m_lock)
- {
- return (PermissionInfo[]) m_permissions.clone();
- }
- }
-
- PermissionInfo[] _getPermissionInfos()
- {
- synchronized (m_lock)
- {
- return m_permissions;
- }
- }
-
- public String getEncoded()
- {
- StringBuffer buffer = new StringBuffer();
- buffer.append(m_allow ? "ALLOW " : "DENY ");
- buffer.append('{');
- buffer.append(' ');
- synchronized (m_lock)
- {
- writeTo(m_conditions, buffer);
- writeTo(m_permissions, buffer);
- }
- buffer.append('}');
- buffer.append(' ');
- buffer.append('"');
- escapeString(m_name, buffer);
- buffer.append('"');
- return buffer.toString();
- }
-
- /**
- * This escapes the quotes, backslashes, \n, and \r in the string using a
- * backslash and appends the newly escaped string to a StringBuffer.
- */
- private static void escapeString(String str, StringBuffer output) {
- int len = str.length();
- for (int i = 0; i < len; i++) {
- char c = str.charAt(i);
- switch (c) {
- case '"' :
- case '\\' :
- output.append('\\');
- output.append(c);
- break;
- case '\r' :
- output.append("\\r");
- break;
- case '\n' :
- output.append("\\n");
- break;
- default :
- output.append(c);
- break;
- }
- }
- }
-
- private void writeTo(Object[] elements, StringBuffer buffer)
- {
- for (int i = 0; i < elements.length; i++)
- {
- buffer.append(elements[i]);
- buffer.append(' ');
- }
- }
-
- public String toString()
- {
- return getEncoded();
- }
-
- public String getAccessDecision()
- {
- return m_allow ? ConditionalPermissionInfo.ALLOW
- : ConditionalPermissionInfo.DENY;
- }
-
- public boolean isAllow()
- {
- return m_allow;
- }
-}
diff --git a/framework.security/src/main/java/org/apache/felix/framework/security/condpermadmin/DomainGripper.java b/framework.security/src/main/java/org/apache/felix/framework/security/condpermadmin/DomainGripper.java
deleted file mode 100644
index c9c299f789..0000000000
--- a/framework.security/src/main/java/org/apache/felix/framework/security/condpermadmin/DomainGripper.java
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.felix.framework.security.condpermadmin;
-
-import java.security.AccessControlContext;
-import java.security.AccessController;
-import java.security.AllPermission;
-import java.security.DomainCombiner;
-import java.security.Permission;
-import java.security.PrivilegedAction;
-import java.security.ProtectionDomain;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.felix.framework.BundleProtectionDomain;
-
-/**
- * This class is a hack to get all BundleProtectionDomains currently on the
- * security stack. This way we don't need to have our own security manager set.
- */
-final class DomainGripper implements DomainCombiner, PrivilegedAction
-{
- private static final ProtectionDomain[] ALL_PERMISSION_PD = new ProtectionDomain[] { new ProtectionDomain(
- null, null)
- {
- public boolean implies(Permission perm)
- {
- return true;
- }
- } };
-
- // A per thread cache of DomainGripper objects. We might want to wrap them
- // in a softreference eventually
- private static final ThreadLocal m_cache = new ThreadLocal();
-
- private static final Permission ALL_PERMISSION = new AllPermission();
-
- private final List m_domains = new ArrayList();
-
- private AccessControlContext m_system = null;
-
- /**
- * Get all bundle protection domains and add them to the m_domains. Then
- * return the ALL_PERMISSION_PD.
- */
- public ProtectionDomain[] combine(ProtectionDomain[] current,
- ProtectionDomain[] assigned)
- {
- filter(current, m_domains);
- filter(assigned, m_domains);
-
- return ALL_PERMISSION_PD;
- }
-
- private void filter(ProtectionDomain[] assigned, List domains)
- {
- if (assigned != null)
- {
- for (int i = 0; i < assigned.length; i++)
- {
- if ((assigned[i].getClass() == BundleProtectionDomain.class)
- && !domains.contains(assigned[i]))
- {
- domains.add(assigned[i]);
- }
- }
- }
- }
-
- /**
- * Get the current bundle protection domains on the stack up to the last
- * privileged call.
- */
- public static List grab()
- {
- // First try to get a cached version. We cache by thread.
- DomainGripper gripper = (DomainGripper) m_cache.get();
- if (gripper == null)
- {
- // there is none so create one and cache it
- gripper = new DomainGripper();
- m_cache.set(gripper);
- }
- else
- {
- // This thread has a cached version so prepare it
- gripper.m_domains.clear();
- }
-
- // Get the current context.
- gripper.m_system = AccessController.getContext();
-
- // and merge it with the current combiner (i.e., gripper)
- AccessControlContext context = (AccessControlContext) AccessController
- .doPrivileged(gripper);
-
- gripper.m_system = null;
-
- // now get the protection domains
- AccessController.doPrivileged(gripper, context);
-
- // and return them
- return gripper.m_domains;
- }
-
- public Object run()
- {
- // this is a call to merge with the current context.
- if (m_system != null)
- {
- return new AccessControlContext(m_system, this);
- }
-
- // this is a call to get the protection domains.
- AccessController.checkPermission(ALL_PERMISSION);
- return null;
- }
-}
diff --git a/framework.security/src/main/java/org/apache/felix/framework/security/permissionadmin/PermissionAdminImpl.java b/framework.security/src/main/java/org/apache/felix/framework/security/permissionadmin/PermissionAdminImpl.java
deleted file mode 100644
index 92617d812f..0000000000
--- a/framework.security/src/main/java/org/apache/felix/framework/security/permissionadmin/PermissionAdminImpl.java
+++ /dev/null
@@ -1,296 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.felix.framework.security.permissionadmin;
-
-import java.io.IOException;
-import java.security.AllPermission;
-import java.security.Permission;
-import java.security.ProtectionDomain;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.felix.framework.security.condpermadmin.ConditionalPermissionAdminImpl;
-import org.apache.felix.framework.security.util.Permissions;
-import org.apache.felix.framework.security.util.PropertiesCache;
-
-//import org.apache.felix.moduleloader.IContent;
-import org.apache.felix.framework.cache.Content;
-
-import org.osgi.framework.Bundle;
-import org.osgi.service.permissionadmin.PermissionAdmin;
-import org.osgi.service.permissionadmin.PermissionInfo;
-
-/**
- * This class is a relatively straight forward implementation of the
- * PermissionAdmin service. The only somewhat involved thing is that it respects
- * the presents of a conditionalpermissionadmin service as per spec.
- */
-// TODO: Do we need this class at all or can we just emulate it using the
-// condpermadmin?
-public final class PermissionAdminImpl implements PermissionAdmin
-{
- private static final PermissionInfo[] ALL_PERMISSION = new PermissionInfo[] { new PermissionInfo(
- AllPermission.class.getName(), "", "") };
-
- private final Map m_store = new HashMap();
-
- private final PropertiesCache m_cache;
-
- private final Permissions m_permissions;
-
- private PermissionInfo[] m_default = null;
-
- public PermissionAdminImpl(Permissions permissions, PropertiesCache cache)
- throws IOException
- {
- m_permissions = permissions;
- m_cache = cache;
- m_cache.read(PermissionInfo[].class, m_store);
- }
-
- public PermissionInfo[] getDefaultPermissions()
- {
- synchronized (m_store)
- {
- if (m_default == null)
- {
- return null;
- }
- return (PermissionInfo[]) m_default.clone();
- }
- }
-
- public synchronized String[] getLocations()
- {
- synchronized (m_store)
- {
- if (m_store.isEmpty())
- {
- return null;
- }
-
- return (String[]) m_store.keySet().toArray(
- new String[m_store.size()]);
- }
- }
-
- public PermissionInfo[] getPermissions(String location)
- {
- synchronized (m_store)
- {
- if (m_store.containsKey(location))
- {
- return (PermissionInfo[]) ((PermissionInfo[]) m_store
- .get(location)).clone();
- }
- return null;
- }
- }
-
- /**
- * This will do the actual permission check as described in the core spec
- * 10.2 It will respect a present condpermadmin service as described in
- * 9.10.
- *
- * @param location
- * the location of the bundle.
- * @param bundle
- * the bundle in question.
- * @param permission
- * the permission to check.
- * @param cpai
- * A condpermadmin if one is present else null.
- * @param pd
- * the protectiondomain
- * @return Boolean.TRUE if the location is bound and the permission is
- * granted or if there is no cpa and the default permissions imply
- * the permission Boolean.FALSE otherwise unless the location is not
- * bound and their is a cpa in which case null is returned.
- */
- public Boolean hasPermission(String location, Bundle bundle,
- Permission permission, ConditionalPermissionAdminImpl cpai,
- ProtectionDomain pd, Content content)
- {
- PermissionInfo[] permissions = null;
- PermissionInfo[] defaults = null;
- boolean contains = false;
- synchronized (m_store)
- {
- contains = m_store.containsKey(location);
- permissions = (PermissionInfo[]) m_store.get(location);
- defaults = m_default;
- }
- if (contains)
- {
- if (check(permissions, permission, bundle))
- {
- return Boolean.TRUE;
- }
- return check(m_permissions.getImplicit(bundle), permission, bundle) ? Boolean.TRUE
- : Boolean.FALSE;
- }
- else if (cpai == null
- || (cpai.isEmpty() && cpai
- .impliesLocal(bundle, content, permission)))
- {
- if (defaults != null)
- {
- if (check(defaults, permission, null))
- {
- return Boolean.TRUE;
- }
- return check(m_permissions.getImplicit(bundle), permission,
- bundle) ? Boolean.TRUE : Boolean.FALSE;
- }
- else
- {
- return Boolean.TRUE;
- }
- }
- else
- {
- return null;
- }
- }
-
- private boolean check(PermissionInfo[] permissions, Permission permission,
- Bundle bundle)
- {
- Permissions permissionsObject = m_permissions
- .getPermissions(permissions);
-
- return permissionsObject.implies(permission, bundle);
- }
-
- public void setDefaultPermissions(PermissionInfo[] permissions)
- {
- Object sm = System.getSecurityManager();
- if (sm != null)
- {
- ((SecurityManager) sm).checkPermission(Permissions.ALL_PERMISSION);
- }
-
- synchronized (m_cache)
- {
- PermissionInfo[] def = null;
- Map store = null;
- synchronized (m_store)
- {
- def = m_default;
- store = new HashMap(m_store);
-
- m_default = (permissions != null) ? notNull(permissions) : null;
- }
-
- try
- {
- m_cache.write(setDefaults(store, def));
- }
- catch (IOException ex)
- {
- synchronized (m_store)
- {
- m_default = def;
- }
-
- ex.printStackTrace();
- // TODO: log this
- throw new IllegalStateException(ex.getMessage());
- }
- }
- }
-
- public void setPermissions(String location, PermissionInfo[] permissions)
- {
- Object sm = System.getSecurityManager();
- if (sm != null)
- {
- ((SecurityManager) sm).checkPermission(Permissions.ALL_PERMISSION);
- }
-
- synchronized (m_cache)
- {
- if (location != null)
- {
- Map store = null;
- Map storeCopy = null;
- PermissionInfo[] def = null;
- synchronized (m_store)
- {
- storeCopy = new HashMap(m_store);
- if (permissions != null)
- {
- m_store.put(location, notNull(permissions));
- }
- else
- {
- m_store.remove(location);
- }
- store = new HashMap(m_store);
- }
- try
- {
- m_cache.write(setDefaults(store, def));
- }
- catch (IOException ex)
- {
- synchronized (m_store)
- {
- m_store.clear();
- m_store.putAll(storeCopy);
- }
-
- ex.printStackTrace();
- // TODO: log this
- throw new IllegalStateException(ex.getMessage());
- }
- }
- }
- }
-
- private Map setDefaults(Map store, PermissionInfo[] def)
- {
- if (def != null)
- {
- store.put("DEFAULT", def);
- }
- else
- {
- store.remove("DEFAULT");
- }
- return store;
- }
-
- private PermissionInfo[] notNull(PermissionInfo[] permissions)
- {
- List result = new ArrayList();
-
- for (int i = 0; i < permissions.length; i++)
- {
- if (permissions[i] != null)
- {
- result.add(permissions[i]);
- }
- }
- return (PermissionInfo[]) result.toArray(new PermissionInfo[result
- .size()]);
- }
-}
diff --git a/framework.security/src/main/java/org/apache/felix/framework/security/util/BundleInputStream.java b/framework.security/src/main/java/org/apache/felix/framework/security/util/BundleInputStream.java
deleted file mode 100644
index bb78d662c9..0000000000
--- a/framework.security/src/main/java/org/apache/felix/framework/security/util/BundleInputStream.java
+++ /dev/null
@@ -1,227 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.felix.framework.security.util;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Enumeration;
-import java.util.List;
-import java.util.jar.JarEntry;
-import java.util.jar.JarOutputStream;
-
-//import org.apache.felix.moduleloader.IContent;
-import org.apache.felix.framework.cache.Content;
-
-/**
- * This class makes a given content available as a inputstream with a jar
- * content. In other words the stream can be used as input to a JarInputStream.
- */
-public final class BundleInputStream extends InputStream
-{
- private final Content m_root;
- private final Enumeration m_content;
- private final OutputStreamBuffer m_outputBuffer = new OutputStreamBuffer();
-
- private ByteArrayInputStream m_buffer = null;
- private JarOutputStream m_output = null;
-
- private static final String DUMMY_ENTRY = "__DUMMY-ENTRY__/";
-
- public BundleInputStream(Content root) throws IOException
- {
- m_root = root;
-
- List entries = new ArrayList();
-
- int count = 0;
- boolean inMetaInf = true;
- String manifest = null;
- for (Enumeration e = m_root.getEntries(); e.hasMoreElements();)
- {
- String entry = (String) e.nextElement();
- if (entry.endsWith("/"))
- {
- // ignore
- }
- else if (entry.equalsIgnoreCase("META-INF/MANIFEST.MF"))
- {
- if (manifest == null)
- {
- manifest = entry;
- }
- }
- else if (entry.toUpperCase().startsWith("META-INF/")
- && entry.indexOf('/', "META-INF/".length()) < 0)
- {
- entries.add(count++, entry);
- }
- else
- {
- entries.add(entry);
- }
- }
- entries.add(count++, DUMMY_ENTRY);
- if (manifest == null)
- {
- manifest = "META-INF/MANIFEST.MF";
- }
- m_content = Collections.enumeration(entries);
-
- try
- {
- m_output = new JarOutputStream(m_outputBuffer);
- readNext(manifest);
- m_buffer = new ByteArrayInputStream(m_outputBuffer.m_outBuffer
- .toByteArray());
-
- m_outputBuffer.m_outBuffer = null;
- }
- catch (IOException ex)
- {
- // TODO: figure out what is wrong
- ex.printStackTrace();
- throw ex;
- }
- }
-
- public int read() throws IOException
- {
- if ((m_output == null) && (m_buffer == null))
- {
- return -1;
- }
-
- if (m_buffer != null)
- {
- int result = m_buffer.read();
-
- if (result == -1)
- {
- m_buffer = null;
- return read();
- }
-
- return result;
- }
-
- if (m_content.hasMoreElements())
- {
- String current = (String) m_content.nextElement();
-
- readNext(current);
-
- if (!m_content.hasMoreElements())
- {
- m_output.close();
- m_output = null;
- }
-
- m_buffer = new ByteArrayInputStream(m_outputBuffer.m_outBuffer
- .toByteArray());
-
- m_outputBuffer.m_outBuffer = null;
- }
- else
- {
- m_output.close();
- m_output = null;
- }
-
- return read();
- }
-
- private void readNext(String path) throws IOException
- {
- m_outputBuffer.m_outBuffer = new ByteArrayOutputStream();
-
- if (path == DUMMY_ENTRY)
- {
- JarEntry entry = new JarEntry(path);
-
- m_output.putNextEntry(entry);
- }
- else
- {
- InputStream in = null;
- try
- {
- in = m_root.getEntryAsStream(path);
-
- if (in == null)
- {
- throw new IOException("Missing entry");
- }
-
- JarEntry entry = new JarEntry(path);
-
- m_output.putNextEntry(entry);
-
- byte[] buffer = new byte[4 * 1024];
-
- for (int c = in.read(buffer); c != -1; c = in.read(buffer))
- {
- m_output.write(buffer, 0, c);
- }
- }
- finally
- {
- if (in != null)
- {
- try
- {
- in.close();
- }
- catch (Exception ex)
- {
- // Not much we can do
- }
- }
- }
- }
-
- m_output.closeEntry();
-
- m_output.flush();
- }
-
- private static final class OutputStreamBuffer extends OutputStream
- {
- ByteArrayOutputStream m_outBuffer = null;
-
- public void write(int b)
- {
- m_outBuffer.write(b);
- }
-
- public void write(byte[] buffer) throws IOException
- {
- m_outBuffer.write(buffer);
- }
-
- public void write(byte[] buffer, int offset, int length)
- {
- m_outBuffer.write(buffer, offset, length);
- }
- }
-}
diff --git a/framework.security/src/main/java/org/apache/felix/framework/security/util/Conditions.java b/framework.security/src/main/java/org/apache/felix/framework/security/util/Conditions.java
deleted file mode 100644
index 739576cb24..0000000000
--- a/framework.security/src/main/java/org/apache/felix/framework/security/util/Conditions.java
+++ /dev/null
@@ -1,404 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.felix.framework.security.util;
-
-import java.security.Permission;
-import java.util.Dictionary;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Hashtable;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.WeakHashMap;
-
-import org.apache.felix.framework.BundleRevisionImpl;
-import org.apache.felix.framework.security.condpermadmin.ConditionalPermissionInfoImpl;
-import org.apache.felix.framework.util.SecureAction;
-import org.osgi.framework.Bundle;
-import org.osgi.service.condpermadmin.Condition;
-import org.osgi.service.condpermadmin.ConditionInfo;
-
-/**
- * This class caches conditions instances by their infos. Furthermore, it allows
- * to eval postponed condition permission tuples as per spec (see 9.45).
- */
-public final class Conditions
-{
- private static final ThreadLocal m_conditionStack = new ThreadLocal();
- private static final Map m_conditionCache = new HashMap();
-
- private final Map m_cache = new WeakHashMap();
-
- private final BundleRevisionImpl m_module;
-
- private final ConditionInfo[] m_conditionInfos;
- private final Condition[] m_conditions;
- private final SecureAction m_action;
-
- public Conditions(SecureAction action)
- {
- this(null, null, action);
- }
-
- private Conditions(BundleRevisionImpl module, ConditionInfo[] conditionInfos,
- SecureAction action)
- {
- m_module = module;
- m_conditionInfos = conditionInfos;
- if ((module != null) && (conditionInfos != null))
- {
- synchronized (m_conditionCache)
- {
- Map conditionMap = (Map) m_conditionCache.get(module);
- if (conditionMap == null)
- {
- conditionMap = new HashMap();
- conditionMap.put(m_conditionInfos,
- new Condition[m_conditionInfos.length]);
- m_conditionCache.put(module, conditionMap);
- }
- Condition[] conditions = (Condition[]) conditionMap
- .get(m_conditionInfos);
- if (conditions == null)
- {
- conditions = new Condition[m_conditionInfos.length];
- conditionMap.put(m_conditionInfos, conditions);
- }
- m_conditions = conditions;
- }
- }
- else
- {
- m_conditions = null;
- }
- m_action = action;
- }
-
- public Conditions getConditions(BundleRevisionImpl key, ConditionInfo[] conditions)
- {
- Conditions result = null;
- Map index = null;
- synchronized (m_cache)
- {
- index = (Map) m_cache.get(conditions);
- if (index == null)
- {
- index = new HashMap();
- m_cache.put(conditions, index);
- }
- }
- synchronized (index)
- {
- if (key != null)
- {
- result = (Conditions) index.get(key);
- }
- if (result == null)
- {
- result = new Conditions(key, conditions, m_action);
- index.put(key, result);
- }
- }
-
- return result;
- }
-
- public void remove(BundleRevisionImpl key) {
- final Map conditionMap;
- synchronized (m_conditionCache)
- {
- conditionMap = (Map) m_conditionCache.remove(key);
- }
-
- if (conditionMap != null)
- {
- final Iterator iter = conditionMap.keySet().iterator();
- if (iter.hasNext())
- {
- synchronized (m_cache)
- {
- do
- {
- final Map index = (Map) m_cache.get(iter.next());
- if (index != null)
- {
- index.remove(key);
- }
- }
- while (iter.hasNext());
- }
- }
- }
- }
-
- // See whether the given list is satisfied or not
- public boolean isSatisfied(List posts, Permissions permissions,
- Permission permission)
- {
- if (m_conditionInfos == null)
- {
- return true;
- }
- boolean check = true;
- for (int i = 0; i < m_conditionInfos.length; i++)
- {
- if (m_module == null)
- {
- // TODO: check whether this is correct!
- break;
- }
- try
- {
- Condition condition = null;
- boolean add = false;
- Class clazz = Class.forName(m_conditionInfos[i].getType());
-
- synchronized (m_conditions)
- {
- if (m_conditions[i] == null)
- {
- m_conditions[i] = createCondition(m_module.getBundle(),
- clazz, m_conditionInfos[i]);
- }
- condition = m_conditions[i];
- }
-
- Object current = m_conditionStack.get();
- if (current != null)
- {
- if (current instanceof HashSet)
- {
- if (((HashSet) current).contains(clazz))
- {
- return false;
- }
- }
- else
- {
- if (current == clazz)
- {
- return false;
- }
- }
- }
-
- if (condition.isPostponed())
- {
- if (check && !permissions.implies(permission, null))
- {
- return false;
- }
- else
- {
- check = false;
- }
- posts.add(new Object[] { condition, new Integer(i) });
- }
- else
- {
-
- if (current == null)
- {
- m_conditionStack.set(clazz);
- }
- else
- {
- if (current instanceof HashSet)
- {
- if (((HashSet) current).contains(clazz))
- {
- return false;
- }
- ((HashSet) current).add(clazz);
- }
- else
- {
- if (current == clazz)
- {
- return false;
- }
- HashSet frame = new HashSet();
- frame.add(current);
- frame.add(clazz);
- m_conditionStack.set(frame);
- current = frame;
- }
- }
- try
- {
- boolean mutable = condition.isMutable();
- boolean result = condition.isSatisfied();
-
- if (!mutable
- && ((condition != Condition.TRUE) && (condition != Condition.FALSE)))
- {
- synchronized (m_conditions)
- {
- m_conditions[i] = result ? Condition.TRUE
- : Condition.FALSE;
- }
- }
- if (!result)
- {
- return false;
- }
- }
- finally
- {
- if (current == null)
- {
- m_conditionStack.set(null);
- }
- else
- {
- ((HashSet) current).remove(clazz);
- if (((HashSet) current).isEmpty())
- {
- m_conditionStack.set(null);
- }
- }
- }
- }
- }
- catch (Exception e)
- {
- // TODO: log this as per spec
- e.printStackTrace();
- return false;
- }
- }
- return true;
- }
-
- public boolean evalRecursive(List entries)
- {
- Map contexts = new HashMap();
- outer: for (Iterator iter = entries.iterator(); iter.hasNext();)
- {
- List tuples = (List) iter.next();
- inner: for (Iterator inner = tuples.iterator(); inner.hasNext();)
- {
- Object[] entry = (Object[]) inner.next();
- List conditions = (List) entry[1];
- if (conditions == null)
- {
- if (!((ConditionalPermissionInfoImpl) entry[0]).isAllow())
- {
- return false;
- }
- continue outer;
- }
- for (Iterator iter2 = conditions.iterator(); iter2.hasNext();)
- {
- Object[] condEntry = (Object[]) iter2.next();
- Condition cond = (Condition) condEntry[0];
- Dictionary context = (Dictionary) contexts.get(cond
- .getClass());
- if (context == null)
- {
- context = new Hashtable();
- contexts.put(cond.getClass(), context);
- }
- Object current = m_conditionStack.get();
- if (current == null)
- {
- m_conditionStack.set(cond.getClass());
- }
- else
- {
- if (current instanceof HashSet)
- {
- ((HashSet) current).add(cond.getClass());
- }
- else
- {
- HashSet frame = new HashSet();
- frame.add(current);
- frame.add(cond.getClass());
- m_conditionStack.set(frame);
- current = frame;
- }
- }
- boolean result;
- boolean mutable = cond.isMutable();
- try
- {
- result = cond.isSatisfied(new Condition[] { cond },
- context);
- }
- finally
- {
- if (current == null)
- {
- m_conditionStack.set(null);
- }
- else
- {
- ((HashSet) current).remove(cond.getClass());
- if (((HashSet) current).isEmpty())
- {
- m_conditionStack.set(null);
- }
- }
- }
- if (!mutable && (cond != Condition.TRUE)
- && (cond != Condition.FALSE))
- {
- synchronized (((Conditions) entry[2]).m_conditions)
- {
- ((Conditions) entry[2]).m_conditions[((Integer) condEntry[1])
- .intValue()] = result ? Condition.TRUE
- : Condition.FALSE;
- }
- }
- if (!result)
- {
- continue inner;
- }
- }
- if (!((ConditionalPermissionInfoImpl) entry[0]).isAllow())
- {
- return false;
- }
- continue outer;
- }
- return false;
- }
- return true;
- }
-
- private Condition createCondition(final Bundle bundle, final Class clazz,
- final ConditionInfo info) throws Exception
- {
- try
- {
- return (Condition) m_action.getMethod(clazz, "getCondition",
- new Class[] { Bundle.class, ConditionInfo.class }).invoke(null,
- new Object[] { bundle, info });
- }
- catch (Exception ex)
- {
- ex.printStackTrace();
- return (Condition) m_action.getConstructor(clazz,
- new Class[] { Bundle.class, ConditionInfo.class }).newInstance(
- new Object[] { bundle, info });
- }
- }
-}
diff --git a/framework.security/src/main/java/org/apache/felix/framework/security/util/LocalPermissions.java b/framework.security/src/main/java/org/apache/felix/framework/security/util/LocalPermissions.java
deleted file mode 100644
index 4f921c30d3..0000000000
--- a/framework.security/src/main/java/org/apache/felix/framework/security/util/LocalPermissions.java
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.felix.framework.security.util;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.security.AllPermission;
-import java.security.Permission;
-import java.util.ArrayList;
-import java.util.Map;
-import java.util.WeakHashMap;
-
-//import org.apache.felix.moduleloader.IContent;
-import org.apache.felix.framework.cache.Content;
-import org.osgi.framework.Bundle;
-import org.osgi.service.permissionadmin.PermissionInfo;
-
-/**
- * A cache for local permissions. Local permissions are read from a given bundle
- * and cached for later lookup. See core spec 9.2.1.
- */
-// TODO: maybe use bundle events to clean thing up or weak/soft references
-public final class LocalPermissions
-{
- private static final PermissionInfo[] ALL_PERMISSION = new PermissionInfo[] { new PermissionInfo(
- AllPermission.class.getName(), "", "") };
-
- private final Map m_cache = new WeakHashMap();
- private final Permissions m_permissions;
-
- public LocalPermissions(Permissions permissions) throws IOException
- {
- m_permissions = permissions;
- }
-
- /**
- * Return true in case that the given permission is implied by the local
- * permissions of the given bundle or if there are none otherwise, false.
- * See core spec 9.2.1.
- *
- * @param root
- * the root to use for cacheing as a key
- * @param loader
- * the loader to get the content of the bundle from
- * @param bundle
- * the bundle in quesiton
- * @param permission
- * the permission to check
- * @return true if implied by local permissions.
- */
- public boolean implies(Content content, Bundle bundle,
- Permission permission)
- {
- PermissionInfo[] permissions = null;
-
- synchronized (m_cache)
- {
- if (!m_cache.containsKey(content))
- {
- InputStream in = null;
- try
- {
- in = content.getEntryAsStream("OSGI-INF/permissions.perm");
- if (in != null)
- {
- ArrayList perms = new ArrayList();
-
- BufferedReader reader = new BufferedReader(
- new InputStreamReader(in, "UTF-8"));
- for (String line = reader.readLine(); line != null; line = reader
- .readLine())
- {
- String trim = line.trim();
- if (trim.startsWith("#") || trim.startsWith("//")
- || (trim.length() == 0))
- {
- continue;
- }
- perms.add(new PermissionInfo(line));
- }
-
- permissions = (PermissionInfo[]) perms
- .toArray(new PermissionInfo[perms.size()]);
- }
- }
- catch (Exception ex)
- {
- }
- finally
- {
- if (in != null)
- {
- try
- {
- in.close();
- }
- catch (IOException ex)
- {
- // TODO Auto-generated catch block
- ex.printStackTrace();
- }
- }
- }
-
- if (permissions == null)
- {
- permissions = ALL_PERMISSION;
- }
-
- m_cache.put(content, permissions);
- }
- else
- {
- permissions = (PermissionInfo[]) m_cache.get(content);
- }
- }
-
- return m_permissions.getPermissions(permissions).implies(permission,
- bundle);
- }
-}
diff --git a/framework.security/src/main/java/org/apache/felix/framework/security/util/Permissions.java b/framework.security/src/main/java/org/apache/felix/framework/security/util/Permissions.java
deleted file mode 100644
index df971594bd..0000000000
--- a/framework.security/src/main/java/org/apache/felix/framework/security/util/Permissions.java
+++ /dev/null
@@ -1,634 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.felix.framework.security.util;
-
-import java.io.File;
-import java.io.FilePermission;
-import java.lang.ref.ReferenceQueue;
-import java.lang.ref.SoftReference;
-import java.lang.ref.WeakReference;
-import java.security.AccessController;
-import java.security.AllPermission;
-import java.security.Permission;
-import java.security.PermissionCollection;
-import java.security.PrivilegedAction;
-import java.util.Arrays;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.PropertyPermission;
-
-import org.apache.felix.framework.util.SecureAction;
-import org.osgi.framework.AdminPermission;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.CapabilityPermission;
-import org.osgi.framework.InvalidSyntaxException;
-import org.osgi.framework.PackagePermission;
-import org.osgi.framework.ServicePermission;
-import org.osgi.framework.ServiceReference;
-import org.osgi.service.packageadmin.ExportedPackage;
-import org.osgi.service.packageadmin.PackageAdmin;
-import org.osgi.service.permissionadmin.PermissionInfo;
-
-/**
- * A permission cache that uses permission infos as keys. Permission are
- * created from the parent classloader or any exported package.
- */
-// TODO: maybe use bundle events instead of soft/weak references
-public final class Permissions
-{
- private static final ClassLoader m_classLoader = Permissions.class
- .getClassLoader();
-
- private static final Map m_permissionCache = new HashMap();
- private static final Map m_permissions = new HashMap();
- private static final ReferenceQueue m_permissionsQueue = new ReferenceQueue();
-
- private static final ThreadLocal m_stack = new ThreadLocal();
-
- private final Map m_cache;
- private final ReferenceQueue m_queue;
- private final BundleContext m_context;
- private final PermissionInfo[] m_permissionInfos;
- private final boolean m_allPermission;
- private final SecureAction m_action;
-
- public static final AllPermission ALL_PERMISSION = new AllPermission();
-
- private static final PermissionInfo[] IMPLICIT = new PermissionInfo[] { new PermissionInfo(
- FilePermission.class.getName(), "-", "read,write,delete") };
-
- Permissions(PermissionInfo[] permissionInfos, BundleContext context,
- SecureAction action)
- {
- m_context = context;
- m_permissionInfos = permissionInfos;
- m_cache = new HashMap();
- m_queue = new ReferenceQueue();
- m_action = action;
- for (int i = 0; i < m_permissionInfos.length; i++)
- {
- if (m_permissionInfos[i].getType().equals(
- AllPermission.class.getName()))
- {
- m_allPermission = true;
- return;
- }
- }
- m_allPermission = false;
- }
-
- public Permissions(BundleContext context, SecureAction action)
- {
- m_context = context;
- m_permissionInfos = null;
- m_cache = null;
- m_queue = null;
- m_allPermission = true;
- m_action = action;
- }
-
- public PermissionInfo[] getImplicit(Bundle bundle)
- {
- return new PermissionInfo[] {
- IMPLICIT[0],
- new PermissionInfo(PropertyPermission.class.getName(), "org.osgi.framework.*", "read"),
- new PermissionInfo(
- AdminPermission.class.getName(),
- "(id=" + bundle.getBundleId() + ")",
- AdminPermission.CLASS + "," + AdminPermission.METADATA + "," + AdminPermission.RESOURCE + "," + AdminPermission.CONTEXT),
- new PermissionInfo(CapabilityPermission.class.getName(), "(|(capability.namespace=osgi.ee)(capability.namespace=osgi.native))", CapabilityPermission.REQUIRE),
- new PermissionInfo(PackagePermission.class.getName(),"(package.name=java.*)",PackagePermission.IMPORT),
- new PermissionInfo(ServicePermission.class.getName(),"org.osgi.service.condition.Condition", ServicePermission.GET)
- };
- }
-
- public Permissions getPermissions(PermissionInfo[] permissionInfos)
- {
- cleanUp(m_permissionsQueue, m_permissions);
-
- Permissions result;
- synchronized (m_permissions)
- {
- result = (Permissions) m_permissions.get(new Entry(permissionInfos));
- if (result == null)
- {
- //permissionInfos may not be referenced by the new Permissions, as
- //otherwise the reference in m_permissions prevents the key from
- //being garbage collectable.
- PermissionInfo[] permissionInfosClone = new PermissionInfo[permissionInfos.length];
- System.arraycopy(permissionInfos, 0, permissionInfosClone, 0, permissionInfos.length);
- result = new Permissions(permissionInfosClone, m_context, m_action);
- m_permissions.put(
- new Entry(permissionInfos, m_permissionsQueue), result);
- }
- }
- return result;
- }
-
- private static final class Entry extends WeakReference
- {
- private final int m_hashCode;
-
- // Replace with Arrays.hashCode(Object[]) by supporting Java 5+.
- private static int hashCode(Object[] array)
- {
- int hash = 0;
- for (int i = 0; i < array.length; ++i)
- {
- Object element = array[i];
- hash = hash * 31 + ((element == null) ? 0 : element.hashCode());
- }
- return hash;
- }
-
- Entry(Object entry, ReferenceQueue queue)
- {
- super(entry, queue);
- m_hashCode = entry instanceof Object[] ? hashCode((Object[]) entry): entry.hashCode();
- }
-
- Entry(Object entry)
- {
- this(entry, null);
- }
-
- public int hashCode()
- {
- return m_hashCode;
- }
-
- public boolean equals(Object o)
- {
- if (o == null)
- {
- return false;
- }
-
- if (o == this)
- {
- return true;
- }
-
- final Object entry = get();
-
- if (o instanceof Entry)
- {
-
- final Object otherEntry = ((Entry) o).get();
- if (entry == null)
- {
- return otherEntry == null;
- }
- if (otherEntry == null)
- {
- return false;
- }
- if (!entry.getClass().equals(otherEntry.getClass()))
- {
- return false;
- }
- if (entry instanceof Object[])
- {
- return Arrays.equals((Object[])entry, (Object[])otherEntry);
- }
- return entry.equals(otherEntry);
- }
- else
- {
- return false;
- }
- }
- }
-
- private static final class DefaultPermissionCollection extends
- PermissionCollection
- {
- private final Map m_perms = new HashMap();
-
- public void add(Permission perm)
- {
- synchronized (m_perms)
- {
- m_perms.put(perm, perm);
- }
- }
-
- public Enumeration elements()
- {
- throw new IllegalStateException("Not implemented");
- }
-
- public boolean implies(Permission perm)
- {
- Map perms = null;
-
- synchronized (m_perms)
- {
- perms = m_perms;
- }
-
- Permission permission = (Permission) perms.get(perm);
-
- if ((permission != null) && permission.implies(perm))
- {
- return true;
- }
-
- for (Iterator iter = perms.values().iterator(); iter.hasNext();)
- {
- Permission current = (Permission) iter.next();
- if ((current != null) && (current != permission)
- && current.implies(perm))
- {
- return true;
- }
- }
- return false;
- }
- }
-
- private void cleanUp(ReferenceQueue queue, Map cache)
- {
- for (Entry entry = (Entry) queue.poll(); entry != null; entry = (Entry) queue
- .poll())
- {
- synchronized (cache)
- {
- cache.remove(entry);
- }
- }
- }
-
- /**
- * @param target
- * the permission to be implied
- * @param bundle
- * if not null then allow implicit permissions like file access
- * to local data area
- * @return true if the permission is implied by this permissions object.
- */
- public boolean implies(Permission target, final Bundle bundle)
- {
- if (m_allPermission)
- {
- return true;
- }
-
- Class targetClass = target.getClass();
-
- cleanUp(m_queue, m_cache);
-
- if ((bundle != null) && targetClass == FilePermission.class)
- {
- for (int i = 0; i < m_permissionInfos.length; i++)
- {
- if (m_permissionInfos[i].getType().equals(
- FilePermission.class.getName()))
- {
- String postfix = "";
- String name = m_permissionInfos[i].getName();
- if (!"<>".equals(name))
- {
- if (name.endsWith("*") || name.endsWith("-"))
- {
- postfix = name.substring(name.length() - 1);
- name = name.substring(0, name.length() - 1);
- }
- if (!(new File(name)).isAbsolute())
- {
- BundleContext context = (BundleContext) AccessController
- .doPrivileged(new PrivilegedAction()
- {
- public Object run()
- {
- return bundle.getBundleContext();
- }
- });
- if (context == null)
- {
- break;
- }
- name = m_action.getAbsolutePath(new File(context
- .getDataFile(""), name));
- }
- if (postfix.length() > 0)
- {
- if ((name.length() > 0) && !name.endsWith("/"))
- {
- name += "/" + postfix;
- }
- else
- {
- name += postfix;
- }
- }
- }
- Permission source = createPermission(new PermissionInfo(
- FilePermission.class.getName(), name,
- m_permissionInfos[i].getActions()), targetClass);
- if (source.implies(target))
- {
- return true;
- }
- }
- }
- return false;
- }
-
- Object current = m_stack.get();
-
- if (current == null)
- {
- m_stack.set(targetClass);
- }
- else
- {
- if (current instanceof HashSet)
- {
- if (((HashSet) current).contains(targetClass))
- {
- return false;
- }
- ((HashSet) current).add(targetClass);
- }
- else
- {
- if (current == targetClass)
- {
- return false;
- }
- HashSet frame = new HashSet();
- frame.add(current);
- frame.add(targetClass);
- m_stack.set(frame);
- current = frame;
- }
- }
-
- try
- {
- PermissionCollection collection = null;
-
- synchronized (m_cache)
- {
- final SoftReference collectionEntry = (SoftReference) m_cache.get(targetClass);
-
- if (collectionEntry != null)
- {
- collection = (PermissionCollection) collectionEntry.get();
- }
- }
-
- if (collection == null)
- {
- collection = target.newPermissionCollection();
-
- if (collection == null)
- {
- collection = new DefaultPermissionCollection();
- }
-
- for (int i = 0; i < m_permissionInfos.length; i++)
- {
- PermissionInfo permissionInfo = m_permissionInfos[i];
- String infoType = permissionInfo.getType();
- String permissionType = targetClass.getName();
-
- if (infoType.equals(permissionType))
- {
- Permission permission = createPermission(
- permissionInfo, targetClass);
-
- if (permission != null)
- {
- collection.add(permission);
- }
- }
- }
-
- synchronized (m_cache)
- {
- m_cache.put(new Entry(target.getClass(), m_queue),
- new SoftReference(collection));
- }
- }
-
- return collection.implies(target);
- }
- finally
- {
- if (current == null)
- {
- m_stack.set(null);
- }
- else
- {
- ((HashSet) current).remove(targetClass);
- if (((HashSet) current).isEmpty())
- {
- m_stack.set(null);
- }
- }
- }
- }
-
- private Permission addToCache(String encoded, Permission permission)
- {
- if (permission == null)
- {
- return null;
- }
-
- synchronized (m_permissionCache)
- {
- Map inner = null;
-
- SoftReference ref = (SoftReference) m_permissionCache.get(encoded);
- if (ref != null)
- {
- inner = (Map) ref.get();
- }
- if (inner == null)
- {
- inner = new HashMap();
- m_permissionCache.put(encoded,
- new SoftReference(inner));
- }
-
- inner.put(new Entry(permission.getClass()), new Entry(permission));
- }
-
- return permission;
- }
-
- private Permission getFromCache(String encoded, Class target)
- {
- synchronized (m_permissionCache)
- {
- SoftReference ref = (SoftReference) m_permissionCache.get(encoded);
- if (ref != null)
- {
- Map inner = (Map) ref.get();
- if (inner != null)
- {
- Entry entry = (Entry) inner.get(target);
- if (entry != null)
- {
- Permission result = (Permission) entry.get();
- if (result != null)
- {
- return result;
- }
- inner.remove(entry);
- }
- if (inner.isEmpty())
- {
- m_permissionCache.remove(encoded);
- }
- }
- else
- {
- m_permissionCache.remove(encoded);
- }
- }
-
- }
-
- return null;
- }
-
- private Permission createPermission(final PermissionInfo permissionInfo,
- final Class target)
- {
- return (Permission) AccessController
- .doPrivileged(new PrivilegedAction()
- {
- public Object run()
- {
- Permission cached = getFromCache(permissionInfo
- .getEncoded(), target);
-
- if (cached != null)
- {
- return cached;
- }
-
- try
- {
- if (m_classLoader.loadClass(target.getName()) == target)
- {
- return addToCache(permissionInfo.getEncoded(),
- createPermission(permissionInfo.getName(),
- permissionInfo.getActions(), target));
- }
- }
- catch (ClassNotFoundException e1)
- {
- }
-
- ServiceReference[] refs = null;
- try
- {
- refs = m_context.getServiceReferences(
- PackageAdmin.class.getName(), null);
- }
- catch (InvalidSyntaxException e)
- {
- }
- if (refs != null)
- {
- for (int i = 0; i < refs.length; i++)
- {
- PackageAdmin admin = (PackageAdmin) m_context
- .getService(refs[i]);
-
- if (admin != null)
- {
- Permission result = null;
- Bundle bundle = admin.getBundle(target);
- if (bundle != null)
- {
- ExportedPackage[] exports = admin
- .getExportedPackages(bundle);
- if (exports != null)
- {
- String name = target.getName();
- name = name.substring(0, name
- .lastIndexOf('.'));
-
- for (int j = 0; j < exports.length; j++)
- {
- if (exports[j].getName().equals(
- name))
- {
- result = createPermission(
- permissionInfo.getName(),
- permissionInfo.getActions(),
- target);
- break;
- }
- }
- }
- }
-
- m_context.ungetService(refs[i]);
-
- return addToCache(permissionInfo.getEncoded(),
- result);
- }
- }
- }
-
- return null;
- }
- });
- }
-
- private Permission createPermission(String name, String action, Class target)
- {
- // System.out.println("\n\n|" + name + "|\n--\n|" + action + "|\n--\n" +
- // target + "\n\n");
- try
- {
- try
- {
- return (Permission) m_action.getConstructor(target,
- new Class[] { String.class, String.class }).newInstance(
- new Object[] { name, action });
- }
- // Fall-back to action-less constructor
- catch (NoSuchMethodException ex)
- {
- return (Permission) m_action.getConstructor(target,
- new Class[] { String.class }).newInstance(
- new Object[] { name });
- }
- }
- catch (Exception ex)
- {
- // TODO: log this or something
- }
-
- return null;
- }
-}
diff --git a/framework.security/src/main/java/org/apache/felix/framework/security/util/PropertiesCache.java b/framework.security/src/main/java/org/apache/felix/framework/security/util/PropertiesCache.java
deleted file mode 100644
index 6c76d39c2e..0000000000
--- a/framework.security/src/main/java/org/apache/felix/framework/security/util/PropertiesCache.java
+++ /dev/null
@@ -1,242 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.felix.framework.security.util;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.lang.reflect.Array;
-import java.lang.reflect.Constructor;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Properties;
-import java.util.TreeMap;
-import java.util.Map.Entry;
-
-import org.apache.felix.framework.util.SecureAction;
-
-public final class PropertiesCache
-{
- private final File m_file;
-
- private final File m_tmp;
-
- private final SecureAction m_action;
-
- public PropertiesCache(File store, File tmp, SecureAction action)
- {
- m_action = action;
- m_file = store;
- m_tmp = tmp;
- }
-
- public void write(Map data) throws IOException
- {
- OutputStream out = null;
- File tmp = null;
- File tmp2 = null;
- try
- {
- tmp = m_action.createTempFile("tmp", null, m_tmp);
- tmp2 = m_action.createTempFile("tmp", null, m_tmp);
- m_action.deleteFile(tmp2);
- Exception org = null;
- try
- {
- out = m_action.getFileOutputStream(tmp);
-
- Properties store = new Properties();
-
- int count = 0;
-
- for (Iterator iter = data.entrySet().iterator(); iter.hasNext();)
- {
- Entry entry = (Entry) iter.next();
- store.setProperty(count++ + "-" + (String) entry.getKey(),
- getEncoded(entry.getValue()));
- }
-
- store.store(out, null);
- }
- catch (IOException ex)
- {
- org = ex;
- throw ex;
- }
- finally
- {
- if (out != null)
- {
- try
- {
- out.close();
- }
- catch (IOException ex)
- {
- if (org == null)
- {
- throw ex;
- }
- }
- }
- }
- if ((m_action.fileExists(m_file) && !m_action.renameFile(m_file,
- tmp2))
- || !m_action.renameFile(tmp, m_file))
- {
- throw new IOException("Unable to write permissions");
- }
- }
- catch (IOException ex)
- {
- if (!m_action.fileExists(m_file) && (tmp2 != null)
- && m_action.fileExists(tmp2))
- {
- m_action.renameFile(tmp2, m_file);
- }
- throw ex;
- }
- finally
- {
- if (tmp != null)
- {
- m_action.deleteFile(tmp);
- }
- if (tmp2 != null)
- {
- m_action.deleteFile(tmp2);
- }
- }
- }
-
- public void read(Class target, Map map) throws IOException
- {
- if (!m_file.isFile())
- {
- return;
- }
- InputStream in = null;
- Exception other = null;
- Map result = new TreeMap();
- try
- {
- in = m_action.getFileInputStream(m_file);
-
- Properties store = new Properties();
- store.load(in);
-
- for (Iterator iter = store.entrySet().iterator(); iter.hasNext();)
- {
- Entry entry = (Entry) iter.next();
- result.put(entry.getKey(), getUnencoded((String) entry
- .getValue(), target));
- }
- }
- catch (IOException ex)
- {
- other = ex;
- throw ex;
- }
- finally
- {
- if (in != null)
- {
- try
- {
- in.close();
- }
- catch (IOException ex)
- {
- if (other == null)
- {
- throw ex;
- }
- }
- }
- }
- for (Iterator iter = result.entrySet().iterator(); iter.hasNext();)
- {
- Entry entry = (Entry) iter.next();
- String key = (String) entry.getKey();
- map.put(key.substring(key.indexOf("-")), entry.getValue());
- }
- }
-
- private String getEncoded(Object target) throws IOException
- {
- Properties props = new Properties();
- if (target.getClass().isArray())
- {
-
- Object[] array = (Object[]) target;
- for (int i = 0; i < array.length; i++)
- {
- props.setProperty(Integer.toString(i), array[i].toString());
- }
-
- ByteArrayOutputStream tmp = new ByteArrayOutputStream();
- props.store(tmp, null);
- return new String(tmp.toByteArray());
- }
-
- return target.toString();
- }
-
- private Object getUnencoded(String encoded, Class target)
- throws IOException
- {
- try
- {
- if (target.isArray())
- {
- Properties props = new Properties();
- props.load(new ByteArrayInputStream(encoded.getBytes()));
- Class componentType = target.getComponentType();
- Constructor constructor = m_action.getConstructor(
- componentType, new Class[] { String.class });
- Object[] params = new Object[1];
- Object[] result = (Object[]) Array.newInstance(componentType,
- props.size());
-
- for (Iterator iter = props.entrySet().iterator(); iter
- .hasNext();)
- {
- Entry entry = (Entry) iter.next();
- params[0] = entry.getValue();
- result[Integer.parseInt((String) entry.getKey())] = constructor
- .newInstance(params);
- }
-
- return result;
- }
-
- return m_action.invoke(m_action.getConstructor(target,
- new Class[] { String.class }), new Object[] { encoded });
- }
- catch (Exception ex)
- {
- ex.printStackTrace();
-
- throw new IOException(ex.getMessage());
- }
- }
-}
diff --git a/framework.security/src/main/java/org/apache/felix/framework/security/util/TrustManager.java b/framework.security/src/main/java/org/apache/felix/framework/security/util/TrustManager.java
deleted file mode 100644
index 5b2520e08e..0000000000
--- a/framework.security/src/main/java/org/apache/felix/framework/security/util/TrustManager.java
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.felix.framework.security.util;
-
-import java.io.File;
-import java.io.InputStream;
-import java.io.PrintStream;
-import java.security.KeyStore;
-import java.security.cert.CertificateFactory;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Enumeration;
-import java.util.StringTokenizer;
-
-import org.apache.felix.framework.util.SecureAction;
-
-/*
- * TODO: the certificate stores as well as the CRLs might change over time
- * (added/removed certificates). We need a way to detect that and act on it.
- * The problem is to find a good balance between re-checking and caching...
- */
-public final class TrustManager
-{
- private final SecureAction m_action;
- private final String m_crlList;
- private final String m_typeList;
- private final String m_passwdList;
- private final String m_storeList;
- private Collection m_caCerts = null;
- private Collection m_crls = null;
-
- public TrustManager(String crlList, String typeList, String passwdList,
- String storeList, SecureAction action)
- {
- m_crlList = crlList;
- m_typeList = typeList;
- m_passwdList = passwdList;
- m_storeList = storeList;
- m_action = action;
- }
-
- private synchronized void init()
- {
- if (m_caCerts == null)
- {
- try
- {
- initCRLs();
- initCaCerts();
- }
- catch (Exception ex)
- {
- m_caCerts = new ArrayList();
- m_crls = new ArrayList();
- // TODO: log this
- ex.printStackTrace();
- }
- }
- }
-
- private void initCRLs() throws Exception
- {
- final Collection result = new ArrayList();
-
- if (m_crlList.trim().length() != 0)
- {
- CertificateFactory fac = CertificateFactory.getInstance("X509");
-
- for (StringTokenizer tok = new StringTokenizer(m_crlList, "|"); tok
- .hasMoreElements();)
- {
- InputStream input = null;
- try
- {
- input = m_action.getURLConnectionInputStream(m_action
- .createURL(null, tok.nextToken(), null)
- .openConnection());
- result.addAll(fac.generateCRLs(input));
- }
- catch (Exception ex)
- {
- // TODO: log this or something
- ex.printStackTrace();
- }
- finally
- {
- if (input != null)
- {
- try
- {
- input.close();
- }
- catch (Exception ex)
- {
- // TODO: log this or something
- ex.printStackTrace();
- }
- }
- }
- }
- }
-
- m_crls = result;
- }
-
- private void initCaCerts() throws Exception
- {
- final Collection result = new ArrayList();
-
- if (m_storeList.trim().length() != 0)
- {
-
- StringTokenizer storeTok = new StringTokenizer(m_storeList, "|");
- StringTokenizer passwdTok = new StringTokenizer(m_passwdList, "|");
- StringTokenizer typeTok = new StringTokenizer(m_typeList, "|");
-
- while (storeTok.hasMoreTokens())
- {
- KeyStore ks = KeyStore.getInstance(typeTok.nextToken().trim());
-
- InputStream input = null;
- try
- {
- input = m_action.getURLConnectionInputStream(m_action
- .createURL(null, storeTok.nextToken().trim(), null)
- .openConnection());
- String pass = passwdTok.nextToken().trim();
-
- ks.load(input, (pass.length() > 0) ? pass.toCharArray()
- : null);
-
- for (Enumeration e = ks.aliases(); e.hasMoreElements();)
- {
- String alias = (String) e.nextElement();
- result.add(ks.getCertificate(alias));
- }
- }
- catch (Exception ex)
- {
- // TODO: log this or something
- ex.printStackTrace();
- }
- finally
- {
- if (input != null)
- {
- try
- {
- input.close();
- }
- catch (Exception ex)
- {
- // TODO: log this or something
- ex.printStackTrace();
- }
- }
- }
- }
- }
-
- m_caCerts = result;
- }
-
- public Collection getCRLs()
- {
- init();
-
- return m_crls;
- }
-
- public Collection getCaCerts()
- {
- init();
-
- return m_caCerts;
- }
-}
diff --git a/framework.security/src/main/java/org/apache/felix/framework/security/verifier/BundleDNParser.java b/framework.security/src/main/java/org/apache/felix/framework/security/verifier/BundleDNParser.java
deleted file mode 100644
index d24c4d42f3..0000000000
--- a/framework.security/src/main/java/org/apache/felix/framework/security/verifier/BundleDNParser.java
+++ /dev/null
@@ -1,550 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.felix.framework.security.verifier;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.lang.reflect.Method;
-import java.security.cert.CRL;
-import java.security.cert.Certificate;
-import java.security.cert.CertificateException;
-import java.security.cert.X509Certificate;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.WeakHashMap;
-import java.util.jar.JarEntry;
-import java.util.jar.JarInputStream;
-
-import org.apache.felix.framework.BundleRevisionImpl;
-import org.apache.felix.framework.Logger;
-import org.apache.felix.framework.security.util.BundleInputStream;
-import org.apache.felix.framework.security.util.TrustManager;
-/*
-import org.apache.felix.moduleloader.IContent;
-import org.apache.felix.moduleloader.IModule;
-*/
-import org.apache.felix.framework.cache.Content;
-
-
-import org.osgi.framework.Bundle;
-
-public final class BundleDNParser
-{
- private static final Method m_getCodeSigners;
- private static final Method m_getSignerCertPath;
- private static final Method m_getCertificates;
-
- static
- {
- Method getCodeSigners = null;
- Method getSignerCertPath = null;
- Method getCertificates = null;
- try
- {
- getCodeSigners = Class.forName("java.util.jar.JarEntry").getMethod(
- "getCodeSigners", null);
- getSignerCertPath = Class.forName("java.security.CodeSigner")
- .getMethod("getSignerCertPath", null);
- getCertificates = Class.forName("java.security.cert.CertPath")
- .getMethod("getCertificates", null);
- }
- catch (Exception ex)
- {
- ex.printStackTrace();
- getCodeSigners = null;
- getSignerCertPath = null;
- getCertificates = null;
- }
- m_getCodeSigners = getCodeSigners;
- m_getSignerCertPath = getSignerCertPath;
- m_getCertificates = getCertificates;
- }
-
- private final Logger m_logger;
- private final Map m_cache = new WeakHashMap();
- private final Map m_allCache = new WeakHashMap();
-
- private final TrustManager m_manager;
-
- public BundleDNParser(TrustManager manager, Logger logger)
- {
- m_manager = manager;
- m_logger = logger;
- }
-
- public Map getCache()
- {
- synchronized (m_cache)
- {
- return new HashMap(m_cache);
- }
- }
-
- public void put(String root, X509Certificate[] dnChains)
- {
- synchronized (m_cache)
- {
- m_cache.put(root, dnChains);
- }
- }
-
- public void checkDNChains(BundleRevisionImpl root, Content content, int signersType)
- throws Exception
- {
- if (signersType == Bundle.SIGNERS_TRUSTED)
- {
- synchronized (m_cache)
- {
- if (m_cache.containsKey(root))
- {
- Map result = (Map) m_cache.get(root);
- if ((result != null) && (result.isEmpty()))
- {
- throw new IOException("Bundle not properly signed");
- }
- return;
- }
- }
- }
- else
- {
- synchronized (m_allCache)
- {
- if (m_allCache.containsKey(root))
- {
- Map result = (Map) m_allCache.get(root);
- if ((result != null) && (result.isEmpty()))
- {
- throw new IOException("Bundle not properly signed");
- }
- return;
- }
- }
- }
-
- Map result = null;
- Exception org = null;
- try
- {
- result = _getDNChains(content,
- signersType == Bundle.SIGNERS_TRUSTED);
- }
- catch (Exception ex)
- {
- org = ex;
- }
-
- if (signersType == Bundle.SIGNERS_TRUSTED)
- {
- synchronized (m_cache)
- {
- m_cache.put(root, result);
- }
- }
- else
- {
- synchronized (m_allCache)
- {
- m_allCache.put(root, result);
- }
- }
-
- if (org != null)
- {
- throw org;
- }
- }
-
- public Map getDNChains(BundleRevisionImpl root, Content bundleRevision,
- int signersType)
- {
- if (signersType == Bundle.SIGNERS_TRUSTED)
- {
- synchronized (m_cache)
- {
- if (m_cache.containsKey(root))
- {
- Map result = (Map) m_cache.get(root);
- return (result == null) ? new HashMap() : new HashMap(
- result);
- }
- }
- }
- else
- {
- synchronized (m_allCache)
- {
- if (m_allCache.containsKey(root))
- {
- Map result = (Map) m_allCache.get(root);
- return (result == null) ? new HashMap() : new HashMap(
- result);
- }
- }
- }
-
- Map result = null;
-
- try
- {
- result = _getDNChains(bundleRevision,
- signersType == Bundle.SIGNERS_TRUSTED);
- }
- catch (Exception ex)
- {
- // Ignore
- }
-
- if (signersType == Bundle.SIGNERS_TRUSTED)
- {
- synchronized (m_cache)
- {
- m_cache.put(root, result);
- }
- }
- else
- {
- synchronized (m_allCache)
- {
- m_allCache.put(root, result);
- }
- }
-
- return (result == null) ? new HashMap() : new HashMap(result);
- }
-
- private Map _getDNChains(Content content, boolean check)
- throws IOException
- {
- X509Certificate[] certificates = null;
-
- certificates = getCertificates(new BundleInputStream(content), check);
-
- if (certificates == null)
- {
- return null;
- }
-
- List rootChains = new ArrayList();
-
- getRootChains(certificates, rootChains, check);
-
- Map result = new HashMap();
-
- for (Iterator rootIter = rootChains.iterator(); rootIter.hasNext();)
- {
- StringBuffer buffer = new StringBuffer();
-
- List chain = (List) rootIter.next();
-
- Iterator iter = chain.iterator();
-
- X509Certificate current = (X509Certificate) iter.next();
-
- result.put(current, chain);
- }
-
- if (!result.isEmpty())
- {
- return result;
- }
-
- throw new IOException();
- }
-
- private X509Certificate[] getCertificates(InputStream input, boolean check)
- throws IOException
- {
- JarInputStream bundle = new JarInputStream(input, true);
-
- if (bundle.getManifest() == null)
- {
- return null;
- }
-
- List certificateChains = new ArrayList();
-
- int count = certificateChains.size();
-
- // This is tricky: jdk1.3 doesn't say anything about what is happening
- // if a bad sig is detected on an entry - later jdk's do say that they
- // will throw a security Exception. The below should cater for both
- // behaviors.
- for (JarEntry entry = bundle.getNextJarEntry(); entry != null; entry = bundle
- .getNextJarEntry())
- {
-
- if (entry.isDirectory() ||
- (entry.getName().startsWith("META-INF/") &&
- (entry.getName().indexOf('/', "META-INF/".length()) < 0)))
- {
- continue;
- }
-
- for (byte[] tmp = new byte[4096]; bundle.read(tmp, 0, tmp.length) != -1;)
- {
- }
-
- Certificate[] certificates = entry.getCertificates();
-
- // Workaround stupid bug in the sun jdk 1.5.x - getCertificates()
- // returns null there even if there are valid certificates.
- // This is a regression bug that has been fixed in 1.6.
- //
- // We use reflection to see whether we have a SignerCertPath
- // for the entry (available >= 1.5) and if so check whether
- // there are valid certificates - don't try this at home.
- if ((certificates == null) && (m_getCodeSigners != null))
- {
- try
- {
- Object[] signers = (Object[]) m_getCodeSigners.invoke(
- entry, null);
-
- if (signers != null)
- {
- List certChains = new ArrayList();
-
- for (int i = 0; i < signers.length; i++)
- {
- Object path = m_getSignerCertPath.invoke(
- signers[i], null);
-
- certChains.addAll((List) m_getCertificates.invoke(
- path, null));
- }
-
- certificates = (Certificate[]) certChains
- .toArray(new Certificate[certChains.size()]);
- }
- }
- catch (Exception ex)
- {
- ex.printStackTrace();
- // Not much we can do - probably we are not on >= 1.5
- }
- }
-
- if ((certificates == null) || (certificates.length == 0))
- {
- return null;
- }
-
- List chains = new ArrayList();
-
- getRootChains(certificates, chains, check);
-
- if (certificateChains.isEmpty())
- {
- certificateChains.addAll(chains);
- count = certificateChains.size();
- }
- else
- {
- for (Iterator iter2 = certificateChains.iterator(); iter2
- .hasNext();)
- {
- X509Certificate cert = (X509Certificate) ((List) iter2
- .next()).get(0);
- boolean found = false;
- for (Iterator iter3 = chains.iterator(); iter3.hasNext();)
- {
- X509Certificate cert2 = (X509Certificate) ((List) iter3
- .next()).get(0);
-
- if (cert.getSubjectDN().equals(cert2.getSubjectDN())
- && cert.equals(cert2))
- {
- found = true;
- break;
- }
- }
- if (!found)
- {
- iter2.remove();
- }
- }
- }
-
- if (certificateChains.isEmpty())
- {
- if (count > 0)
- {
- throw new IOException("Bad signers");
- }
- return null;
- }
- }
-
- List result = new ArrayList();
-
- for (Iterator iter = certificateChains.iterator(); iter.hasNext();)
- {
- result.addAll((List) iter.next());
- }
-
- return (X509Certificate[]) (!result.isEmpty() ? result.toArray(new X509Certificate[result
- .size()]) : null);
- }
-
- private boolean isRevoked(Certificate certificate)
- {
- for (Iterator iter = m_manager.getCRLs().iterator(); iter.hasNext();)
- {
- if (((CRL) iter.next()).isRevoked(certificate))
- {
- return true;
- }
- }
-
- return false;
- }
-
- private void getRootChains(Certificate[] certificates, List chains,
- boolean check)
- {
- List chain = new ArrayList();
-
- boolean revoked = false;
-
- for (int i = 0; i < certificates.length - 1; i++)
- {
- X509Certificate certificate = (X509Certificate) certificates[i];
-
- if (!revoked && isRevoked(certificate))
- {
- revoked = true;
- }
- if (!check || !revoked)
- {
- try
- {
- if (check)
- {
- certificate.checkValidity();
- }
-
- chain.add(certificate);
- }
- catch (CertificateException ex)
- {
- m_logger.log(Logger.LOG_WARNING, "Invalid Certificate", ex);
- revoked = true;
- }
- }
-
- if (!((X509Certificate) certificates[i + 1]).getSubjectDN().equals(
- certificate.getIssuerDN()))
- {
- if (!check || (!revoked && trusted(certificate)))
- {
- chains.add(chain);
- }
-
- revoked = false;
-
- if (!chain.isEmpty())
- {
- chain = new ArrayList();
- }
- }
- }
- // The final entry in the certs array is always
- // a "root" certificate
- if (!check || !revoked)
- {
- chain.add(certificates[certificates.length - 1]);
- if (!check
- || trusted((X509Certificate) certificates[certificates.length - 1]))
- {
- chains.add(chain);
- }
- }
- }
-
- private boolean trusted(X509Certificate cert)
- {
- if (m_manager.getCaCerts().isEmpty() || isRevoked(cert))
- {
- return false;
- }
-
- for (Iterator iter = m_manager.getCaCerts().iterator(); iter.hasNext();)
- {
- X509Certificate trustedCaCert = (X509Certificate) iter.next();
-
- if (isRevoked(trustedCaCert))
- {
- continue;
- }
-
- // If the cert has the same SubjectDN
- // as a trusted CA, check whether
- // the two certs are the same.
- if (cert.getSubjectDN().equals(trustedCaCert.getSubjectDN()))
- {
- if (cert.equals(trustedCaCert))
- {
- try
- {
- cert.checkValidity();
- trustedCaCert.checkValidity();
- return true;
- }
- catch (CertificateException ex)
- {
- // Not much we can do
- m_logger.log(Logger.LOG_WARNING, "Invalid Certificate", ex);
- }
- }
- }
- }
-
- // cert issued by any of m_trustedCaCerts ? return true : return false
- for (Iterator iter = m_manager.getCaCerts().iterator(); iter.hasNext();)
- {
- X509Certificate trustedCaCert = (X509Certificate) iter.next();
-
- if (isRevoked(trustedCaCert))
- {
- continue;
- }
-
- if (cert.getIssuerDN().equals(trustedCaCert.getSubjectDN()))
- {
- try
- {
- cert.verify(trustedCaCert.getPublicKey());
- cert.checkValidity();
- trustedCaCert.checkValidity();
- return true;
- }
- catch (Exception ex)
- {
- m_logger.log(Logger.LOG_WARNING, "Invalid Certificate", ex);
- }
- }
- }
-
- return false;
- }
-}
diff --git a/framework/pom.xml b/framework/pom.xml
index 7ab7ae6f9e..6d9966133a 100644
--- a/framework/pom.xml
+++ b/framework/pom.xml
@@ -30,7 +30,10 @@
7.1.0-SNAPSHOT$
- 8
+
+ 9scm:git:https://github.com/apache/felix-dev.git
@@ -41,15 +44,6 @@
-
- org.apache.maven.plugins
- maven-surefire-plugin
-
-
- -Djava.security.manager=allow
-
-
- org.moditectmoditect-maven-plugin
@@ -219,10 +213,18 @@
+
+
+ org.ow2.asm
+ asm
+ 9.8
+ test
+ org.ow2.asm
- asm-all
- 5.2
+ asm-tree
+ 9.8test
diff --git a/framework/src/main/java/org/apache/felix/framework/BundleContextImpl.java b/framework/src/main/java/org/apache/felix/framework/BundleContextImpl.java
index fba86d21b5..24ed215399 100644
--- a/framework/src/main/java/org/apache/felix/framework/BundleContextImpl.java
+++ b/framework/src/main/java/org/apache/felix/framework/BundleContextImpl.java
@@ -25,22 +25,18 @@
import java.util.Collections;
import java.util.Dictionary;
-import org.osgi.framework.AdminPermission;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleException;
import org.osgi.framework.BundleListener;
-import org.osgi.framework.Constants;
import org.osgi.framework.Filter;
import org.osgi.framework.FrameworkListener;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceFactory;
import org.osgi.framework.ServiceListener;
import org.osgi.framework.ServiceObjects;
-import org.osgi.framework.ServicePermission;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
-import org.osgi.framework.SynchronousBundleListener;
class BundleContextImpl implements BundleContext
{
@@ -71,22 +67,6 @@ public String getProperty(String name)
// the result is the same as if the calling thread had
// won the race condition.
- Object sm = System.getSecurityManager();
-
- if (sm != null)
- {
- if (!(Constants.FRAMEWORK_VERSION.equals(name) ||
- Constants.FRAMEWORK_VENDOR.equals(name) ||
- Constants.FRAMEWORK_LANGUAGE.equals(name)||
- Constants.FRAMEWORK_OS_NAME.equals(name) ||
- Constants.FRAMEWORK_OS_VERSION.equals(name) ||
- Constants.FRAMEWORK_PROCESSOR.equals(name)))
- {
- ((SecurityManager) sm).checkPermission(
- new java.util.PropertyPermission(name, "read"));
- }
- }
-
return m_felix.getProperty(name);
}
@@ -135,22 +115,7 @@ public Bundle installBundle(String location, InputStream is)
// the result is the same as if the calling thread had
// won the race condition.
- Bundle result = null;
-
- Object sm = System.getSecurityManager();
-
- if (sm != null)
- {
- result = m_felix.installBundle(m_bundle, location, is);
- // Do check the bundle again in case that is was installed
- // already.
- ((SecurityManager) sm).checkPermission(
- new AdminPermission(result, AdminPermission.LIFECYCLE));
- }
- else
- {
- result = m_felix.installBundle(m_bundle, location, is);
- }
+ Bundle result = m_felix.installBundle(m_bundle, location, is);
return result;
}
@@ -205,17 +170,6 @@ public void addBundleListener(BundleListener l)
// while holding the event queue lock, so it will either succeed
// or fail.
- Object sm = System.getSecurityManager();
-
- if (sm != null)
- {
- if (l instanceof SynchronousBundleListener)
- {
- ((SecurityManager) sm).checkPermission(new AdminPermission(m_bundle,
- AdminPermission.LISTENER));
- }
- }
-
m_felix.addBundleListener(m_bundle, l);
}
@@ -229,17 +183,6 @@ public void removeBundleListener(BundleListener l)
// the result is the same as if the calling thread had
// won the race condition.
- Object sm = System.getSecurityManager();
-
- if (sm != null)
- {
- if (l instanceof SynchronousBundleListener)
- {
- ((SecurityManager) sm).checkPermission(new AdminPermission(m_bundle,
- AdminPermission.LISTENER));
- }
- }
-
m_felix.removeBundleListener(m_bundle, l);
}
@@ -328,19 +271,6 @@ public ServiceRegistration> registerService(
// because internally the framework acquires the bundle state
// lock to ensure state consistency.
- Object sm = System.getSecurityManager();
-
- if (sm != null)
- {
- if (clazzes != null)
- {
- for (String clazz : clazzes) {
- ((SecurityManager) sm).checkPermission(
- new ServicePermission(clazz, ServicePermission.REGISTER));
- }
- }
- }
-
return m_felix.registerService(this, clazzes, svcObj, dict);
}
@@ -466,13 +396,6 @@ public S getService(ServiceReference ref)
throw new NullPointerException("Specified service reference cannot be null.");
}
- Object sm = System.getSecurityManager();
-
- if (sm != null)
- {
- ((SecurityManager) sm).checkPermission(new ServicePermission(ref, ServicePermission.GET));
- }
-
return m_felix.getService(m_bundle, ref, false);
}
@@ -539,13 +462,6 @@ public ServiceObjects getServiceObjects(final ServiceReference ref)
{
checkValidity();
- Object sm = System.getSecurityManager();
-
- if (sm != null)
- {
- ((SecurityManager) sm).checkPermission(new ServicePermission(ref, ServicePermission.GET));
- }
-
ServiceRegistrationImpl reg =
((ServiceRegistrationImpl.ServiceReferenceImpl) ref).getRegistration();
if ( reg.isValid() )
@@ -576,13 +492,6 @@ public S getService() {
// the result is the same as if the calling thread had
// won the race condition.
- final Object sm = System.getSecurityManager();
-
- if (sm != null)
- {
- ((SecurityManager) sm).checkPermission(new ServicePermission(m_ref, ServicePermission.GET));
- }
-
return m_felix.getService(m_bundle, m_ref, true);
}
diff --git a/framework/src/main/java/org/apache/felix/framework/BundleImpl.java b/framework/src/main/java/org/apache/felix/framework/BundleImpl.java
index 49cf856bbb..97127a1824 100644
--- a/framework/src/main/java/org/apache/felix/framework/BundleImpl.java
+++ b/framework/src/main/java/org/apache/felix/framework/BundleImpl.java
@@ -45,14 +45,11 @@
import org.apache.felix.framework.util.StringMap;
import org.apache.felix.framework.util.Util;
import org.osgi.dto.DTO;
-import org.osgi.framework.AdaptPermission;
-import org.osgi.framework.AdminPermission;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleException;
import org.osgi.framework.Constants;
-import org.osgi.framework.ServicePermission;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.Version;
import org.osgi.framework.hooks.bundle.CollisionHook;
@@ -246,14 +243,6 @@ synchronized void setActivator(BundleActivator activator)
@Override
public BundleContext getBundleContext()
{
- Object sm = System.getSecurityManager();
-
- if (sm != null)
- {
- ((SecurityManager) sm).checkPermission(
- new AdminPermission(this, AdminPermission.CONTEXT));
- }
-
return m_context;
}
@@ -283,63 +272,18 @@ public long getBundleId()
@Override
public URL getEntry(String name)
{
- Object sm = System.getSecurityManager();
-
- if (sm != null)
- {
- try
- {
- ((SecurityManager) sm).checkPermission(new AdminPermission(this,
- AdminPermission.RESOURCE));
- }
- catch (Exception e)
- {
- return null; // No permission
- }
- }
-
return getFramework().getBundleEntry(this, name);
}
@Override
public Enumeration getEntryPaths(String path)
{
- Object sm = System.getSecurityManager();
-
- if (sm != null)
- {
- try
- {
- ((SecurityManager) sm).checkPermission(new AdminPermission(this,
- AdminPermission.RESOURCE));
- }
- catch (Exception e)
- {
- return null; // No permission
- }
- }
-
return getFramework().getBundleEntryPaths(this, path);
}
@Override
public Enumeration findEntries(String path, String filePattern, boolean recurse)
{
- Object sm = System.getSecurityManager();
-
- if (sm != null)
- {
- try
- {
- ((SecurityManager) sm).checkPermission(new AdminPermission(this,
- AdminPermission.RESOURCE));
- }
- catch (Exception e)
- {
- return null; // No permission
- }
- }
-
return getFramework().findBundleEntries(
this, path, filePattern, recurse);
}
@@ -353,14 +297,6 @@ public Dictionary getHeaders()
@Override
public Dictionary getHeaders(String locale)
{
- Object sm = System.getSecurityManager();
-
- if (sm != null)
- {
- ((SecurityManager) sm).checkPermission(new AdminPermission(this,
- AdminPermission.METADATA));
- }
-
if (locale == null)
{
locale = Locale.getDefault().toString();
@@ -623,13 +559,6 @@ void setLastModified(long l)
@Override
public String getLocation()
{
- Object sm = System.getSecurityManager();
-
- if (sm != null)
- {
- ((SecurityManager) sm).checkPermission(new AdminPermission(this,
- AdminPermission.METADATA));
- }
return _getLocation();
}
@@ -658,42 +587,12 @@ String _getLocation()
@Override
public URL getResource(String name)
{
- Object sm = System.getSecurityManager();
-
- if (sm != null)
- {
- try
- {
- ((SecurityManager) sm).checkPermission(
- new AdminPermission(this, AdminPermission.RESOURCE));
- }
- catch (Exception e)
- {
- return null; // No permission
- }
- }
-
return getFramework().getBundleResource(this, name);
}
@Override
public Enumeration getResources(String name) throws IOException
{
- Object sm = System.getSecurityManager();
-
- if (sm != null)
- {
- try
- {
- ((SecurityManager) sm).checkPermission(
- new AdminPermission(this, AdminPermission.RESOURCE));
- }
- catch (Exception e)
- {
- return null; // No permission
- }
- }
-
// Spec says we should return null when resources not found,
// even though ClassLoader.getResources() returns empty enumeration.
Enumeration e = getFramework().getBundleResources(this, name);
@@ -709,84 +608,12 @@ public Enumeration getResources(String name) throws IOException
@Override
public ServiceReference>[] getRegisteredServices()
{
- Object sm = System.getSecurityManager();
-
- if (sm != null)
- {
- ServiceReference>[] refs = getFramework().getBundleRegisteredServices(this);
-
- if (refs == null)
- {
- return refs;
- }
-
- List> result = new ArrayList<>();
-
- for (ServiceReference> ref : refs) {
- try
- {
- ((SecurityManager) sm).checkPermission(new ServicePermission(
- ref, ServicePermission.GET));
-
- result.add(ref);
- }
- catch (Exception ex)
- {
- // Silently ignore.
- }
- }
-
- if (result.isEmpty())
- {
- return null;
- }
-
- return (ServiceReference[]) result.toArray(new ServiceReference[result.size()]);
- }
- else
- {
- return getFramework().getBundleRegisteredServices(this);
- }
+ return getFramework().getBundleRegisteredServices(this);
}
@Override
public ServiceReference>[] getServicesInUse()
{
- Object sm = System.getSecurityManager();
-
- if (sm != null)
- {
- ServiceReference>[] refs = getFramework().getBundleServicesInUse(this);
-
- if (refs == null)
- {
- return refs;
- }
-
- List> result = new ArrayList<>();
-
- for (ServiceReference> ref : refs) {
- try
- {
- ((SecurityManager) sm).checkPermission(
- new ServicePermission(ref, ServicePermission.GET));
-
- result.add(ref);
- }
- catch (Exception ex)
- {
- // Silently ignore.
- }
- }
-
- if (result.isEmpty())
- {
- return null;
- }
-
- return (ServiceReference[]) result.toArray(new ServiceReference[result.size()]);
- }
-
return getFramework().getBundleServicesInUse(this);
}
@@ -968,21 +795,6 @@ public Class> loadClass(String name) throws ClassNotFoundException
throw new ClassNotFoundException("Extension bundles cannot load classes.");
}
- Object sm = System.getSecurityManager();
-
- if (sm != null)
- {
- try
- {
- ((SecurityManager) sm).checkPermission(new AdminPermission(this,
- AdminPermission.CLASS));
- }
- catch (Exception ex)
- {
- throw new ClassNotFoundException("No permission.", ex);
- }
- }
-
return getFramework().loadBundleClass(this, name);
}
@@ -995,14 +807,6 @@ public void start() throws BundleException
@Override
public void start(int options) throws BundleException
{
- Object sm = System.getSecurityManager();
-
- if (sm != null)
- {
- ((SecurityManager) sm).checkPermission(new AdminPermission(this,
- AdminPermission.EXECUTE));
- }
-
getFramework().startBundle(this, options);
}
@@ -1015,14 +819,6 @@ public void update() throws BundleException
@Override
public void update(InputStream is) throws BundleException
{
- Object sm = System.getSecurityManager();
-
- if (sm != null)
- {
- ((SecurityManager) sm).checkPermission(new AdminPermission(this,
- AdminPermission.LIFECYCLE));
- }
-
getFramework().updateBundle(this, is);
}
@@ -1035,28 +831,12 @@ public void stop() throws BundleException
@Override
public void stop(int options) throws BundleException
{
- Object sm = System.getSecurityManager();
-
- if (sm != null)
- {
- ((SecurityManager) sm).checkPermission(new AdminPermission(this,
- AdminPermission.EXECUTE));
- }
-
getFramework().stopBundle(this, ((options & Bundle.STOP_TRANSIENT) == 0));
}
@Override
public void uninstall() throws BundleException
{
- Object sm = System.getSecurityManager();
-
- if (sm != null)
- {
- ((SecurityManager) sm).checkPermission(new AdminPermission(this,
- AdminPermission.LIFECYCLE));
- }
-
Map headers = getCurrentLocalizedHeader(Locale.getDefault().toString());
// Uninstall the bundle.
@@ -1085,17 +865,6 @@ public void uninstall() throws BundleException
void checkAdapt(Class type)
{
- Object sm = System.getSecurityManager();
- if ((sm != null) && (getFramework().getSecurityProvider() != null))
- {
- Class>[] classes = m_smEx.getClassContext();
- if (classes.length < 3 || ((Felix.m_secureAction.getClassLoader(classes[3]) != m_classloader) ||
- !classes[3].getName().startsWith("org.apache.felix.framework.")))
- {
- ((SecurityManager) sm).checkPermission(
- new AdaptPermission(type.getName(), this, AdaptPermission.ADAPT));
- }
- }
}
@SuppressWarnings("unchecked")
diff --git a/framework/src/main/java/org/apache/felix/framework/BundleProtectionDomain.java b/framework/src/main/java/org/apache/felix/framework/BundleProtectionDomain.java
index c9dede2d4f..f7bf5d77c8 100644
--- a/framework/src/main/java/org/apache/felix/framework/BundleProtectionDomain.java
+++ b/framework/src/main/java/org/apache/felix/framework/BundleProtectionDomain.java
@@ -29,12 +29,10 @@
import java.net.URL;
import java.net.URLConnection;
import java.net.URLStreamHandler;
-import java.security.AccessController;
import java.security.CodeSource;
import java.security.Permission;
import java.security.PermissionCollection;
import java.security.Permissions;
-import java.security.PrivilegedAction;
import java.security.ProtectionDomain;
import java.security.cert.Certificate;
import java.util.ArrayList;
@@ -323,22 +321,7 @@ protected URLConnection openConnection(URL u) throws IOException
private static boolean getUseCachedURL(final BundleRevisionImpl revision)
{
- String property;
-
- if (System.getSecurityManager() != null)
- {
- property = AccessController.doPrivileged(new PrivilegedAction(){
- @Override
- public String run()
- {
- return getUseCachedURLProperty(revision);
- }
- });
- }
- else
- {
- property = getUseCachedURLProperty(revision);
- }
+ String property = getUseCachedURLProperty(revision);
return Boolean.parseBoolean(property);
}
diff --git a/framework/src/main/java/org/apache/felix/framework/BundleWiringImpl.java b/framework/src/main/java/org/apache/felix/framework/BundleWiringImpl.java
index 809bb358c9..accf994d6a 100644
--- a/framework/src/main/java/org/apache/felix/framework/BundleWiringImpl.java
+++ b/framework/src/main/java/org/apache/felix/framework/BundleWiringImpl.java
@@ -33,10 +33,8 @@
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleException;
import org.osgi.framework.BundleReference;
-import org.osgi.framework.CapabilityPermission;
import org.osgi.framework.Constants;
import org.osgi.framework.FrameworkEvent;
-import org.osgi.framework.PackagePermission;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.hooks.weaving.WeavingException;
import org.osgi.framework.hooks.weaving.WeavingHook;
@@ -56,10 +54,6 @@
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.net.URL;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-import java.security.PrivilegedActionException;
-import java.security.PrivilegedExceptionAction;
import java.security.SecureClassLoader;
import java.util.ArrayList;
import java.util.Collection;
@@ -387,37 +381,6 @@ protected Class> loadClass(String name, boolean resolve) throws ClassNotFoundE
}
}
- if (System.getSecurityManager() != null)
- {
- for (Iterator iter = capList.iterator(); iter.hasNext();)
- {
- BundleCapability cap = iter.next();
- String bundleNamespace = cap.getNamespace();
- if (bundleNamespace.isEmpty())
- {
- iter.remove();
- }
- else if (bundleNamespace.equals(BundleRevision.PACKAGE_NAMESPACE))
- {
- if (!((BundleProtectionDomain) ((BundleRevisionImpl) cap.getRevision()).getProtectionDomain()).impliesDirect(
- new PackagePermission((String) cap.getAttributes().get(BundleRevision.PACKAGE_NAMESPACE), PackagePermission.EXPORTONLY)))
- {
- iter.remove();
- }
- }
- else if (!bundleNamespace.equals(BundleRevision.HOST_NAMESPACE)
- && !bundleNamespace.equals(BundleRevision.BUNDLE_NAMESPACE)
- && !bundleNamespace.equals("osgi.ee"))
- {
- CapabilityPermission permission = new CapabilityPermission(bundleNamespace, CapabilityPermission.PROVIDE);
- if (!((BundleProtectionDomain) ((BundleRevisionImpl) cap.getRevision()).getProtectionDomain()).impliesDirect(permission))
- {
- iter.remove();
- }
- }
- }
- }
-
m_resolvedCaps = Util.newImmutableList(capList);
m_includedPkgFilters = (includedPkgFilters.isEmpty())
? Collections.emptyMap() : includedPkgFilters;
@@ -740,16 +703,7 @@ private synchronized ClassLoader _getClassLoaderInternal()
if (m_classLoader == null)
{
- m_classLoader = BundleRevisionImpl.getSecureAction().run(
- new PrivilegedAction()
- {
- @Override
- public BundleClassLoader run()
- {
- return new BundleClassLoader(BundleWiringImpl.this, determineParentClassLoader(), m_logger);
- }
- }
- );
+ m_classLoader = new BundleClassLoader(BundleWiringImpl.this, determineParentClassLoader(), m_logger);
}
}
return m_classLoader;
@@ -1714,38 +1668,7 @@ private Object tryImplicitBootDelegation(final String name, final boolean isClas
// Get the class context to see the classes on the stack.
final Class>[] classes = m_sm.getClassContext();
- try
- {
- if (System.getSecurityManager() != null)
- {
- return AccessController
- .doPrivileged(new PrivilegedExceptionAction()
- {
- @Override
- public Object run() throws Exception
- {
- return doImplicitBootDelegation(classes, name,
- isClass);
- }
- });
- }
- else
- {
- return doImplicitBootDelegation(classes, name, isClass);
- }
- }
- catch (PrivilegedActionException ex)
- {
- Exception cause = ex.getException();
- if (cause instanceof ClassNotFoundException)
- {
- throw (ClassNotFoundException) cause;
- }
- else
- {
- throw (ResourceNotFoundException) cause;
- }
- }
+ return doImplicitBootDelegation(classes, name, isClass);
}
return null;
}
diff --git a/framework/src/main/java/org/apache/felix/framework/EventDispatcher.java b/framework/src/main/java/org/apache/felix/framework/EventDispatcher.java
index 2e86fe35cf..f843ce4562 100644
--- a/framework/src/main/java/org/apache/felix/framework/EventDispatcher.java
+++ b/framework/src/main/java/org/apache/felix/framework/EventDispatcher.java
@@ -18,8 +18,6 @@
*/
package org.apache.felix.framework;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -44,7 +42,6 @@
import org.osgi.framework.FrameworkListener;
import org.osgi.framework.ServiceEvent;
import org.osgi.framework.ServiceListener;
-import org.osgi.framework.ServicePermission;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.SynchronousBundleListener;
import org.osgi.framework.UnfilteredServiceListener;
@@ -219,12 +216,6 @@ else if (clazz == BundleListener.class)
}
else if (clazz == ServiceListener.class)
{
- // Remember security context for filtering service events.
- Object sm = System.getSecurityManager();
- if (sm != null)
- {
- acc = ((SecurityManager) sm).getSecurityContext();
- }
// We need to create a Set for keeping track of matching service
// registrations so we can fire ServiceEvent.MODIFIED_ENDMATCH
// events. We need a Set even if filter is null, since the
@@ -864,21 +855,7 @@ private static void invokeFrameworkListenerCallback(
if ((bundle.getState() == Bundle.STARTING) ||
(bundle.getState() == Bundle.ACTIVE))
{
- if (System.getSecurityManager() != null)
- {
- AccessController.doPrivileged(new PrivilegedAction() {
- @Override
- public Object run()
- {
- ((FrameworkListener) l).frameworkEvent((FrameworkEvent) event);
- return null;
- }
- });
- }
- else
- {
- ((FrameworkListener) l).frameworkEvent((FrameworkEvent) event);
- }
+ ((FrameworkListener) l).frameworkEvent((FrameworkEvent) event);
}
}
@@ -898,21 +875,7 @@ private static void invokeBundleListenerCallback(
((bundle.getState() == Bundle.STARTING) ||
(bundle.getState() == Bundle.ACTIVE)))
{
- if (System.getSecurityManager() != null)
- {
- AccessController.doPrivileged(new PrivilegedAction() {
- @Override
- public Object run()
- {
- ((BundleListener) l).bundleChanged((BundleEvent) event);
- return null;
- }
- });
- }
- else
- {
- ((BundleListener) l).bundleChanged((BundleEvent) event);
- }
+ ((BundleListener) l).bundleChanged((BundleEvent) event);
}
}
@@ -929,93 +892,38 @@ private static void invokeServiceListenerCallback(
return;
}
- // Check that the bundle has permission to get at least
- // one of the service interfaces; the objectClass property
- // of the service stores its service interfaces.
- ServiceReference> ref = ((ServiceEvent) event).getServiceReference();
-
- boolean hasPermission = true;
- Object sm = System.getSecurityManager();
- if ((acc != null) && (sm != null))
+ // Dispatch according to the filter.
+ boolean matched;
+ if (l instanceof UnfilteredServiceListener)
{
- try
- {
- ServicePermission perm =
- new ServicePermission(
- ref, ServicePermission.GET);
- ((SecurityManager) sm).checkPermission(perm, acc);
- }
- catch (Exception ex)
- {
- hasPermission = false;
- }
+ // An UnfilteredServiceListener always matches, regardless of the filter.
+ // The filter is still passed on to the Service Registry Hooks.
+ matched = true;
}
-
- if (hasPermission)
+ else
{
- // Dispatch according to the filter.
- boolean matched;
- if (l instanceof UnfilteredServiceListener)
- {
- // An UnfilteredServiceListener always matches, regardless of the filter.
- // The filter is still passed on to the Service Registry Hooks.
- matched = true;
- }
- else
- {
- matched = (filter == null)
- || filter.match(((ServiceEvent) event).getServiceReference());
- }
+ matched = (filter == null)
+ || filter.match(((ServiceEvent) event).getServiceReference());
+ }
- if (matched)
+ if (matched)
+ {
+ if ((l instanceof AllServiceListener) ||
+ Util.isServiceAssignable(bundle, ((ServiceEvent) event).getServiceReference()))
{
- if ((l instanceof AllServiceListener) ||
- Util.isServiceAssignable(bundle, ((ServiceEvent) event).getServiceReference()))
- {
- if (System.getSecurityManager() != null)
- {
- AccessController.doPrivileged(new PrivilegedAction()
- {
- @Override
- public Object run()
- {
- ((ServiceListener) l).serviceChanged((ServiceEvent) event);
- return null;
- }
- });
- }
- else
- {
- ((ServiceListener) l).serviceChanged((ServiceEvent) event);
- }
- }
+ ((ServiceListener) l).serviceChanged((ServiceEvent) event);
}
- // We need to send an MODIFIED_ENDMATCH event if the listener
- // matched previously.
- else if (((ServiceEvent) event).getType() == ServiceEvent.MODIFIED)
+ }
+ // We need to send an MODIFIED_ENDMATCH event if the listener
+ // matched previously.
+ else if (((ServiceEvent) event).getType() == ServiceEvent.MODIFIED)
+ {
+ if (filter.match(oldProps))
{
- if (filter.match(oldProps))
- {
- final ServiceEvent se = new ServiceEvent(
- ServiceEvent.MODIFIED_ENDMATCH,
- ((ServiceEvent) event).getServiceReference());
- if (System.getSecurityManager() != null)
- {
- AccessController.doPrivileged(new PrivilegedAction()
- {
- @Override
- public Object run()
- {
- ((ServiceListener) l).serviceChanged(se);
- return null;
- }
- });
- }
- else
- {
- ((ServiceListener) l).serviceChanged(se);
- }
- }
+ final ServiceEvent se = new ServiceEvent(
+ ServiceEvent.MODIFIED_ENDMATCH,
+ ((ServiceEvent) event).getServiceReference());
+ ((ServiceListener) l).serviceChanged(se);
}
}
}
diff --git a/framework/src/main/java/org/apache/felix/framework/ExtensionManager.java b/framework/src/main/java/org/apache/felix/framework/ExtensionManager.java
index ee899853e6..704be317ee 100644
--- a/framework/src/main/java/org/apache/felix/framework/ExtensionManager.java
+++ b/framework/src/main/java/org/apache/felix/framework/ExtensionManager.java
@@ -34,7 +34,6 @@
import org.apache.felix.framework.wiring.BundleRequirementImpl;
import org.apache.felix.framework.wiring.BundleWireImpl;
import org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement;
-import org.osgi.framework.AdminPermission;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
@@ -61,9 +60,6 @@
import java.io.OutputStreamWriter;
import java.net.URI;
import java.net.URL;
-import java.security.AccessController;
-import java.security.AllPermission;
-import java.security.PrivilegedExceptionAction;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -408,18 +404,6 @@ public BundleRevisionImpl getRevision()
*/
void addExtensionBundle(BundleImpl bundle) throws Exception
{
- Object sm = System.getSecurityManager();
- if (sm != null)
- {
- ((SecurityManager) sm).checkPermission(
- new AdminPermission(bundle, AdminPermission.EXTENSIONLIFECYCLE));
-
- if (!((BundleProtectionDomain) bundle.getProtectionDomain()).impliesDirect(new AllPermission()))
- {
- throw new SecurityException("Extension Bundles must have AllPermission");
- }
- }
-
String directive = ManifestParser.parseExtensionBundleHeader((String)
((BundleRevisionImpl) bundle.adapt(BundleRevision.class))
.getHeaders().get(Constants.FRAGMENT_HOST));
@@ -581,15 +565,7 @@ else if (revisionContent instanceof DirectoryContent)
{
try
{
- AccessController.doPrivileged(new PrivilegedExceptionAction()
- {
- @Override
- public Void run() throws Exception
- {
- m_extenderFramework.add(f);
- return null;
- }
- });
+ m_extenderFramework.add(f);
}
catch (Exception ex)
{
diff --git a/framework/src/main/java/org/apache/felix/framework/Felix.java b/framework/src/main/java/org/apache/felix/framework/Felix.java
index e52eac6829..f2104d2aa5 100644
--- a/framework/src/main/java/org/apache/felix/framework/Felix.java
+++ b/framework/src/main/java/org/apache/felix/framework/Felix.java
@@ -208,9 +208,6 @@ public class Felix extends BundleImpl implements Framework
// Shutdown gate.
private volatile ThreadGate m_shutdownGate = null;
- // Security Manager created by the framework
- private SecurityManager m_securityManager = null;
-
// Do we need to consult the default java security policy if no security provider is present?
private volatile boolean m_securityDefaultPolicy;
@@ -662,34 +659,15 @@ public void init(final FrameworkListener... listeners) throws BundleException
{
if ((getState() == Bundle.INSTALLED) || (getState() == Bundle.RESOLVED))
{
+ // Java SE 24 permanently disabled the Security Manager (JEP 486), so this
+ // framework can no longer enforce the OSGi security layer. Fail fast rather
+ // than silently launching without the security the launcher asked for.
String security = (String) m_configMap.get(Constants.FRAMEWORK_SECURITY);
if (security != null)
{
- if (System.getSecurityManager() != null)
- {
- throw new SecurityException("SecurityManager already installed");
- }
- security = security.trim();
- if (Constants.FRAMEWORK_SECURITY_OSGI.equalsIgnoreCase(security) || (security.length() == 0))
- {
- System.setSecurityManager(m_securityManager = new SecurityManager());
- }
- else
- {
- try
- {
- System.setSecurityManager(m_securityManager =
- (SecurityManager) Class.forName(security).newInstance());
- }
- catch (Throwable t)
- {
- SecurityException se =
- new SecurityException(
- "Unable to install custom SecurityManager: " + security);
- se.initCause(t);
- throw se;
- }
- }
+ throw new SecurityException(
+ "The " + Constants.FRAMEWORK_SECURITY + " property is not supported: the Java"
+ + " Security Manager is permanently disabled as of Java SE 24 (JEP 486).");
}
// Generate a framework UUID.
@@ -909,7 +887,7 @@ public void init(final FrameworkListener... listeners) throws BundleException
// We have to check with the security provider (if there is one).
// This is to avoid having bundles in the cache that have been tampered with
SecurityProvider sp = getFramework().getSecurityProvider();
- if ((sp != null) && (System.getSecurityManager() != null))
+ if (sp != null)
{
boolean locked = acquireGlobalLock();
if (!locked)
@@ -1077,7 +1055,7 @@ void setBundleProtectionDomain(BundleRevisionImpl revisionImpl) throws Exception
{
Object certificates = null;
SecurityProvider sp = getFramework().getSecurityProvider();
- if ((sp != null) && (System.getSecurityManager() != null))
+ if (sp != null)
{
BundleImpl bundleImpl = revisionImpl.getBundle();
sp.checkBundle(bundleImpl);
@@ -1160,14 +1138,6 @@ public void start(int options) throws BundleException
@Override
public void stop() throws BundleException
{
- Object sm = System.getSecurityManager();
-
- if (sm != null)
- {
- ((SecurityManager) sm).checkPermission(new AdminPermission(this,
- AdminPermission.EXECUTE));
- }
-
if ((getState() & (Bundle.INSTALLED | Bundle.RESOLVED)) == 0)
{
// Spec says stop() on SystemBundle should return immediately and
@@ -1254,14 +1224,6 @@ public void update() throws BundleException
@Override
public void update(InputStream is) throws BundleException
{
- Object sm = System.getSecurityManager();
-
- if (sm != null)
- {
- ((SecurityManager) sm).checkPermission(new AdminPermission(this,
- AdminPermission.EXECUTE));
- }
-
// Spec says to close input stream first.
try
{
@@ -1337,15 +1299,6 @@ public void run()
private void stopRefresh() throws BundleException
{
- Object sm = System.getSecurityManager();
-
- if (sm != null)
- {
- ((SecurityManager) sm).checkPermission(new AdminPermission(this,
- AdminPermission.EXECUTE));
- }
-
-
// Stop the framework on a separate thread.
new Thread(new Runnable() {
@Override
@@ -2051,7 +2004,9 @@ boolean bundleHasPermission(BundleImpl bundle, Object obj)
throw new IllegalStateException("The bundle is uninstalled.");
}
- if (System.getSecurityManager() != null)
+ // Without a Security Manager there is nothing to enforce, so only consult an
+ // explicitly installed SecurityProvider; otherwise every permission is granted.
+ if (m_securityProvider != null)
{
try
{
@@ -2470,11 +2425,6 @@ void activateBundle(BundleImpl bundle, boolean fireEvent) throws BundleException
{
throw (BundleException) th;
}
- else if ((System.getSecurityManager() != null) &&
- (th instanceof java.security.PrivilegedActionException))
- {
- th = ((java.security.PrivilegedActionException) th).getException();
- }
// Rethrow all other exceptions as a BundleException.
throw new BundleException(
@@ -2580,14 +2530,6 @@ void updateBundle(BundleImpl bundle, InputStream is)
// Verify bundle revision.
try
{
- Object sm = System.getSecurityManager();
-
- if (sm != null)
- {
- ((SecurityManager) sm).checkPermission(
- new AdminPermission(bundle, AdminPermission.LIFECYCLE));
- }
-
// If this is an update from a normal to an extension bundle
// then attach the extension
if (!wasExtension && bundle.isExtension())
@@ -2869,11 +2811,6 @@ void stopBundle(BundleImpl bundle, boolean record)
{
throw (BundleException) rethrow;
}
- else if ((System.getSecurityManager() != null) &&
- (rethrow instanceof java.security.PrivilegedActionException))
- {
- rethrow = ((java.security.PrivilegedActionException) rethrow).getException();
- }
// Rethrow all other exceptions as a BundleException.
throw new BundleException(
@@ -3293,16 +3230,7 @@ Bundle installBundle(
releaseGlobalLock();
}
- if (!bundle.isExtension())
- {
- Object sm = System.getSecurityManager();
- if (sm != null)
- {
- ((SecurityManager) sm).checkPermission(
- new AdminPermission(bundle, AdminPermission.LIFECYCLE));
- }
- }
- else
+ if (bundle.isExtension())
{
m_extensionManager.addExtensionBundle(bundle);
}
@@ -3931,8 +3859,6 @@ ServiceReference>[] getServiceReferences(
/**
* Retrieves Array of {@link ServiceReference} objects based on calling bundle, service class name,
* optional filter expression, and optionally filters further on the version.
- * If running under a {@link SecurityManager}, checks that the calling bundle has permissions to
- * see the service references and removes references that aren't.
* @param bundle Calling Bundle
* @param className Service Classname or null for all
* @param expr Filter Criteria or null
@@ -3944,36 +3870,9 @@ ServiceReference>[] getAllowedServiceReferences(
BundleImpl bundle, String className, String expr, boolean checkAssignable)
throws InvalidSyntaxException
{
- ServiceReference>[] refs = getServiceReferences(bundle, className, expr, checkAssignable);
-
- Object sm = System.getSecurityManager();
-
- if ((sm == null) || (refs == null))
- {
- return refs;
- }
-
- List> result = new ArrayList<>();
-
- for (ServiceReference> ref : refs) {
- try
- {
- ((SecurityManager) sm).checkPermission(new ServicePermission(ref, ServicePermission.GET));
- result.add(ref);
- }
- catch (Exception ex)
- {
- // Ignore, since we are just testing permission.
- }
- }
-
- if (result.isEmpty())
- {
- return null;
- }
-
- return (ServiceReference[]) result.toArray(new ServiceReference[result.size()]);
-
+ // Without a Security Manager there are no ServicePermission restrictions to
+ // filter on, so every visible reference is allowed.
+ return getServiceReferences(bundle, className, expr, checkAssignable);
}
S getService(Bundle bundle, ServiceReference ref, boolean isServiceObjetcs)
@@ -5227,11 +5126,6 @@ public void stop(BundleContext context)
}
m_reg.unregister();
m_activatorList.clear();
- if (m_securityManager != null)
- {
- System.setSecurityManager(null);
- m_securityManager = null;
- }
m_dependencies.removeDependents(adapt(BundleRevision.class));
diff --git a/framework/src/main/java/org/apache/felix/framework/FrameworkStartLevelImpl.java b/framework/src/main/java/org/apache/felix/framework/FrameworkStartLevelImpl.java
index 083ac36e02..c6c378146d 100644
--- a/framework/src/main/java/org/apache/felix/framework/FrameworkStartLevelImpl.java
+++ b/framework/src/main/java/org/apache/felix/framework/FrameworkStartLevelImpl.java
@@ -21,7 +21,6 @@
import java.util.ArrayList;
import java.util.List;
-import org.osgi.framework.AdminPermission;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.FrameworkListener;
@@ -108,14 +107,6 @@ public int getStartLevel()
@Override
public void setStartLevel(int startlevel, FrameworkListener... listeners)
{
- Object sm = System.getSecurityManager();
-
- if (sm != null)
- {
- ((SecurityManager) sm).checkPermission(
- new AdminPermission(m_felix, AdminPermission.STARTLEVEL));
- }
-
if (startlevel <= 0)
{
throw new IllegalArgumentException(
@@ -178,13 +169,6 @@ public int getInitialBundleStartLevel()
@Override
public void setInitialBundleStartLevel(int startlevel)
{
- Object sm = System.getSecurityManager();
-
- if (sm != null)
- {
- ((SecurityManager) sm).checkPermission(
- new AdminPermission(m_felix, AdminPermission.STARTLEVEL));
- }
m_felix.setInitialBundleStartLevel(startlevel);
}
@@ -217,14 +201,6 @@ public int getStartLevel()
@Override
public void setStartLevel(int startlevel)
{
- Object sm = System.getSecurityManager();
-
- if (sm != null)
- {
- ((SecurityManager) sm).checkPermission(
- new AdminPermission(m_bundle, AdminPermission.EXECUTE));
- }
-
if (m_bundle.getBundleId() == 0)
{
throw new IllegalArgumentException(
diff --git a/framework/src/main/java/org/apache/felix/framework/FrameworkWiringImpl.java b/framework/src/main/java/org/apache/felix/framework/FrameworkWiringImpl.java
index 693e239f24..365ccb2394 100644
--- a/framework/src/main/java/org/apache/felix/framework/FrameworkWiringImpl.java
+++ b/framework/src/main/java/org/apache/felix/framework/FrameworkWiringImpl.java
@@ -22,7 +22,6 @@
import java.util.Collection;
import java.util.List;
-import org.osgi.framework.AdminPermission;
import org.osgi.framework.Bundle;
import org.osgi.framework.FrameworkListener;
import org.osgi.framework.ServiceRegistration;
@@ -89,13 +88,6 @@ public Bundle getBundle()
@Override
public void refreshBundles(Collection bundles, FrameworkListener... listeners)
{
- Object sm = System.getSecurityManager();
-
- if (sm != null)
- {
- ((SecurityManager) sm).checkPermission(
- new AdminPermission(m_felix, AdminPermission.RESOLVE));
- }
synchronized (m_requests)
{
// Start a thread to perform asynchronous package refreshes.
@@ -116,14 +108,6 @@ public void refreshBundles(Collection bundles, FrameworkListener... list
@Override
public boolean resolveBundles(Collection bundles)
{
- Object sm = System.getSecurityManager();
-
- if (sm != null)
- {
- ((SecurityManager) sm).checkPermission(
- new AdminPermission(m_felix, AdminPermission.RESOLVE));
- }
-
if (m_thread == null)
{
return false;
diff --git a/framework/src/main/java/org/apache/felix/framework/ServiceRegistrationImpl.java b/framework/src/main/java/org/apache/felix/framework/ServiceRegistrationImpl.java
index 64665e167a..f5b7bb90a0 100644
--- a/framework/src/main/java/org/apache/felix/framework/ServiceRegistrationImpl.java
+++ b/framework/src/main/java/org/apache/felix/framework/ServiceRegistrationImpl.java
@@ -18,9 +18,6 @@
*/
package org.apache.felix.framework;
-import java.security.AccessController;
-import java.security.PrivilegedActionException;
-import java.security.PrivilegedExceptionAction;
import java.util.Collection;
import java.util.Collections;
import java.util.Dictionary;
@@ -239,32 +236,7 @@ Object getService(Bundle acqBundle)
// let it create the service object.
if (m_factory != null)
{
- Object svcObj = null;
- try
- {
- if (System.getSecurityManager() != null)
- {
- svcObj = AccessController.doPrivileged(
- new ServiceFactoryPrivileged<>(acqBundle, null));
- }
- else
- {
- svcObj = getFactoryUnchecked(acqBundle);
- }
- }
- catch (PrivilegedActionException ex)
- {
- if (ex.getException() instanceof ServiceException)
- {
- throw (ServiceException) ex.getException();
- }
- else
- {
- throw new ServiceException(
- "Service factory exception: " + ex.getException().getMessage(),
- ServiceException.FACTORY_EXCEPTION, ex.getException());
- }
- }
+ Object svcObj = getFactoryUnchecked(acqBundle);
return svcObj;
}
else
@@ -281,15 +253,7 @@ void ungetService(Bundle relBundle, S svcObj)
{
try
{
- if (System.getSecurityManager() != null)
- {
- AccessController.doPrivileged(
- new ServiceFactoryPrivileged<>(relBundle, svcObj));
- }
- else
- {
- ungetFactoryUnchecked(relBundle, svcObj);
- }
+ ungetFactoryUnchecked(relBundle, svcObj);
}
catch (Throwable ex)
{
@@ -395,38 +359,6 @@ private void ungetFactoryUnchecked(Bundle bundle, S svcObj)
m_factory.ungetService(bundle, this, svcObj);
}
- /**
- * This simple class is used to ensure that when a service factory
- * is called, that no other classes on the call stack interferes
- * with the permissions of the factory itself.
- **/
- private class ServiceFactoryPrivileged implements PrivilegedExceptionAction
- {
- private Bundle m_bundle = null;
- private S m_svcObj = null;
-
- public ServiceFactoryPrivileged(Bundle bundle, S svcObj)
- {
- m_bundle = bundle;
- m_svcObj = svcObj;
- }
-
- @SuppressWarnings("unchecked")
- @Override
- public A run() throws Exception
- {
- if (m_svcObj == null)
- {
- return (A)getFactoryUnchecked(m_bundle);
- }
- else
- {
- ungetFactoryUnchecked(m_bundle, m_svcObj);
- }
- return null;
- }
- }
-
//
// ServiceReference implementation
//
diff --git a/framework/src/main/java/org/apache/felix/framework/StatefulResolver.java b/framework/src/main/java/org/apache/felix/framework/StatefulResolver.java
index 7dcfe632a1..a88d9a3f18 100644
--- a/framework/src/main/java/org/apache/felix/framework/StatefulResolver.java
+++ b/framework/src/main/java/org/apache/felix/framework/StatefulResolver.java
@@ -50,10 +50,7 @@
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleEvent;
import org.osgi.framework.BundleException;
-import org.osgi.framework.BundlePermission;
-import org.osgi.framework.CapabilityPermission;
import org.osgi.framework.Constants;
-import org.osgi.framework.PackagePermission;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
import org.osgi.framework.hooks.resolver.ResolverHook;
@@ -293,11 +290,6 @@ synchronized List findProvidersInternal(
BundleCapability bcap = (BundleCapability) cap;
- // Filter according to security.
- if (invokeHooksAndSecurity && filteredBySecurity((BundleRequirement)req, bcap))
- {
- continue;
- }
// Filter already resolved hosts, since we don't support
// dynamic attachment of fragments.
if (req.getNamespace().equals(BundleRevision.HOST_NAMESPACE)
@@ -352,69 +344,6 @@ synchronized List findProvidersInternal(
return result;
}
- private boolean filteredBySecurity(BundleRequirement req, BundleCapability cap)
- {
- if (System.getSecurityManager() != null)
- {
- BundleRevisionImpl reqRevision = (BundleRevisionImpl) req.getRevision();
-
- if (req.getNamespace().equals(BundleRevision.PACKAGE_NAMESPACE))
- {
- if (!((BundleProtectionDomain) ((BundleRevisionImpl) cap.getRevision()).getProtectionDomain()).impliesDirect(
- new PackagePermission((String) cap.getAttributes().get(BundleRevision.PACKAGE_NAMESPACE),
- PackagePermission.EXPORTONLY)) ||
- !((reqRevision == null) ||
- ((BundleProtectionDomain) reqRevision.getProtectionDomain()).impliesDirect(
- new PackagePermission((String) cap.getAttributes().get(BundleRevision.PACKAGE_NAMESPACE),
- cap.getRevision().getBundle(),PackagePermission.IMPORT))
- ))
- {
- if (reqRevision != cap.getRevision())
- {
- return true;
- }
- }
- }
- else if (req.getNamespace().equals(BundleRevision.BUNDLE_NAMESPACE))
- { if (!((BundleProtectionDomain) ((BundleRevisionImpl) cap.getRevision()).getProtectionDomain()).impliesDirect(
- new BundlePermission(cap.getRevision().getSymbolicName(), BundlePermission.PROVIDE)) ||
- !((reqRevision == null) ||
- ((BundleProtectionDomain) reqRevision.getProtectionDomain()).impliesDirect(
- new BundlePermission(cap.getRevision().getSymbolicName(), BundlePermission.REQUIRE))
- ))
- {
- return true;
- }
- }
- else if (req.getNamespace().equals(BundleRevision.HOST_NAMESPACE))
- {
- if (!((BundleProtectionDomain) reqRevision.getProtectionDomain())
- .impliesDirect(new BundlePermission(
- cap.getRevision().getSymbolicName(),
- BundlePermission.FRAGMENT))
- || !((BundleProtectionDomain) ((BundleRevisionImpl) cap.getRevision()).getProtectionDomain())
- .impliesDirect(new BundlePermission(
- cap.getRevision().getSymbolicName(),
- BundlePermission.HOST)))
- {
- return true;
- }
- }
- else if (!req.getNamespace().equals("osgi.ee"))
- {
- if (!((BundleProtectionDomain) ((BundleRevisionImpl) cap.getRevision()).getProtectionDomain()).impliesDirect(
- new CapabilityPermission(req.getNamespace(), CapabilityPermission.PROVIDE))
- ||
- !((reqRevision == null) || ((BundleProtectionDomain) reqRevision.getProtectionDomain()).impliesDirect(
- new CapabilityPermission(req.getNamespace(), cap.getAttributes(), cap.getRevision().getBundle(), CapabilityPermission.REQUIRE))))
- {
- return true;
- }
- }
- }
- return false;
- }
-
void resolve(
Set mandatory,
Set optional)
diff --git a/framework/src/main/java/org/apache/felix/framework/URLHandlersBundleStreamHandler.java b/framework/src/main/java/org/apache/felix/framework/URLHandlersBundleStreamHandler.java
index ba524fa94e..e8f7a00cb7 100644
--- a/framework/src/main/java/org/apache/felix/framework/URLHandlersBundleStreamHandler.java
+++ b/framework/src/main/java/org/apache/felix/framework/URLHandlersBundleStreamHandler.java
@@ -20,14 +20,10 @@
import java.io.IOException;
import java.lang.reflect.Constructor;
-import java.lang.reflect.Method;
import java.net.*;
-import java.security.Permission;
import org.apache.felix.framework.util.SecureAction;
import org.apache.felix.framework.util.Util;
-import org.osgi.framework.AdminPermission;
-import org.osgi.framework.Bundle;
class URLHandlersBundleStreamHandler extends URLStreamHandler
{
@@ -49,10 +45,6 @@ public URLHandlersBundleStreamHandler(SecureAction action)
@Override
protected URLConnection openConnection(URL url) throws IOException
{
- if (!"felix".equals(url.getAuthority()))
- {
- checkPermission(url);
- }
Object framework = m_framework;
if (framework == null)
@@ -92,10 +84,7 @@ protected void parseURL(URL u, String spec, int start, int limit)
{
super.parseURL(u, spec, start, limit);
- if (checkPermission(u))
- {
- super.setURL(u, u.getProtocol(), u.getHost(), u.getPort(), "felix", u.getUserInfo(), u.getPath(), u.getQuery(), u.getRef());
- }
+ super.setURL(u, u.getProtocol(), u.getHost(), u.getPort(), "felix", u.getUserInfo(), u.getPath(), u.getQuery(), u.getRef());
}
@Override
@@ -129,62 +118,4 @@ protected java.net.InetAddress getHostAddress(URL u)
{
return null;
}
-
- private boolean checkPermission(URL u)
- {
- SecurityManager sm = System.getSecurityManager();
- if (sm != null)
- {
- Object framework = m_framework;
- if (framework == null)
- {
- framework = URLHandlers.getFrameworkFromContext(Util.getFrameworkUUIDFromURL(u.getHost()));
- }
- try {
- long bundleId = Util.getBundleIdFromRevisionId(Util.getRevisionIdFromURL(u.getHost()));
-
- if (framework instanceof Felix)
- {
- Bundle bundle = ((Felix) framework).getBundle(bundleId);
- if (bundle != null)
- {
- sm.checkPermission(new AdminPermission(bundle, AdminPermission.RESOURCE));
- return true;
- }
- }
- else if (framework != null)
- {
- Method method = m_action.getDeclaredMethod(framework.getClass(), "getBundle", new Class[]{long.class});
- m_action.setAccesssible(method);
- Object bundle = method.invoke(framework, bundleId);
- if (bundle != null)
- {
- ClassLoader loader = m_action.getClassLoader(framework.getClass());
-
- sm.checkPermission((Permission) m_action.getConstructor(
- loader.loadClass(AdminPermission.class.getName()),
- new Class[] {loader.loadClass(Bundle.class.getName()), String.class}).newInstance(bundle, AdminPermission.RESOURCE));
- return true;
- }
- }
- else
- {
- throw new IOException("No framework context found");
- }
- }
- catch (SecurityException ex)
- {
- throw ex;
- }
- catch (Exception ex)
- {
- throw new SecurityException(ex);
- }
- }
- else
- {
- return true;
- }
- return false;
- }
}
diff --git a/framework/src/main/java/org/apache/felix/framework/WovenClassImpl.java b/framework/src/main/java/org/apache/felix/framework/WovenClassImpl.java
index e4361d95d9..be3f5cff46 100644
--- a/framework/src/main/java/org/apache/felix/framework/WovenClassImpl.java
+++ b/framework/src/main/java/org/apache/felix/framework/WovenClassImpl.java
@@ -27,8 +27,6 @@
import org.apache.felix.framework.util.Util;
import org.apache.felix.framework.util.manifestparser.ManifestParser;
-import org.osgi.framework.AdminPermission;
-import org.osgi.framework.PackagePermission;
import org.osgi.framework.hooks.weaving.WovenClass;
import org.osgi.framework.wiring.BundleWiring;
@@ -71,12 +69,6 @@ synchronized void completeDefine(Class> definedClass)
@Override
public synchronized byte[] getBytes()
{
- SecurityManager sm = System.getSecurityManager();
- if (sm != null)
- {
- sm.checkPermission(new AdminPermission(m_wiring.getBundle(),
- AdminPermission.WEAVE));
- }
byte[] bytes = m_bytes;
if (m_isComplete)
{
@@ -89,12 +81,6 @@ public synchronized byte[] getBytes()
@Override
public synchronized void setBytes(byte[] bytes)
{
- SecurityManager sm = System.getSecurityManager();
- if (sm != null)
- {
- sm.checkPermission(new AdminPermission(m_wiring.getBundle(),
- AdminPermission.WEAVE));
- }
if (m_state >= TRANSFORMED)
{
throw new IllegalStateException(
@@ -193,12 +179,6 @@ public synchronized T[] toArray(T[] ts)
@Override
public synchronized boolean add(String s)
{
- SecurityManager sm = System.getSecurityManager();
- if (sm != null)
- {
- sm.checkPermission(new AdminPermission(m_wiring.getBundle(),
- AdminPermission.WEAVE));
- }
if (s != null)
{
try
@@ -210,31 +190,14 @@ public synchronized boolean add(String s)
throw new IllegalArgumentException(
"Unable to parse dynamic import.", ex);
}
- checkImport(s);
return m_imports.add(s);
}
return false;
}
- private void checkImport(String s)
- {
- SecurityManager sm = System.getSecurityManager();
-
- if (sm != null)
- {
- sm.checkPermission(new PackagePermission(s, PackagePermission.IMPORT));
- }
- }
-
@Override
public synchronized boolean remove(Object o)
{
- SecurityManager sm = System.getSecurityManager();
- if (sm != null)
- {
- sm.checkPermission(new AdminPermission(m_wiring.getBundle(),
- AdminPermission.WEAVE));
- }
return m_imports.remove(o);
}
@@ -247,12 +210,6 @@ public synchronized boolean containsAll(Collection> collection)
@Override
public synchronized boolean addAll(Collection extends String> collection)
{
- SecurityManager sm = System.getSecurityManager();
- if (sm != null)
- {
- sm.checkPermission(new AdminPermission(m_wiring.getBundle(),
- AdminPermission.WEAVE));
- }
for (String s : collection)
{
try
@@ -264,7 +221,6 @@ public synchronized boolean addAll(Collection extends String> collection)
throw new IllegalArgumentException(
"Unable to parse dynamic import.", ex);
}
- checkImport(s);
}
return m_imports.addAll(collection);
}
@@ -273,12 +229,6 @@ public synchronized boolean addAll(Collection extends String> collection)
public synchronized boolean addAll(int i,
Collection extends String> collection)
{
- SecurityManager sm = System.getSecurityManager();
- if (sm != null)
- {
- sm.checkPermission(new AdminPermission(m_wiring.getBundle(),
- AdminPermission.WEAVE));
- }
for (String s : collection)
{
try
@@ -290,7 +240,6 @@ public synchronized boolean addAll(int i,
throw new IllegalArgumentException(
"Unable to parse dynamic import.", ex);
}
- checkImport(s);
}
return m_imports.addAll(i, collection);
}
@@ -298,36 +247,18 @@ public synchronized boolean addAll(int i,
@Override
public synchronized boolean removeAll(Collection> collection)
{
- SecurityManager sm = System.getSecurityManager();
- if (sm != null)
- {
- sm.checkPermission(new AdminPermission(m_wiring.getBundle(),
- AdminPermission.WEAVE));
- }
return m_imports.removeAll(collection);
}
@Override
public synchronized boolean retainAll(Collection> collection)
{
- SecurityManager sm = System.getSecurityManager();
- if (sm != null)
- {
- sm.checkPermission(new AdminPermission(m_wiring.getBundle(),
- AdminPermission.WEAVE));
- }
return m_imports.retainAll(collection);
}
@Override
public synchronized void clear()
{
- SecurityManager sm = System.getSecurityManager();
- if (sm != null)
- {
- sm.checkPermission(new AdminPermission(m_wiring.getBundle(),
- AdminPermission.WEAVE));
- }
m_imports.clear();
}
@@ -340,12 +271,6 @@ public synchronized String get(int i)
@Override
public synchronized String set(int i, String s)
{
- SecurityManager sm = System.getSecurityManager();
- if (sm != null)
- {
- sm.checkPermission(new AdminPermission(m_wiring.getBundle(),
- AdminPermission.WEAVE));
- }
try
{
ManifestParser
@@ -355,19 +280,12 @@ public synchronized String set(int i, String s)
throw new IllegalArgumentException(
"Unable to parse dynamic import.", ex);
}
- checkImport(s);
return m_imports.set(i, s);
}
@Override
public synchronized void add(int i, String s)
{
- SecurityManager sm = System.getSecurityManager();
- if (sm != null)
- {
- sm.checkPermission(new AdminPermission(m_wiring.getBundle(),
- AdminPermission.WEAVE));
- }
try
{
ManifestParser
@@ -378,19 +296,12 @@ public synchronized void add(int i, String s)
throw new IllegalArgumentException(
"Unable to parse dynamic import.", ex);
}
- checkImport(s);
m_imports.add(i, s);
}
@Override
public synchronized String remove(int i)
{
- SecurityManager sm = System.getSecurityManager();
- if (sm != null)
- {
- sm.checkPermission(new AdminPermission(m_wiring.getBundle(),
- AdminPermission.WEAVE));
- }
return m_imports.remove(i);
}
diff --git a/framework/src/main/java/org/apache/felix/framework/util/SecureAction.java b/framework/src/main/java/org/apache/felix/framework/util/SecureAction.java
index 85895665c3..95fffc6f6c 100644
--- a/framework/src/main/java/org/apache/felix/framework/util/SecureAction.java
+++ b/framework/src/main/java/org/apache/felix/framework/util/SecureAction.java
@@ -44,11 +44,7 @@
import java.nio.channels.FileChannel;
import java.nio.file.Files;
import java.nio.file.StandardOpenOption;
-import java.security.AccessControlContext;
-import java.security.AccessController;
-import java.security.Policy;
import java.security.PrivilegedAction;
-import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.Collection;
import java.util.HashMap;
@@ -72,14 +68,16 @@
/**
*
- * If the worker thread does not terminate within 5 seconds it is killed
- * by calling the (deprecated) Thread.stop() method. It may
- * be that the worker thread may be blocked by a deadlock (it should not,
- * though). In this case hope is that Thread.stop() will be
- * able to released that deadlock at the expense of one or more tasks to
- * not be executed any longer.... In any case an ERROR message is logged
- * with the LogService in this situation.
+ * If the worker thread does not terminate within 5 seconds it is
+ * interrupted. It may be that the worker thread is blocked by a deadlock
+ * (it should not, though); interrupting it releases the thread if it is
+ * waiting on an interruptible operation, at the expense of one or more
+ * tasks not being executed any longer. In any case an ERROR message is
+ * logged with the LogService in this situation.
+ *
+ * This used to call Thread.stop(), which has thrown
+ * UnsupportedOperationException since Java 20 and so could
+ * only turn a slow shutdown into a failed one.
*/
synchronized void terminate()
{
@@ -176,9 +179,9 @@ synchronized void terminate()
if ( workerThread.isAlive() )
{
Log.logger.log( LogService.LOG_ERROR,
- "Worker thread {0} did not terminate within 5 seconds; trying to kill", new Object[]
+ "Worker thread {0} did not terminate within 5 seconds; interrupting it", new Object[]
{ workerBaseName } );
- workerThread.stop();
+ workerThread.interrupt();
}
}
}
diff --git a/connect/pom.xml b/connect/pom.xml
index 8cbf5d093f..a71ec78d29 100644
--- a/connect/pom.xml
+++ b/connect/pom.xml
@@ -19,7 +19,7 @@
org.apache.felixfelix-parent
- 5
+ 9../pom/pom.xml4.0.0
@@ -97,8 +97,8 @@
org.apache.maven.pluginsmaven-compiler-plugin
- 1.6
- 1.6
+ 8
+ 8
diff --git a/examples/extenderbased.circle/pom.xml b/examples/extenderbased.circle/pom.xml
index 1afccaaab2..98ea05d538 100644
--- a/examples/extenderbased.circle/pom.xml
+++ b/examples/extenderbased.circle/pom.xml
@@ -60,8 +60,8 @@
org.apache.maven.pluginsmaven-compiler-plugin
- 1.5
- 1.5
+ 8
+ 8
- * If the worker thread does not terminate within 5 seconds it is
- * interrupted. It may be that the worker thread is blocked by a deadlock
- * (it should not, though); interrupting it releases the thread if it is
- * waiting on an interruptible operation, at the expense of one or more
- * tasks not being executed any longer. In any case an ERROR message is
- * logged with the LogService in this situation.
- *
- * This used to call Thread.stop(), which has thrown
- * UnsupportedOperationException since Java 20 and so could
- * only turn a slow shutdown into a failed one.
+ * If the worker thread does not terminate within 5 seconds it is killed
+ * by calling the (deprecated) Thread.stop() method. It may
+ * be that the worker thread may be blocked by a deadlock (it should not,
+ * though). In this case hope is that Thread.stop() will be
+ * able to released that deadlock at the expense of one or more tasks to
+ * not be executed any longer.... In any case an ERROR message is logged
+ * with the LogService in this situation.
*/
synchronized void terminate()
{
@@ -179,9 +176,9 @@ synchronized void terminate()
if ( workerThread.isAlive() )
{
Log.logger.log( LogService.LOG_ERROR,
- "Worker thread {0} did not terminate within 5 seconds; interrupting it", new Object[]
+ "Worker thread {0} did not terminate within 5 seconds; trying to kill", new Object[]
{ workerBaseName } );
- workerThread.interrupt();
+ workerThread.stop();
}
}
}
diff --git a/connect/pom.xml b/connect/pom.xml
index a71ec78d29..8cbf5d093f 100644
--- a/connect/pom.xml
+++ b/connect/pom.xml
@@ -19,7 +19,7 @@
org.apache.felixfelix-parent
- 9
+ 5../pom/pom.xml4.0.0
@@ -97,8 +97,8 @@
org.apache.maven.pluginsmaven-compiler-plugin
- 8
- 8
+ 1.6
+ 1.6
diff --git a/examples/extenderbased.circle/pom.xml b/examples/extenderbased.circle/pom.xml
index 98ea05d538..1afccaaab2 100644
--- a/examples/extenderbased.circle/pom.xml
+++ b/examples/extenderbased.circle/pom.xml
@@ -60,8 +60,8 @@
org.apache.maven.pluginsmaven-compiler-plugin
- 8
- 8
+ 1.5
+ 1.5
diff --git a/examples/extenderbased.square/pom.xml b/examples/extenderbased.square/pom.xml
index 7fb5872664..02723f4f83 100644
--- a/examples/extenderbased.square/pom.xml
+++ b/examples/extenderbased.square/pom.xml
@@ -60,8 +60,8 @@
org.apache.maven.pluginsmaven-compiler-plugin
- 8
- 8
+ 1.5
+ 1.5
diff --git a/examples/extenderbased.triangle/pom.xml b/examples/extenderbased.triangle/pom.xml
index 78eff1a5f6..b0895a7d8d 100644
--- a/examples/extenderbased.triangle/pom.xml
+++ b/examples/extenderbased.triangle/pom.xml
@@ -60,8 +60,8 @@
org.apache.maven.pluginsmaven-compiler-plugin
- 8
- 8
+ 1.5
+ 1.5
diff --git a/framework.tck/pom.xml b/framework.tck/pom.xml
index 8834c108cc..e3d9314512 100644
--- a/framework.tck/pom.xml
+++ b/framework.tck/pom.xml
@@ -29,7 +29,7 @@
jarApache Felix Frameworkorg.apache.felix.framework.tck
- 8.0.0-SNAPSHOT
+ 7.1.0-SNAPSHOT$8
diff --git a/gogo/runtime/pom.xml b/gogo/runtime/pom.xml
index 572d7e0fcf..971bf62256 100644
--- a/gogo/runtime/pom.xml
+++ b/gogo/runtime/pom.xml
@@ -31,7 +31,7 @@
bundleApache Felix Gogo Runtimeorg.apache.felix.gogo.runtime
- 1.1.7-SNAPSHOT
+ 1.2.0-SNAPSHOThttp://felix.apache.org/scm:git:https://github.com/apache/felix-dev.git
diff --git a/log.extension/pom.xml b/log.extension/pom.xml
index 724c77a38c..111884fac8 100644
--- a/log.extension/pom.xml
+++ b/log.extension/pom.xml
@@ -20,7 +20,7 @@
org.apache.felixfelix-parent
- 9
+ 5../pom/pom.xml4.0.0
@@ -33,8 +33,8 @@
org.apache.felix.log.extension
- 8
- 8
+ 1.7
+ 1.7
diff --git a/log/pom.xml b/log/pom.xml
index da797b57e3..1ebbf68529 100644
--- a/log/pom.xml
+++ b/log/pom.xml
@@ -33,8 +33,8 @@
org.apache.felix.log
- 8
- 8
+ 1.7
+ 1.7
diff --git a/main.distribution/pom.xml b/main.distribution/pom.xml
index 035b238bcc..63f01d4621 100644
--- a/main.distribution/pom.xml
+++ b/main.distribution/pom.xml
@@ -27,7 +27,7 @@
pomApache Felix Main Distributionorg.apache.felix.main.distribution
- 8.0.0-SNAPSHOT
+ 7.1.0-SNAPSHOT$7.0.5
diff --git a/main/pom.xml b/main/pom.xml
index e64cd3653d..93ec09dc7e 100644
--- a/main/pom.xml
+++ b/main/pom.xml
@@ -27,7 +27,7 @@
bundleApache Felix Mainorg.apache.felix.main
- 8.0.0-SNAPSHOT
+ 7.1.0-SNAPSHOTscm:git:https://github.com/apache/felix-dev.gitscm:git:https://github.com/apache/felix-dev.git
diff --git a/resolver/pom.xml b/resolver/pom.xml
index 1355825d5a..cc2844dfd9 100644
--- a/resolver/pom.xml
+++ b/resolver/pom.xml
@@ -20,7 +20,7 @@
org.apache.felixfelix-parent
- 9
+ 5../pom/pom.xml4.0.0
@@ -61,14 +61,14 @@
test
-
org.mockito
- mockito-core
- 5.18.0
+ mockito-all
+ 1.10.19test
+ 6
diff --git a/scr/pom.xml b/scr/pom.xml
index 0ae9793dae..ed244e9585 100644
--- a/scr/pom.xml
+++ b/scr/pom.xml
@@ -30,7 +30,7 @@
Implementation of the Declarative Services specification 1.5
org.apache.felix.scr
- 2.2.19-SNAPSHOT
+ 2.3.0-SNAPSHOTscm:git:ssh://git@github.com/apache/felix-dev.gitscm:git:ssh://git@github.com/apache/felix-dev.git
diff --git a/utils/pom.xml b/utils/pom.xml
index b591157659..7b028dbe04 100644
--- a/utils/pom.xml
+++ b/utils/pom.xml
@@ -20,7 +20,7 @@
org.apache.felixfelix-parent
- 9
+ 5
@@ -38,6 +38,7 @@
+ 7
@@ -82,8 +83,8 @@
maven-compiler-plugin
- 8
- 8
+ 1.7
+ 1.7
diff --git a/webconsole/pom.xml b/webconsole/pom.xml
index 5259346dfa..e701e9ee2c 100644
--- a/webconsole/pom.xml
+++ b/webconsole/pom.xml
@@ -28,7 +28,7 @@
org.apache.felix.webconsolebundle
- 5.0.19-SNAPSHOT
+ 5.1.0-SNAPSHOTApache Felix Web Management Console
From 92ebd7811029797946eb145e2d8c32e88a15bf57 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Paul=20R=C3=BCtter?=
Date: Sat, 29 Aug 2026 23:24:39 +0200
Subject: [PATCH 20/26] FELIX-6759-Java-25-LTS - Repair the paths-filter block
Removing the split-out modules from the workflow left their filter keys behind
without their path lists:
configadmin:
utils:
resolver:
...
That is still valid YAML, as a nested mapping, which is why a parse check did not
catch it, but it is not what dorny/paths-filter expects.
Co-Authored-By: Claude Opus 4.8
---
.github/workflows/maven-ci.yml | 8 --------
1 file changed, 8 deletions(-)
diff --git a/.github/workflows/maven-ci.yml b/.github/workflows/maven-ci.yml
index 47630d0d4b..ded3fe1d5b 100644
--- a/.github/workflows/maven-ci.yml
+++ b/.github/workflows/maven-ci.yml
@@ -76,14 +76,6 @@ jobs:
- 'framework.tck/**'
gogo:
- 'gogo/**'
- configadmin:
- utils:
- resolver:
- connect:
- log.extension:
- bundlerepository:
- examples:
-
- name: Felix SCR
if: steps.changes.outputs.scr == 'true'
run: mvn -B -V -Dstyle.color=always --file scr/pom.xml clean verify
From 8a7dba6f93c6eb3dc6bbaadc0c01586f53a2ba8c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Paul=20R=C3=BCtter?=
Date: Sat, 29 Aug 2026 23:29:26 +0200
Subject: [PATCH 21/26] FELIX-6759-Java-25-LTS - Record the changes in each
module's changelog
Every module whose code changed now documents it where that module already keeps its
history:
- scr/changelog.txt gains a 2.3.0 entry.
- gogo/runtime/doc/changelog.txt gains a 1.1.6 to 1.2.0 entry.
- webconsole/README.md gains a 5.1.0 entry under Releases, which is where that
project records its history rather than in a separate changelog file.
framework/doc/changelog.txt was already updated with the 8.0.0 entry. http is not
included: only its test code changed.
The webconsole Security section is left alone. It documents HTTP authentication and
CSRF, which is unrelated to the Java Security Manager.
Co-Authored-By: Claude Opus 4.8
---
gogo/runtime/doc/changelog.txt | 8 ++++++++
scr/changelog.txt | 12 ++++++++++++
webconsole/README.md | 7 +++++++
3 files changed, 27 insertions(+)
diff --git a/gogo/runtime/doc/changelog.txt b/gogo/runtime/doc/changelog.txt
index 0504f78621..f1bbf6e94c 100644
--- a/gogo/runtime/doc/changelog.txt
+++ b/gogo/runtime/doc/changelog.txt
@@ -1,3 +1,11 @@
+Changes from 1.1.6 to 1.2.0
+---------------------------
+Improvement
+ Removed the Security Manager based ThreadGroup selection in ThreadUtils. Java SE
+ 24 permanently disabled the Security Manager (JEP 486), so the thread group is
+ now always taken from the current thread.
+
+
Changes from 1.1.4 to 1.1.6
---------------------------
Bug
diff --git a/scr/changelog.txt b/scr/changelog.txt
index 935c67f7f0..0b974782b8 100644
--- a/scr/changelog.txt
+++ b/scr/changelog.txt
@@ -1,3 +1,15 @@
+Changes in 2.3.0
+-----------------
+** Improvement
+ * Removed the Security Manager based permission checks. Java SE 24 permanently
+ disabled the Security Manager (JEP 486), so these checks could never run:
+ DependencyManager.hasGetPermission and
+ AbstractComponentManager.hasServiceRegistrationPermissions now always allow,
+ the AccessController.doPrivileged wrappers around ConfigurationAdmin access and
+ around setAccessible on injected fields and lifecycle methods are gone, and the
+ multilocation ConfigurationPermission check in RegionConfigurationSupport is
+ removed. No exported API changed.
+
Changes in 2.2.16
-----------------
** Improvement
diff --git a/webconsole/README.md b/webconsole/README.md
index 2650a1f66c..3c6e38f3df 100644
--- a/webconsole/README.md
+++ b/webconsole/README.md
@@ -118,6 +118,13 @@ In this case the Configuration Manager displays the name "myRealm, myClass" as d
## Releases
+### Changes in 5.1.0
+
+#### Improvement
+
+- Removed the Security Manager based `AccessController.doPrivileged` wrappers in `AbstractWebConsolePlugin`, `OsgiManager` and `ConfigurationSupport`. Java SE 24 permanently disabled the Security Manager ([JEP 486](https://openjdk.org/jeps/486)), so those blocks could never take effect. No exported API changed, and the Web Console's own HTTP authentication is unaffected.
+
+
### Changes in 5.0.18 (22/Sep/25)
#### Bug
From 8d767f750dbe7b7898cac5cefb6e1d7d57e0a13a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Paul=20R=C3=BCtter?=
Date: Sat, 29 Aug 2026 23:58:39 +0200
Subject: [PATCH 22/26] FELIX-6759-Java-25-LTS - Install the framework so the
TCK tests the local build
The TCK step failed to resolve the framework:
Could not find artifact org.apache.felix:org.apache.felix.framework:jar:
8.0.0-SNAPSHOT in apache.snapshots
The framework step ran clean verify, which does not install. The TCK is a separate
Maven invocation, so it resolves org.apache.felix.framework from the repository
rather than from the build that just ran. While the framework was 7.1.0-SNAPSHOT that
version existed in apache.snapshots, so resolution succeeded and the TCK quietly
exercised the published snapshot instead of the code under test. Renaming to 8.0.0
turned that silent substitution into a resolution error.
Running clean install makes the TCK test the framework this build produced, which is
what the step was always meant to do.
Co-Authored-By: Claude Opus 4.8
---
.github/workflows/maven-ci.yml | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/.github/workflows/maven-ci.yml b/.github/workflows/maven-ci.yml
index ded3fe1d5b..e936a5f39b 100644
--- a/.github/workflows/maven-ci.yml
+++ b/.github/workflows/maven-ci.yml
@@ -96,7 +96,11 @@ jobs:
run: mvn -B -V -Dstyle.color=always --file webconsole/pom.xml clean install verify
- name: Felix Framework
if: steps.changes.outputs.framework == 'true'
- run: mvn -B -V -Dstyle.color=always --file framework/pom.xml clean verify
+ # install, not verify: the TCK below is a separate Maven invocation and resolves
+ # the framework from the repository, so without installing it would silently test
+ # whatever org.apache.felix.framework happens to be published rather than the
+ # build under test.
+ run: mvn -B -V -Dstyle.color=always --file framework/pom.xml clean install
- name: OSGi-TCK Framework
if: steps.changes.outputs.framework == 'true'
run: mvn -B -V -Dstyle.color=always --file framework.tck/pom.xml clean verify
From 97898b335b70df8622f0596b0fd839e4e06badd4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Paul=20R=C3=BCtter?=
Date: Sun, 30 Aug 2026 00:40:41 +0200
Subject: [PATCH 23/26] FELIX-6759-Java-25-LTS - Point gogo.jline at the new
gogo.runtime version
gogo.runtime moved to 1.2.0-SNAPSHOT, but gogo.jline still declared a dependency on
1.1.7-SNAPSHOT, which no longer exists locally and is not published:
Could not find artifact org.apache.felix:org.apache.felix.gogo.runtime:jar:
1.1.7-SNAPSHOT in apache.snapshots
gogo.jline is the only module referencing the snapshot; gogo.bom and gogo.command
reference the released 1.1.4 and are unaffected.
Co-Authored-By: Claude Opus 4.8
---
gogo/jline/pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/gogo/jline/pom.xml b/gogo/jline/pom.xml
index ee5e0ed6c8..9508dc688c 100644
--- a/gogo/jline/pom.xml
+++ b/gogo/jline/pom.xml
@@ -58,7 +58,7 @@
org.apache.felixorg.apache.felix.gogo.runtime
- 1.1.7-SNAPSHOT
+ 1.2.0-SNAPSHOTorg.apache.felix
From 466bd67753a326b9edacdef4a95ff1f1bd781bb7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Paul=20R=C3=BCtter?=
Date: Sun, 30 Aug 2026 00:46:31 +0200
Subject: [PATCH 24/26] FELIX-6759-Java-25-LTS - Build main in CI, and repair
its build
main is changed by this branch, its dependency on the framework moves to
8.0.0-SNAPSHOT, and it embeds the framework, yet nothing verified it: there was no
main path filter and no build step, so a break would only have surfaced at release
time.
Building it locally first showed it does not build on a modern JDK at all, for the
same reason as the modules in the split-out build repair change: it declares
felix-parent 6, which does not match the local pom, so Maven resolves the released
parent from Central. That parent brings in ianal-maven-plugin 1.0-alpha-1, which
reflects into java.io and is blocked from Java 16 on:
Unable to make private java.io.File(java.lang.String,java.io.File) accessible:
module java.base does not "opens java.io" to unnamed module
Moving to felix-parent 9 removes ianal but pins maven-antrun-plugin 3.1.0, which
rejects the legacy tasks element:
You are using 'tasks' which has been removed from the maven-antrun-plugin
Both antrun executions now use target instead.
main has no code change, so its version stays at 7.1.0-SNAPSHOT. The step runs after
the framework step, which installs the framework it embeds.
Verified on JDK 25: main builds, the jar embeds the framework, and launching it
starts the framework and keeps running, with no Security Manager error. The only
output is the known sun.misc.Unsafe warning from URLHandlers.
Co-Authored-By: Claude Opus 4.8
---
.github/workflows/maven-ci.yml | 7 +++++++
main/bundle/jansi-1.18.jar | Bin 0 -> 287352 bytes
main/bundle/jline-3.13.2.jar | Bin 0 -> 839360 bytes
...rg.apache.felix.bundlerepository-2.0.10.jar | Bin 0 -> 237308 bytes
.../org.apache.felix.gogo.command-1.1.2.jar | Bin 0 -> 39691 bytes
.../org.apache.felix.gogo.jline-1.1.8.jar | Bin 0 -> 130450 bytes
.../org.apache.felix.gogo.runtime-1.1.4.jar | Bin 0 -> 203477 bytes
main/pom.xml | 10 +++++-----
8 files changed, 12 insertions(+), 5 deletions(-)
create mode 100644 main/bundle/jansi-1.18.jar
create mode 100644 main/bundle/jline-3.13.2.jar
create mode 100644 main/bundle/org.apache.felix.bundlerepository-2.0.10.jar
create mode 100644 main/bundle/org.apache.felix.gogo.command-1.1.2.jar
create mode 100644 main/bundle/org.apache.felix.gogo.jline-1.1.8.jar
create mode 100644 main/bundle/org.apache.felix.gogo.runtime-1.1.4.jar
diff --git a/.github/workflows/maven-ci.yml b/.github/workflows/maven-ci.yml
index e936a5f39b..e501beb07c 100644
--- a/.github/workflows/maven-ci.yml
+++ b/.github/workflows/maven-ci.yml
@@ -13,6 +13,7 @@ on:
- 'framework/**'
- 'gogo/**'
- 'framework.tck/**'
+ - 'main/**'
pull_request:
branches: [ "master", "feature/**", "maintenance/**" ]
paths:
@@ -25,6 +26,7 @@ on:
- 'framework/**'
- 'gogo/**'
- 'framework.tck/**'
+ - 'main/**'
# Cancel superseded runs when a branch is pushed again. github.head_ref is only set
# for pull_request events, so pushes to master fall back to the unique run_id and are
@@ -76,6 +78,8 @@ jobs:
- 'framework.tck/**'
gogo:
- 'gogo/**'
+ main:
+ - 'main/**'
- name: Felix SCR
if: steps.changes.outputs.scr == 'true'
run: mvn -B -V -Dstyle.color=always --file scr/pom.xml clean verify
@@ -104,6 +108,9 @@ jobs:
- name: OSGi-TCK Framework
if: steps.changes.outputs.framework == 'true'
run: mvn -B -V -Dstyle.color=always --file framework.tck/pom.xml clean verify
+ - name: Felix Main
+ if: steps.changes.outputs.main == 'true'
+ run: mvn -B -V -Dstyle.color=always --file main/pom.xml clean verify
- name: Felix Gogo Shell
if: steps.changes.outputs.gogo == 'true'
run: mvn -B -V -Dstyle.color=always --file gogo/pom.xml clean verify
diff --git a/main/bundle/jansi-1.18.jar b/main/bundle/jansi-1.18.jar
new file mode 100644
index 0000000000000000000000000000000000000000..a7be6dbd80bc5975580ea6a9aee84387c11d0b49
GIT binary patch
literal 287352
zcmeFab#Poynk8ykEQ^_$nb~4yW@ct)*^1r+@c>`~>nzT3CsnMqEaO?rrGP
zC*V(VlHd@3UGe$fE|dF*m63m6@&8tq=9du{5mr>9l@{?6TRShi?-d;#I>|Q7Xv*
zfhs6wmrG3G^D8M_ZVd_Ah+R-$_P@G6CT6BY_89D9I^P{lWBWq+fLYgNo6Vd=CfVIcokBh){W}z**h%`p~T=oU}>M%YaAfdlc-V#8L&x
zD0N6+w6p%RagG80xssVq!_~|NKrk4Q03%+n>muEvHafhLgTAzQzV(><;r_eNefu$|
zJZyD&?~GdCLqgh24c=j)dZqwa_e>ufyc8w3@w~4t#VgHr2i>*F1f6&F2=~0Zzb~k&
z-+;>tifnVWM}Z7Gkek*r5MN-A%CqY818e#uP6R32skZeoJ^pK2TH-M^IhtF#LOIbMfpD$xS#;c<=-}9;Ol@Mb@~zI@lE278`eypMa^8D-L6SM1R6O
zl2MO*OrPVa38W#DV5lXqa~sC}DS+CM6Jz_LWL|xE;@Dd3pD(B>|>0BINFeG~b%R$(x4)sA=1RMkC%^?|CwXJ09Mk
zHza21G>|pF*jB7{KYG0d`SR#eZxk{lmxwqL2Uh@pvnem9>!t^U9#R6SqU;_zQn5>X
z$6#g@gmDS0D#HL&<~V@qdJ5R#j%-E%y9o|@K9f1S$-^j}facfmp~-#G$44Xie8xV9
z8UWH#K?@q!Ta4netj)x1|I!XeGm~c=U=mPCF$7@OYcPd=c3*0MQ4?jAYk?TXHS1p9
zIr2!*c@}Eoy~3Ad24jAkhLEo1Y5!Cj0&f~6RBJ>-4pTNE#!`yCsq#g#B+FmE**Zn!
zC>GMN-p%U7UxVl?rUw*$TQZ1kia@N##XO_*6w}cq&7zkUuhqu#)tgWA67f7m+4-hL
z+f%ev>}_Z+mRd!7&%V*^CUkUNuBDx-3
z`RkjXL)(%`BPkQ~Ig&ZgEacsy(>Ro*C6idspwUn?Se#?~X4sN{=F(W6#v#kI&v`OW
ztL%hpNASQ5Z1Pc1aPPy3OX=UlvSmv_&P3&s
zoOhvN=5t-H`myd;I*98WP4qX!c<9Hd48d!arNwOv5pI%DMoy`MyUo)g^}*49lnfW*
zYvG-4GjJn1EvR>NZtle757gXwdK)aAUsgJw%Gi-O$}^`f@=uG?wWEx)k8+sOQ#df+
zX-sj6II0yq)l`?{nyhpvsw?JpIOJxs3RmflA1Vg11@Sg5!MOIaLdiyoByzw%0S@0r
z82fz7zMe(1t)35cQ9s|rd?E}>sTVRkkx>$I0ii^u(zWd~HoW?5@A{4d`FtdWoVh_S
zo;qz28FRS4w{eG2@N9}S{s#KjO-o!<;VuFE=~D;zKf7s}|37b93w;|$bGpBM)0j9I
z8yh$pF){wp@=N@m?Bh>XPl5kroB#8;|9#wkE;}r<-f8Rl
zyIn<_Nh!G0njcM^ltiu;Vd?fOG>kfN;sk#)VkhoG%qC%p^F8khM0T5`vA;9EjZOv!
z-~ZtVdidTHOmxG?D5LJ+VYhP!3okCfnlpHEv+;V+?e2VGIB}W9E(4y!lt|0O*@|?q
zxajD#a{Ri1eIMB_x)q5J_Jz3%p}V=saFOY4<+L-=m6;fl3@M%rDVAcyCsgoZybL?{
z-Qw(E;WWn-akG;ehuaqhIgwhFK_@o=GT!ksF}bKBCV~(ufjDR`B$Rr(2r?M~za!-t
zGL~R3C?Xy-Br7U<6~hMLg1P<@9#ui-u@#B%>*dc!uQLOZ(&3sEG;{8=HmvjvU6^s4
zXw@^fETI6$_?QldRR7#bd#(9KnJ22xea%>)qTvy+XV$b+n!8Mu6=LI(dhU
zRaCA)i+n$(a%!5|0;4_)@UO*g1kt90E{}WO!#7qhl6>3Uu=#(ASO(nJ36A=o;C;4I;*zg&h
zH@dgsZS=O_zWY@CT`8IDi;Sd|yTbK3GA{dW%>D9iD}hybwIC90zGf$_jBL~AcEg-l
zb8r(goFAXr;ppB@UKbtFyd2=gR4)u!31Tky`Q$I!pri;3?6yK6;%gsk!*>t$5I@Pg
zLYEMxLK^9c@pRhpghMr~+*nZ`UT7PD1fblp
zI@TX?zs8HG`APO>9ly|=RZ@=ZYJ4+9>@@M-I