/* * Copyright (c) 2012-2014, 2016 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(); } } }