Package com.google.nigori.server

Source Code of com.google.nigori.server.HashMapDatabase

/*
* Copyright (C) 2011 Alastair R. Beresford
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.nigori.server;

import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.google.nigori.common.Nonce;
import com.google.nigori.common.RevValue;

/**
* An in-memory database used for system testing.
*
* Do not use in production as data is not saved to non-volatile storage nor consistent across
* potentially many instances of App Engine.
*
* @author Alastair Beresford
*
*/
public class HashMapDatabase extends AbstractDatabase implements Serializable {

  private static final long serialVersionUID = 1L;
  // TODO(drt24) provide a WeakHashMap version so this can be used as a cache
  private HashMap<User,Map<Bytes, Map<Bytes,Bytes>>> stores = new HashMap<User,Map<Bytes, Map<Bytes,Bytes>>>();
  private HashMap<Bytes,User> users = new HashMap<Bytes,User>();
  private HashMap<Bytes,Set<Nonce>> nonces = new HashMap<Bytes,Set<Nonce>>();

  @Override
  public boolean addUser(byte[] publicKey, byte[] publicHash) {
    //TODO(beresford): check authority to carry out action
    if (haveUser(publicHash)){
      return false;
    }
    User user = new JUser(publicKey, publicHash, new Date());
    users.put(Bytes.copyFrom(publicHash),user);
    stores.put(user, new HashMap<Bytes, Map<Bytes,Bytes>>());
    return true;
  }
 
  @Override
  public boolean haveUser(byte[] publicHash) {
    return users.containsKey(Bytes.copyFrom(publicHash));
  }

  @Override
  public boolean deleteUser(User existingUser) {
    //TODO(beresford): check authority to carry out action
    User user = users.remove(Bytes.copyFrom(existingUser.getPublicHash()));
    return user != null && stores.remove(user) != null;
  }

  @Override
  public byte[] getPublicKey(byte[] publicHash) throws UserNotFoundException {
    assert publicHash != null;
    assert publicHash.length > 0;
    User user = users.get(Bytes.copyFrom(publicHash));
    if (user == null) {
      throw new UserNotFoundException();
    }
    return user.getPublicKey();
  }

  @Override
  public User getUser(byte[] publicHash) throws UserNotFoundException {
    assert publicHash != null;
    assert publicHash.length > 0;
    User user = users.get(Bytes.copyFrom(publicHash));
    if (user == null) {
      throw new UserNotFoundException();
    }
    return user;
  }

  @Override
  public Collection<RevValue> getRecord(User user, byte[] key) {

    // TODO(beresford): check authority to carry out action
    if (key == null) {
      return null;
    }

    Map<Bytes, Bytes> revisions = stores.get(user).get(Bytes.copyFrom(key));
    if (revisions != null) {
      List<RevValue> answer = new ArrayList<RevValue>(revisions.size());
      for (Map.Entry<Bytes, Bytes> rv : revisions.entrySet()) {
        answer.add(new RevValue(rv.getKey().toByteArray(), rv.getValue().toByteArray()));
      }

      return answer;
    } else {
      return null;
    }
  }

  @Override
  public RevValue getRevision(User user, byte[] key, byte[] revision) throws IOException {
    if (key == null) {
      return null;
    }

    Map<Bytes, Bytes> revisions = stores.get(user).get(Bytes.copyFrom(key));
    if (revisions != null) {
      Bytes value = revisions.get(Bytes.copyFrom(revision));
      if (value != null) {
        return new RevValue(revision, value.toByteArray());
      }
    }
    return null;
  }

  @Override
  public Collection<byte[]> getIndices(User user) {
    Set<Bytes> indices = stores.get(user).keySet();
    List<byte[]> answer = new ArrayList<byte[]>(indices.size());
    for (Bytes index : indices){
      answer.add(index.toByteArray());
    }
    return answer;
  }

  @Override
  public Collection<byte[]> getRevisions(User user, byte[] key) {
// TODO(beresford): check authority to carry out action
    if (key == null) {
      return null;
    }

    Map<Bytes, Bytes> revisions = stores.get(user).get(Bytes.copyFrom(key));
    if (revisions != null) {
      List<byte[]> answer = new ArrayList<byte[]>(revisions.size());
      for (Bytes rev : revisions.keySet()) {
        answer.add(rev.toByteArray());
      }

      return answer;
    } else {
      return null;
    }
  }

  @Override
  public boolean putRecord(User user, byte[] key, byte[] revision, byte[] value) {
    // TODO(beresford): check authority to carry out action
    if (key == null || revision == null || value == null) {
      return false;
    }
    Map<Bytes, Bytes> revisions = stores.get(user).get(Bytes.copyFrom(key));
    if (revisions == null) {
      revisions = new HashMap<Bytes, Bytes>();
      stores.get(user).put(Bytes.copyFrom(key), revisions);
    }
    Bytes bRevision = Bytes.copyFrom(revision);
    Bytes bValue = Bytes.copyFrom(value);
    Bytes existing = revisions.get(bRevision);
    if (existing == null) {
      revisions.put(bRevision, bValue);
    } else if (!existing.equals(bValue)) {
      return false;
    }
    return true;
  }
 
  @Override
  public boolean deleteRecord(User user, byte[] key) {
    //TODO(beresford): check authority to carry out action
    return stores.get(user).remove(Bytes.copyFrom(key)) != null;
  }

  @Override
  public UserFactory getUserFactory() {
    return JUser.Factory.getInstance();
  }

  @Override
  public boolean checkAndAddNonce(Nonce nonce, byte[] publicKey) {
    if (!nonce.isRecent()){
      return false;
    }
    Bytes pk = Bytes.copyFrom(publicKey);
    Set<Nonce> nonceSet = nonces.get(pk);
    if (nonceSet == null){
      nonceSet = new HashSet<Nonce>();
      nonces.put(pk,nonceSet);
    }
    if (nonceSet.contains(nonce))
      return false;
    else {
      nonceSet.add(nonce);
      return true;
    }
  }

  @Override
  public void clearOldNonces() {
    for (Set<Nonce> nonceSet : nonces.values()){
      Iterator<Nonce> nonceIterator = nonceSet.iterator();
      Nonce nonce;
      while (nonceIterator.hasNext()){
        nonce = nonceIterator.next();
        if (!nonce.isRecent()){
          nonceIterator.remove();
        }
      }
    }
  }

  private static class Bytes implements Serializable {
    private static final long serialVersionUID = 1L;

    private final byte[] bytes;

    private Bytes(byte[] bytes) {
      this.bytes = bytes;
    }

    /**
     * @param publicKey
     * @return
     */
    public static Bytes copyFrom(byte[] publicKey) {
      return new Bytes(Arrays.copyOf(publicKey, publicKey.length));
    }

    /**
     * @return
     */
    public byte[] toByteArray() {
      return bytes;
    }

    @Override
    public int hashCode() {
      final int prime = 31;
      int result = 1;
      result = prime * result + Arrays.hashCode(bytes);
      return result;
    }

    @Override
    public boolean equals(Object obj) {
      if (this == obj)
        return true;
      if (obj == null)
        return false;
      if (getClass() != obj.getClass())
        return false;
      Bytes other = (Bytes) obj;
      if (!Arrays.equals(bytes, other.bytes))
        return false;
      return true;
    }

  }
}
TOP

Related Classes of com.google.nigori.server.HashMapDatabase

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.