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.storagemodel;

import org.netbeans.mdr.NBMDRepositoryImpl;
import org.netbeans.mdr.handlers.BaseObjectHandler;
import org.netbeans.mdr.persistence.*;
import org.netbeans.mdr.util.*;
import javax.jmi.model.ModelElement;
import javax.jmi.model.ModelPackage;
import javax.jmi.model.NameNotFoundException;
import javax.jmi.model.Namespace;
import javax.jmi.reflect.*;
import java.io.IOException;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.lang.ref.Reference;
import java.lang.reflect.Constructor;
import java.util.*;

/**
 * Instances of MdrStorage create and wrap {@link
 * org.netbeans.mdr.persistence.Storage storages}. The latter are generic
 * indexed object databases, the former add MDR specific functionality.
 * An instance of MdrStorage mediates between one or more storages and
 * a {@link org.netbeans.mdr.NBMDRepositoryImpl repository}. It creates and
 * manages all the indices specific for MDR repositories.
 *
 * 

There is one boot storage. Further storages may be mounted and unmounted * additionally. * * @author Petr Hrebejk, Pavel Buzek, Martin Matula * @version */ public class MdrStorage implements MOFConstants, ObjectResolver { /* -------------------------------------------------------------------- */ /* -- Private static constants ---------------------------------------- */ /* -------------------------------------------------------------------- */ private static final int STORAGE_VERSION = 24; // names of global storage indexes static final String IDX_OBJECTS_BY_CLASSES = "ObjectsByClasses"; private static final String IDX_MDR_STORAGE_PROPERTIES = "Properties"; private static final String IDX_END1_CLASSES_BY_ASSOCIATIONS = "End1ClassesByAssociations"; private static final String IDX_END2_CLASSES_BY_ASSOCIATIONS = "End2ClassesByAssociations"; private static final String IDX_CONTEXTS = "Contexts"; // prefixes for context-specific indexes private static final String PREFIX_ATTR_INDEX = "ai:"; private static final String PREFIX_ATTR_INDEXES_BY_NAME = "aibn:"; private static final String PREFIX_ATTR_INDEXES_CLASS_PROXY = "aicp:"; private static final String PREFIX_ASSOC_END = "ae:"; /** name of storage property which holds MOFID of outermost package * representing the first meta layer (MOF) */ public static final String MOF_TOP_PACKAGE = "TOPMOST_PACKAGE"; /** name of storage property which holds ID of cached values */ public static final String VALUES_ID = "VALUES_ID"; /** instances of MdrStorage by storage ID */ private static final Hashtable instances = new Hashtable(); private InstanceMap externalObjects = null; // private static MdrStorage currentMdrStorage = null; // private static Storage currentStorage = null; /* -------------------------------------------------------------------- */ /* -- Static methods -------------------------------------------------- */ /* -------------------------------------------------------------------- */ /** Returns instance wrapping the given storage * @param storage * @return MdrStorage wrapping storage */ public static MdrStorage getInstance(Storage storage) { MdrStorage result = (MdrStorage) instances.get(storage); // if (result == null) result = currentMdrStorage; return result; } public void registerExternal(StorableBaseObject storable) { if (externalObjects == null) { externalObjects = new InstanceMap(); } externalObjects.put(storable.getMofId(), storable); } public void removeExternal(StorableBaseObject storable) { if (externalObjects != null) { externalObjects.remove(storable.getMofId()); } } private StorableBaseObject getExternal(MOFID mofId) { StorableBaseObject result = null; if (externalObjects != null) { result = (StorableBaseObject) externalObjects.get(mofId); } return result; } /* -------------------------------------------------------------------- */ /* -- Private attributes ---------------------------------------------- */ /* -------------------------------------------------------------------- */ /** reference to implementation of Storage interface (the "real" storage) */ // private Storage storage; /** reference to implementation of {@link org.netbeans.mdr.persistence.Storage} * interface (the "real" boot storage) */ private Storage bootStorage; private org.netbeans.mdr.persistence.MOFID bootNullMofId; /** Boot storage and all partition storages used by * this MdrStorage instance, hashed by storageId */ private HashMap storages; /** cached value of storage's NULL MOFID */ // private String nullMofId; private HashMap nullMofId; // references to global storage indexes // primary index // private SinglevaluedIndex objects; /** HashMap containing the primary indices, * storing the objects to make them accessible by ID. * This are the only indices having objects as values, all other indices * have IDs as values. */ private HashMap objects; // IDX_OBJECTS_BY_CLASSES // private MultivaluedIndex objByCls; /** Multi-valued indices making instance IDs accessible by class proxy ID. */ private HashMap objByCls; // IDX_CONTEXTS // private SinglevaluedIndex contexts; /** Singe-valued indices making contexts (references to outermost * package extents) accessible by name. */ private HashMap contexts; // IDX_MDR_STORAGE_PROPERTIES // private SinglevaluedIndex properties; /** Single-valued indices making property IDs accessible by name. */ private HashMap properties; // IDX_END1_CLASSES_BY_ASSOCIATIONS // private SinglevaluedIndex associationsEnd1; // IDX_END2_CLASSES_BY_ASSOCIATIONS // private SinglevaluedIndex associationsEnd2; //private ValuesObject valuesObject; // Should be stored into the storage where the metamodel is stored /** * */ private HashMap valuesObjects; // to ensure that all the partitions see it. /** * The repository. */ private final NBMDRepositoryImpl repository; /** Mutex for transaction locks. */ private final TransactionMutex repositoryMutex; /** Mutex for transaction locks. */ private final EventNotifier eventNotifier; /* -- Transient support ---*/ private org.netbeans.mdr.storagemodel.transientimpl.TransientStorage transientStorage; /* -- boot specific stuff --------------------------------------------- */ /** * Determines whether the storage is ready or not. */ private boolean booting; /** boot class proxies */ private Collection bootClasses = null; /** boot instances */ private Collection bootObjects = null; /** boot association proxies */ private Collection bootAssociations = null; private volatile boolean silent = false; /* -------------------------------------------------------------------- */ /* -- Setters/Getters (public) ---------------------------------------- */ /* -------------------------------------------------------------------- */ public TransactionMutex getRepositoryMutex() { return repositoryMutex; } public EventNotifier getEventNotifier() { return eventNotifier; } public NBMDRepositoryImpl getRepository() { return repository; } /** * Announce that this storage is being booted. Only the storage which holds * the MOF metamodel should be called with `true' as argument. */ public void setBooting(boolean flag) { this.booting = flag; } public boolean isBooting() { return this.booting; } public void enableEvents() { silent = false; } public void disableEvents() { silent = true; } public boolean eventsEnabled() { return !silent; } /* -------------------------------------------------------------------- */ /* -- Constructor (public) -------------------------------------------- */ /* -------------------------------------------------------------------- */ /** Creates a new MdrStorage using factory storageClass * and parameters properties. Creates a default storage, if the * storageClass is not a * {@link org.netbeans.mdr.persistence.StorageFactory} or cannot be instantiated. * * @param repository * @param storageClass fully qualified name of class implementing * {@link org.netbeans.mdr.persistence.StorageFactory} * @param properties parameters for storage creation * @exception DebugException if the storage cannot be created */ public MdrStorage(NBMDRepositoryImpl repository, String storageClass, Map properties) { this.storages = new HashMap(); this.nullMofId = new HashMap(); this.objects = new HashMap(); this.objByCls = new HashMap(); this.contexts = new HashMap(); this.properties = new HashMap(); this.valuesObjects = new HashMap(); this.repository = repository; StorageFactory storageFactory = null; try { // try to instantiate storage factory (its class name was passed as storageClass argument) Class storageFactoryClass = Class.forName(storageClass); // does the class implement StorageFactory interface? if (StorageFactory.class.isAssignableFrom(storageFactoryClass)) { // yes - create new instance storageFactory = (StorageFactory) storageFactoryClass.newInstance(); } else { // no - throw exception // (this exception will not be propagated - it will be caught immediately - see following lines) throw new Exception("class "+storageClass+" does not implement StorageFactory"); } } catch (Exception e) { // in case the passed StorageFactory class could not be created, create default implementation // of StorageFactory interface Logger.getDefault().notify(Logger.INFORMATIONAL, e); Logger.getDefault().log("using: org.netbeans.mdr.persistence.memoryimpl.StorageFactoryImpl"); storageFactory = new org.netbeans.mdr.persistence.memoryimpl.StorageFactoryImpl(); } try { // create storage passing the parameters to the factory method this.bootStorage = storageFactory.createStorage(properties); // cache the NULL MOFID of the boot storage this.bootNullMofId = storageFactory.createNullMOFID(); } catch (StorageException e) { throw (DebugException) Logger.getDefault().annotate(new DebugException("Failed accessing storage factory."), e); } // create the utilities for storage management eventNotifier = new EventNotifier(); String mutexClass = (String) properties.get("mutexClass"); TransactionMutex mutex = null; if (mutexClass != null) { try { Constructor mutexConstructor = BaseObjectHandler.resolveImplementation(mutexClass).getConstructor(new Class[] {Object.class, Object.class, Object.class}); mutex = (TransactionMutex) mutexConstructor.newInstance(new Object[] {this, eventNotifier, repository}); } catch (Exception e) { Logger.getDefault().notify(Logger.INFORMATIONAL, e); } } if (mutex == null) { mutex = new MultipleReadersMutex(this, eventNotifier, repository); } repositoryMutex = mutex; } /* -------------------------------------------------------------------- */ /* -- (Un)mounting additional storages -------------------------------- */ /* -------------------------------------------------------------------- */ /** * Mounts a new storage, adding it to the collection of all storages * managed by this MdrStorage. * * @param storageFactoryClass the name of factory class * @param properties the storage creation parameter * @return the storage ID of the newly created storages or null * of storageFactoryClass does not implement {@link * org.netbeans.mdr.persistence.Storage} * @exception StorageException * @exception InstantiationException * @exception IllegalAccessException * @exception ClassNotFoundException if storageFactoryClass is * not a valid class name */ public String mountStorage(String storageFactoryClass, Map properties) throws StorageException, InstantiationException, ClassNotFoundException, IllegalAccessException { return this.mountStorage(Class.forName(storageFactoryClass), properties); } /** * Mounts a new storage, adding it to the collection of all storages * managed by this MdrStorage. * * @param storageFactoryClass the factory class * @param properties the storage creation parameter * @return the storage ID of the newly created storages or null * of storageFactoryClass does not implement {@link * org.netbeans.mdr.persistence.Storage} * @exception StorageException * @exception InstantiationException * @exception IllegalAccessException */ public String mountStorage(Class storageFactoryClass, Map properties) throws StorageException, InstantiationException, IllegalAccessException { if (StorageFactory.class.isAssignableFrom(storageFactoryClass)) { StorageFactory storageFactory = (StorageFactory) storageFactoryClass.newInstance(); Storage st = storageFactory.createStorage(properties); org.netbeans.mdr.persistence.MOFID nullMofId = storageFactory.createNullMOFID(); this.init(st,nullMofId, false); return st.getStorageId(); } return null; } /** * Unmounts the storage with ID storageId. Does nothing * if storageId is not a valid storage ID. * * @param storageId the storage to be unmounted * @exception StorageException */ public void unmountStorage(String storageId) throws StorageException { Storage selStorage = (Storage) this.storages.get(storageId); if (selStorage == null) return; selStorage.shutDown(); this.instances.remove(selStorage); this.nullMofId.remove(storageId); this.objects.remove(storageId); this.objByCls.remove(storageId); this.contexts.remove(storageId); this.storages.remove(storageId); } /* -------------------------------------------------------------------- */ /* -- Methods for initialization and reinitialization (public/private) */ /* -------------------------------------------------------------------- */ /** Initializes MdrStorage instance. * This method is called by the {@link org.netbeans.mdr.NBMDRepositoryImpl repository} * during its initialization. It initializes resp. creates the boot storage. * * @return returns true if the storage file exists; false * if the storage is new and needs to be booted * @throws StorageException unexpected problem in storage * @see #init(Storage, String, boolean) */ public boolean init() throws StorageException { return this.init(this.bootStorage, this.bootNullMofId, true); } /** * Initializes the {@link org.netbeans.mdr.persistence.Storage} * storage. * *

Storage initialization consists in: *

    *
  1. the storage is opened
  2. *
  3. the indices are initialized
  4. *
  5. true is returned to indicate that the storage is * ready
  6. *
* *

Storage creation consists in: *

    *
  1. the storage is created resp. recreated (the latter, if it was * corrupted)
  2. *
  3. the indices are created
  4. *
  5. the properties are initialized
  6. *
  7. false is returned to indicate the need to boot the * storage
  8. *
* * @param storage the storage to be initialized * @param nullMofId * @param defaultStorage true, if the boot storage is * to be initialized, false otherwise * @return returns false * if the storage is new and needs to be booted * @throws StorageException unexpected problem in storage */ public boolean init(Storage storage, org.netbeans.mdr.persistence.MOFID nullMofId, boolean defaultStorage) throws StorageException { // NOTE: no synchronization is needed in this method, it will be invoked as a part of synchronized code // (whole storage initialization and boot will be synchronized in upper level: // synchronized void NBMDRepository.initCheck()) // QUESTION: how is NBMDRepository.mountStorage(..) synchronized ? boolean result; String storageId = null; try { // try to open the storage (if open fails, exception is thrown and program continues in catch block // currentMdrStorage = this; // currentStorage = storage; storage.open(true, this); // currentStorage = null; // currentMdrStorage = null; storageId = storage.getStorageId(); // read indexes initializeIndexes(storage, defaultStorage, false); // everything succeeded -> return true result = true; } catch (Exception e) { if (e instanceof StorageException) { Logger.getDefault().notify(Logger.INFORMATIONAL, e); } Logger.getDefault().log("Rebooting storage. Reason: " + e); // storage not found or corrupted -> create new one try { // in case the storage is already open, try to close it storage.close(); } catch (StorageException ex) { } // create a new storage storage.create(true, this); storageId = storage.getStorageId(); // get the primary index SinglevaluedIndex objectsIndex = storage.getPrimaryIndex(); objects.put(storageId, objectsIndex); // create all global indexes contexts.put(storageId, storage.createSinglevaluedIndex(IDX_CONTEXTS + STORAGE_VERSION, Storage.EntryType.STRING, Storage.EntryType.MOFID)); objByCls.put(storageId, storage.createMultivaluedIndex(IDX_OBJECTS_BY_CLASSES, Storage.EntryType.MOFID, Storage.EntryType.MOFID, false)); // it is not effective to set this index as unique, although it is SinglevaluedIndex propertiesIndex = storage.createSinglevaluedIndex(IDX_MDR_STORAGE_PROPERTIES, Storage.EntryType.STRING, Storage.EntryType.MOFID); propertiesIndex.put(MODEL_ASSOCIATION_END, nullMofId); propertiesIndex.put(MODEL_ATTRIBUTE, nullMofId); propertiesIndex.put(MODEL_REFERENCE, nullMofId); propertiesIndex.put(MODEL_OPERATION, nullMofId); MOFID valuesID = new MOFID (storage); propertiesIndex.put(VALUES_ID, valuesID); this.properties.put(storageId, propertiesIndex); ValuesObject valuesObject = new ValuesObject(storage, valuesID); this.valuesObjects.put(storageId, valuesObject); objectsIndex.add(valuesID, valuesObject); storage.objectStateChanged(valuesID); // storage has to be booted -> return false result = ! defaultStorage; } // register this storage instance into the table of instances instances.put(storage, this); this.nullMofId.put(storageId, nullMofId); this.storages.put(storageId, storage); return result; } /** * Initializes the references to global storage indices. * * @throws DebugExceptions if any of the global indices was not found or * */ private void initializeIndexes(Storage storage, boolean defaultStorage, boolean rollBack) { try { // get the primary index String storageId = storage.getStorageId(); SinglevaluedIndex objectsIndex = storage.getPrimaryIndex(); MultivaluedIndex objByClsIndex = storage.getMultivaluedIndex(IDX_OBJECTS_BY_CLASSES); SinglevaluedIndex contextsIndex = storage.getSinglevaluedIndex(IDX_CONTEXTS + STORAGE_VERSION); if (objByClsIndex==null || objectsIndex==null || contextsIndex==null) { throw new DebugException("Missing storage files or different storage version."); } if (!defaultStorage && !rollBack && !silent) { // Fire events for adding all extents for (Iterator it = contextsIndex.keySet().iterator(); it.hasNext();) { String extentName = (String) it.next(); org.netbeans.api.mdr.events.ExtentEvent event = new org.netbeans.api.mdr.events.ExtentEvent(this.repository, org.netbeans.api.mdr.events.ExtentEvent.EVENT_EXTENT_CREATE, extentName, null, null,false); this.getEventNotifier().REPOSITORY.firePlannedChange(this, event); } } this.objects.put(storageId, objectsIndex); this.contexts.put(storageId, contextsIndex); this.objByCls.put(storageId, objByClsIndex); SinglevaluedIndex props = storage.getSinglevaluedIndex(IDX_MDR_STORAGE_PROPERTIES); if (props == null) { throw new DebugException("Different storage version."); } this.properties.put(storageId, props); this.valuesObjects.put(storageId, objectsIndex.get(props.get(VALUES_ID))); } catch (StorageException e) { throw new DebugException("Missing storage files or different storage version."); } } /* -------------------------------------------------------------------- */ /* -- Transaction related methods (public) ---------------------------- */ /* -------------------------------------------------------------------- */ /** * Commits (saves) storage changes. */ public void commit() throws StorageException { save(); } /** * Rolls back storage changes. */ public synchronized void rollback() throws StorageException { for (Iterator it = this.storages.values().iterator(); it.hasNext();) { Storage storage = (Storage) it.next(); // it.remove(); storage.rollBackChanges(); // reinitialize the global indices if (storage != transientStorage) initializeIndexes(storage, storage == this.bootStorage, true); } } /** Commits changes to the storage. * @throws StorageException problem in storage */ public synchronized void save() throws StorageException { /* synchronized (valuesObject) { storage.objectStateChanged(getProperty(VALUES_ID)); } */ for (Iterator it = this.storages.values().iterator(); it.hasNext();) { Storage storage = (Storage) it.next(); // it.remove (); storage.commitChanges(); } } /** * Notifies storage about shutDown. * @throws StorageException problem in storage */ public void shutDown() throws StorageException { try { for (Iterator it = this.storages.values().iterator(); it.hasNext();) { Storage s = (Storage)it.next(); s.shutDown(); repository.notifyShutdownStep(); } } finally { eventNotifier.shutdown(); repository.notifyShutdownStep(); } } public int getShutdownSteps() { return storages.size() + 1; } /* -------------------------------------------------------------------- */ /* -- Storage properties accessors & mutators ------------------------- */ /* -------------------------------------------------------------------- */ /** Returns value of the specified boot storage property. * @param key property name * @return value of property of the specified name (an MOF ID) */ org.netbeans.mdr.persistence.MOFID getProperty(String key) { return this.getProperty(this.bootStorage.getStorageId(),key); } /** Returns value of the specified storage property. * @param storageId the ID of the {@link * org.netbeans.mdr.persistence.Storage} a property of which has to be * returned * @param key property name * @return value of property of the specified name (an MOF ID) * @exception DebugException if there is not storage with the given ID */ org.netbeans.mdr.persistence.MOFID getProperty(String storageId, String key) { try { SinglevaluedIndex propertiesIndex = this.getPropertiesIndexByStorageId(storageId); if (propertiesIndex == null) throw new DebugException("No such storage"); return (org.netbeans.mdr.persistence.MOFID) propertiesIndex.get(key); } catch (StorageException e) { throw (DebugException) Logger.getDefault().annotate(new DebugException(), e); } } /** Sets value of the specified property in the boot storage. * @param key property name * @param value new property value (an MOF ID) */ void setProperty(String key, org.netbeans.mdr.persistence.MOFID value) { this.setProperty(this.bootStorage.getStorageId(), key, value); } /** Sets value of the specified property. * @param storageId the ID of the {@link * org.netbeans.mdr.persistence.Storage} a property of which has to be * set * @param key property name * @param value new property value (an MOF ID) * @exception DebugException if there is not storage with the given ID */ void setProperty(String storageId, String key, org.netbeans.mdr.persistence.MOFID value) { try { SinglevaluedIndex propertiesIndex = this.getPropertiesIndexByStorageId(storageId); if (propertiesIndex == null) throw new DebugException("No such storage"); propertiesIndex.put(key, value); } catch (StorageException e) { throw (DebugException) Logger.getDefault().annotate(new DebugException(), e); } } /** * @return */ /* SinglevaluedIndex properties { return properties; } */ /* -------------------------------------------------------------------- */ /* -- ValuesObject accessors ------------------------------------------- */ /* -------------------------------------------------------------------- */ public ValuesObject values(org.netbeans.mdr.persistence.MOFID mofId) { String storageId = getStorageIdFromMofId(mofId); return this.storageValues(storageId); } public ValuesObject storageValues(String storageId) { if (storageId == null) { storageId = this.bootStorage.getStorageId(); } return (ValuesObject) valuesObjects.get(storageId); } /* -------------------------------------------------------------------- */ /* -- Primary index accessors ------------------------------------------- */ /* -------------------------------------------------------------------- */ /** Gets object from primary index. * @param mofid MOFID of object to be found or null * @return object with specified mofid or null if no MOF ID was * given (method called with null argument) * @throws StorageException object with specified MOFID was not found or other problem in storage */ public StorableBaseObject getObject(org.netbeans.mdr.persistence.MOFID mofid) throws StorageException { if (mofid == null) return null; StorableBaseObject result = getExternal(mofid); if (result == null) { SinglevaluedIndex objectsIndex = getObjectsIndexByMofId(mofid); if (objectsIndex == null) return null; // Partition was not found synchronized (getStorageById(mofid.getStorageID())) { result = (StorableBaseObject) objectsIndex.getIfExists(mofid); } } return result; } /** Gets object from a singlevalued index using primary index. * @param index singlevalued index containing reference to object to be returned * @param key key under which the reference is stored in the index * @throws StorageException problem in storage * @return searched object */ public StorableBaseObject getObjectFromIndexIfExists(SinglevaluedIndex index, Object key) throws StorageException { Object mofId = index.getIfExists(key); if (!(mofId instanceof org.netbeans.mdr.persistence.MOFID)) return null; else return getObject((org.netbeans.mdr.persistence.MOFID) mofId); } /** Retrieves collection of objects from a multivalued index using primary index. * @param index multivalued index to be searched in * @param key key under which the searched collection is stored * @throws StorageException problem in storage * @return collection of objects corresponding to the supplied key */ public Collection getObjectsFromIndex(MultivaluedIndex index, Object key) throws StorageException { SinglevaluedIndex objectsIndex = this.getObjectsIndexByMofId((org.netbeans.mdr.persistence.MOFID)key); if (objectsIndex == null) throw new DebugException("Invalid key"); synchronized (getStorageById(((org.netbeans.mdr.persistence.MOFID) key).getStorageID())) { if (index instanceof MultivaluedOrderedIndex) { return ((MultivaluedOrderedIndex) index).getObjectsOrdered(key, objectsIndex); } else { return index.getObjects(key, objectsIndex); } } } /** Adds object to the primary index using its MOF ID. * @param object object to be added * @throws StorageException problem in the storage */ void addObject (StorableBaseObject object) throws StorageException { org.netbeans.mdr.persistence.MOFID mofId = object.getMofId(); SinglevaluedIndex objectsIndex = getObjectsIndexByMofId(mofId); if (objectsIndex == null) { throw new DebugException("Storage not found"); } objectsIndex.add(mofId, object); } /** * Removes object from the primary index. * @param object the object to be removed */ void removeObject(StorableBaseObject object) throws StorageException { org.netbeans.mdr.persistence.MOFID mofId = object.getMofId(); this.removeObject (mofId); } void removeObject (org.netbeans.mdr.persistence.MOFID mofId) throws StorageException { SinglevaluedIndex objectsIndex = (SinglevaluedIndex) this.getObjectsIndexByMofId(mofId); if (objectsIndex == null) { throw new DebugException("Storage not found"); } objectsIndex.remove(mofId); } /** Adds object to the primary index and associates the object with its * class proxy. * @param object object to be added * @throws StorageException problem in the storage */ void addInstance(StorableObject object) throws StorageException { addObject(object); org.netbeans.mdr.persistence.MOFID mofId = object.getMofId(); String storageId = getStorageIdFromMofId(mofId); if (storageId == null) { throw new DebugException("Invalid MOF ID"); } MultivaluedIndex objByClsIndex = (MultivaluedIndex) objByCls.get(storageId); if (objByClsIndex == null) { throw new DebugException("Storage not found"); } objByClsIndex.add(object.getClassProxyId(), mofId); } /** * Removes object from the primary index and dissolves the association with * its class proxy. * @param object the object to be removed */ void removeInstance(StorableObject object) throws StorageException { org.netbeans.mdr.persistence.MOFID mofId = object.getMofId(); org.netbeans.mdr.persistence.MOFID classProxyMofId = object.getClassProxyId(); this.removeInstance (mofId, classProxyMofId); } void removeInstance (org.netbeans.mdr.persistence.MOFID mofId, org.netbeans.mdr.persistence.MOFID classProxyMofId) throws StorageException { removeObject(mofId); MultivaluedIndex objByClsIndex = this.getObjectsByClassesByMofId (mofId); if (objByClsIndex == null) { throw new DebugException("Storage not found"); } objByClsIndex.remove( classProxyMofId, mofId); } /** * Returns the index associating class proxy IDs with instance IDs. * * @param classProxy a class proxy of the storage owning the index * requested */ public MultivaluedIndex getInstancesIndex(StorableClass classProxy) { return this.getInstancesIndex(classProxy.getMofId()); } /** * Returns the index associating class proxy IDs with instance IDs. * * @param classProxyId the MOF ID a class proxy of the storage owning the index * requested */ public MultivaluedIndex getInstancesIndex(org.netbeans.mdr.persistence.MOFID classProxyId) { String storageId = getStorageIdFromMofId(classProxyId); if (storageId == null) { throw new DebugException("Invalid MOF ID"); } MultivaluedIndex objByClsIndex = (MultivaluedIndex) objByCls.get(storageId); if (objByClsIndex == null) { throw new DebugException("Storage not found"); } return objByClsIndex; } /** * Returns the instances for the class proxy with the given ID. * * @param classID the ID of a class proxy */ public Collection getInstancesIds(org.netbeans.mdr.persistence.MOFID classProxyId) throws StorageException { String storageId = getStorageIdFromMofId(classProxyId); if (storageId == null) { throw new DebugException("Invalid MOF ID"); } MultivaluedIndex objByClsIndex = (MultivaluedIndex) objByCls.get(storageId); if (objByClsIndex == null) { throw new DebugException("Storage not found"); } return objByClsIndex.getItems(classProxyId); } // CONTEXT MANIPULATION METHODS //////////////////////////////////////////////// /** Creates a new context (reference to outermost package extent). * This includes creation of context specific indexes needed for the new context. * @param name name of the new context * @param mofId MOF ID of the outermost package in the context * @throws StorageException problem in storage */ void createContext(String name, org.netbeans.mdr.persistence.MOFID mofId) throws StorageException { String storageId = getStorageIdFromMofId(mofId); if (storageId == null) { throw new DebugException("Invalid MOF ID"); } Storage storage = (Storage) this.storages.get(storageId); if (storage == null) { throw new DebugException("Storage not found"); } // create set of context specific indexes storage.createSinglevaluedIndex(PREFIX_ATTR_INDEXES_BY_NAME + mofId.getSerialNumber(), Storage.EntryType.STRING, Storage.EntryType.STRING); storage.createSinglevaluedIndex(PREFIX_ATTR_INDEXES_CLASS_PROXY + mofId.getSerialNumber(), Storage.EntryType.STRING, Storage.EntryType.MOFID); // add context to the index of contexts if (name != null) { SinglevaluedIndex contextsIndex = (SinglevaluedIndex) this.contexts.get(storageId); if (contextsIndex == null) { throw new DebugException("Storage not found"); } contextsIndex.put(name, mofId); } } /** Deletes the specified context (reference to outermost package extent) from the storage. * This includes deletion of all context indexes and objects contained in these indexes. * @param name name of context to be deleted * @throws StorageException */ void dropContext(String name, org.netbeans.mdr.persistence.MOFID mofId) throws StorageException { // drop all context attribute indexes String storageId = getStorageIdFromMofId(mofId); if (storageId == null) { throw new DebugException("Invalid MOF ID"); } Storage storage = (Storage) this.storages.get(storageId); if (storage == null) { throw new DebugException("Storage not found"); } for (Iterator it = storage.getSinglevaluedIndex(PREFIX_ATTR_INDEXES_BY_NAME + mofId.getSerialNumber()).values().iterator(); it.hasNext();) { storage.dropIndex(getAdditionalIndexName(mofId, (String) it.next())); } // drop the rest of context indexes storage.dropIndex(PREFIX_ATTR_INDEXES_BY_NAME + mofId.getSerialNumber()); storage.dropIndex(PREFIX_ATTR_INDEXES_CLASS_PROXY + mofId.getSerialNumber()); // delete context if (name != null) { SinglevaluedIndex contextsIndex = (SinglevaluedIndex) this.contexts.get(storageId); if (contextsIndex == null) { throw new DebugException("Storage not found"); } contextsIndex.remove(name); } } /** Returns all contexts references to outermost package extent) in the * boot storage. * @throws StorageException problem in storage * @return collection of context names */ public Collection getContexts() throws StorageException { HashSet result = new HashSet(); for (Iterator it = contexts.values().iterator(); it.hasNext();) { SinglevaluedIndex sv = (SinglevaluedIndex) it.next(); result.addAll(sv.keySet()); } return result; } /** Returns all contexts references to outermost package extent) in the * the storage with the given ID. * * @param storageId * @throws StorageException problem in storage * @return collection of context names */ public Collection getContexts(String storageId) throws StorageException { SinglevaluedIndex context = (SinglevaluedIndex) this.contexts.get(storageId); if (context == null) throw new IllegalArgumentException(); HashSet result = new HashSet(); result.addAll(context.keySet()); return result; } /** * Returns the outermost package proxy for the given context name. * * @param context name of a context (reference to outermost package extent) * @return the outermost package proxy named by context or * null if there is no such context */ public StorablePackage getContextOutermostPackage(String context) throws StorageException { Object id = null; for (Iterator it = this.contexts.values().iterator(); it.hasNext();) { SinglevaluedIndex contextsIndex = (SinglevaluedIndex) it.next(); id = contextsIndex.getIfExists(context); if (id != null) { return (StorablePackage) getObject((org.netbeans.mdr.persistence.MOFID) id); } } return null; } // ADDITIONAL INDEXING SUPPORT ///////////////////////////////////////////////// /** * Creates new additional index in the given context. * * @param context * @param attrMofId identifies the attribute * @param indexName names the index to be created * @throws StorageException */ public void createAdditionalIndex(org.netbeans.mdr.persistence.MOFID context, String indexName, org.netbeans.mdr.persistence.MOFID proxyId) throws StorageException { Storage storage = getStorageByMofId(context); if (storage == null) { throw new DebugException("Storage not found"); } // the following two indexes can be merged if index is able to return 'key iterator' storage.getSinglevaluedIndex(PREFIX_ATTR_INDEXES_BY_NAME + context.getSerialNumber()).put(indexName, indexName); storage.getSinglevaluedIndex(PREFIX_ATTR_INDEXES_CLASS_PROXY + context.getSerialNumber()).put(indexName, proxyId); storage.createMultivaluedIndex(getAdditionalIndexName(context, indexName), Storage.EntryType.STRING, Storage.EntryType.MOFID, false); } /** * Returns index for attribte attrMofId in the given context * or null if there is no such index. * * @param context * @param indexName * @return the index for the given attribute or null */ private MultivaluedIndex getAdditionalIndex(org.netbeans.mdr.persistence.MOFID context, String indexName) { try { Storage storage = getStorageByMofId(context); if (storage == null) { throw new DebugException("Storage not found"); } return storage.getMultivaluedIndex(getAdditionalIndexName(context, indexName)); } catch (StorageException e) { return null; } } private StorableClass getIndexClassProxy (org.netbeans.mdr.persistence.MOFID context, String indexName) { try { Storage storage = getStorageByMofId(context); if (storage == null) { throw new DebugException("Storage not found"); } return (StorableClass) getObject((org.netbeans.mdr.persistence.MOFID)storage.getSinglevaluedIndex(PREFIX_ATTR_INDEXES_CLASS_PROXY + context.getSerialNumber()).get(indexName)); } catch (StorageException e) { return null; } } /** * The same as {@link #getAdditionalIndex(String, String)}. * *

[PENDING] Probably this method should be removed. */ MultivaluedIndex acquireAdditionalIndex(org.netbeans.mdr.persistence.MOFID context, String indexName) { MultivaluedIndex result = getAdditionalIndex(context, indexName); return result; } /** * Currently does nothing. */ void releaseAdditionalIndex() { } /** * This method is for internal usage only (NamespaceImpl) ! */ public Collection objectsFromAdditionalIndex(org.netbeans.mdr.persistence.MOFID context, String indexName, String value) { try { SinglevaluedIndex objectsIndex = getObjectsIndexByMofId (context); return getAdditionalIndex (context, resolveAttrMofId(context, indexName)).getObjects (value, objectsIndex); } catch (StorageException e) { return null; } } /** * @param context mof id of related outermost package extent * @param indexName name of the queried index * @param value queried key value, can be used only in case of one-field indexes * @return */ public Collection getItemsFromAdditionalIndex(org.netbeans.mdr.persistence.MOFID context, String indexName, Object value) { try { StorableClass sc = getIndexClassProxy (context, indexName); if (sc == null) { throw new DebugException ("Index " + indexName + " does not exist in the specified context."); } StorableClass.IndexDescriptor desc = sc.getAdditionalIndex (indexName); String valueToString = StorableObject.valueToKey (value, desc.getFields()); return getAdditionalIndex(context, resolveAttrMofId(context, indexName)).getItems(valueToString); } catch (StorageException e) { return null; } } /** * @param context mof id of related outermost package extent * @param indexName name of the queried index * @param value queried key value, can be used only in case of one-field indexes * @return */ public Collection getObjectsFromAdditionalIndex(org.netbeans.mdr.persistence.MOFID context, String indexName, Object value) { try { StorableClass sc = getIndexClassProxy (context, indexName); if (sc == null) { throw new DebugException ("Index " + indexName + " does not exist in the specified context."); } StorableClass.IndexDescriptor desc = sc.getAdditionalIndex (indexName); String valueToString = StorableObject.valueToKey (value, desc.getFields()); SinglevaluedIndex objectsIndex = getObjectsIndexByMofId (context); return getAdditionalIndex (context, resolveAttrMofId(context, indexName)).getObjects (valueToString, objectsIndex); } catch (StorageException e) { return null; } } /** * @param context mof id of related outermost package extent * @param indexName name of the queried index * @param prefix key prefix * @return */ public Collection getObjectsFromAIByPrefix(org.netbeans.mdr.persistence.MOFID context, String indexName, String prefix) { try { StorableClass sc = getIndexClassProxy (context, indexName); if (sc == null) { throw new DebugException ("Index " + indexName + " does not exist in the specified context."); } StorableClass.IndexDescriptor desc = sc.getAdditionalIndex (indexName); SinglevaluedIndex objectsIndex = getObjectsIndexByMofId (context); return getAdditionalIndex (context, resolveAttrMofId(context, indexName)).queryByKeyPrefix(prefix, objectsIndex); } catch (StorageException e) { return null; } } /** * @param context mof id of related outermost package extent * @param indexName name of the queried index * @param map map of pairs (field name, queried value) * @return */ public Collection queryAdditionalIndex(org.netbeans.mdr.persistence.MOFID context, String indexName, Map map) { try { StorableClass sc = getIndexClassProxy (context, indexName); if (sc == null) { throw new DebugException ("Index " + indexName + " does not exist in the specified context."); } StorableClass.IndexDescriptor desc = sc.getAdditionalIndex (indexName); String valueToString = StorableObject.valuesToKey (map, desc.getFields()); SinglevaluedIndex objectsIndex = getObjectsIndexByMofId (context); return getAdditionalIndex (context, resolveAttrMofId(context, indexName)).getObjects (valueToString, objectsIndex); } catch (StorageException e) { return null; } } /** * @param context * @param indexName * @throws StorageException * @return */ private String resolveAttrMofId(org.netbeans.mdr.persistence.MOFID context, String indexName) throws StorageException { Storage storage = this.getStorageByMofId(context); return (String) storage.getSinglevaluedIndex(PREFIX_ATTR_INDEXES_BY_NAME + context.getSerialNumber()).get(indexName); } /** * @param context * @param indexName * @return */ private String getAdditionalIndexName(org.netbeans.mdr.persistence.MOFID context, String indexName) { return PREFIX_ATTR_INDEX + context.getSerialNumber() + ":" + indexName; } // BOOT SUPPORT //////////////////////////////////////////////////////////////// // NOTE: following methods don't have to be synchronized - whole boot sequence is synchronized /** * @param mofId */ void addBootObject(org.netbeans.mdr.persistence.MOFID mofId) { if (bootObjects == null) { bootObjects = new ArrayList(); } bootObjects.add(mofId); } /** * @param mofId */ void addBootClass(org.netbeans.mdr.persistence.MOFID mofId) { addBootObject(mofId); if (bootClasses == null) { bootClasses = new ArrayList(); } bootClasses.add(mofId); } /** * @param mofId */ void addBootAssociation(org.netbeans.mdr.persistence.MOFID mofId) { addBootObject(mofId); if (bootAssociations == null) { bootAssociations = new ArrayList(); } bootAssociations.add(mofId); } /** * @throws StorageException */ void dropBoot() throws StorageException { String name = NBMDRepositoryImpl.BOOT_MOF; org.netbeans.mdr.persistence.MOFID extent = getContextOutermostPackage(name).getMofId(); org.netbeans.mdr.persistence.MOFID mofId; String storageId = getStorageIdFromMofId(extent); MultivaluedIndex objByClsIndex = (MultivaluedIndex) this.objByCls.get(storageId); SinglevaluedIndex objectsIndex = (SinglevaluedIndex) this.objects.get(storageId); SinglevaluedIndex contextsIndex = (SinglevaluedIndex) this.contexts.get(storageId); Storage storage = (Storage) this.storages.get(storageId); if (objByClsIndex == null || objectsIndex == null || contextsIndex == null || storage == null) throw new DebugException("Illegal MdrStorage state"); for (Iterator it = bootClasses.iterator(); it.hasNext();) { objByClsIndex.remove((org.netbeans.mdr.persistence.MOFID) it.next()); } for (Iterator it = bootObjects.iterator(); it.hasNext();) { objectsIndex.remove(it.next ()); } for (Iterator it = bootAssociations.iterator(); it.hasNext();) { mofId = (org.netbeans.mdr.persistence.MOFID) it.next(); storage.dropIndex(getContextAssocEndIndexName(extent, mofId, 1)); storage.dropIndex(getContextAssocEndIndexName(extent, mofId, 2)); } storage.dropIndex(PREFIX_ATTR_INDEXES_BY_NAME + extent.getSerialNumber()); storage.dropIndex(PREFIX_ATTR_INDEXES_CLASS_PROXY + extent.getSerialNumber()); contextsIndex.remove(name); bootObjects = null; bootClasses = null; getRepository().freeCache(); } /** * @param table * @param object * @throws StorageException */ void replaceMeta(Hashtable table, RefBaseObject object) throws StorageException { StorableBaseObject sObject = this.getObject(((BaseObjectHandler)object)._getDelegate().getMofId()); sObject.replaceValues(table); } /** * @param pkg * @param qualifiedName * @return */ private RefObject qnToObject(RefPackage pkg, List qualifiedName) { ModelPackage mofPackage = (ModelPackage) pkg; RefClass pc = mofPackage.getMofPackage(); Iterator it = qualifiedName.iterator(); ModelElement object = getPackageElement(pc, (String)it.next() ); try { while (it.hasNext()) { object = ((Namespace) object).lookupElement((String) it.next()); } } catch (NameNotFoundException e) { object = null; } return object; } /** * @param pc * @param name * @return */ private ModelElement getPackageElement(RefClass pc, String name) { ModelElement object = null; ModelElement result = null; Iterator it = pc.refAllOfClass().iterator(); result = (ModelElement) it.next(); for (;it.hasNext();){ object = (ModelElement)it.next(); if (name.equals( object.getName() ) ) { result = object; break; } } return result; } /** * @param object * @return */ private List objectToQN(RefObject object) { return ((ModelElement) object).getQualifiedName(); } public void rebuildMofContext() { try { RefPackage bootMOF = (RefPackage) getRepository().getHandler(getContextOutermostPackage(NBMDRepositoryImpl.BOOT_MOF)); RefPackage pureMOF = (RefPackage) getRepository().getHandler(getContextOutermostPackage(NBMDRepositoryImpl.PURE_MOF)); RefClass classProxy; RefObject pureObject; RefObject bootObject; Hashtable fromTo = new Hashtable(); fromTo.put(((BaseObjectHandler)bootMOF)._getDelegate().getMofId(), ((BaseObjectHandler)pureMOF)._getDelegate().getMofId()); // create a conversion table for (Iterator classes = pureMOF.refAllClasses().iterator(); classes.hasNext();) { classProxy = (RefClass) classes.next(); for (Iterator instances = classProxy.refAllOfClass().iterator(); instances.hasNext();) { pureObject = (RefObject) instances.next(); bootObject = qnToObject(bootMOF, objectToQN(pureObject)); if (bootObject != null) { fromTo.put(((BaseObjectHandler)bootObject)._getDelegate().getMofId(), ((BaseObjectHandler)pureObject)._getDelegate().getMofId()); } } } // make a conversion for the package replaceMeta(fromTo, pureMOF); // replace class proxy metas for (Iterator classes = pureMOF.refAllClasses().iterator(); classes.hasNext();) { classProxy = (RefClass) classes.next(); replaceMeta(fromTo, classProxy); // replace instance metas for (Iterator instances = classProxy.refAllOfClass().iterator(); instances.hasNext();) { pureObject = (RefObject) instances.next(); replaceMeta(fromTo, pureObject); } } for (Iterator associations = pureMOF.refAllAssociations().iterator(); associations.hasNext();) { replaceMeta(fromTo, (RefAssociation) associations.next()); } rebuildMetas(NBMDRepositoryImpl.PURE_MOF, fromTo); dropBoot(); } catch (Exception e) { throw (DebugException) Logger.getDefault().annotate(new DebugException(), e); } } /** * @param mofContext * @param table * @throws StorageException */ void rebuildMetas(String mofContext, Map table) throws StorageException { /* Hashtable temp = new Hashtable(); Object key; String extent = getContextOutermostPackage(mofContext).getMofId(); // rebuild attribute indexes SinglevaluedIndex attributeIndexes = bootStorage.getSinglevaluedIndex(PREFIX_ATTR_INDEXES_BY_NAME + extent); String oldValue; String newValue; MultivaluedIndex oldAttributeIndex, newAttributeIndex; for (Iterator it = new HashSet(attributeIndexes.keySet()).iterator(); it.hasNext();) { key = it.next(); oldValue = (String) attributeIndexes.get(key); newValue = (String) table.get(oldValue); createContextAttrIndex(mofContext, newValue, (String) key); newAttributeIndex = getContextAttrIndex(extent, newValue); oldAttributeIndex = getContextAttrIndex(extent, oldValue); for (Iterator it2 = oldAttributeIndex.keySet().iterator(); it2.hasNext();) { key = it2.next(); for (Iterator it3 = oldAttributeIndex.getItems(key).iterator(); it3.hasNext();) { newAttributeIndex.add(key, it3.next()); } } bootStorage.dropIndex(oldAttributeIndex.getName()); } */ Object key; org.netbeans.mdr.persistence.MOFID newValue; org.netbeans.mdr.persistence.MOFID value; for (Iterator it = new HashSet(((SinglevaluedIndex)properties.get(this.bootStorage.getStorageId())).keySet()).iterator(); it.hasNext();) { key = it.next(); value = getProperty((String) key); if (this.bootNullMofId.equals(value)) { newValue = (org.netbeans.mdr.persistence.MOFID) table.get(key); } else { newValue = (org.netbeans.mdr.persistence.MOFID) table.get(value); } if (newValue != null) { setProperty((String) key, newValue); } } } // /** // * @param isEndA // * @throws StorageException // * @return // */ // Collection getUnrelatedItems(String assocId, int end, Index endIndex) throws StorageException { // SinglevaluedIndex assocIndex; // if (end == 1) { // assocIndex = associationsEnd2; // } else { // assocIndex = associationsEnd1; // } // // try { piMutex.enter(false); assocMutex.enter(false); // HashSet result = new HashSet(); // collectObjects((StorableClass) assocIndex.getObject(assocId, objects), new HashSet(), result); // // for (Iterator it = endIndex.keySet().iterator(); it.hasNext();) { // result.remove(it.next()); // } // // return result; // } finally { // assocMutex.leave(); // piMutex.leave(); // } // } // ///** // * @param classProxy // * @param visited // * @param result // * @throws StorageException */ // private void collectObjects(StorableClass classProxy, Set visited, Set result) throws StorageException { // visited.add(classProxy.getMofId()); // // try { objByClsMutex.enter(false); // result.addAll(objByCls.getItems(classProxy.getMofId())); // } finally { // objByClsMutex.leave(); // } // // String subclass; // for (Iterator it = classProxy.getSubclasses().iterator(); it.hasNext();) { // subclass = (String) it.next(); // if (!visited.contains(subclass)) { // collectObjects((StorableClass) objects.get(subclass), visited, result); // } // } // } // // private StorableObject lookupByName(StorableObject object, String name) { // try { // Collection contents = (Collection) object.getReference(SH_MODEL_NAMESPACE_CONTENTS); // StorableObject result = findNamed(contents, name); // // if (result == null) { // Collection supertypes = (Collection) object.getReference(SH_MODEL_GENERALIZABLE_ELEMENT_SUPERTYPES); // for (Iterator it = supertypes.iterator(); it.hasNext();) { // result = lookupByName((StorableObject) it.next(), name); // if (result != null) { // break; // } // } // } // // return result; // } catch (java.lang.Exception e) { // throw Logger.getDefault().annotate(new DebugException(), e); // } // } // // private StorableObject findNamed(Collection objects, String featureName) throws StorageException { // for( Iterator it = objects.iterator(); it.hasNext(); ) { // StorableObject so = (StorableObject) it.next(); // String objectName = (String) so.getAttribute(SH_MODEL_MODEL_ELEMENT_NAME); // if ( objectName != null && objectName.equals( featureName ) ) { // return so; // } // } // // return null; // } //////////////////////////////////////////////////////////////////////////////// /* -------------------------------------------------------------------- */ /* -- Wrappers for org.netbeans.mdr.persistence.Storage methods ------- */ /* -------------------------------------------------------------------- */ public MOFID generateMOFID (MOFID immediatePackageId) throws StorageException { Storage st = null; if (immediatePackageId == null) { return this.generateMOFID(this.bootStorage); } else { return this.generateMOFID(getStorageByMofId(immediatePackageId)); } } public MOFID generateMOFID (String storageId) throws StorageException { Storage st = (Storage) this.storages.get(storageId); if (st == null && org.netbeans.mdr.storagemodel.transientimpl.TransientStorage.STORAGE_ID.equals(storageId)) { st = this.getTransientStorage (); } return this.generateMOFID (st); } private org.netbeans.mdr.persistence.MOFID generateMOFID(Storage storage) throws StorageException { if (storage == null) { throw new IllegalArgumentException("Wrong storage id"); //NOI18N } return new org.netbeans.mdr.persistence.MOFID (storage); } public void objectStateWillChange(org.netbeans.mdr.persistence.MOFID mofId) throws StorageException { Storage storage = this.getStorageByMofId(mofId); if (storage == null) { throw new DebugException("Storage not found"); } storage.objectStateWillChange(mofId); } public void objectStateChanged(org.netbeans.mdr.persistence.MOFID mofId) throws StorageException { Storage storage = this.getStorageByMofId(mofId); if (storage == null) { throw new DebugException("Storage not found"); } storage.objectStateChanged(mofId); } public Index getIndex(org.netbeans.mdr.persistence.MOFID context, org.netbeans.mdr.persistence.MOFID assocMofId, int end ) throws StorageException { Storage storage = getStorageByMofId(context); if (storage == null) { throw new DebugException("Storage not found"); } String indexName = getContextAssocEndIndexName(context, assocMofId, end); return storage.getIndex(indexName); } /** Create index that holds exactly one value for each key. * @return created index * @param name name of the index * @param keyType type of keys in the index * @param valueType type of values in the index (any type except STREAMABLE) */ SinglevaluedIndex createSinglevaluedIndex(org.netbeans.mdr.persistence.MOFID context, org.netbeans.mdr.persistence.MOFID assocMofId, int end, Storage.EntryType keyType, Storage.EntryType valueType) throws StorageException { Storage storage = getStorageByMofId(context); if (storage == null) { throw new DebugException("Storage not found"); } String indexName = getContextAssocEndIndexName(context, assocMofId, end); return storage.createSinglevaluedIndex(indexName, keyType, valueType); } /** Create index that holds sorted set of values for each key. * @return created index * @param name name of the index * @param keyType type of keys in the index * @param valueType type of values in the index (any type except STREAMABLE) * @param unique true if values associated with one key do not contain duplicates */ MultivaluedOrderedIndex createMultivaluedOrderedIndex(org.netbeans.mdr.persistence.MOFID context, org.netbeans.mdr.persistence.MOFID assoccMofId, int end, Storage.EntryType keyType, Storage.EntryType valueType, boolean unique) throws StorageException { Storage storage = getStorageByMofId(context); if (storage == null) { throw new DebugException("Storage not found"); } String indexName = getContextAssocEndIndexName(context, assoccMofId, end); return storage.createMultivaluedOrderedIndex(indexName, keyType, valueType, unique); } /** Create index that hold a set of values for each key. Elements in one Multivalued are * not sorted. Set does not contain duplicate values. * @return created index * @param name name of the index * @param keyType type of keys in the index * @param valueType type of values in the index (any type except STREAMABLE) * @param unique true if values associated with one key do not contain duplicates */ MultivaluedIndex createMultivaluedIndex(org.netbeans.mdr.persistence.MOFID context, org.netbeans.mdr.persistence.MOFID assoccMofId, int end, Storage.EntryType keyType, Storage.EntryType valueType, boolean unique) throws StorageException { Storage storage = getStorageByMofId(context); if (storage == null) { throw new DebugException("Storage not found"); } String indexName = getContextAssocEndIndexName(context, assoccMofId, end); return storage.createMultivaluedIndex(indexName, keyType, valueType, unique); } void dropIndex(org.netbeans.mdr.persistence.MOFID context, org.netbeans.mdr.persistence.MOFID assoccMofId, int end) throws StorageException { Storage storage = getStorageByMofId (context); if (storage == null) { throw new DebugException("Storage not found"); } String indexName = getContextAssocEndIndexName(context, assoccMofId, end); storage.dropIndex(indexName); } /* -------------------------------------------------------------------- */ /* -- ------- */ /* -------------------------------------------------------------------- */ /** * @param context * @param assocMofId * @param end * @return */ private String getContextAssocEndIndexName (org.netbeans.mdr.persistence.MOFID context, org.netbeans.mdr.persistence.MOFID assocMofId, int end) { return PREFIX_ASSOC_END + context.getSerialNumber() + ":" + assocMofId.getSerialNumber() + ":" + end; } public Storage getStorageByMofId (org.netbeans.mdr.persistence.MOFID mofId) { String storageId = getStorageIdFromMofId (mofId); return getStorageById(storageId); } public Storage getStorageById(String storageId) { if (storageId == null) { return null; } Storage result = (Storage) this.storages.get(storageId); // if (result == null) result = currentStorage; return result; } private SinglevaluedIndex getObjectsIndexByMofId (org.netbeans.mdr.persistence.MOFID mofId) { String storageId = getStorageIdFromMofId(mofId); if (storageId == null) { return null; } SinglevaluedIndex result = (SinglevaluedIndex) this.objects.get(storageId); // if (result == null) { // Storage s = getStorageById(mofId.getStorageID()); // if (s != null) try { // result = s.getPrimaryIndex(); // } catch (StorageException e) { // result = null; // } // } return result; } private MultivaluedIndex getObjectsByClassesByMofId (org.netbeans.mdr.persistence.MOFID mofId) { String storageId = getStorageIdFromMofId (mofId); if (storageId == null) { return null; } return (MultivaluedIndex) this.objByCls.get (storageId); } private SinglevaluedIndex getPropertiesIndexByStorageId (String storageId) { return (SinglevaluedIndex) this.properties.get(storageId); } public static String getStorageIdFromMofId(org.netbeans.mdr.persistence.MOFID mofId) { return mofId.getStorageID (); } /* -------------------------------------------------------------------- */ /* -- Implementation of org.netbeans.mdr.persistence.ObjectResolver --- */ /* -------------------------------------------------------------------- */ /** Resolves object specified by storage id and key. * @param uuid of storage, where an object resides * @param key key * @return resolved object */ public Object resolve(String storageID, Object key) throws StorageException { SinglevaluedIndex objectsIndex = (SinglevaluedIndex) this.objects.get(storageID); if (objectsIndex == null) return null; synchronized (getStorageById(storageID)) { return objectsIndex.get(key); } } public synchronized Storage getTransientStorage () throws StorageException { if (this.transientStorage == null) { this.transientStorage = new org.netbeans.mdr.storagemodel.transientimpl.TransientStorage ("TransientStorage"); this.transientStorage.create(false, this); this.objects.put (org.netbeans.mdr.storagemodel.transientimpl.TransientStorage.STORAGE_ID, transientStorage.getPrimaryIndex ()); this.objByCls.put (org.netbeans.mdr.storagemodel.transientimpl.TransientStorage.STORAGE_ID, transientStorage.createMultivaluedIndex (IDX_OBJECTS_BY_CLASSES, Storage.EntryType.MOFID, Storage.EntryType.MOFID, false)); this.transientStorage.commitChanges (); // Commit indexes creation, it is save to call commit on the storage, because it was not used before this.storages.put (org.netbeans.mdr.storagemodel.transientimpl.TransientStorage.STORAGE_ID, transientStorage); } return this.transientStorage; } public static boolean isTransientMofId(org.netbeans.mdr.persistence.MOFID mofId) { String storageID = getStorageIdFromMofId(mofId); return org.netbeans.mdr.storagemodel.transientimpl.TransientStorage.STORAGE_ID.equals(storageID); } /* -------------------------------------------------------------------- */ /* -- MdrStorage.ValuesObject (inner class) --------------------------- */ /* -------------------------------------------------------------------- */ /** * A ValuesObject manages a unique list of values. */ public static class ValuesObject implements Streamable, StorageClient { private Storage storage; private org.netbeans.mdr.persistence.MOFID id; /** The list of values managed by this object. */ private List list = new ArrayList(); /** Maps managed objects to their indices in list, * to monitor uniqueness. */ private final transient Map map = new HashMap(); /** * Constructor for the recreation of this object from a stream. */ public ValuesObject() { } /** * Constructor for the initial creation of this object. * * @param storage the storage for which this object is created * @param id the id of the object in the storage */ private ValuesObject(Storage storage, org.netbeans.mdr.persistence.MOFID id) { this.storage = storage; this.id = id; } /** * Called by the {@link org.netbeans.persistence.Storage} implementation * when it creates this object. */ public void setStorage(Storage storage) { this.storage = storage; } // this is always called from a synchronized section /** * Adds value to the list of objects managed by this * ValuesObject. Returns the index of the newly added * object. If value is already managed by this object, it * is not added, only the index is returned. * * @param value the object to be added to this ValuesObject * @return the index of value, always >= 1. */ public int store(Object value) { if (value == null) return 0; try { storage.objectStateWillChange(id); Object index = new Integer(map.size()); Object old = map.put(value, index); if (old != null) { map.put(value, old); index = old; } else { list.add(value); storage.objectStateChanged(id); } return ((Integer) index).intValue() + 1; } catch (StorageException e) { throw (DebugException) Logger.getDefault().annotate(new DebugException(), e); } } // this is always called from a synchronized section /** * Returns the object with the given index. * * @param index an index (>= 1) of a managed object * or 0 * @return the managed object with the given index or null * for index 0 * @throws IndexOutOfBoundsException if index is out of range */ public Object resolve(int index) { if (index == 0) return null; return list.get(index - 1); } // this is always called from a synchronized section /** * Returns the index of the managed object value. * * @param value the object the index of which has to be returned * @return the index of value (always >= 1) * or 0 if value == null * @throws Exception if value is neither managed by this * object nor null */ public int indexOf(Object value) { if (value == null) return 0; Integer result = (Integer) map.get(value); if (result == null) { throw new DebugException("Value not found: " + value); } return result.intValue() + 1; } /** Restore state of the {@link org.netbeans.mdr.persistence.Streamable} * object from the stream. * @param inputStream InputStream that represents an internal representation of fields of a Streamable object * in which it was written by {@link write } method */ public void read(java.io.InputStream inputStream) throws StorageException { try { id = IOUtils.readMOFID (inputStream, this.storage); list = (List) IOUtils.read(inputStream); for (int i = 0; i < list.size(); i++) { map.put(list.get(i), new Integer(i)); } } catch (IOException e) { throw (DebugException) Logger.getDefault().annotate(new DebugException(), e); } } /** This method will be used to move changed object from storage cache * to the persistent part of storage. It writes the object`s state * (set of attributes) in the stream as an array of bytes, for example * in textual representation. * @param outputStream OutputStream that holds value of a * {@link org.netbeans.mdr.persistence.Streamable} object */ public void write(java.io.OutputStream outputStream) throws StorageException { try { IOUtils.writeMOFID (outputStream, id, this.storage); IOUtils.write(outputStream, list); } catch (IOException e) { throw (DebugException) Logger.getDefault().annotate(new DebugException(), e); } } } private class InstanceMap extends HashMap { private final ReferenceQueue queue = new ReferenceQueue(); private class InstanceReference extends WeakReference { private Object key; public InstanceReference(Object key, Object instance) { super(instance, queue); this.key = key; } public Object getKey() { return key; } } private void cleanUp() { InstanceMap.InstanceReference reference; while ((reference = (InstanceMap.InstanceReference) queue.poll()) != null) { // Logger.getDefault().log("Removing: " + reference.getProxyMofId()); Object key = reference.getKey(); Reference currentRef = (Reference) super.remove(key); if (currentRef != null && currentRef != reference && currentRef.get() != null) { super.put(key, currentRef); } } } public Object put(Object key, Object value) { cleanUp(); Object result = super.put(key, new InstanceMap.InstanceReference(key, value)); if (result != null) { return ((InstanceMap.InstanceReference) result).get(); } else { return result; } } public Object get(Object key) { cleanUp(); Object result = super.get(key); if (result != null) { return ((InstanceMap.InstanceReference) result).get(); } else { return result; } } public Collection values() { ArrayList result = new ArrayList(); cleanUp(); for (Iterator it = super.values().iterator(); it.hasNext();) { result.add(((InstanceMap.InstanceReference) it.next()).get()); } return result; } } }

... 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.