All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.ow2.bonita.identity.impl.XMLIdentityService Maven / Gradle / Ivy

/**
 * Copyright (C) 2007  Bull S. A. S.
 * Bull, Rue Jean Jaures, B.P.68, 78340, Les Clayes-sous-Bois
 * This library is free software; you can redistribute it and/or modify it under the terms
 * of the GNU Lesser General Public License as published by the Free Software Foundation
 * version 2.1 of the License.
 * This library 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 GNU Lesser General Public License for more details.
 * You should have received a copy of the GNU Lesser General Public License along with this
 * program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
 * Floor, Boston, MA  02110-1301, USA.
 **/
package org.ow2.bonita.identity.impl;

import java.beans.XMLDecoder;
import java.beans.XMLEncoder;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.Permission;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Properties;
import java.util.Set;

import org.ow2.bonita.identity.GroupOp;
import org.ow2.bonita.identity.Membership;
import org.ow2.bonita.identity.UserOp;
import org.ow2.bonita.util.Misc;
import org.xml.sax.SAXParseException;

/**
 * @author "Pierre Vigneras"
 * @date Dec 13, 2007
 */
public class XMLIdentityService extends PersistentIdentityService {

  public XMLIdentityService(final String fileName, boolean create) throws IOException {
    this(new File(fileName), create);
  }

  public XMLIdentityService(final File file, boolean create) throws IOException {
    super(file, create);
  }

  protected void flush() {
    XMLEncoder encoder = null;
    try {
      encoder = new XMLEncoder(new BufferedOutputStream(new FileOutputStream(
          file)));
      encoder.writeObject(next);
      writeGroups(encoder);
      writeUsers(encoder);
      encoder.flush();
    } catch (IOException ioe) {
      throw new RuntimeException(ioe);
    } finally {
      Misc.close(encoder);
    }
  }

  //private static final String NEXT_HEADER = "Next";

  private static final String USERS_NB_HEADER = "Users nb";

  private static final String USER_ID_HEADER = "UserOp id";

  //private static final String USER_PROPERTIES_NB_HEADER = "UserOp Properties nb";

  private static final String USER_PROPERTIES_HEADER = "UserOp Properties";

  private static final String USER_MEMBERSHIPS_NB_HEADER = "UserOp Memberships nb";

  private static final String USER_PERMISSIONS_HEADER = "UserOp Permissions";

  private static final String GROUP_NB_HEADER = "Groups nb";

  private static final String GROUP_ID_HEADER = "GroupOp id";

  private static final String GROUP_PARENT_HEADER = "GroupOp parent";

  private static final String GROUP_CHILDREN_NB_HEADER = "GroupOp children";

  //private static final String GROUP_PROPERTIES_NB_HEADER = "GroupOp Properties nb";

  private static final String GROUP_PROPERTIES_HEADER = "GroupOp Properties";

  private static final String GROUP_MEMBERSHIPS_NB_HEADER = "GroupOp Memberships nb";

  private static final String GROUP_PERMISSIONS_HEADER = "GroupOp Permissions";

  //private static final String GROUP_PERMISSIONS_NB_HEADER = "Group Pemissions nb";

  private void writeGroups(final XMLEncoder encoder) throws IOException {
    encoder.writeObject(GROUP_NB_HEADER);
    encoder.writeObject(groupOps.size());
    final Collection< ? extends GroupOp> groupCollection = groupOps.values();
    for (GroupOp groupOp : groupCollection) {
      encoder.writeObject(GROUP_ID_HEADER);
      encoder.writeObject(groupOp.getId());
      encoder.writeObject(GROUP_PARENT_HEADER);
      encoder.writeObject(groupOp.getParent().getId());
      final Set children = groupOp.getChildren();
      encoder.writeObject(GROUP_CHILDREN_NB_HEADER);
      encoder.writeObject(children.size());
      for (GroupOp child : children) {
        encoder.writeObject(child.getId());
      }
      encoder.writeObject(GROUP_PROPERTIES_HEADER);
      // writeProperties(encoder, groupOp.getProperties());
      encoder.writeObject(groupOp.getProperties());
      final Set memberships = groupOp.getMemberships();
      encoder.writeObject(GROUP_MEMBERSHIPS_NB_HEADER);
      encoder.writeObject(memberships.size());
      for (Membership m : memberships) {
        encoder.writeObject(m.getUser().getId());
      }
      encoder.writeObject(GROUP_PERMISSIONS_HEADER);
      writePermissions(encoder, groupOp.getPermissions());
    }
  }

  private void writePermissions(final XMLEncoder encoder,
      Set permissions) {
    encoder.writeObject(permissions);
  }
/*
  private void writeProperties(final XMLEncoder encoder, Properties properties) {
    encoder.writeObject(properties.size());
    for (Entry e : properties.entrySet()) {
      encoder.writeObject(e.getKey());
      encoder.writeObject(e.getValue());
    }
  }
*/
  private void writeUsers(final XMLEncoder encoder) throws IOException {
    encoder.writeObject(USERS_NB_HEADER);
    encoder.writeObject(users.size());
    final Collection< ? extends UserOp> set = users.values();
    for (UserOp userOp : set) {
      encoder.writeObject(USER_ID_HEADER);
      encoder.writeObject(userOp.getId());
      encoder.writeObject(USER_PROPERTIES_HEADER);
      // writeProperties(encoder, userOp.getProperties());
      encoder.writeObject(userOp.getProperties());
      final Set memberships = userOp.getMemberships();
      encoder.writeObject(USER_MEMBERSHIPS_NB_HEADER);
      encoder.writeObject(memberships.size());
      for (Membership m : memberships) {
        encoder.writeObject(m.getGroup().getId());
      }
      encoder.writeObject(USER_PERMISSIONS_HEADER);
      writePermissions(encoder, userOp.getPermissions());
    }
  }

  protected void sync() {
    XMLDecoder decoder = null;
    try {
      decoder = new XMLDecoder(new BufferedInputStream(
          new FileInputStream(file)));
      next = ((Integer) decoder.readObject()).intValue();
      final Map> groupMemberships = new HashMap>();
      groupOps = readGroups(decoder, groupMemberships);
      final Map> userMemberships = new HashMap>();
      users = readUsers(decoder, userMemberships);
      applyMemberships(userMemberships, groupMemberships);
    } catch (NoSuchElementException nsee) {
      init();
    } catch (Exception e) {
      if (e instanceof SAXParseException) {
        final SAXParseException spe = (SAXParseException) e;
        final Throwable t = spe.getCause();
        if (t != null) {
          t.printStackTrace();
        } else {
          spe.printStackTrace();
        }
      } else {
        throw new RuntimeException(e);
      }
    }
  }

  @SuppressWarnings("unchecked")
  private Map readGroups(XMLDecoder decoder,
      Map> groupMemberships) throws NumberFormatException, IOException {
    final Map defined = new HashMap();
    defined.put(InMemoryIdentityService.ROOT_ID, GroupImpl.root());
    decoder.readObject().equals(GROUP_NB_HEADER);
    int groupNb = ((Integer) decoder.readObject()).intValue();
    while (groupNb-- != 0) {
      decoder.readObject().equals(GROUP_ID_HEADER);
      // TODO: Depends on GroupImpl id: InMemoryIdentityService uses an Integer,
      // but it may be any object.
      final String id = (String) decoder.readObject();
      // Check if this group has already been referenced
      GroupImpl group = (GroupImpl) defined.get(id);
      if (group == null) {
        group = freshGroup();
        group.setId(id);
        defined.put(id, group);
      }
      decoder.readObject().equals(GROUP_PARENT_HEADER);
      final String parentId = (String) decoder.readObject();
      GroupImpl parent = (GroupImpl) defined.get(parentId);
      if (parent == null) {
        parent = freshGroup();
        parent.setId(parentId);
        defined.put(parentId, parent);
      }
      group.setParent(parent);
      decoder.readObject().equals(GROUP_CHILDREN_NB_HEADER);
      int childrenNb = ((Integer) decoder.readObject()).intValue();
      final Set children = new HashSet();
      int nb = childrenNb;
      while (nb-- > 0) {
        final String childId = (String) decoder.readObject();
        GroupImpl child = (GroupImpl) defined.get(childId);
        if (child == null) {
          child = freshGroup();
          child.setId(childId);
          defined.put(childId, child);
        }
        children.add(child);
      }
      if (childrenNb != children.size()) {
        throw new IOException(
            "Inconsistency detected: declared children nb is different from listed one!");
      }
      group.setChildren(children);
      decoder.readObject().equals(GROUP_PROPERTIES_HEADER);
      group.setProperties((Properties) decoder.readObject());
      decoder.readObject().equals(GROUP_MEMBERSHIPS_NB_HEADER);
      int membershipNb = ((Integer) decoder.readObject()).intValue();
      final Set ids = readMembershipsIds(decoder, membershipNb);
      groupMemberships.put(group, ids);
      decoder.readObject().equals(GROUP_PERMISSIONS_HEADER);
      group.setPermissions((Set) decoder.readObject());
    }
    // if (defined.size() != references.size()) throw new
    // IOException("Inconsistency detected: referenced groupOps and defined
    // groupOps are different!");
    return defined;
  }
/*
  private void readPermissions(XMLDecoder decoder,
      final Set permissions) {
    final Set perms = (Set) decoder.readObject();
    permissions.addAll(perms);
  }

  private void readProperties(XMLDecoder decoder, final Properties properties) {
    // int nb = ((Integer) decoder.readObject()).intValue();
    // while(nb-- > 0) {
    // final String key = (String) decoder.readObject();
    // final String value = (String) decoder.readObject();
    // properties.setProperty(key, value);
    // }
  }
*/
  @SuppressWarnings("unchecked")
  private Map readUsers(final XMLDecoder decoder,
      Map> userMemberships) throws IOException {
    final Map result = new HashMap();
    decoder.readObject().equals(USERS_NB_HEADER);
    int userNb = ((Integer) decoder.readObject()).intValue();
    while (userNb-- != 0) {
      // TODO: Depends on UserImpl id: InMemoryIdentityService uses an Integer,
      // but it may be any object.
      decoder.readObject().equals(USER_ID_HEADER);
      final String id = (String) decoder.readObject();
      final UserImpl user = freshUser();
      user.setId(id);
      decoder.readObject().equals(USER_PROPERTIES_HEADER);
      user.setProperties((Properties) decoder.readObject());
      decoder.readObject().equals(USER_MEMBERSHIPS_NB_HEADER);
      int membershipNb = ((Integer) decoder.readObject()).intValue();
      final Set ids = readMembershipsIds(decoder, membershipNb);
      userMemberships.put(user, ids);
      decoder.readObject().equals(USER_PERMISSIONS_HEADER);
      user.setPermissions((Set) decoder.readObject());
      result.put(id, user);
    }
    return result;
  }

  /**
   * @param decoder
   * @param membershipNb
   * @throws IOException
   */
  private Set readMembershipsIds(final XMLDecoder decoder,
      int membershipNb) throws IOException {
    final Set ids = new HashSet();
    while (membershipNb-- > 0) {
      final String id = (String) decoder.readObject();
      ids.add(id);
    }
    return ids;
  }

  private void applyMemberships(Map> userMemberships,
      Map> groupMemberships) throws IOException {
    final Collection ums = new ArrayList();
    for (UserImpl user : userMemberships.keySet()) {
      for (String groupId : userMemberships.get(user)) {
        final GroupImpl group = (GroupImpl) groupOps.get(groupId);
        if (group == null) {
          throw new IOException("Unknown GroupOp Id: " + groupId);
        }
        ums.add(new MembershipImpl(user, group));
      }
    }
    final Collection gms = new ArrayList();
    for (GroupImpl group : groupMemberships.keySet()) {
      for (String userId : groupMemberships.get(group)) {
        final UserImpl user = (UserImpl) users.get(userId);
        if (user == null) {
          throw new IOException("Unknown UserOp Id: " + userId);
        }
        gms.add(new MembershipImpl(user, group));
      }
    }
    for (MembershipImpl um : ums) {
      if (!gms.contains(um)) {
        throw new IOException("Inconsistency detected: user membership " + um
            + " is not specified in group memberships");
      }
      setMembership(um);
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy