1 19 package org.netbeans.mdr.persistence.memoryimpl; 20 21 import java.util.*; 22 import java.io.*; 23 24 import org.netbeans.mdr.persistence.*; 25 import org.netbeans.mdr.util.*; 26 27 29 34 public class StorageImpl implements Storage { 35 static final String PRIMARY_INDEX_NAME = "PI"; 36 private static final int INDEX_SINGLEVALUED = 1; 37 private static final int INDEX_MULTIVALUED = 2; 38 private static final int INDEX_ORDERED = 3; 39 40 private final HashMap maps = new HashMap(); 41 private final String storageId; 42 private final String fileName; 43 44 private PrimaryIndexImpl primaryIndex; 45 private int lastMofId = 0; 46 47 private Set newIndexes = new HashSet (); private HashMap removedIndexes = new HashMap (); 51 52 public StorageImpl(String name, String fileName) { 53 this.storageId = name; 54 this.fileName = fileName; 55 } 56 57 public void writeMOFID (OutputStream outputStream, MOFID mofid) throws StorageException { 58 try { 59 if (storageId.equals(mofid.getStorageID())) { 60 IOUtils.writeString(outputStream, null); 61 } else { 62 IOUtils.writeString(outputStream, mofid.getStorageID()); 63 } 64 IOUtils.writeLong(outputStream, mofid.getSerialNumber()); 65 } catch (IOException ioException) { 66 throw new StorageIOException (ioException); 67 } 68 } 69 70 public MOFID readMOFID (java.io.InputStream inputStream) throws StorageException { 71 try { 72 String storageId = IOUtils.readString(inputStream); 73 if (storageId == null) storageId = this.storageId; 74 long serial = IOUtils.readLong(inputStream); 75 return new MOFID(serial, storageId); 76 } catch (java.io.IOException ioException) { 77 throw new StorageIOException (ioException); 78 } 79 } 80 81 public synchronized void create(boolean replace, ObjectResolver resolver) throws StorageException { 83 if (fileName != null) { 84 if (!replace && exists()) { 85 throw new StorageBadRequestException("Storage already exists"); 86 } 87 new File(getName()).delete(); 88 } 89 createPrimaryIndex(); 90 } 91 92 public synchronized void close() throws StorageException { 93 shutDown(); 94 } 95 96 public synchronized boolean delete() throws StorageException { 97 return new File(getName()).delete(); 98 } 99 100 public String getName() { 101 return this.fileName + ".mem"; 102 } 103 104 public String getStorageId() { 105 return this.storageId; 106 } 107 108 public synchronized long getSerialNumber () { 109 return this.lastMofId++; 110 } 111 112 public synchronized boolean exists() throws StorageException { 113 return new File(getName()).exists(); 114 } 115 116 public synchronized void open(boolean createOnNoExist, ObjectResolver resolver) throws StorageException { 117 createPrimaryIndex(); 119 if (fileName != null) { 120 try { 121 if (!exists() && !createOnNoExist) { 122 throw new StorageBadRequestException("Storage " + getName() + " does not exist."); 123 } 124 125 InputStream is = new BufferedInputStream(new FileInputStream(getName())); 126 lastMofId = IOUtils.readInt(is); 127 String id = IOUtils.readString(is); 128 if (!storageId.equals(id)) { 129 throw new StoragePersistentDataException("Invalid storage id in the persistent file: " + id + " (expected: " + storageId + ")"); 130 } 131 primaryIndex.read(is); 132 int size = IOUtils.readInt(is); 133 for (int i = 0; i < size; i++) { 134 Streamable index; 135 switch (IOUtils.readInt(is)) { 136 case INDEX_SINGLEVALUED: 137 index = new SinglevaluedIndexImpl(); 138 break; 139 case INDEX_MULTIVALUED: 140 index = new MultivaluedOrderedIndexImpl(); 141 break; 142 case INDEX_ORDERED: 143 index = new MultivaluedOrderedIndexImpl(); 144 break; 145 default: 146 throw new StoragePersistentDataException("Unknown type of index."); 147 } 148 index.read(is); 149 maps.put(((Index) index).getName(), index); 150 } 151 } catch ( java.io.IOException e ) { 152 if (e instanceof java.io.FileNotFoundException && createOnNoExist) { 153 return; 154 } 155 throw (StorageIOException) Logger.getDefault().annotate(new StorageIOException(e), e); 156 } 157 } 158 } 160 161 public synchronized void objectStateWillChange(Object key) throws StorageException { 162 primaryIndex.willChange (key); 163 } 164 165 public synchronized void objectStateChanged(Object key) throws StorageException { 166 primaryIndex.changed (key); 167 } 168 169 public synchronized void rollBackChanges() throws StorageException { 170 Iterator iter = newIndexes.iterator(); 172 while (iter.hasNext()) { 173 maps.remove(iter.next()); 174 } 175 iter = removedIndexes.keySet().iterator(); 177 while (iter.hasNext()) { 178 String name = (String ) iter.next (); 179 maps.put (name, removedIndexes.get (name)); 180 } 181 182 iter = maps.entrySet().iterator(); 184 while (iter.hasNext()) { 185 Object index = ((Map.Entry)iter.next()).getValue(); 186 if (index instanceof SinglevaluedIndexImpl) 187 ((SinglevaluedIndexImpl) index).rollBackChanges(); 188 else if (index instanceof MultivaluedIndexImpl) 189 ((MultivaluedIndexImpl) index).rollBackChanges(); 190 } 191 primaryIndex.rollBackChanges(); 192 } 193 194 synchronized void serialize() throws StorageException { 195 if (fileName == null) { 196 throw new StorageBadRequestException("No storage file name specified"); 197 } 198 try { 199 OutputStream out = new BufferedOutputStream(new FileOutputStream(getName())); 200 IOUtils.writeInt(out, lastMofId); 201 IOUtils.writeString(out, storageId); 202 primaryIndex.write(out); 203 IOUtils.writeInt(out, maps.size()); 204 for (Iterator it = maps.values().iterator(); it.hasNext();){ 205 Index index = (Index) it.next(); 206 if (index instanceof SinglevaluedIndexImpl) { 207 out.write(INDEX_SINGLEVALUED); 208 } else if (index instanceof MultivaluedOrderedIndexImpl) { 209 out.write(INDEX_ORDERED); 210 } else if (index instanceof MultivaluedIndexImpl) { 211 out.write(INDEX_MULTIVALUED); 212 } else { 213 throw new DebugException("Invalid index class: " + index.getClass().getName()); 214 } 215 ((Streamable) index).write(out); 216 } 217 out.close(); 218 } catch (IOException e) { 219 throw (StorageIOException) Logger.getDefault().annotate(new StorageIOException(e), e); 220 } 221 } 222 223 public synchronized void shutDown() throws StorageException { 224 commitChanges(); 225 } 226 227 public synchronized void commitChanges() throws StorageException { 228 newIndexes.clear(); 229 removedIndexes.clear(); 230 231 Iterator iter = maps.entrySet().iterator(); 233 while (iter.hasNext()) { 234 Object index = ((Map.Entry)iter.next()).getValue(); 235 if (index instanceof SinglevaluedIndexImpl) 236 ((SinglevaluedIndexImpl) index).commitChanges(); 237 else if (index instanceof MultivaluedIndexImpl) 238 ((MultivaluedIndexImpl) index).commitChanges(); 239 } 240 primaryIndex.commitChanges(); 241 } 242 243 public synchronized SinglevaluedIndex getSinglevaluedIndex(String name) throws StorageException { 244 return (SinglevaluedIndex) getIndex(name); 245 } 246 247 public synchronized MultivaluedIndex getMultivaluedIndex(String name) throws StorageException { 248 return (MultivaluedIndex) getIndex(name); 249 } 250 251 public synchronized MultivaluedOrderedIndex getMultivaluedOrderedIndex(String name) throws StorageException { 252 return (MultivaluedOrderedIndex) getIndex(name); 253 } 254 255 public synchronized void dropIndex(String name) throws StorageException { 256 Object index = maps.remove(name); 257 if ((index != null) && !newIndexes.remove(name)) 258 removedIndexes.put (name, index); 259 } 260 261 private synchronized void addIndex(String name, Index index) throws StorageException { 262 maps.put(name, index); 263 newIndexes.add (name); 264 } 265 266 270 275 public synchronized SinglevaluedIndex createSinglevaluedIndex(String name,EntryType keyType,EntryType valueType) throws StorageException { 276 if (valueType.equals(EntryType.STREAMABLE)) { 277 throw new StorageBadRequestException("Cannot create another primary index with STREAMABLE value type."); 278 } 279 SinglevaluedIndex sm = new SinglevaluedIndexImpl(name, this, keyType, valueType); 280 addIndex(name, sm); 281 return sm; 282 } 283 284 289 public synchronized MultivaluedOrderedIndex createMultivaluedOrderedIndex(String name,EntryType keyType,EntryType valueType,boolean unique) throws StorageException { 290 MultivaluedOrderedIndex sm = new MultivaluedOrderedIndexImpl(name, this, keyType, valueType, unique); 291 addIndex(name, sm); 292 return sm; 293 } 294 295 300 public synchronized MultivaluedIndex createMultivaluedIndex(String name,EntryType keyType,EntryType valueType,boolean unique) throws StorageException { 301 MultivaluedIndex sm = new MultivaluedOrderedIndexImpl(name, this, keyType, valueType, unique); 302 addIndex(name, sm); 303 return sm; 304 } 305 306 309 public synchronized SinglevaluedIndex getPrimaryIndex() throws StorageException { 310 return this.primaryIndex; 311 } 312 313 315 private void createPrimaryIndex() throws StorageException { 316 this.primaryIndex = new PrimaryIndexImpl(this); 317 } 319 320 324 public synchronized Index getIndex(String name) throws StorageException { 325 return (Index) maps.get(name); 326 } 327 } 328 | Popular Tags |