Package com.google.k2crypto.storage.driver.impl

Source Code of com.google.k2crypto.storage.driver.impl.K2MemoryDriver$MemorySpace

/*
* Copyright 2014 Google. Inc.
*
* 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.k2crypto.storage.driver.impl;

import static com.google.k2crypto.storage.driver.AddressUtilities.checkNoAuthority;
import static com.google.k2crypto.storage.driver.AddressUtilities.checkNoQuery;
import static com.google.k2crypto.storage.driver.AddressUtilities.checkNoFragment;
import static com.google.k2crypto.storage.driver.AddressUtilities.extractRawPath;

import com.google.k2crypto.Key;
import com.google.k2crypto.K2Context;
import com.google.k2crypto.KeyProto.KeyData;
import com.google.k2crypto.exceptions.InvalidKeyDataException;
import com.google.k2crypto.exceptions.UnregisteredKeyVersionException;
import com.google.k2crypto.storage.IllegalAddressException;
import com.google.k2crypto.storage.StoreException;
import com.google.k2crypto.storage.StoreIOException;
import com.google.k2crypto.storage.driver.ReadableDriver;
import com.google.k2crypto.storage.driver.Driver;
import com.google.k2crypto.storage.driver.DriverInfo;
import com.google.k2crypto.storage.driver.WritableDriver;

import java.net.URI;
import java.util.HashMap;
import java.util.Map;

/**
* K2-native in-memory (i.e. volatile) key storage driver.
*
* <p>This driver uses the normalized path component of the storage address
* to uniquely identify the memory slot for saving or loading the key. In other
* words, a key stored at a certain address can be retrieved at a later time
* as long as the same logical address is used. Stored keys are retained only
* for the lifetime of the Java virtual machine.
* <p>The driver accepts storage addresses only in the following format:
* {@code [mem:]{ANY LEGAL URI PATH}}
*
* @author darylseah@gmail.com (Daryl Seah)
*/
@DriverInfo(
    id = K2MemoryDriver.NATIVE_SCHEME,
    name = "K2 Native Memory Driver",
    version = "0.1")
public class K2MemoryDriver implements Driver, ReadableDriver, WritableDriver {
 
  /**
   * Name of the native scheme in use (also the identifier of the driver).
   */
  static final String NATIVE_SCHEME = "mem";
 
  // Memory space that will be shared among all driver instances
  private static final MemorySpace sharedMemorySpace = new MemorySpace();

  // Context for the current K2 session
  private K2Context context;

  // Address of the storage slot in the memory space
  private URI address;
 
  // Memory space associated with the current driver session
  private MemorySpace memSpace;
 
  /**
   * @see Driver#initialize(K2Context)
   */
  public void initialize(K2Context context) {
    this.context = context;
  }

  /**
   * @see Driver#open(java.net.URI)
   */
  public URI open(final URI address) throws IllegalAddressException {
    // Check for unsupported components in the address and scheme.
    // (we only accept a scheme + path + optional fragment)
    checkNoAuthority(address);
    checkNoQuery(address);
    checkNoFragment(address);
    checkScheme(address);
   
    // Extract normalized path
    String path = extractRawPath(address.normalize());
   
    // Reconstitute final address
    StringBuilder sb =
        new StringBuilder(2 + NATIVE_SCHEME.length() + path.length());
    sb.append(NATIVE_SCHEME).append(':');
    if (path.charAt(0) != '/') {
      sb.append('/');
    }
    sb.append(path);
    URI normAddress = URI.create(sb.toString());
    this.address = normAddress;   
   
    // Assign memory space to use (currently just shared among all instances)
    memSpace = sharedMemorySpace;
    return normAddress;
  }
 
  /**
   * Checks that there is no scheme or that the scheme is identical to the
   * driver identifier.
   * 
   * @param address Address to check.
   *
   * @throws IllegalAddressException if the address has an invalid scheme.
   */
  private void checkScheme(URI address) throws IllegalAddressException {
    String scheme = address.getScheme();
    if (scheme != null && !NATIVE_SCHEME.equalsIgnoreCase(scheme)) {
      // Unrecognized scheme
      throw new IllegalAddressException(
          address, IllegalAddressException.Reason.INVALID_SCHEME, null);
    }
  }
 
  /**
   * @see Driver#close()
   */
  public void close() {
    // Free resources.
    context = null;
    address = null;
    memSpace = null;
  }

  /**
   * @see ReadableDriver#isEmpty()
   */
  public boolean isEmpty() throws StoreException {
    return memSpace.isEmpty(address);
  }

  /**
   * @see WritableDriver#save(Key)
   */
  public void save(Key key) throws StoreException {
    KeyData data;
    try {
      data = key.buildData().build();
    } catch (RuntimeException ex) {
      throw new StoreIOException(
          StoreIOException.Reason.SERIALIZATION_ERROR, ex);
    }
    memSpace.save(address, data);
  }
 
  /**
   * @see ReadableDriver#load()
   */
  public Key load() throws StoreException {
    KeyData data = memSpace.load(address);
    if (data == null) {
      return null;
    }
    try {
      return new Key(context, data);
    } catch (InvalidKeyDataException ex) {
      throw new StoreIOException(
          StoreIOException.Reason.DESERIALIZATION_ERROR, ex);
    } catch (UnregisteredKeyVersionException ex) {
      throw new StoreIOException(
          StoreIOException.Reason.UNREGISTERED_KEY_VERSION, ex);
    }
  }
 
  /**
   * @see WritableDriver#erase()
   */
  public boolean erase() throws StoreException {
    return memSpace.erase(address);
  }
 
  /**
   * A memory-based key storage space.
   *
   * <p>All methods synchronize directly on the object for thread-safety.
   * Should be acceptable since it is private to the driver.   
   */
  private static final class MemorySpace {
    // Storage is simply a mapping from addresses to key proto data 
    private final Map<URI, KeyData> slots = new HashMap<URI, KeyData>();
   
    /** Back-end for {@code ReadableDriver#isEmpty()}. */
    synchronized boolean isEmpty(URI address) {
      return !slots.containsKey(address);
    }
   
    /** Back-end for {@code ReadableDriver#load()}. */
    synchronized KeyData load(URI address) {
      return slots.get(address);
    }

    /** Back-end for {@code WritableDriver#save(Key)}. */
    synchronized void save(URI address, KeyData data) {
      slots.put(address, data);
    }
   
    /** Back-end for {@code WritableDriver#erase()}. */
    synchronized boolean erase(URI address) {
      return slots.remove(address) != null;
    }
  } 
}
TOP

Related Classes of com.google.k2crypto.storage.driver.impl.K2MemoryDriver$MemorySpace

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.