/* Copyright (C) 2009 Mobile Sorcery AB
This program is free software; you can redistribute it and/or modify it
under the terms of the Eclipse Public License v1.0.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the Eclipse Public License v1.0 for
more details.
You should have received a copy of the Eclipse Public License v1.0 along
with this program. It is also available at http://www.eclipse.org/legal/epl-v10.html
*/
package com.mobilesorcery.sdk.internal.security;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import org.eclipse.core.runtime.Path;
import com.mobilesorcery.sdk.core.MoSyncBuilder;
import com.mobilesorcery.sdk.core.MoSyncProject;
import com.mobilesorcery.sdk.core.PropertyUtil;
import com.mobilesorcery.sdk.core.Util;
import com.mobilesorcery.sdk.core.security.IApplicationPermissions;
import com.mobilesorcery.sdk.core.security.ICommonPermissions;
/**
* The default application permissions implementation; automatically keeps
* the associated project's properties in sync.
* @author Mattias Bybro
*
*/
public class ApplicationPermissions implements IApplicationPermissions {
public final static String APPLICATION_PERMISSIONS_PROP = MoSyncBuilder.BUILD_PREFS_PREFIX + "app.permissions";
private final static String ROOT = "__root";
private final TreeMap<String, Set<String>> availablePermissionLookup = new TreeMap<String, Set<String>>();
private TreeSet<String> requestedPermissions;
private final MoSyncProject project;
private boolean isWorkingCopy = false;
public ApplicationPermissions(MoSyncProject project) {
this.project = project;
String[] permissions = project.getProfileManager().getAvailableCapabilities(true);
for (int i = 0; i < permissions.length; i++) {
addAvailablePermission(permissions[i]);
}
refresh();
}
/**
* Refreshes this application permission object using
* the associated project's properties.
*/
public void refresh() {
init(project.getProperty(APPLICATION_PERMISSIONS_PROP));
}
private void init(String applicationPermissionProperty) {
requestedPermissions = new TreeSet<String>(Arrays.asList(PropertyUtil.toStrings(applicationPermissionProperty)));
}
private void addAvailablePermission(String permission) {
String parent = Util.getParentKey(permission);
if (parent == null) {
parent = ROOT;
}
Set<String> lookupSet = availablePermissionLookup.get(parent);
if (lookupSet == null) {
lookupSet = new TreeSet<String>();
availablePermissionLookup.put(parent, lookupSet);
}
lookupSet.add(permission);
}
@Override
public List<String> getRequestedPermissions(boolean includeChildren) {
if (includeChildren) {
ArrayList<String> result = new ArrayList<String>();
for (String requestedPermission : requestedPermissions) {
List<String> children = getAvailablePermissions(requestedPermission);
result.add(requestedPermission);
result.addAll(children);
}
return result;
} else {
return new ArrayList<String>(requestedPermissions);
}
}
@Override
public void resetRequestedPermissions(List<String> requested) {
this.requestedPermissions = new TreeSet<String>(requested);
save();
}
@Override
public void setRequestedPermission(String requested, boolean set) {
setRequestedPermission(requested, set, true);
}
@Override
public void setRequestedPermissions(List<String> requested, boolean set) {
for (String oneRequested : requested) {
setRequestedPermission(oneRequested, set);
}
}
private void setRequestedPermission(String requested, boolean set, boolean setSubPermissions) {
if (requested == null) {
return;
}
if (set) {
requestedPermissions.add(requested);
if (setSubPermissions) {
List<String> subPermissions = getAvailablePermissions(requested);
requestedPermissions.addAll(subPermissions);
}
} else {
requestedPermissions.remove(requested);
if (setSubPermissions) {
List<String> subPermissions = getAvailablePermissions(requested);
requestedPermissions.removeAll(subPermissions);
}
}
String parentPermission = Util.getParentKey(requested);
setRequestedPermission(parentPermission, allSubPermissionsSet(parentPermission), false);
save();
}
private boolean allSubPermissionsSet(String parentPermission) {
TreeSet<String> available = new TreeSet<String>(getAvailablePermissions(parentPermission));
available.removeAll(requestedPermissions);
return available.isEmpty();
}
private void save() {
if (!isWorkingCopy) {
String propertyString = toPropertyString(requestedPermissions.toArray(new String[0]));
project.setProperty(APPLICATION_PERMISSIONS_PROP, propertyString);
}
}
public final static String toPropertyString(String... permissions) {
return PropertyUtil.fromStrings(permissions);
}
@Override
public List<String> getAvailablePermissions(String parentPermission) {
if (parentPermission == null) {
parentPermission = ROOT;
}
Set<String> availablePermissions = availablePermissionLookup.get(parentPermission);
ArrayList<String> result = new ArrayList<String>();
if (availablePermissions != null) {
result.addAll(availablePermissions);
}
return result;
}
@Override
public boolean isPermissionRequested(String key) {
if (key == null) {
return false;
}
return requestedPermissions.contains(key) || isPermissionRequested(Util.getParentKey(key));
}
@Override
public IApplicationPermissions createWorkingCopy() {
ApplicationPermissions copy = new ApplicationPermissions(project);
copy.isWorkingCopy = true;
return copy;
}
@Override
public void apply(IApplicationPermissions workingCopy) {
resetRequestedPermissions(workingCopy.getRequestedPermissions(false));
}
@Override
public String toString() {
return requestedPermissions.toString();
}
public static IApplicationPermissions getDefaultPermissions(MoSyncProject project) {
ApplicationPermissions result = new ApplicationPermissions(project);
result.isWorkingCopy = true;
result.init(project.getDefaultProperty(APPLICATION_PERMISSIONS_PROP));
return result;
}
}