blob: 61c0f0da05400e8b0d2021dfcd1968b08893b85a [file] [log] [blame]
/*
* Copyright (c) 2012-2014 Eike Stepper (Berlin, Germany) and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Eike Stepper - initial API and implementation
*/
package org.eclipse.emf.cdo.server.spi.security;
import org.eclipse.emf.cdo.common.model.CDOPackageInfo;
import org.eclipse.emf.cdo.common.model.CDOPackageRegistry;
import org.eclipse.emf.cdo.common.model.CDOPackageUnit;
import org.eclipse.emf.cdo.security.Access;
import org.eclipse.emf.cdo.security.FilterPermission;
import org.eclipse.emf.cdo.security.PermissionFilter;
import org.eclipse.emf.cdo.security.Realm;
import org.eclipse.emf.cdo.security.RealmUtil;
import org.eclipse.emf.cdo.security.Role;
import org.eclipse.emf.cdo.security.SecurityFactory;
import org.eclipse.emf.cdo.security.SecurityItem;
import org.eclipse.emf.cdo.security.SecurityPackage;
import org.eclipse.emf.cdo.security.User;
import org.eclipse.emf.cdo.server.IStoreAccessor.CommitContext;
import org.eclipse.emf.cdo.server.security.ISecurityManager.RealmOperation;
import org.eclipse.emf.cdo.server.spi.security.InternalSecurityManager.CommitHandler;
import org.eclipse.net4j.util.factory.ProductCreationException;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EModelElement;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.util.EcoreUtil;
import java.util.StringTokenizer;
/**
* If the meaning of this type isn't clear, there really should be more of a description here...
*
* @author Eike Stepper
*/
public class AnnotationHandler implements InternalSecurityManager.CommitHandler
{
public static final String SOURCE_URI = "http://www.eclipse.org/CDO/Security";
public static final String READ_KEY = "read";
public static final String WRITE_KEY = "write";
public static final String DELIMITERS = " ,;|";
public AnnotationHandler()
{
}
public void init(InternalSecurityManager securityManager, boolean firstTime)
{
if (firstTime)
{
CDOPackageRegistry packageRegistry = securityManager.getRepository().getPackageRegistry();
handlePackageUnits(securityManager, packageRegistry.getPackageUnits());
}
}
public void handleCommit(InternalSecurityManager securityManager, CommitContext commitContext, User user)
{
handlePackageUnits(securityManager, commitContext.getNewPackageUnits());
}
protected void handlePackageUnits(InternalSecurityManager securityManager, final CDOPackageUnit[] packageUnits)
{
securityManager.modify(new RealmOperation()
{
public void execute(Realm realm)
{
if (packageUnits != null && packageUnits.length != 0)
{
for (CDOPackageUnit packageUnit : packageUnits)
{
for (CDOPackageInfo packageInfo : packageUnit.getPackageInfos())
{
EPackage ePackage = packageInfo.getEPackage();
handlePackage(realm, ePackage);
}
}
}
}
});
}
protected void handlePackage(Realm realm, EPackage ePackage)
{
handlePackagePermission(realm, ePackage, READ_KEY, Access.READ);
handlePackagePermission(realm, ePackage, WRITE_KEY, Access.WRITE);
for (EClassifier eClassifier : ePackage.getEClassifiers())
{
if (eClassifier instanceof EClass)
{
EClass eClass = (EClass)eClassifier;
handleClassPermission(realm, eClass, READ_KEY, Access.READ);
handleClassPermission(realm, eClass, WRITE_KEY, Access.WRITE);
}
}
}
protected void handlePackagePermission(Realm realm, EPackage ePackage, String key, Access access)
{
EClass filterClass = SecurityPackage.Literals.PACKAGE_FILTER;
EReference filterFeature = SecurityPackage.Literals.PACKAGE_FILTER__APPLICABLE_PACKAGE;
handlePermission(realm, ePackage, key, access, filterClass, filterFeature);
}
protected void handleClassPermission(Realm realm, EClass eClass, String key, Access access)
{
EClass filterClass = SecurityPackage.Literals.CLASS_FILTER;
EReference filterFeature = SecurityPackage.Literals.CLASS_FILTER__APPLICABLE_CLASS;
handlePermission(realm, eClass, key, access, filterClass, filterFeature);
}
protected void handlePermission(Realm realm, EModelElement modelElement, String key, Access access,
EClass filterClass, EReference filterFeature)
{
String annotation = EcoreUtil.getAnnotation(modelElement, SOURCE_URI, key);
if (annotation == null || annotation.length() == 0)
{
return;
}
EList<SecurityItem> items = realm.getItems();
StringTokenizer tokenizer = new StringTokenizer(annotation, DELIMITERS);
while (tokenizer.hasMoreTokens())
{
String token = tokenizer.nextToken();
if (token != null && token.length() != 0)
{
PermissionFilter filter = (PermissionFilter)EcoreUtil.create(filterClass);
filter.eSet(filterFeature, modelElement);
FilterPermission permission = SecurityFactory.eINSTANCE.createFilterPermission(access, filter);
Role role = RealmUtil.findRole(items, token);
if (role == null)
{
role = SecurityFactory.eINSTANCE.createRole();
role.setId(token);
items.add(role);
}
role.getPermissions().add(permission);
}
}
}
@Override
public String toString()
{
return getClass().getSimpleName();
}
/**
* Creates {@link AnnotationHandler} instances.
*
* @author Eike Stepper
* @since 4.3
*/
public static class Factory extends InternalSecurityManager.CommitHandler.Factory
{
public Factory()
{
super("annotation");
}
@Override
public CommitHandler create(String description) throws ProductCreationException
{
return new AnnotationHandler();
}
}
}