1 /*
   2  * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package org.openjdk.jigsaw;
  27 
  28 import java.io.Closeable;
  29 import java.io.File;
  30 import java.io.IOException;
  31 import java.security.AccessController;
  32 import java.security.PrivilegedAction;
  33 
  34 // Not really a java.util.TreeMap ...
  35 
  36 public class PersistentTreeMap implements Closeable {
  37 
  38     private final long db;
  39     private final boolean readOnly;
  40 
  41     protected PersistentTreeMap(long db) {
  42         this(db, true);
  43     }
  44 
  45     protected PersistentTreeMap(long db, boolean readOnly) {
  46         this.db = db;
  47         this.readOnly = readOnly;
  48     }
  49 
  50     private static native long create0(String f) throws IOException;
  51 
  52     //creates file is doesn't exist, truncates, document.
  53     public static PersistentTreeMap create(File f) throws IOException {
  54         return new PersistentTreeMap(create0(f.getPath()), false);
  55     }
  56 
  57     private static native long open0(String f) throws IOException;
  58 
  59     public static PersistentTreeMap open(File f) throws IOException {
  60         return new PersistentTreeMap(open0(f.getPath()));
  61     }
  62 
  63     private native void put0(long db, String k, String v)
  64         throws IOException;
  65 
  66     // overwrites existing value, if there is one
  67     public void put(String key, String value) throws IOException {
  68         if (readOnly)
  69             throw new IOException("attempt to modify a read-only database");
  70 
  71         put0(db, key, value);
  72     }
  73 
  74     private native String get0(long db, String k)
  75         throws IOException;
  76 
  77     // null if key not found
  78     public String get(String key) throws IOException {
  79         return get0(db, key);
  80     }
  81 
  82     private native void put1(long db, String k, int v)
  83         throws IOException;
  84 
  85     // overwrites existing value, if there is one
  86     public void put(String key, int value) throws IOException {
  87         if (readOnly)
  88             throw new IOException("attempt to modify a read-only database");
  89 
  90         put1(db, key, value);
  91     }
  92 
  93     private native int get1(long db, String k)
  94         throws IOException;
  95 
  96     // Returns -1 if key not found
  97     public int getInt(String key) throws IOException {
  98         return get1(db, key);
  99     }
 100 
 101     private native void put2(long db, String k, String sv, int iv)
 102         throws IOException;
 103 
 104     // overwrites existing value, if there is one
 105     public void put(String key, String sval, int ival) throws IOException {
 106         if (readOnly)
 107             throw new IOException("attempt to modify a read-only database");
 108 
 109         put2(db, key, sval, ival);
 110     }
 111 
 112     public static class StringAndInt {
 113         public final String s;
 114         public final int i;
 115         public StringAndInt(String s, int i) {
 116             this.s = s;
 117             this.i = i;
 118         }
 119     }
 120 
 121     private native boolean get2(long db, String k, String[] svala, int[] ivala)
 122         throws IOException;
 123 
 124     // This is simpler than hassling with creating the result object
 125     // directly in JNI
 126 
 127     private String[] svala = new String[1];
 128     private int[] ivala = new int[1];
 129 
 130     // null if key not found
 131     public synchronized StringAndInt getStringAndInt(String key)
 132         throws IOException
 133     {
 134         if (!get2(db, key, svala, ivala))
 135             return null;
 136         return new StringAndInt(svala[0], ivala[0]);
 137     }
 138 
 139     private native void close0(long db) throws IOException;
 140 
 141     @Override
 142     public void close() throws IOException {
 143         close0(db);
 144     }
 145     
 146     private static native void initialize();
 147     
 148     static {
 149         initialize();
 150     }
 151 }