/******************************************************************************* * Copyright (c) 2012 RelationWare, Benno Luthiger * 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: * RelationWare, Benno Luthiger ******************************************************************************/ package org.ripla.useradmin.internal; import java.security.AccessController; import java.security.PrivilegedActionException; import java.security.PrivilegedExceptionAction; import org.osgi.service.prefs.BackingStoreException; import org.osgi.service.prefs.Preferences; import org.osgi.service.prefs.PreferencesService; import org.osgi.service.useradmin.Group; import org.osgi.service.useradmin.Role; import org.ripla.useradmin.admin.RiplaGroup; import org.ripla.useradmin.admin.RiplaRole; import org.ripla.useradmin.admin.RiplaUser; import org.ripla.useradmin.admin.RiplaUserAdmin; import org.ripla.useradmin.interfaces.IUserAdminStore; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Store for roles, users and groups using the preferences service to persist * the data. * * @author Luthiger */ public class UserAdminStore implements IUserAdminStore { // NOPMD by Luthiger on 07.09.12 00:32 private static final Logger LOG = LoggerFactory .getLogger(UserAdminStore.class); private static final String PREFS_USER_ROOT = "userAdmin"; private static final String PREFS_NODE_PROPERTIES = "properties"; private static final String PREFS_NODE_CREDENTIALS = "credentials"; private static final String PREFS_NODE_MEMBERS = "members"; private static final String PREFS_NODE_TYPES = "types"; private static final String STRING_TYPE = "type"; private static final String STRING_BASIC = "basic"; private static final String STRING_REQUIRED = "required"; private transient PreferencesService preferences; private final transient RiplaUserAdmin userAdmin; private transient Preferences rootNode; public UserAdminStore(final PreferencesService inPreferences, final RiplaUserAdmin inUserAdmin) { preferences = inPreferences; userAdmin = inUserAdmin; } /** * Initializes the store, i.e. loads the persisted roles. * * @throws BackingStoreException */ @Override public void initialize() throws BackingStoreException { try { AccessController .doPrivileged(new PrivilegedExceptionAction<Object>() { @Override public Object run() throws BackingStoreException { rootNode = preferences .getUserPreferences(PREFS_USER_ROOT); loadRoles(); return null; } }); } catch (final PrivilegedActionException exc) { LOG.error("Error during init().", exc); throw (BackingStoreException) exc.getException(); } } // --- roles --- @Override public void addRole(final Role inRole) throws BackingStoreException { try { AccessController .doPrivileged(new PrivilegedExceptionAction<Object>() { @Override public Object run() throws BackingStoreException { final Preferences lNode = rootNode.node(inRole .getName()); lNode.putInt(STRING_TYPE, inRole.getType()); lNode.flush(); return null; } }); } catch (final PrivilegedActionException exc) { LOG.error("Error while adding a role.", exc); throw (BackingStoreException) exc.getException(); } } @Override public void removeRole(final Role inRole) throws BackingStoreException { try { AccessController .doPrivileged(new PrivilegedExceptionAction<Object>() { @Override public Object run() throws BackingStoreException { final Preferences lNode = rootNode.node(inRole .getName()); lNode.removeNode(); rootNode.node("").flush(); return null; } }); } catch (final PrivilegedActionException exc) { LOG.error("Error while removing a role.", exc); throw (BackingStoreException) exc.getException(); } } // --- properties --- @Override public void clearProperties(final Role inRole) throws BackingStoreException { try { AccessController .doPrivileged(new PrivilegedExceptionAction<Object>() { @Override public Object run() throws BackingStoreException { final Preferences lPropertyNode = rootNode .node(inRole.getName() + "/" + PREFS_NODE_PROPERTIES); lPropertyNode.clear(); if (lPropertyNode.nodeExists(PREFS_NODE_TYPES)) { lPropertyNode.node(PREFS_NODE_TYPES) .removeNode(); } lPropertyNode.flush(); return null; } }); } catch (final PrivilegedActionException exc) { LOG.error("Error while clearing properties.", exc); throw (BackingStoreException) exc.getException(); } } @Override public void addProperty(final Role inRole, final String inKey, final Object inValue) throws BackingStoreException { try { AccessController .doPrivileged(new PrivilegedExceptionAction<Object>() { @Override public Object run() throws BackingStoreException { final Preferences lPropertyNode = rootNode .node(inRole.getName() + "/" + PREFS_NODE_PROPERTIES); final Preferences lTypesNode = lPropertyNode .node(PREFS_NODE_TYPES); if (inValue instanceof String) { lPropertyNode.put(inKey, (String) inValue); lTypesNode.putBoolean(inKey, true); } else { lPropertyNode.putByteArray(inKey, (byte[]) inValue); lTypesNode.putBoolean(inKey, false); } lPropertyNode.flush(); return null; } }); } catch (final PrivilegedActionException exc) { LOG.error("Error while adding property.", exc); throw (BackingStoreException) exc.getException(); } } @Override public void removeProperty(final Role inRole, final String inKey) throws BackingStoreException { try { AccessController .doPrivileged(new PrivilegedExceptionAction<Object>() { @Override public Object run() throws BackingStoreException { final Preferences lPropertyNode = rootNode .node(inRole.getName() + "/" + PREFS_NODE_PROPERTIES); lPropertyNode.remove(inKey); if (lPropertyNode.nodeExists(PREFS_NODE_TYPES)) { lPropertyNode.node(PREFS_NODE_TYPES).remove( inKey); } lPropertyNode.flush(); return null; } }); } catch (final PrivilegedActionException exc) { LOG.error("Error while removing property.", exc); throw (BackingStoreException) exc.getException(); } } // --- credentials --- @Override public void clearCredentials(final Role inRole) throws BackingStoreException { try { AccessController .doPrivileged(new PrivilegedExceptionAction<Object>() { @Override public Object run() throws BackingStoreException { final Preferences lCredentialNode = rootNode .node(inRole.getName() + "/" + PREFS_NODE_CREDENTIALS); lCredentialNode.clear(); if (lCredentialNode.nodeExists(PREFS_NODE_TYPES)) { lCredentialNode.node(PREFS_NODE_TYPES) .removeNode(); } lCredentialNode.flush(); return null; } }); } catch (final PrivilegedActionException exc) { LOG.error("Error while clearing credentials.", exc); throw (BackingStoreException) exc.getException(); } } @Override public void addCredential(final Role inRole, final String inKey, final Object inValue) throws BackingStoreException { try { AccessController .doPrivileged(new PrivilegedExceptionAction<Object>() { @Override public Object run() throws BackingStoreException { final Preferences lCredentialNode = rootNode .node(inRole.getName() + "/" + PREFS_NODE_CREDENTIALS); final Preferences lTypesNode = lCredentialNode .node(PREFS_NODE_TYPES); if (inValue instanceof String) { lCredentialNode.put(inKey, (String) inValue); lTypesNode.putBoolean(inKey, true); } else { lCredentialNode.putByteArray(inKey, (byte[]) inValue); lTypesNode.putBoolean(inKey, false); } lCredentialNode.flush(); return null; } }); } catch (final PrivilegedActionException exc) { LOG.error("Error while adding credential.", exc); throw (BackingStoreException) exc.getException(); } } @Override public void removeCredential(final Role inRole, final String inKey) throws BackingStoreException { try { AccessController .doPrivileged(new PrivilegedExceptionAction<Object>() { @Override public Object run() throws BackingStoreException { final Preferences lCredentialNode = rootNode .node(inRole.getName() + "/" + PREFS_NODE_CREDENTIALS); lCredentialNode.remove(inKey); if (lCredentialNode.nodeExists(PREFS_NODE_TYPES)) { lCredentialNode.node(PREFS_NODE_TYPES).remove( inKey); } lCredentialNode.flush(); return null; } }); } catch (final PrivilegedActionException exc) { LOG.error("Error while removing credential.", exc); throw (BackingStoreException) exc.getException(); } } // --- members --- @Override public void addMember(final Group inGroup, final Role inRole) throws BackingStoreException { addMember(inGroup, inRole, STRING_BASIC); } @Override public void addRequiredMember(final Group inGroup, final Role inRole) throws BackingStoreException { addMember(inGroup, inRole, STRING_REQUIRED); } protected void addMember(final Group inGroup, final Role inRole, final String inMemberType) throws BackingStoreException { try { AccessController .doPrivileged(new PrivilegedExceptionAction<Object>() { @Override public Object run() throws BackingStoreException { final Preferences lMemberNode = rootNode .node(inGroup.getName() + "/" + PREFS_NODE_MEMBERS); lMemberNode.put(inRole.getName(), inMemberType); lMemberNode.flush(); return null; } }); } catch (final PrivilegedActionException exc) { LOG.error("Error while adding member.", exc); throw (BackingStoreException) exc.getException(); } } @Override public void removeMember(final Group inGroup, final Role inRole) throws BackingStoreException { try { AccessController .doPrivileged(new PrivilegedExceptionAction<Object>() { @Override public Object run() throws BackingStoreException { final Preferences lMemberNode = rootNode .node(inGroup.getName() + "/" + PREFS_NODE_MEMBERS); lMemberNode.remove(inRole.getName()); lMemberNode.flush(); return null; } }); } catch (final PrivilegedActionException exc) { LOG.error("Error while removing member.", exc); throw (BackingStoreException) exc.getException(); } } protected void loadRoles() throws BackingStoreException { synchronized (this) { createAnonymousRole(); final String[] lChildren = rootNode.node("").childrenNames(); for (int i = 0; i < lChildren.length; i++) { if (userAdmin.getRole(lChildren[i]) == null) { loadRole(rootNode.node(lChildren[i]), null); } } } } protected void loadRole(final Preferences inNode, Role inRole) // NOPMD by Luthiger on 07.09.12 00:32 throws BackingStoreException { final int lType = inNode.getInt(STRING_TYPE, Integer.MIN_VALUE); if (lType == Integer.MIN_VALUE) { final String lErrorMsg = String.format( "Unable to load role \"%s\"!", inNode.name()); LOG.error(lErrorMsg); throw new BackingStoreException(lErrorMsg); } if (inRole == null) { inRole = userAdmin.createRole(inNode.name(), lType, false); } final Preferences lPropertiesNode = inNode.node(PREFS_NODE_PROPERTIES); String[] lKeys = lPropertiesNode.keys(); final AbstractUserAdminHashtable lProperties = (AbstractUserAdminHashtable) inRole .getProperties(); // load properties Object lValue; final Preferences lTypesNode = lPropertiesNode.node(PREFS_NODE_TYPES); for (int i = 0; i < lKeys.length; i++) { if (lTypesNode.getBoolean(lKeys[i], true)) { lValue = lPropertiesNode.get(lKeys[i], null); } else { lValue = lPropertiesNode.getByteArray(lKeys[i], null); } lProperties.put(lKeys[i], lValue, inRole, false); } // load credentials if (lType == Role.GROUP || lType == Role.USER) { Object lCredentialValue; final Preferences lCredentialNode = inNode .node(PREFS_NODE_CREDENTIALS); final Preferences lCredentialTypesNode = lCredentialNode .node(STRING_TYPE); lKeys = lCredentialNode.keys(); final CredentialsHashtable lCredentials = (CredentialsHashtable) ((RiplaUser) inRole) .getCredentials(); for (int i = 0; i < lKeys.length; i++) { if (lCredentialTypesNode.getBoolean(lKeys[i], true)) { lCredentialValue = lCredentialNode.get(lKeys[i], null); } else { lCredentialValue = lCredentialNode.getByteArray(lKeys[i], null); } lCredentials.put(lKeys[i], lCredentialValue, inRole, false); } } // load group members if (lType == Role.GROUP) { final Preferences lMemberNode = inNode.node(PREFS_NODE_MEMBERS); lKeys = lMemberNode.keys(); for (int i = 0; i < lKeys.length; i++) { lValue = lMemberNode.get(lKeys[i], null); Role lMember = userAdmin.getRole(lKeys[i]); if (lMember == null) { // then we have not loaded this one yet, so load it loadRole(rootNode.node(lKeys[i]), null); lMember = userAdmin.getRole(lKeys[i]); } if (lValue.equals(STRING_REQUIRED)) { ((RiplaGroup) inRole).addRequiredMember(lMember, false); } else { ((RiplaGroup) inRole).addMember(lMember, false); } } } } private void createAnonymousRole() throws BackingStoreException { RiplaRole lRole = null; if (!rootNode.nodeExists(Role.USER_ANYONE)) { // If the user.anyone role is not present, create it lRole = (RiplaRole) userAdmin.createRole(Role.USER_ANYONE, Role.ROLE, true); } /* modified to solve defect 95982 */ if (lRole == null) { loadRole(rootNode.node(Role.USER_ANYONE), null); } else { loadRole(rootNode.node(Role.USER_ANYONE), lRole); } } @Override public void destroy() { try { rootNode.flush(); rootNode = null; // NOPMD by Luthiger on 07.09.12 00:31 preferences = null; // NOPMD by Luthiger on 07.09.12 00:31 } catch (final BackingStoreException exc) { LOG.error("Error while destroying the user admin store!", exc); } } }