blob: 5052f984e6d6cb79e8b4411089f1a67025c946c6 [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.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.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;
Map old = m_cache.read(PermissionInfo[].class);
if (old != null)
{
m_store.putAll(old);
}
}
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)
{
PermissionInfo[] permissions = null;
boolean file = false;
synchronized (m_store)
{
if (m_store.containsKey(location))
{
permissions = (PermissionInfo[]) m_store.get(location);
file = true;
}
else if ((cpai == null) || (cpai.isEmpty()))
{
if (m_default != null)
{
permissions = m_default;
}
else
{
permissions = ALL_PERMISSION;
}
}
}
if ((cpai == null) || cpai.isEmpty() || file)
{
if (check(permissions, permission, file ? bundle : null))
{
return Boolean.TRUE;
}
}
permissions = m_permissions.getImplicit(bundle);
if (check(permissions, permission, bundle))
{
return Boolean.TRUE;
}
if ((cpai != null) && !file)
{
return null;
}
return Boolean.FALSE;
}
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()]);
}
}