alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

What this is

This file is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Other links

The source code

/*
 *                 Sun Public License Notice
 *
 * The contents of this file are subject to the Sun Public License
 * Version 1.0 (the "License"). You may not use this file except in
 * compliance with the License. A copy of the License is available at
 * http://www.sun.com/
 *
 * The Original Code is NetBeans. The Initial Developer of the Original
 * Code is Sun Microsystems, Inc. Portions Copyright 1997-2001 Sun
 * Microsystems, Inc. All Rights Reserved.
 */
package org.netbeans.mdr.persistence.memoryimpl;

import java.util.*;
import java.io.*;

import org.netbeans.mdr.persistence.*;
import org.netbeans.mdr.util.*;
import org.netbeans.mdr.util.IOUtils;

//import org.w3c.dom.*;

/** Default memory implementation of the Storage.
 * This implementation supports only one index with STORABLE values.
 * @author  Pavel Buzek, Martin Matula
 * @version
 */
public class StorageImpl implements Storage {
    static final String PRIMARY_INDEX_NAME = "PI";
    private static final int INDEX_SINGLEVALUED = 1;
    private static final int INDEX_MULTIVALUED = 2;
    private static final int INDEX_ORDERED = 3;

    private final HashMap maps = new HashMap();
    private final String storageId;
    private final String fileName;
    
    private PrimaryIndexImpl primaryIndex;
    private int lastMofId = 0;
    
    // variables related to transaction support
    private Set newIndexes = new HashSet (); // stores names of all new, still existing, indexes created during current transaction
    private HashMap removedIndexes = new HashMap (); // maps names to indexes created before the current transaction and dropped during the transaction
    
    /** Creates new StorageImpl */
    public StorageImpl(String name, String fileName) {
        this.storageId = name;
        this.fileName = fileName;
    }
    
    public void writeMOFID (OutputStream outputStream, MOFID mofid) throws StorageException {
        try {
            if (storageId.equals(mofid.getStorageID())) {
                IOUtils.writeString(outputStream, null);
            } else {
                IOUtils.writeString(outputStream, mofid.getStorageID());
            }
            IOUtils.writeLong(outputStream, mofid.getSerialNumber());
        } catch (IOException ioException) {
            throw new StorageIOException (ioException);
        }
    }
    
    public MOFID readMOFID (java.io.InputStream inputStream) throws StorageException {
        try {
            String storageId = IOUtils.readString(inputStream);
            if (storageId == null) storageId = this.storageId;
            long serial = IOUtils.readLong(inputStream);
            return new MOFID(serial, storageId);
        } catch (java.io.IOException ioException) {
            throw new StorageIOException (ioException);
        }
    }

    // used to pre-boot the storage
    public synchronized void create(boolean replace, ObjectResolver resolver) throws StorageException {
        if (fileName != null) {
            if (!replace && exists()) {
                throw new StorageBadRequestException("Storage already exists");
            }
            new File(getName()).delete();
        }
        createPrimaryIndex();
    }
    
    public synchronized void close() throws StorageException {
        shutDown();
    }
    
    public synchronized boolean delete() throws StorageException {
        return new File(getName()).delete();
    }
    
    public String getName() {
        return this.fileName + ".mem";
    }
    
    public String getStorageId() {
        return this.storageId;
    }
    
    public synchronized long getSerialNumber () {
        return this.lastMofId++;
    }
    
    public synchronized boolean exists() throws StorageException {
        return new File(getName()).exists();
    }
    
    public synchronized void open(boolean createOnNoExist, ObjectResolver resolver) throws StorageException {
//        Logger.getDefault().log("Reading storage from XML document ...");
        createPrimaryIndex();
        if (fileName != null) {
            try {
                if (!exists() && !createOnNoExist) {
                    throw new StorageBadRequestException("Storage " + getName() + " does not exist.");
                }

                InputStream is = new BufferedInputStream(new FileInputStream(getName()));
                lastMofId = IOUtils.readInt(is);
                String id = IOUtils.readString(is);
                if (!storageId.equals(id)) {
                    throw new StoragePersistentDataException("Invalid storage id in the persistent file: " + id + " (expected: " + storageId + ")");
                }
                primaryIndex.read(is);
                int size = IOUtils.readInt(is);
                for (int i = 0; i < size; i++) {
                    Streamable index;
                    switch (IOUtils.readInt(is)) {
                        case INDEX_SINGLEVALUED:
                            index = new SinglevaluedIndexImpl();
                            break;
                        case INDEX_MULTIVALUED:
                            index = new MultivaluedOrderedIndexImpl();
                            break;
                        case INDEX_ORDERED:
                            index = new MultivaluedOrderedIndexImpl();
                            break;
                        default:
                            throw new StoragePersistentDataException("Unknown type of index.");
                    }
                    index.read(is);
                    maps.put(((Index) index).getName(), index);
                }
            } catch ( java.io.IOException e ) {
                if (e instanceof java.io.FileNotFoundException && createOnNoExist) {
                    return;
                }
                throw (StorageIOException) Logger.getDefault().annotate(new StorageIOException(e), e);
            }
        }
//        Logger.getDefault().log("Finished reading document.");
    }
    
    public synchronized void objectStateWillChange(Object key) throws StorageException {
        primaryIndex.willChange (key);
    }
    
    public synchronized void objectStateChanged(Object key) throws StorageException {
        primaryIndex.changed (key);
    }
    
    public synchronized void rollBackChanges() throws StorageException {
        // drop all indexes created during the transaction
        Iterator iter = newIndexes.iterator();
        while (iter.hasNext()) {
            maps.remove(iter.next());
        }
        // restore all indexes existing before the transaction that have been removed by the transaction
        iter = removedIndexes.keySet().iterator();
        while (iter.hasNext()) {
            String name = (String) iter.next ();
            maps.put (name, removedIndexes.get (name));
        }

        // call rollback on all indexes
        iter = maps.entrySet().iterator();
        while (iter.hasNext()) {
            Object index = ((Map.Entry)iter.next()).getValue();
            if (index instanceof SinglevaluedIndexImpl)
                ((SinglevaluedIndexImpl) index).rollBackChanges();
            else if (index instanceof MultivaluedIndexImpl)
                ((MultivaluedIndexImpl) index).rollBackChanges();
        }
    }
    
    synchronized void serialize() throws StorageException {
        if (fileName == null) {
            throw new StorageBadRequestException("No storage file name specified");
        }
        try {
            OutputStream out = new BufferedOutputStream(new FileOutputStream(getName()));
            IOUtils.writeInt(out, lastMofId);
            IOUtils.writeString(out, storageId);
            primaryIndex.write(out);
            IOUtils.writeInt(out, maps.size());
            for (Iterator it = maps.values().iterator(); it.hasNext();){
                Index index = (Index) it.next();
                if (index instanceof SinglevaluedIndexImpl) {
                    out.write(INDEX_SINGLEVALUED);
                } else if (index instanceof MultivaluedOrderedIndexImpl) {
                    out.write(INDEX_ORDERED);
                } else if (index instanceof MultivaluedIndexImpl) {
                    out.write(INDEX_MULTIVALUED);
                } else {
                    throw new DebugException("Invalid index class: " + index.getClass().getName());
                }
                ((Streamable) index).write(out);
            }
            out.close();
        } catch (IOException e) {
            throw (StorageIOException) Logger.getDefault().annotate(new StorageIOException(e), e);
        }
    }
    
    public synchronized void shutDown() throws StorageException {
        commitChanges();
    }
    
    public synchronized void commitChanges() throws StorageException {
        newIndexes.clear();
        removedIndexes.clear();
        
        // call commit on all indexes
        Iterator iter = maps.entrySet().iterator();
        while (iter.hasNext()) {
            Object index = ((Map.Entry)iter.next()).getValue();
            if (index instanceof SinglevaluedIndexImpl)
                ((SinglevaluedIndexImpl) index).commitChanges();
            else if (index instanceof MultivaluedIndexImpl)
                ((MultivaluedIndexImpl) index).commitChanges();
        }
    }
    
    public synchronized SinglevaluedIndex getSinglevaluedIndex(String name) throws StorageException {
        return (SinglevaluedIndex) getIndex(name);
    }
    
    public synchronized MultivaluedIndex getMultivaluedIndex(String name) throws StorageException {
        return (MultivaluedIndex) getIndex(name);
    }
    
    public synchronized MultivaluedOrderedIndex getMultivaluedOrderedIndex(String name) throws StorageException {
        return (MultivaluedOrderedIndex) getIndex(name);
    }
    
    public synchronized void dropIndex(String name) throws StorageException {
        Object index = maps.remove(name);
        if ((index != null) && !newIndexes.remove(name))
            removedIndexes.put (name, index);            
    }
    
    private synchronized void addIndex(String name, Index index) throws StorageException {
        maps.put(name, index);        
        newIndexes.add (name);
    }
    
//    public boolean supportsMultipleStorableIndexes() throws StorageException {
//        return true;
//    }
    
    /** Creates SinglevaluedIndex.
     * @param name Singlevalued name of the index
     * @param type type of indexes values
     * @return created index
     */
    public synchronized SinglevaluedIndex createSinglevaluedIndex(String name,EntryType keyType,EntryType valueType) throws StorageException {
        if (valueType.equals(EntryType.STREAMABLE)) {
            throw new StorageBadRequestException("Cannot create another primary index with STREAMABLE value type.");
        }
        SinglevaluedIndex sm = new SinglevaluedIndexImpl(name, this, keyType, valueType);
        addIndex(name, sm);
        return sm;
    }
    
    /** Creates MultivaluedOrderedIndex.
     * @param name
     * @param type
     * @return
     */
    public synchronized MultivaluedOrderedIndex createMultivaluedOrderedIndex(String name,EntryType keyType,EntryType valueType,boolean unique) throws StorageException {
        MultivaluedOrderedIndex sm = new MultivaluedOrderedIndexImpl(name, this, keyType, valueType, unique);
        addIndex(name, sm);
        return sm;
    }
    
    /** Creates MultivaluedIndex.
     * @param name
     * @param type type of indexes values
     * @return created index
     */
    public synchronized MultivaluedIndex createMultivaluedIndex(String name,EntryType keyType,EntryType valueType,boolean unique) throws StorageException {
        MultivaluedIndex sm = new MultivaluedOrderedIndexImpl(name, this, keyType, valueType, unique);
        addIndex(name, sm);
        return sm;
    }
    
    /** Returns the primary index in this Storage. There is exactly one primary
     * index in every storage.
     */
    public synchronized SinglevaluedIndex getPrimaryIndex() throws StorageException {
        return this.primaryIndex;
    }
    
    /** Creates primary index. Primary index is SinglevaluedIndex with STREAMABLE valueType.
     */
    private void createPrimaryIndex() throws StorageException {
        this.primaryIndex = new PrimaryIndexImpl(this);
        //addIndex(PRIMARY_INDEX_NAME, this.primaryIndex);
    }
    
    /** Retrieve index by name.
     * @param name name of the index
     * @return index of the specified name
     */
    public synchronized Index getIndex(String name) throws StorageException {
        return (Index) maps.get(name);
    }
}
... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.