/* * 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; } }