blob: c9c299f78926d3fb7dbb12cec6bcb211dcec7e98 [file] [log] [blame]
/*
* 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;
}
}