Index: build.xml
===================================================================
RCS file: /usr/local/cvs/case/netbeans/mdr/build.xml,v
retrieving revision 1.1.1.2
retrieving revision 1.6
diff -u -r1.1.1.2 -r1.6
--- build.xml 18 Jul 2002 08:37:22 -0000 1.1.1.2
+++ build.xml 18 Jul 2002 10:06:31 -0000 1.6
@@ -14,17 +14,44 @@
Note: This bitmask is empty, because there are not
+ * events which originate on packages. Packages receive only events
+ * propagated from other objects. As a consequence this bitmask is
+ * useless. It is nevertheless part of the API to achieve greater
+ * uniformity of the API.
- * The repository should distribute all the events in the following way:
+ *
+ * The repository distributes all the events recursively in the following way:
*
- *
- * All the events are propagated recursively till they reach the repository object (e.g. each
+ * Figure XXX: MARTIN, PLEASE ADD THE FIGURE, I'VE CREATED shows where the
+ * events are initially fired and how they propagate.
+ *
All the events are propagated recursively till they reach the repository object (e.g. each
* instance event is as a result of propagation always fired on the instance itself,
* on its class proxy, on its immediate package proxy, on all other package proxies containing
* the immediate package proxy to the outermost package proxy and at the end on the repository containing
- * instance).
- * In addition, any event is fired only once for each listener (so no matter how many objects
+ * instance).
In addition, any event is fired only once for each listener (so no matter how many objects * on the event's propagation path is a listener registered on - e.g. on both - * class proxy and its instances - it receives each notification only once per event). + * class proxy and its instances - it receives each notification only once per event).
+ * + *Listeners may be added specifically for certain events only by calling
+ * {@link #addListener(MDRChangeListener, int) addListener(MDRChangeListener, int)}.
+ * If instead {@link #addListener(MDRChangeListener) addListener(MDRChangeListener)}
+ * is used for listener addition and, hence, no event mask is speficied, the listener
+ * receives all events which are propagated to the source it is registered for.
*
* @author Martin Matula
+ * @author Holger Krug.
*/
public interface MDRChangeSource {
- /** Registers a listener for receiving event notifications.
+
+ /** Registers a listener for receiving event notifications using the default
+ * event mask. The default event mask depends on the type of the change source
+ * and filters all events which are initially fired on this object.
* @param listener Object that implements {@link MDRChangeListener} interface.
*/
public void addListener(MDRChangeListener listener);
+ /** Registers a listener for receiving notifications about events the type
+ * of which matches mask
.
+ * @param listener Object that implements {@link MDRChangeListener} interface.
+ * @param eventMask bitmask to be used in a call to {@link MdrChangeEvent#isOfType()}
+ * to filter events based on the mask
+ */
+ public void addListener(MDRChangeListener listener, int mask);
/** Removes listener from the list of objects registered for events notifications.
* @param listener Object that implements {@link MDRChangeListener} interface.
*/
public void removeListener(MDRChangeListener listener);
+ /** Removes listener only for events of types matching mask
.
+ * If a listener is additionally registered for events of other types, it
+ * proceeds listening on the remaining event types.
+ * @param listener Object that implements {@link MDRChangeListener} interface.
+ * @param mask determines the types of events the listener shall stop
+ * to listen on
+ */
+ public void removeListener(MDRChangeListener listener, int mask);
}
Index: src/org/netbeans/api/mdr/events/TransactionEvent.java
===================================================================
RCS file: src/org/netbeans/api/mdr/events/TransactionEvent.java
diff -N src/org/netbeans/api/mdr/events/TransactionEvent.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/org/netbeans/api/mdr/events/TransactionEvent.java 11 Jul 2002 08:53:42 -0000 1.2
@@ -0,0 +1,42 @@
+/*
+ * 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.api.mdr.events;
+
+import javax.jmi.reflect.RefFeatured;
+import org.netbeans.api.mdr.MDRepository;
+
+/** Class representing MDR events related to start, commit and
+ * rollback of write transactions.
+ *
+ * @author Holger Krug.
+ */
+public class TransactionEvent extends MDRChangeEvent {
+
+ /** Bitmask representing all event types related to write transactions */
+ public static final int EVENTMASK_TRANSACTION = 0x011FFFF;
+
+ /** Event type indicating that a write transaction has been started. */
+ public static final int EVENT_TRANSACTION_START = 0x0110001;
+ /** Event type indicating that a write transaction has been committed. */
+ public static final int EVENT_TRANSACTION_COMMIT = 0x0110002;
+ /** Event type indicating that a write transaction has been rolled back. */
+ public static final int EVENT_TRANSACTION_ROLLBACK = 0x0110004;
+
+ /** Creates new TransactionEvent
instance.
+ * @param source the event source, an instance of MDRepository
.
+ * @param type the event type.
+ */
+ public TransactionEvent(MDRepository source, int type) {
+ super(source, type);
+ }
+}
Index: src/org/netbeans/mdr/NBMDRepositoryImpl.java
===================================================================
RCS file: /usr/local/cvs/case/netbeans/mdr/src/org/netbeans/mdr/NBMDRepositoryImpl.java,v
retrieving revision 1.1.1.3
retrieving revision 1.12
diff -u -r1.1.1.3 -r1.12
--- src/org/netbeans/mdr/NBMDRepositoryImpl.java 18 Jul 2002 08:37:24 -0000 1.1.1.3
+++ src/org/netbeans/mdr/NBMDRepositoryImpl.java 18 Jul 2002 11:16:52 -0000 1.12
@@ -1,11 +1,11 @@
/*
* 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.
@@ -42,8 +42,8 @@
/* -------------------------------------------------------------------- */
/* -- Private static constants ---------------------------------------- */
/* -------------------------------------------------------------------- */
-
-// private static final Collection instances = new HashSet();
+
+ // private static final Collection instances = new HashSet();
private static final URL MOF_XML_URL = ModelPackage.class.getResource("resources/mof.xml");
private static final URL BOOTMOF_XML_URL = ModelPackage.class.getResource("resources/mof.xml");
@@ -55,22 +55,22 @@
private static final String INTERCEPTABLE_TAG_ID = "org.netbeans.mdr.interceptable";
private static final String TRANSIENT_TAG_ID = "org.netbeans.mdr.transient";
private static final String TAG_VALUE_TRUE = "true";
-
+
public static final String BOOT_MOF = "BootMOF";
public static final String PURE_MOF = "MOF";
-
+
/* -------------------------------------------------------------------- */
/* -- Private attributes ---------------------------------------------- */
/* -------------------------------------------------------------------- */
-
+
private MdrStorage mdrStorage = null;
-
+
private Map classProxies = null;
private Map associationProxies = null;
- private Map classProxiesMofIds = null;
+ private Map classProxiesMofIds = null;
private final Map parameters;
-
+
/* --------------------------------------------------------------------- */
/* -- Constructors ----------------------------------------------------- */
/* --------------------------------------------------------------------- */
@@ -95,18 +95,67 @@
*
Additionally the following properties allow to replace parts +// * of the MDR implementation by tailor-made classes, namely the base classes +// * for generated handler classes. This is an experimental feature, use +// * it with care. Currently no documentation is available about the features +// * the replacing classes must provide in order to cooperate with the generated code:
+// * +// *org.netbeans.mdr.handlers.PackageProxyHandler |
+// * (no default) | +// *fully qualified name of the class replacing PackageProxyHandler
+// * as base class for package proxy implementations |
+// *
org.netbeans.mdr.handlers.ClassProxyHandler |
+// * (no default) | +// *fully qualified name of the class replacing ClassProxyHandler
+// * as default base class for class proxy implementations |
+// *
org.netbeans.mdr.handlers.InstanceHandler |
+// * (no default) | +// *fully qualified name of the class replacing InstanceHandler
+// * as default base class for instance implementations |
+// *
org.netbeans.mdr.handlers.AssociationHandler |
+// * (no default) | +// *fully qualified name of the class replacing AssociationHandler
+// * as default base class for association implementations |
+// *
org.netbeans.mdr.handlers.StructureHandler |
+// * (no default) | +// *fully qualified name of the class replacing StructImpl
+// * as base class for structure implementations |
+// *
storage
: name of a class implementing {@link
* org.netbeans.mdr.persistence.StorageFactory}fileName
: storage locationAdditionally the following parameters allow to replace parts +// * of the MDR implementation by tailor-made classes, namely the base classes +// * for generated handler classes. This is an experimental feature, use +// * it with care. Currently no documentation is available about the features +// * the replacing classes must provide in order to cooperate with the generated code:
+// * +// *PackageProxyHandler
: fully qualified name of the super-class
+// * for package proxy implementations (default:
+// * org.netbeans.mdr.handler.PackageProxyHandler
)ClassProxyHandler
: fully qualified name of the default super-class
+// * for class proxy implementations (default:
+// * org.netbeans.mdr.handler.ClassProxyHandler
)InstanceHandler
: fully qualified name of the default super-class
+// * for instance implementations (default:
+// * org.netbeans.mdr.handler.InstanceHandler
)AssociationHandler
: fully qualified name of the default super-class
+// * for assocation proxy implementations (default:
+// * org.netbeans.mdr.handler.AssociationHandler
)StructureHandler
: fully qualified name of the super-class
+// * for structure implementations (default:
+// * org.netbeans.mdr.handler.StructImpl
)mofId
.
+ */
+ public RefBaseObject getByMofId(String mofId) {
+ initCheck();
+ try {
+ beginTrans(false);
+ StorableBaseObject storable = mdrStorage.getObject(mofId);
+ if ( storable == null ) {
+ throw new NoSuchElementException("No object with MOF ID: " + mofId);
+ } else {
+ return BaseObjectHandler.getHandler(storable);
+ }
+ } catch (StorageException e) {
+ e.printStackTrace();
+ throw new DebugException();
+ } finally {
+ endTrans();
+ }
+ }
+
/**
* Called on repository exit. Should perform all needed finalization actions.
*/
@@ -261,16 +373,16 @@
}
}
}
-
+
/* -------------------------------------------------------------------- */
/* -- Extending java.lang.Object -------------------------------------- */
- /* -------------------------------------------------------------------- */
+ /* -------------------------------------------------------------------- */
public String toString() {
StringBuffer sb = new StringBuffer("IDE MOF Repository");
return sb.toString();
}
-
+
/* -------------------------------------------------------------------- */
/* -- Create an outermost package instance ---------------------------- */
/* -------------------------------------------------------------------- */
@@ -288,76 +400,63 @@
initCheck();
RefPackage result;
-
- if (substName.equals(BOOT_MOF) && mdrStorage.isBooting()) {
- // instantiate BootMOF
- // this piece of code does not need to be locked because it can be invoked
- // only during booting and the booting process itself runs in a locked session
- // [PENDING] probably this code should be removed from here and put
- // directly into installFakeMof()
- createBootMOF();
- result = getExtent(substName);
- if (result == null) {
- throw new CreationFailedException("Fatal error during bootstrapping.");
+
+ boolean fail = true;
+ if (metaPackage == null) {
+ metaPackage = getMOFModelPackage();
+ }
+ ExtentEvent event = new ExtentEvent(
+ this,
+ ExtentEvent.EVENT_EXTENT_CREATE,
+ substName,
+ metaPackage,
+ new ImmutableList(existingInstances)
+ );
+
+ try {
+ beginTrans(true);
+ mdrStorage.getEventNotifier().REPOSITORY.firePlannedChange(mdrStorage, event);
+ Map instancesToCluster = new HashMap();
+
+ // Traverse the metamodel containtment
+ classProxies = new HashMap();
+ associationProxies = new HashMap();
+ classProxiesMofIds = new HashMap();
+
+ if (existingInstances != null) {
+ for (int i = 0; i < existingInstances.length; i++) {
+ collectPackageInstances(existingInstances[i], instancesToCluster);
+ }
}
- } else {
- boolean fail = true;
- if (metaPackage == null) {
- metaPackage = getMOFModelPackage();
- }
- ExtentEvent event = new ExtentEvent(
- this,
- ExtentEvent.EVENT_EXTENT_CREATE,
- substName,
- metaPackage,
- new ImmutableList(existingInstances)
- );
-
try {
- beginTrans(true);
- mdrStorage.getEventNotifier().REPOSITORY.firePlannedChange(mdrStorage, event);
- Map instancesToCluster = new HashMap();
-
- // Traverse the metamodel containtment
- classProxies = new HashMap();
- associationProxies = new HashMap();
- classProxiesMofIds = new HashMap();
-
- if (existingInstances != null) {
- for (int i = 0; i < existingInstances.length; i++) {
- collectPackageInstances(existingInstances[i], instancesToCluster);
- }
- }
- try {
- instantiatePackage(substName, null, (MofPackage) metaPackage, instancesToCluster, storageId, false);
- } catch (RuntimeException e) {
- e.printStackTrace();
- throw new CreationFailedException("Cannot instantiate package because of unexpected exception: " + e);
- }
-
- classProxies = null;
- associationProxies = null;
- classProxiesMofIds = null;
-
- result = getExtent(substName);
- if (result == null) {
- throw new CreationFailedException("Cannot find created package.");
- }
-
- fail = false;
- } finally {
- endTrans(fail);
+ instantiatePackage(substName, null, (MofPackage) metaPackage, instancesToCluster, storageId, false);
+ } catch (RuntimeException e) {
+ e.printStackTrace();
+ throw new CreationFailedException("Cannot instantiate package because of unexpected exception: " + e);
+ }
+
+ classProxies = null;
+ associationProxies = null;
+ classProxiesMofIds = null;
+
+ result = getExtent(substName);
+ if (result == null) {
+ throw new CreationFailedException("Cannot find created package.");
}
+
+ fail = false;
+ } finally {
+ endTrans(fail);
}
-
+
return result;
}
-
+
/* -------------------------------------------------------------------- */
/* -- Storage partitions ---------------------------------------------- */
/* -------------------------------------------------------------------- */
-
- /**
+
+ /**
* Mounts new partition into current repository,
* The partition is created and initialized, if it does not exist.
* @param String storageFactoryClass, name of storage factory class, which will create a new storage.
@@ -365,48 +464,48 @@
* @return String id.
* @exception MountFailedException thrown when mounting fails.
*/
- public String mountStorage (String storageFactoryClass, Map properties) throws MountFailedException {
+ public String mountStorage(String storageFactoryClass, Map properties) throws MountFailedException {
boolean failed = true;
try {
- beginTrans (true);
+ beginTrans(true);
// Firing of event is done inside a MdrStorage mountStorage method
- String storageId = this.mdrStorage.mountStorage (storageFactoryClass, properties);
+ String storageId = this.mdrStorage.mountStorage(storageFactoryClass, properties);
failed = false;
return storageId;
}catch (Exception e) {
- throw new MountFailedException ("Partition mount failed.", e);
+ throw new MountFailedException("Partition mount failed.", e);
}
finally {
- endTrans (failed);
+ endTrans(failed);
}
}
- /**
+ /**
* Umounts partition from current repository.
- * Umounting partition can affect validity of association links
+ * Umounting partition can affect validity of association links
* which cross partitions. Module developer is responsible for
* either removing cross partition links or handling exceptions
* caused by accessing these links.
* @param String storageId, id of storage.
*/
- public void umountStorage (String storageId) {
+ public void umountStorage(String storageId) {
boolean failed = true;
try {
- beginTrans (true);
- Collection c = mdrStorage.getContexts (storageId);
+ beginTrans(true);
+ Collection c = mdrStorage.getContexts(storageId);
for (Iterator it = c.iterator(); it.hasNext();) {
String extentName = (String)it.next();
- RefPackage pkg = this.getExtent (extentName);
- ExtentEvent event = new ExtentEvent (pkg, ExtentEvent.EVENT_EXTENT_DELETE, extentName, pkg.refMetaObject(), null);
- this.mdrStorage.getEventNotifier().PACKAGE.firePlannedChange (pkg, event);
+ RefPackage pkg = this.getExtent(extentName);
+ ExtentEvent event = new ExtentEvent(pkg, ExtentEvent.EVENT_EXTENT_DELETE, extentName, pkg.refMetaObject(), null);
+ this.mdrStorage.getEventNotifier().PACKAGE.firePlannedChange(pkg, event);
}
- this.mdrStorage.umountStorage (storageId);
+ this.mdrStorage.umountStorage(storageId);
failed = false;
}catch (StorageException e) {
- throw new DebugException ("Umounting failed: "+e.toString());
+ throw new DebugException("Umounting failed: "+e.toString());
}
finally {
- endTrans (failed);
+ endTrans(failed);
}
}
/* -------------------------------------------------------------------- */
@@ -419,7 +518,7 @@
public String getMOFInstanceName() {
return PURE_MOF;
}
-
+
/* -------------------------------------------------------------------- */
/* -- Private helper methods ------------------------------------------ */
/* -------------------------------------------------------------------- */
@@ -429,7 +528,7 @@
private MofPackage getMOFModelPackage() {
ModelPackage mofPackage = (ModelPackage) getExtent(getMOFInstanceName());
MofPackage result;
-
+
for (Iterator it = mofPackage.getMofPackage().refAllOfClass().iterator(); it.hasNext();) {
result = (MofPackage) it.next();
if (result.getName().equals("Model")) {
@@ -440,7 +539,7 @@
return null;
}
- /**
+ /**
* Initializes the repository, if not already initialized: creates and
* initializes the {@link org.netbeans.mdr.storagemodel.MDRStorage}. If
* necessary the repository is bootstrapped.
@@ -448,7 +547,7 @@
private synchronized void initCheck() {
if (mdrStorage == null) {
String storageClass = (String) parameters.get(PARAM_STORAGE_CLASS);
-
+
mdrStorage = new MdrStorage(this, storageClass, this.parameters);
try {
System.out.println("initializing...");
@@ -465,11 +564,11 @@
}
}
}
-
+
/* -------------------------------------------------------------------- */
/* -- Helper methods for extent creation (private) -------------------- */
/* -------------------------------------------------------------------- */
-
+
/**
* Helper method needed for the creation of a new outermost package instance.
* Puts pkg
and, recursively, all its nested packages
@@ -480,9 +579,9 @@
* of their meta-objects as key
* @exception CreationFailedException if two different packages with the
* same keys are added to packages
- *
- */
- private void collectPackageInstances(RefPackage pkg, Map packages) throws CreationFailedException {
+ *
+ */
+ private void collectPackageInstances(RefPackage pkg, Map packages) throws CreationFailedException {
Object result = packages.put(pkg.refMetaObject().refMofId(), pkg);
if (result != null && !result.equals(pkg)) {
throw new CreationFailedException("The provided list of existing package instances contains duplicities.");
@@ -492,7 +591,7 @@
collectPackageInstances(nested, packages);
}
}
-
+
/** Instantiates given package, i.e. packageProxies, classProxies,
* associationProxies.
*
@@ -500,18 +599,18 @@
* @param metaPackage outermost M2 package
* @param clusteredInstances maps MOF IDs of M2 packages to M1 package instances
* @param storageId ID of the storage partition
- */
+ */
private RefPackage instantiatePackage(String substName, StorablePackage immediatePackage, MofPackage metaPackage, Map clusteredInstances, String storageId, boolean clustered) {
// Create package proxy
StorablePackage newPackage = createPackageHandler(metaPackage, immediatePackage, substName, storageId, clustered);
System.out.println("new package: " + newPackage.getMofId() + ", metapackage: " + metaPackage.refMofId());
-
+
Log.out.indent();
-
+
Set localAssocProxies = new HashSet();
Map localClassProxies = new HashMap();
instantiatePackageContent(metaPackage, newPackage, clusteredInstances, localClassProxies, localAssocProxies);
- resolveSuperclasses(localClassProxies);
+ resolveSuperclasses(localClassProxies);
// [PENDING] need to fix the mutex ordering and NPE and then uncomment this
/*
@@ -525,7 +624,7 @@
return (RefPackage) BaseObjectHandler.getHandler(newPackage);
}
-
+
/**
* @param localClassProxies
*/
@@ -586,7 +685,7 @@
}
sc.addSuperclass(current.getMofId());
current.addSubclass(sc.getMofId());
- }
+ }
for (Iterator contents = cls.getContents().iterator(); contents.hasNext();) {
me = (ModelElement) contents.next();
if (me instanceof Reference) {
@@ -614,16 +713,16 @@
}
if (indexTags.size() > 0) {
try {
- sc.buildAdditionalIndexes (indexTags, associationProxies);
+ sc.buildAdditionalIndexes(indexTags, associationProxies);
} catch (StorageException e) {
- throw new DebugException ("Storage exception: " + e);
+ throw new DebugException("Storage exception: " + e);
}
}
*/
} // for
}
-
+
/**
* @param metaPackage
* @param newPackage
@@ -633,24 +732,24 @@
*/
private void instantiatePackageContent(MofPackage metaPackage, StorablePackage newPackage, Map clusteredInstances, Map localClassProxies, Set localAssocProxies) {
Iterator superTypes = metaPackage.allSupertypes().iterator();
- boolean thisTypeNotProcessed = true;
+ boolean thisTypeNotProcessed = true;
while (thisTypeNotProcessed || superTypes.hasNext()) {
Iterator it;
if (thisTypeNotProcessed) {
it = metaPackage.getContents().iterator();
thisTypeNotProcessed = false;
- } else
- it = ((MofPackage) superTypes.next ()).getContents().iterator();
-
+ } else
+ it = ((MofPackage) superTypes.next()).getContents().iterator();
+
while (it.hasNext()) {
Object o = it.next();
ModelElement element = (ModelElement) o;
-
+
if (element instanceof javax.jmi.model.MofClass) {
createClassProxyHandler((javax.jmi.model.MofClass) element, newPackage, localClassProxies);
} else if (element instanceof javax.jmi.model.Association) {
Association assoc = (Association) element;
-
+
Collection content = assoc.getContents();
int i = 0;
AssociationEnd ends[] = new AssociationEnd[2];
@@ -664,7 +763,7 @@
boolean orderA, orderB, uniqueA, uniqueB, aggrA, aggrB, indexedA, indexedB;
int minA, maxA, minB, maxB;
Class typeA, typeB;
-
+
minA = ends[0].getMultiplicity().getLower();
maxA = ends[0].getMultiplicity().getUpper();
minB = ends[1].getMultiplicity().getLower();
@@ -680,36 +779,36 @@
orderB = (ends[1].getMultiplicity().isOrdered());
uniqueA = (ends[0].getMultiplicity().isUnique());
uniqueB = (ends[1].getMultiplicity().isUnique());
-
+
aggrA = ends[0].getAggregation().equals(AggregationKindEnum.COMPOSITE);
aggrB = ends[1].getAggregation().equals(AggregationKindEnum.COMPOSITE);
- indexedA = TagSupport.getTagValue ((StorableObject) ((BaseObjectHandler) ends[0])._getDelegate(), TAGID_INDEX) != null;
- indexedB = TagSupport.getTagValue ((StorableObject) ((BaseObjectHandler) ends[1])._getDelegate(), TAGID_INDEX) != null;
- if (TagProvider.getTagValue (ends[0].getType (), TRANSIENT_TAG_ID, "").equals (TAG_VALUE_TRUE)
- || TagProvider.getTagValue (ends[1].getType (), TRANSIENT_TAG_ID, "").equals (TAG_VALUE_TRUE)) {
- createTransientAssociationHandler((javax.jmi.model.Association) element, newPackage, ends[0].getName(), ends[0].refMofId(), ends[1].getName(), ends[1].refMofId(), typeA, typeB, minA, maxA, minB, maxB, orderA, orderB, uniqueA, uniqueB, aggrA, aggrB, localAssocProxies);
+ indexedA = TagSupport.getTagValue((StorableObject) ((BaseObjectHandler) ends[0])._getDelegate(), TAGID_INDEX) != null;
+ indexedB = TagSupport.getTagValue((StorableObject) ((BaseObjectHandler) ends[1])._getDelegate(), TAGID_INDEX) != null;
+ if (TagProvider.getTagValue(ends[0].getType(), TRANSIENT_TAG_ID, "").equals(TAG_VALUE_TRUE)
+ || TagProvider.getTagValue(ends[1].getType(), TRANSIENT_TAG_ID, "").equals(TAG_VALUE_TRUE)) {
+ createTransientAssociationHandler((javax.jmi.model.Association) element, newPackage, ends[0].getName(), ends[0].refMofId(), ends[1].getName(), ends[1].refMofId(), typeA, typeB, minA, maxA, minB, maxB, orderA, orderB, uniqueA, uniqueB, aggrA, aggrB, localAssocProxies);
}
else {
createAssociationHandler((javax.jmi.model.Association) element, newPackage, ends[0].getName(), ends[0].refMofId(), ends[1].getName(), ends[1].refMofId(), typeA, typeB, minA, maxA, minB, maxB, orderA, orderB, uniqueA, uniqueB, aggrA, aggrB, indexedA, indexedB, localAssocProxies);
}
} else if (element instanceof MofPackage) {
- // System.out.println("found inner package");
- // System.out.println("creating: META: " + element.refMofId() + ", IMMEDIATE: " + newPackage.refMofId() + ", CONTEXT: " + context);
- String storageId = MdrStorage.getStorageIdFromMofId (newPackage.getMofId());
+ // System.out.println("found inner package");
+ // System.out.println("creating: META: " + element.refMofId() + ", IMMEDIATE: " + newPackage.refMofId() + ", CONTEXT: " + context);
+ String storageId = MdrStorage.getStorageIdFromMofId(newPackage.getMofId());
StorablePackage pkg = createPackageHandler((MofPackage) element, newPackage, null, storageId, false);
instantiatePackageContent((MofPackage) element, pkg, clusteredInstances, localClassProxies, localAssocProxies);
} else if (element instanceof Import) {
Import imp = (Import) element;
-
+
if (imp.isClustered()) {
ModelElement metaElement = imp.getImportedNamespace();
if (metaElement instanceof MofPackage) {
MofPackage metaPkg = (MofPackage) metaElement;
RefPackage pkg = (RefPackage) clusteredInstances.get(metaPkg.refMofId());
if (pkg == null) {
- String storageId = MdrStorage.getStorageIdFromMofId (newPackage.getMofId());
+ String storageId = MdrStorage.getStorageIdFromMofId(newPackage.getMofId());
pkg = instantiatePackage(null, newPackage, metaPkg, clusteredInstances, storageId, true);
clusteredInstances.put(metaPkg.refMofId(), pkg);
} else {
@@ -750,14 +849,14 @@
// this package was already collected
return;
}
- classProxies.put((MofClass) cls.refMetaObject(), ((BaseObjectHandler) cls)._getDelegate());
+ classProxies.put((MofClass) cls.refMetaObject(), ((BaseObjectHandler) cls)._getDelegate());
}
for (Iterator it = pkg.refAllPackages().iterator(); it.hasNext();) {
collectAllProxies((RefPackage) it.next());
}
}
-
+
/* -------------------------------------------------------------------- */
/* -- Helper methods for handler creation (private) ------------------- */
/* -------------------------------------------------------------------- */
@@ -778,7 +877,7 @@
ModelElement me;
List members = new ArrayList();
List memberTypes = new ArrayList();
-
+
for (Iterator it2 = ((StructureType) element).getContents().iterator(); it2.hasNext();) {
me = (ModelElement) it2.next();
if (me instanceof StructureField) {
@@ -795,7 +894,7 @@
datatypes.put(element.getName(), new DatatypeDescriptor(mdrStorage, element.getQualifiedName(), members, memberTypes, ifcName, storageId));
}
}
-
+
StorablePackage result = null;
if (storageId != null) {
result = new StorablePackage(mdrStorage, immediatePackage == null ? null : immediatePackage.getMofId(), metaObject.refMofId(), context, datatypes, storageId);
@@ -806,13 +905,13 @@
if (immediatePackage != null && !clustered) {
immediatePackage.addPackage(metaObject.getName(), result.getMofId());
}
-
+
return result;
} catch ( StorageException e ) {
throw new DebugException("Storage exception: " + e.getMessage());
}
}
-
+
/** Creates handler for Class Proxy */
private StorableClass createClassProxyHandler(javax.jmi.model.MofClass metaObject, StorablePackage immediatePackage, Map localClassProxies) {
ModelElement element;
@@ -854,12 +953,12 @@
if (element instanceof EnumerationType) {
List members = new ArrayList(((EnumerationType) element).getLabels());
String ifcName = TagSupport.getTypeFullName((StorableObject) ((BaseObjectHandler) element)._getDelegate());
- datatypes.put(element.getName(), new DatatypeDescriptor(mdrStorage, members, ifcName, MdrStorage.getStorageIdFromMofId (immediatePackage.getMofId())));
+ datatypes.put(element.getName(), new DatatypeDescriptor(mdrStorage, members, ifcName, MdrStorage.getStorageIdFromMofId(immediatePackage.getMofId())));
} else if (element instanceof StructureType) {
ModelElement me;
List members = new ArrayList();
List memberTypes = new ArrayList();
-
+
for (Iterator it2 = ((StructureType) element).getContents().iterator(); it2.hasNext();) {
me = (ModelElement) it2.next();
if (me instanceof StructureField) {
@@ -873,7 +972,7 @@
}
}
String ifcName = TagSupport.getTypeFullName((StorableObject) ((BaseObjectHandler) element)._getDelegate());
- datatypes.put(element.getName(), new DatatypeDescriptor(mdrStorage, element.getQualifiedName(), members, memberTypes, ifcName, MdrStorage.getStorageIdFromMofId (immediatePackage.getMofId())));
+ datatypes.put(element.getName(), new DatatypeDescriptor(mdrStorage, element.getQualifiedName(), members, memberTypes, ifcName, MdrStorage.getStorageIdFromMofId(immediatePackage.getMofId())));
}
isDerived = false;
isInterceptable = false;
@@ -888,60 +987,60 @@
}
}
- String tagValue = TagProvider.getTagValue (metaObject, TRANSIENT_TAG_ID, "");
- if (tagValue.equals (TAG_VALUE_TRUE)) {
- storable = new TransientStorableClass(mdrStorage, immediatePackage.getMofId(),
- metaObject.refMofId(), attrDescs, clAttrDescs, datatypes, classDerived,
- instanceDerived, metaObject.isSingleton(), metaObject.isAbstract());
+ String tagValue = TagProvider.getTagValue(metaObject, TRANSIENT_TAG_ID, "");
+ if (tagValue.equals(TAG_VALUE_TRUE)) {
+ storable = new TransientStorableClass(mdrStorage, immediatePackage.getMofId(),
+ metaObject.refMofId(), attrDescs, clAttrDescs, datatypes, classDerived,
+ instanceDerived, metaObject.isSingleton(), metaObject.isAbstract());
}
else {
- storable = new StorableClass(mdrStorage, immediatePackage.getMofId(),
- metaObject.refMofId(), attrDescs, clAttrDescs, datatypes, classDerived,
- instanceDerived, metaObject.isSingleton(), metaObject.isAbstract());
+ storable = new StorableClass(mdrStorage, immediatePackage.getMofId(),
+ metaObject.refMofId(), attrDescs, clAttrDescs, datatypes, classDerived,
+ instanceDerived, metaObject.isSingleton(), metaObject.isAbstract());
}
-
+
immediatePackage.addClass(metaObject.getName(), storable.getMofId());
classProxies.put(metaObject, storable);
classProxiesMofIds.put(metaObject.refMofId(), storable.getMofId());
localClassProxies.put(metaObject, storable);
return storable;
} catch ( StorageException e ) {
- e.printStackTrace ();
+ e.printStackTrace();
throw new DebugException("Storage exception: " + e.getMessage());
}
}
-
+
/** Creates handler for Association */
private StorableAssociation createAssociationHandler(
- javax.jmi.model.Association metaObject,
- StorablePackage immediatePackage,
- String assocationEnd1, String assocEnd1MofId,
- String assocationEnd2, String assocEnd2MofId,
- Class type1, Class type2,
- int min1, int max1,
- int min2, int max2,
- boolean isOrdered1,
- boolean isOrdered2,
- boolean isUnique1,
- boolean isUnique2,
- boolean isAggr1,
- boolean isAggr2,
- boolean isIndexed1,
- boolean isIndexed2,
- Set localAssocProxies) {
+ javax.jmi.model.Association metaObject,
+ StorablePackage immediatePackage,
+ String assocationEnd1, String assocEnd1MofId,
+ String assocationEnd2, String assocEnd2MofId,
+ Class type1, Class type2,
+ int min1, int max1,
+ int min2, int max2,
+ boolean isOrdered1,
+ boolean isOrdered2,
+ boolean isUnique1,
+ boolean isUnique2,
+ boolean isAggr1,
+ boolean isAggr2,
+ boolean isIndexed1,
+ boolean isIndexed2,
+ Set localAssocProxies) {
try {
StorableAssociation result = new StorableAssociation(
- mdrStorage,
- immediatePackage.getMofId(),
- metaObject.refMofId(),
- assocationEnd1, assocEnd1MofId, assocationEnd2, assocEnd2MofId,
- type1, type2,
- min1, max1, min2, max2,
- isOrdered1, isOrdered2,
- isUnique1, isUnique2,
- isAggr1, isAggr2,
- isIndexed1, isIndexed2);
+ mdrStorage,
+ immediatePackage.getMofId(),
+ metaObject.refMofId(),
+ assocationEnd1, assocEnd1MofId, assocationEnd2, assocEnd2MofId,
+ type1, type2,
+ min1, max1, min2, max2,
+ isOrdered1, isOrdered2,
+ isUnique1, isUnique2,
+ isAggr1, isAggr2,
+ isIndexed1, isIndexed2);
immediatePackage.addAssociation(metaObject.getName(), result.getMofId());
associationProxies.put(metaObject.refMofId(), result.getMofId());
localAssocProxies.add(result.getMofId());
@@ -952,32 +1051,32 @@
}
private StorableAssociation createTransientAssociationHandler(
- javax.jmi.model.Association metaObject,
- StorablePackage immediatePackage,
- String assocationEnd1, String assocEnd1MofId,
- String assocationEnd2, String assocEnd2MofId,
- Class type1, Class type2,
- int min1, int max1,
- int min2, int max2,
- boolean isOrdered1,
- boolean isOrdered2,
- boolean isUnique1,
- boolean isUnique2,
- boolean isAggr1,
- boolean isAggr2,
- Set localAssocProxies) {
+ javax.jmi.model.Association metaObject,
+ StorablePackage immediatePackage,
+ String assocationEnd1, String assocEnd1MofId,
+ String assocationEnd2, String assocEnd2MofId,
+ Class type1, Class type2,
+ int min1, int max1,
+ int min2, int max2,
+ boolean isOrdered1,
+ boolean isOrdered2,
+ boolean isUnique1,
+ boolean isUnique2,
+ boolean isAggr1,
+ boolean isAggr2,
+ Set localAssocProxies) {
try {
StorableAssociation result = new TransientStorableAssociation(
- mdrStorage,
- immediatePackage.getMofId(),
- metaObject.refMofId(),
- assocationEnd1, assocEnd1MofId, assocationEnd2, assocEnd2MofId,
- type1, type2,
- min1, max1, min2, max2,
- isOrdered1, isOrdered2,
- isUnique1, isUnique2,
- isAggr1, isAggr2);
+ mdrStorage,
+ immediatePackage.getMofId(),
+ metaObject.refMofId(),
+ assocationEnd1, assocEnd1MofId, assocationEnd2, assocEnd2MofId,
+ type1, type2,
+ min1, max1, min2, max2,
+ isOrdered1, isOrdered2,
+ isUnique1, isUnique2,
+ isAggr1, isAggr2);
immediatePackage.addAssociation(metaObject.getName(), result.getMofId());
associationProxies.put(metaObject.refMofId(), result.getMofId());
localAssocProxies.add(result.getMofId());
@@ -990,7 +1089,7 @@
/* -------------------------------------------------------------------- */
/* -- Methods for bootstrapping (private) ----------------------------- */
/* -------------------------------------------------------------------- */
-
+
/**
* Main bootstrapping method.
*/
@@ -1002,7 +1101,7 @@
try {
beginTrans(true);
installFakeMof();
- installPureMof();
+ installPureMof();
fail = false;
} catch (Throwable e) {
e.printStackTrace();
@@ -1011,27 +1110,25 @@
endTrans(fail);
}
Log.out.unindent();
- }
-
+ }
+
/** Installs the fake MOF
- */
+ */
private void installFakeMof() {
Log.out.println("Creating boot MOF metamodel ...");
-
- try {
- RefPackage p = createExtent(BOOT_MOF, null, null);
- } catch (CreationFailedException e) {
- e.printStackTrace();
- throw new DebugException("Cannot create instance of BOOT_MOF: " + e.getMessage());
+
+ createBootMOF();
+ if (getExtent(BOOT_MOF) == null) {
+ throw new DebugException("Cannot create instance of BOOT_MOF: Fatal error during bootstrapping.");
}
}
-
+
/** Programatically installs the pure MOF model.
*/
private void installPureMof() {
Log.out.println("Installing pure MOF Metamodel ... ");
Log.out.indent();
-
+
try {
Log.out.println("Parsing MOF model to DOM represtentation ....");
ModelPackage modelPackage = (ModelPackage) createExtent(PURE_MOF, getBMModelPackage());
@@ -1045,7 +1142,7 @@
Log.out.unindent();
}
}
-
+
/**
* Returns the MOF Model package as a model element of the
* bootstrapping MOF model. Needed only during bootstrapping.
@@ -1063,9 +1160,9 @@
}
return null;
}
-
+
/** Reads the XMI description of the mof directly into reporitory
- */
+ */
private void createBootMOF() {
try {
BootReader br = new BootReader(mdrStorage, BOOTMOF_XML_URL);
Index: src/org/netbeans/mdr/handlers/AssociationHandler.java
===================================================================
RCS file: /usr/local/cvs/case/netbeans/mdr/src/org/netbeans/mdr/handlers/AssociationHandler.java,v
retrieving revision 1.1.1.2
retrieving revision 1.4
diff -u -r1.1.1.2 -r1.4
--- src/org/netbeans/mdr/handlers/AssociationHandler.java 18 Jul 2002 08:37:25 -0000 1.1.1.2
+++ src/org/netbeans/mdr/handlers/AssociationHandler.java 18 Jul 2002 11:08:50 -0000 1.4
@@ -302,20 +302,45 @@
/*
public void replace(RefObject oldEnd1, RefObject oldEnd2, RefObject newEnd1, RefObject newEnd2) {
}
+
+ /* -------------------------------------------------------------------- */
+ /* -- Implementation of org.netbeans.api.mdr.events.MDRChangeSource --- */
+ /* -------------------------------------------------------------------- */
+
+ /** Registers a listener for receiving event notifications with are
+ * initially fired on this object.
+ * @param listener Object that implements {@link MDRChangeListener} interface.
*/
+ public void addListener(MDRChangeListener listener) {
+ addListener(listener, MDRChangeEvent.EVENTMASK_ALL);
+ }
+
/** Registers a listener for receiving event notifications.
- * @param listener Object that implements {@link Listener} interface.
+ * @param listener Object that implements {@link MDRChangeListener} interface.
+ * @param mask bitmask to filter types of events the listener listens on
*/
- public void addListener(MDRChangeListener listener) {
- _getMdrStorage().getEventNotifier().ASSOCIATION.addListener(listener, this);
+ public void addListener(MDRChangeListener listener, int mask) {
+ _getMdrStorage().getEventNotifier().ASSOCIATION.addListener(listener, mask, this);
}
- /** Removes listener from the list of objects registered for events notifications.
- * @param listener Object that implements {@link Listener} interface.
+ /** Removes listener from the list of objects registered for event notifications.
+ * @param listener Object that implements {@link MDRChangeListener} interface.
*/
public void removeListener(MDRChangeListener listener) {
_getMdrStorage().getEventNotifier().ASSOCIATION.removeListener(listener, this);
}
+
+ /** Removes listener from the list of objects registered for event notifications.
+ * @param listener Object that implements {@link MDRChangeListener} interface.
+ * @param mask determines type of the events the listeners stops to listen on
+ */
+ public void removeListener(MDRChangeListener listener, int mask) {
+ _getMdrStorage().getEventNotifier().ASSOCIATION.removeListener(listener, mask, this);
+ }
+
+ /* --------------------------------------------------------------------- */
+ /* -- -- */
+ /* --------------------------------------------------------------------- */
static void _removeExternalLink(AssociationHandler associationHandler, RefObject thisEnd, RefObject otherEnd) {
if (MdrStorage.isTransientMofId (thisEnd.refMofId ()) || MdrStorage.isTransientMofId (otherEnd.refMofId ()))
Index: src/org/netbeans/mdr/handlers/BaseObjectHandler.java
===================================================================
RCS file: /usr/local/cvs/case/netbeans/mdr/src/org/netbeans/mdr/handlers/BaseObjectHandler.java,v
retrieving revision 1.1.1.1
retrieving revision 1.3
diff -u -r1.1.1.1 -r1.3
--- src/org/netbeans/mdr/handlers/BaseObjectHandler.java 2 Jul 2002 07:35:26 -0000 1.1.1.1
+++ src/org/netbeans/mdr/handlers/BaseObjectHandler.java 4 Jul 2002 12:49:40 -0000 1.3
@@ -34,57 +34,77 @@
* @version
*/
public abstract class BaseObjectHandler extends ImplClass implements MDRObject/*, OclAny*/ {
+
+ /* --------------------------------------------------------------------- */
+ /* -- Static attributes ------------------------------------------------ */
+ /* --------------------------------------------------------------------- */
+
+ /**
+ * Maps storage objects (instances of {@link StorableBaseObject}) to
+ * JMI compliant handler objects (instances of {@link RefBaseObject}).
+ */
private static final Map facilityCache = new FacilityCache();
+
+ /**
+ * Maps mof ids of meta-objects to the appropriate JMI interfaces (String => Class).
+ */
private static final Hashtable classCache = new Hashtable();
private static MDRClassLoader defaultLoader = null;
private static ClassLoaderProvider provider = null;
-
- /** The object in strorage to delegate to
- */
-// private final StorableBaseObject storableDelegate;
- private final String mofId;
- private final MdrStorage mdrStorage;
- private StorableBaseObject storable;
- protected final void _lock() {
- _lock(true);
- }
+ /* --------------------------------------------------------------------- */
+ /* -- Static setters/getters ------------------------------------------- */
+ /* --------------------------------------------------------------------- */
- protected final void _lock(boolean write) {
- mdrStorage.getRepositoryMutex().enter(write);
+ public static synchronized void setClassLoaderProvider(ClassLoaderProvider provider) {
+ BaseObjectHandler.provider = provider;
}
- protected final void _unlock() {
- mdrStorage.getRepositoryMutex().leave();
- }
-
- protected final void _unlock(boolean fail) {
- mdrStorage.getRepositoryMutex().leave(fail);
+ public static synchronized MDRClassLoader getDefaultClassLoader() {
+ if (defaultLoader == null) {
+ defaultLoader = new MDRClassLoader(provider);
+ }
+// System.out.println(defaultLoader.toString() + " : " + defaultLoader.getClass().getName());
+ return defaultLoader;
}
- public final MDRepository repository() {
- return mdrStorage.getRepository();
- }
-
+ /* --------------------------------------------------------------------- */
+ /* -- Static helper methods (private) ---------------------------------- */
+ /* --------------------------------------------------------------------- */
+
+ /**
+ * Returns the handler class for JMI interface ifc
and storage object s
.
+ *
+ * @param loader the class loader for the definition of new classes
+ * @param ifc JMI interface to be implemented by the class
+ * @param s storage object to be wrapped by an instances of the class
+ * @return class implementing ifc
+ */
private static Class getHandlerClass(MDRClassLoader loader, Class ifc, StorableBaseObject s) throws IllegalArgumentException {
+ /* check if the loader may load the interface */
check(loader, ifc);
+ /* try to load from cache */
Map cache = getLoaderCache(loader);
String className = getName(ifc);
Class result = getFromCache(cache, ifc, className);
if (result == null) {
try {
+ /* generate and define handler class */
byte[] handlerClassFile = HandlerGenerator.generateHandler(className, ifc, s);
-/*
- try {
- java.io.FileOutputStream file = new java.io.FileOutputStream("e:/classes/" + className.substring(className.lastIndexOf('.') + 1) + ".class");
- file.write(handlerClassFile);
- file.close();
- } catch (Exception e) {
- e.printStackTrace();
- }
-*/
+
+ /* [XXX] Allow the use of a system property org.netbeans.mdr.byteCodeDir, write class
+ * files to that directory, if the system property is set.
+ */
+// try {
+// java.io.FileOutputStream file = new java.io.FileOutputStream("e:/classes/" + className.substring(className.lastIndexOf('.') + 1) + ".class");
+// file.write(handlerClassFile);
+// file.close();
+// } catch (Exception e) {
+// e.printStackTrace();
+// }
+
result = loader.defineClass(className, handlerClassFile);
} finally {
releaseCache(cache, result, className);
@@ -94,11 +114,18 @@
return result;
}
+ /**
+ * Returns the JMI interface to be implemented by the handler of s
.
+ *
+ * @param s a storage object
+ * @return the JMI interface for s
+ */
private static Class resolveClass(StorableBaseObject s) {
try {
StorableObject metaObject = s.getMetaObject();
String suffix;
+ /* cache lookup */
if (s instanceof StorableObject || s instanceof StorableAssociation) {
suffix = "";
} else if (s instanceof StorablePackage) {
@@ -112,6 +139,7 @@
String key = metaObject.getMofId() + ":" + suffix;
Class result = (Class) classCache.get(key);
+ /* interface resolution */
if (result == null) {
try {
String metaName = TagSupport.getTypeFullName(metaObject);
@@ -128,12 +156,26 @@
throw new DebugException();
}
}
-
+
+ /* --------------------------------------------------------------------- */
+ /* -- Static methods (public) ------------------------------------------ */
+ /* --------------------------------------------------------------------- */
+
+ /**
+ * Frees the caches of JMI compliant handler objects (for storage objects)
+ * and of JMI implementation classes (for meta-objects).
+ */
public static void _freeCache() {
facilityCache.clear();
classCache.clear();
}
+ /**
+ * Returns JMI compliant handler object for s
.
+ *
+ * @param s the storage object to be wrapped or null
+ * @return handler implementing JMI interface or null
+ */
public static RefBaseObject getHandler(StorableBaseObject s) throws IllegalArgumentException {
if (s == null) {
return null;
@@ -151,11 +193,30 @@
return getHandler(s, ifc);
}
+ /**
+ * Returns JMI compliant handler object for s
.
+ *
+ * @param s the storage object to be wrapped or null
+ * @param ifc the JMI interface to be implemented by the handler
+ * @return handler implementing JMI interface or null
+ */
public static RefBaseObject getHandler(StorableBaseObject s, Class ifc) throws IllegalArgumentException {
if (s == null) {
return null;
}
+
+ /* [XXX] For performance reasons the following piece of code should
+ * be enabled, when it is expected that cache lookup succeeds quite
+ * often. hkrug@rationalizer.com */
+// Object oldRecord;
+// synchronized (facilityCache) {
+// oldRecord = facilityCache.get(s.getMofId());
+// }
+// if ( oldRecord != null ) {
+// return oldRecord;
+// }
+ /* load the handler class */
MDRClassLoader loader = getDefaultClassLoader();
Class cl = getHandlerClass(loader, ifc, s);
@@ -170,6 +231,7 @@
else if (cls.equals (TransientStorableAssociation.class)) {
cls = StorableAssociation.class;
}
+ /* create handler object, if necessary */
Constructor cons = cl.getConstructor(new Class[] {cls});
synchronized (facilityCache) {
@@ -196,18 +258,14 @@
}
}
- public static synchronized void setClassLoaderProvider(ClassLoaderProvider provider) {
- BaseObjectHandler.provider = provider;
- }
-
- public static synchronized MDRClassLoader getDefaultClassLoader() {
- if (defaultLoader == null) {
- defaultLoader = new MDRClassLoader(provider);
- }
-// System.out.println(defaultLoader.toString() + " : " + defaultLoader.getClass().getName());
- return defaultLoader;
- }
-
+ /**
+ * Returns interface ifcName
. The interface is not generated on the
+ * fly, but must be available for loading by the default class-loader
+ * (see {@link #getDefaultClassLoader()}).
+ *
+ * @param ifcName name of the interface to be loaded
+ * @return the interface named ifcName
+ */
public static Class resolveInterface(String ifcName) throws ClassNotFoundException {
try {
return Class.forName(ifcName, true, getDefaultClassLoader());
@@ -222,6 +280,12 @@
}
}
+ /**
+ * Loads the class implName
from the default class loader.
+ *
+ * @param implName class name
+ * @return the class
+ */
public static Class resolveImplementation(String implName) throws ClassNotFoundException {
try {
return Class.forName(implName, true, getDefaultClassLoader());
@@ -238,6 +302,21 @@
throw e;
}
}
+
+ /* --------------------------------------------------------------------- */
+ /* -- Private attributes ----------------------------------------------- */
+ /* --------------------------------------------------------------------- */
+
+// /** The object in strorage to delegate to
+// */
+// private final StorableBaseObject storableDelegate;
+ private final String mofId;
+ private final MdrStorage mdrStorage;
+ private StorableBaseObject storable;
+
+ /* --------------------------------------------------------------------- */
+ /* -- Constructor(s) --------------------------------------------------- */
+ /* --------------------------------------------------------------------- */
/** Creates new RefBaseObjectHandler */
protected BaseObjectHandler(StorableBaseObject storable) {
@@ -255,37 +334,38 @@
this.storable = null;
}
}
-
- public final StorableBaseObject _getDelegate() {
-/*
- StorableBaseObject storable = (StorableBaseObject) storableDelegate.get();
- if (storable == null) {
- try {
- storable = mdrStorage.getObject(mofId);
- storableDelegate = new SoftReference(storable);
- } catch (StorageException e) {
- throw new DebugException("Storage exception: " + e);
- }
- }
- */
- try {
- if (this.storable != null)
- return this.storable;
- else
- return mdrStorage.getObject(mofId);
- } catch (StorageBadRequestException e) {
- throw new InvalidObjectException(null, "Object with MOFID " + mofId + " no longer exists.");
- } catch (StorageException e) {
- throw new DebugException(e.toString());
- }
- //return storableDelegate;
+
+ /* --------------------------------------------------------------------- */
+ /* -- Transaction related methods -------------------------------------- */
+ /* --------------------------------------------------------------------- */
+
+ protected final void _lock() {
+ _lock(true);
}
- protected final MdrStorage _getMdrStorage() {
- return mdrStorage;
+ protected final void _lock(boolean write) {
+ mdrStorage.getRepositoryMutex().enter(write);
+ }
+
+ protected final void _unlock() {
+ mdrStorage.getRepositoryMutex().leave();
}
- // Overriding the java.lang.object methods -----------------------------------
+ protected final void _unlock(boolean fail) {
+ mdrStorage.getRepositoryMutex().leave(fail);
+ }
+
+ /* --------------------------------------------------------------------- */
+ /* -- Implements org.netbeans.api.mdr.MDRObject ------------------------ */
+ /* --------------------------------------------------------------------- */
+
+ public final MDRepository repository() {
+ return mdrStorage.getRepository();
+ }
+
+ /* --------------------------------------------------------------------- */
+ /* -- Extends java.lang.Object ----------------------------------------- */
+ /* --------------------------------------------------------------------- */
public final boolean equals(Object obj) {
if (obj instanceof BaseObjectHandler) {
@@ -316,8 +396,10 @@
public final int hashCode() {
return refMofId().hashCode();
}
-
- // Implementation of the RefBaseObject ---------------------------------------
+
+ /* --------------------------------------------------------------------- */
+ /* -- Implements javax.jmi.reflect.RefBaseObject ----------------------- */
+ /* --------------------------------------------------------------------- */
public final RefObject refMetaObject() {
try {
@@ -360,10 +442,49 @@
else return _verify(new ArrayList());
}
+ /* --------------------------------------------------------------------- */
+ /* -- --------------------------------------------------- */
+ /* --------------------------------------------------------------------- */
+
+ public final StorableBaseObject _getDelegate() {
+/*
+ StorableBaseObject storable = (StorableBaseObject) storableDelegate.get();
+ if (storable == null) {
+ try {
+ storable = mdrStorage.getObject(mofId);
+ storableDelegate = new SoftReference(storable);
+ } catch (StorageException e) {
+ throw new DebugException("Storage exception: " + e);
+ }
+ }
+ */
+ try {
+ if (this.storable != null)
+ return this.storable;
+ else
+ return mdrStorage.getObject(mofId);
+ } catch (StorageBadRequestException e) {
+ throw new InvalidObjectException(null, "Object with MOFID " + mofId + " no longer exists.");
+ } catch (StorageException e) {
+ throw new DebugException(e.toString());
+ }
+ //return storableDelegate;
+ }
+
+ protected final MdrStorage _getMdrStorage() {
+ return mdrStorage;
+ }
+
+ /* --------------------------------------------------------------------- */
+ /* -- Methods to be overridden by sub-classes -------------------------- */
+ /* --------------------------------------------------------------------- */
+
protected abstract Collection _recursiveVerify(Collection violations, Set visited);
protected abstract Collection _verify(Collection violations);
- // private classes ---------------------------------------------
+ /* --------------------------------------------------------------------- */
+ /* -- FacilityCache (static inner class) ------------------------------- */
+ /* --------------------------------------------------------------------- */
/** Weak cache for created Handlers
*/
Index: src/org/netbeans/mdr/handlers/ClassProxyHandler.java
===================================================================
RCS file: /usr/local/cvs/case/netbeans/mdr/src/org/netbeans/mdr/handlers/ClassProxyHandler.java,v
retrieving revision 1.1.1.2
retrieving revision 1.4
diff -u -r1.1.1.2 -r1.4
--- src/org/netbeans/mdr/handlers/ClassProxyHandler.java 18 Jul 2002 08:37:25 -0000 1.1.1.2
+++ src/org/netbeans/mdr/handlers/ClassProxyHandler.java 18 Jul 2002 11:08:50 -0000 1.4
@@ -259,19 +259,37 @@
/* -- Implementation of org.netbeans.api.mdr.events.MDRChangeSource --- */
/* -------------------------------------------------------------------- */
- /** Registers a listener for receiving event notifications.
- * @param listener Object that implements {@link Listener} interface.
+ /** Registers a listener for receiving event notifications with are
+ * initially fired on this object.
+ * @param listener Object that implements {@link MDRChangeListener} interface.
*/
public void addListener(MDRChangeListener listener) {
- _getMdrStorage().getEventNotifier().CLASS.addListener(listener, this);
+ addListener(listener, MDRChangeEvent.EVENTMASK_ALL);
+ }
+
+ /** Registers a listener for receiving event notifications.
+ * @param listener Object that implements {@link MDRChangeListener} interface.
+ * @param mask bitmask to filter types of events the listener listens on
+ */
+ public void addListener(MDRChangeListener listener, int mask) {
+ _getMdrStorage().getEventNotifier().CLASS.addListener(listener, mask, this);
}
- /** Removes listener from the list of objects registered for events notifications.
- * @param listener Object that implements {@link Listener} interface.
+ /** Removes listener from the list of objects registered for event notifications.
+ * @param listener Object that implements {@link MDRChangeListener} interface.
*/
public void removeListener(MDRChangeListener listener) {
_getMdrStorage().getEventNotifier().CLASS.removeListener(listener, this);
}
+
+ /** Removes listener from the list of objects registered for event notifications.
+ * @param listener Object that implements {@link MDRChangeListener} interface.
+ * @param mask determines type of the events the listeners stops to listen on
+ */
+ public void removeListener(MDRChangeListener listener, int mask) {
+ _getMdrStorage().getEventNotifier().CLASS.removeListener(listener, mask, this);
+ }
+
/* -------------------------------------------------------------------- */
/* -- ClassProxyHandler.CreateInstanceEvent (inner class) ------------- */
/* -------------------------------------------------------------------- */
Index: src/org/netbeans/mdr/handlers/FeaturedHandler.java
===================================================================
RCS file: /usr/local/cvs/case/netbeans/mdr/src/org/netbeans/mdr/handlers/FeaturedHandler.java,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -r1.1.1.1 -r1.2
--- src/org/netbeans/mdr/handlers/FeaturedHandler.java 2 Jul 2002 07:35:27 -0000 1.1.1.1
+++ src/org/netbeans/mdr/handlers/FeaturedHandler.java 4 Jul 2002 12:50:07 -0000 1.2
@@ -88,7 +88,7 @@
}
- // Methods to refine for classes with the intercaptable tag set --------------
+ // Methods to refine for classes with the interceptable tag set --------------
protected void _interceptPreSet(String featureName, Object newValue) {
}
Index: src/org/netbeans/mdr/handlers/InstanceHandler.java
===================================================================
RCS file: /usr/local/cvs/case/netbeans/mdr/src/org/netbeans/mdr/handlers/InstanceHandler.java,v
retrieving revision 1.1.1.2
retrieving revision 1.4
diff -u -r1.1.1.2 -r1.4
--- src/org/netbeans/mdr/handlers/InstanceHandler.java 18 Jul 2002 08:37:25 -0000 1.1.1.2
+++ src/org/netbeans/mdr/handlers/InstanceHandler.java 18 Jul 2002 11:08:50 -0000 1.4
@@ -391,18 +391,35 @@
/* -- Implementation of org.netbeans.api.mdr.events.MDRChangeSource --- */
/* -------------------------------------------------------------------- */
- /** Registers a listener for receiving event notifications.
- * @param listener Object that implements {@link Listener} interface.
+ /** Registers a listener for receiving event notifications with are
+ * initially fired on this object.
+ * @param listener Object that implements {@link MDRChangeListener} interface.
*/
public void addListener(MDRChangeListener listener) {
- _getMdrStorage().getEventNotifier().INSTANCE.addListener(listener, this);
+ addListener(listener, MDRChangeEvent.EVENTMASK_ALL);
+ }
+
+ /** Registers a listener for receiving event notifications.
+ * @param listener Object that implements {@link MDRChangeListener} interface.
+ * @param mask bitmask to filter types of events the listener listens on
+ */
+ public void addListener(MDRChangeListener listener, int mask) {
+ _getMdrStorage().getEventNotifier().INSTANCE.addListener(listener, mask, this);
}
- /** Removes listener from the list of objects registered for events notifications.
- * @param listener Object that implements {@link Listener} interface.
+ /** Removes listener from the list of objects registered for event notifications.
+ * @param listener Object that implements {@link MDRChangeListener} interface.
*/
public void removeListener(MDRChangeListener listener) {
_getMdrStorage().getEventNotifier().INSTANCE.removeListener(listener, this);
+ }
+
+ /** Removes listener from the list of objects registered for event notifications.
+ * @param listener Object that implements {@link MDRChangeListener} interface.
+ * @param mask determines type of the events the listeners stops to listen on
+ */
+ public void removeListener(MDRChangeListener listener, int mask) {
+ _getMdrStorage().getEventNotifier().INSTANCE.removeListener(listener, mask, this);
}
/* ---------------------------------------------------------------- */
Index: src/org/netbeans/mdr/handlers/PackageProxyHandler.java
===================================================================
RCS file: /usr/local/cvs/case/netbeans/mdr/src/org/netbeans/mdr/handlers/PackageProxyHandler.java,v
retrieving revision 1.1.1.2
retrieving revision 1.4
diff -u -r1.1.1.2 -r1.4
--- src/org/netbeans/mdr/handlers/PackageProxyHandler.java 18 Jul 2002 08:37:25 -0000 1.1.1.2
+++ src/org/netbeans/mdr/handlers/PackageProxyHandler.java 18 Jul 2002 11:08:50 -0000 1.4
@@ -387,19 +387,36 @@
/* -------------------------------------------------------------------- */
/* -- Implementation of org.netbeans.api.mdr.events.MDRChangeSource --- */
/* -------------------------------------------------------------------- */
-
- /** Registers a listener for receiving event notifications.
- * @param listener Object that implements {@link Listener} interface.
+
+ /** Registers a listener for receiving event notifications with are
+ * initially fired on this object.
+ * @param listener Object that implements {@link MDRChangeListener} interface.
*/
public void addListener(MDRChangeListener listener) {
- _getMdrStorage().getEventNotifier().PACKAGE.addListener(listener, this);
+ addListener(listener, MDRChangeEvent.EVENTMASK_ALL);
}
- /** Removes listener from the list of objects registered for events notifications.
- * @param listener Object that implements {@link Listener} interface.
+ /** Registers a listener for receiving event notifications.
+ * @param listener Object that implements {@link MDRChangeListener} interface.
+ * @param mask bitmask to filter types of events the listener listens on
+ */
+ public void addListener(MDRChangeListener listener, int mask) {
+ _getMdrStorage().getEventNotifier().PACKAGE.addListener(listener, mask, this);
+ }
+
+ /** Removes listener from the list of objects registered for event notifications.
+ * @param listener Object that implements {@link MDRChangeListener} interface.
*/
public void removeListener(MDRChangeListener listener) {
_getMdrStorage().getEventNotifier().PACKAGE.removeListener(listener, this);
+ }
+
+ /** Removes listener from the list of objects registered for event notifications.
+ * @param listener Object that implements {@link MDRChangeListener} interface.
+ * @param mask determines type of the events the listeners stops to listen on
+ */
+ public void removeListener(MDRChangeListener listener, int mask) {
+ _getMdrStorage().getEventNotifier().PACKAGE.removeListener(listener, mask, this);
}
/* ---------------------------------------------------------------- */
Index: src/org/netbeans/mdr/handlers/StructGenerator.java
===================================================================
RCS file: /usr/local/cvs/case/netbeans/mdr/src/org/netbeans/mdr/handlers/StructGenerator.java,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -r1.1.1.1 -r1.2
--- src/org/netbeans/mdr/handlers/StructGenerator.java 2 Jul 2002 07:35:27 -0000 1.1.1.1
+++ src/org/netbeans/mdr/handlers/StructGenerator.java 10 Jul 2002 08:35:59 -0000 1.2
@@ -19,6 +19,7 @@
import java.util.*;
/**
+ * [XXX]: put this class into correct package !
*
* @author mmatula
* @version
@@ -32,12 +33,12 @@
private static final String CONSTRUCTOR_DESCRIPTOR = "(Ljava/util/List;Ljava/util/Map;Ljava/util/List;)V";
- private StructGenerator(String className, Class ifc) {
- super(className, ifc, StructImpl.class);
+ private StructGenerator(String className, Class ifc, Class superClass) {
+ super(className, ifc, superClass);
}
- public static byte[] generateStruct(final String name, Class ifc) {
- StructGenerator gen = new StructGenerator(name, ifc);
+ public static byte[] generateStruct(final String name, Class ifc, Class superClass) {
+ StructGenerator gen = new StructGenerator(name, ifc, superClass);
final byte[] classFile = gen.generateClassFile();
return classFile;
Index: src/org/netbeans/mdr/handlers/StructImpl.java
===================================================================
RCS file: /usr/local/cvs/case/netbeans/mdr/src/org/netbeans/mdr/handlers/StructImpl.java,v
retrieving revision 1.1.1.1
retrieving revision 1.4
diff -u -r1.1.1.1 -r1.4
--- src/org/netbeans/mdr/handlers/StructImpl.java 2 Jul 2002 07:35:27 -0000 1.1.1.1
+++ src/org/netbeans/mdr/handlers/StructImpl.java 10 Jul 2002 08:38:57 -0000 1.4
@@ -1,11 +1,11 @@
/*
* 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.
@@ -22,18 +22,30 @@
import org.netbeans.mdr.storagemodel.*;
/**
+ * Abstract base class for generated structure implementations.
+ *
+ * [XXX]: Replacing this class by a repository parameter is not yet
+ * implemented. The problem is, that in {@link #newInstance(Class, List, Map, List)}
+ * there is no access to the MdrStorage
which holds this parameter.
ifc
.
+ *
+ * @param loader the class-loader for the definition of the implementation class
+ * @param ifc the interface to be implementated by the implementation class
+ * @param superClass the super class for structure implementations
+ * @return a class implementing ifc
+ */
+ private static Class getStructClass(MDRClassLoader loader, Class ifc, Class superClass) throws IllegalArgumentException {
check(loader, ifc);
Map cache = getLoaderCache(loader);
String className = getName(ifc);
@@ -41,7 +53,7 @@
if (result == null) {
try {
- byte[] structClassFile = StructGenerator.generateStruct(className, ifc);
+ byte[] structClassFile = StructGenerator.generateStruct(className, ifc, superClass);
result = loader.defineClass(className, structClassFile);
} finally {
releaseCache(cache, result, className);
@@ -51,6 +63,10 @@
return result;
}
+ private static Class getStructClass(MDRClassLoader loader, Class ifc) throws IllegalArgumentException {
+ return getStructClass(loader, ifc, StructImpl.class);
+ }
+
public static RefStruct newInstance(DatatypeDescriptor dataType, Object fieldValues[]) {
try {
HashMap values = new HashMap(fieldValues.length, 1);
@@ -70,50 +86,81 @@
}
}
+ /**
+ * @param ifc the specific JMI interface for the structure type
+ * @param fields list of field names
+ * @param values maps field names to field values
+ * @param qualifiedName fully qualified name of the structure type
+ */
public static RefStruct newInstance(Class ifc, List fields, Map values, List qualifiedName) {
MDRClassLoader loader = BaseObjectHandler.getDefaultClassLoader();
- Class cl = getStructClass(loader, ifc);
-
+ Class cl = getStructClass(loader, ifc, StructImpl.class);
+
try {
Constructor cons = cl.getConstructor(new Class[] {List.class, Map.class, List.class});
RefStruct struct = (RefStruct) cons.newInstance(new Object[] {fields, values, qualifiedName});
-
+
return struct;
- } catch (NoSuchMethodException e) {
+ } catch (NoSuchMethodException e) {
e.printStackTrace();
- throw new DebugException(e.toString());
- } catch (IllegalAccessException e) {
+ throw new DebugException(e.toString());
+ } catch (IllegalAccessException e) {
e.printStackTrace();
- throw new DebugException(e.toString());
- } catch (InstantiationException e) {
+ throw new DebugException(e.toString());
+ } catch (InstantiationException e) {
e.printStackTrace();
- throw new DebugException(e.toString());
- } catch (InvocationTargetException e) {
+ throw new DebugException(e.toString());
+ } catch (InvocationTargetException e) {
e.printStackTrace();
- throw new DebugException(e.toString());
- }
+ throw new DebugException(e.toString());
+ }
}
-
+
+ /* -------------------------------------------------------------------- */
+ /* -- Attributes (private) -------------------------------------------- */
+ /* -------------------------------------------------------------------- */
+
+ /**
+ * Field names
+ */
+ private final List fields;
+ /**
+ * Field names => values
+ */
+ private final Map values;
+ /**
+ * Fully qualified name of metaobject
+ */
+ private final List qualifiedName;
+
+ /* -------------------------------------------------------------------- */
+ /* -- Constructor (protected) ----------------------------------------- */
+ /* -------------------------------------------------------------------- */
+
/** Creates new StructHandler */
protected StructImpl(List fields, Map values, List qualifiedName) {
this.values = values;
- this.qualifiedName = Collections.unmodifiableList(qualifiedName);
- this.fields = Collections.unmodifiableList(fields);
+ this.qualifiedName = qualifiedName;
+ this.fields = fields;
}
-
- // --- handler methods
-
+
+ /* -------------------------------------------------------------------- */
+ /* -- Methods to be called by generated classes ----------------------- */
+ /* -------------------------------------------------------------------- */
+
protected Object handleGet(String memberName) {
return refGetValue(memberName);
}
-
- // --- implementation of RefStruct interface -------------------------------
-
+
+ /* -------------------------------------------------------------------- */
+ /* -- Implements of javax.jmi.reflect.RefStruct ----------------------- */
+ /* -------------------------------------------------------------------- */
+
public Object refGetValue(String memberName) {
if (values.containsKey(memberName)) {
return values.get(memberName);
} else {
- throw new DebugException("Wrong item name: " + memberName);
+ throw new InvalidNameException(memberName);
}
}
@@ -124,7 +171,13 @@
public List refTypeName() {
return this.qualifiedName;
}
-
+
+ /* -------------------------------------------------------------------- */
+ /* -- Extends java.lang.Object ---------------------------------------- */
+ /* -------------------------------------------------------------------- */
+
+ // [XXX]: hashCode() must be implemented, too !
+
public boolean equals(Object other) {
// check whether other is instance of the same structure
if ((other instanceof RefStruct) && ((RefStruct) other).refTypeName().equals(qualifiedName)) {
Index: src/org/netbeans/mdr/handlers/gen/HandlerGenerator.java
===================================================================
RCS file: /usr/local/cvs/case/netbeans/mdr/src/org/netbeans/mdr/handlers/gen/HandlerGenerator.java,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -r1.1.1.1 -r1.2
--- src/org/netbeans/mdr/handlers/gen/HandlerGenerator.java 2 Jul 2002 07:35:27 -0000 1.1.1.1
+++ src/org/netbeans/mdr/handlers/gen/HandlerGenerator.java 4 Jul 2002 13:00:57 -0000 1.2
@@ -56,6 +56,11 @@
/**
* Generate a handler class given a name, interface and storable object to
* be wrapped by a handler object.
+ *
+ * @param name the name of the handler class
+ * @param ifc JMI interface to be implemented by the handler class
+ * @param storable informs about the super-class for the handler class
+ * @return the byte code for the class implementing ifc
*/
public static byte[] generateHandler(final String name, Class ifc, StorableBaseObject storable) {
HandlerGenerator gen;
@@ -65,7 +70,7 @@
} else if (storable instanceof StorableClass) {
gen = new ClassGenerator(name, ifc, ((StorableClass) storable).getClassSuperclass(), (StorableClass)storable);
} else if (storable instanceof StorablePackage) {
- gen = new PackageGenerator(name, ifc, PackageProxyHandler.class, (StorablePackage)storable);
+ gen = new PackageGenerator(name, ifc, ((StorablePackage)storable).getPackageSuperclass(), (StorablePackage)storable);
} else if (storable instanceof StorableObject) {
gen = new InstanceGenerator(name, ifc, ((StorableObject) storable).getClassProxy().getInstanceSuperclass(), (StorableObject)storable);
} else {
Index: src/org/netbeans/mdr/persistence/MultivaluedIndex.java
===================================================================
RCS file: /usr/local/cvs/case/netbeans/mdr/src/org/netbeans/mdr/persistence/MultivaluedIndex.java,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -r1.1.1.1 -r1.2
--- src/org/netbeans/mdr/persistence/MultivaluedIndex.java 2 Jul 2002 07:35:27 -0000 1.1.1.1
+++ src/org/netbeans/mdr/persistence/MultivaluedIndex.java 10 Jul 2002 14:56:48 -0000 1.2
@@ -19,7 +19,7 @@
*/
public interface MultivaluedIndex extends Index {
/** Returns a collection view of the values associated in the index with specified key.
- * Returned collection is read only and may not be modified.
+ * Returned collection is live and modifiable.
* If there are no values associated with the key empty collection is returned.
* @return
* @param key
Index: src/org/netbeans/mdr/persistence/MultivaluedOrderedIndex.java
===================================================================
RCS file: /usr/local/cvs/case/netbeans/mdr/src/org/netbeans/mdr/persistence/MultivaluedOrderedIndex.java,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -r1.1.1.1 -r1.2
--- src/org/netbeans/mdr/persistence/MultivaluedOrderedIndex.java 2 Jul 2002 07:35:27 -0000 1.1.1.1
+++ src/org/netbeans/mdr/persistence/MultivaluedOrderedIndex.java 10 Jul 2002 14:56:48 -0000 1.2
@@ -19,7 +19,7 @@
*/
public interface MultivaluedOrderedIndex extends MultivaluedIndex {
/** Returns a list view of the values assosiated in the index with specified key.
- * Returned collection is read only and may not be modified.
+ * Returned collection is live and modifiable.
* If there are no values associated with the key empty collection is returned.
* @param key
* @return
Index: src/org/netbeans/mdr/shell/Main.java
===================================================================
RCS file: /usr/local/cvs/case/netbeans/mdr/src/org/netbeans/mdr/shell/Main.java,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -r1.1.1.1 -r1.2
--- src/org/netbeans/mdr/shell/Main.java 2 Jul 2002 07:35:29 -0000 1.1.1.1
+++ src/org/netbeans/mdr/shell/Main.java 4 Jul 2002 06:24:44 -0000 1.2
@@ -1,17 +1,21 @@
/*
* 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.shell;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.InputStream;
+
import java.util.Collection;
import java.util.ArrayList;
import java.util.Iterator;
@@ -29,12 +33,46 @@
import javax.jmi.reflect.*;
public class Main extends Object {
- public static void main( String[] args ) {
+
+ /**
+ * Resources names of the standard library files
+ */
+ public static String[] STANDARD_LIBS = new String[] { "resources/start.ms", "resources/ext.ms" };
+
+ /**
+ * Command line interface of the MDRShell. The MDRShell is a
+ * Dynamic Java shell with preprocessor. Before user input
+ * is processed the files start.ms
and ext.ms
+ * in the package org.netbeans.mdr.shell.resources
and the
+ * files given as command line arguments are processed.
+ *
+ * @param args a list of file names read into the shell
+ * @throws FileNotFoundException if one of the arguments does not denote a
+ * valid file name
+ * @throws SecurityException if there is no read access to a file given as
+ * argument
+ */
+ public static void main( String[] args ) throws FileNotFoundException {
+ /* the input streams */
+ InputStream[] iss = new InputStream[STANDARD_LIBS.length+args.length+1];
+
+ /* standard library files */
+ for ( int i=0; iSystem.in
is used.
*/
public void run( InputStream is ) {
+ run( new InputStream[] { is } );
+ }
+
+ /** Starts interpretting commands in the InputStreams.
+ * @param iss InputStreams to read commands from. If null
+ * System.in
is used.
+ */
+ public void run( InputStream[] iss ) {
- pushInput( is == null ? System.in : is );
+ if ( iss == null ) {
+ pushInput(System.in);
+ } else {
+ for ( int i = iss.length-1; i >= 0; i-- ) {
+ pushInput(iss[i]);
+ }
+ }
DJava.initialize();
DJava.declareVariable( "SHELL", this );
Index: src/org/netbeans/mdr/storagemodel/BootReader.java
===================================================================
RCS file: /usr/local/cvs/case/netbeans/mdr/src/org/netbeans/mdr/storagemodel/BootReader.java,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -r1.1.1.1 -r1.2
--- src/org/netbeans/mdr/storagemodel/BootReader.java 2 Jul 2002 07:35:30 -0000 1.1.1.1
+++ src/org/netbeans/mdr/storagemodel/BootReader.java 9 Jul 2002 14:44:52 -0000 1.2
@@ -159,7 +159,6 @@
private Collection createInstances(Node xmiContent) {
XmiUtils.XmiNodeIterator classes = new XmiUtils.XmiNodeIterator(xmiContent);
Collection result = createInstances(classes, null, "", null);
- classes = new XmiUtils.XmiNodeIterator(xmiContent);
resolveSuperClasses();
resolveReferences();
setValues();
Index: src/org/netbeans/mdr/storagemodel/CompositeCollection.java
===================================================================
RCS file: /usr/local/cvs/case/netbeans/mdr/src/org/netbeans/mdr/storagemodel/CompositeCollection.java,v
retrieving revision 1.1.1.1
retrieving revision 1.3
diff -u -r1.1.1.1 -r1.3
--- src/org/netbeans/mdr/storagemodel/CompositeCollection.java 2 Jul 2002 07:35:30 -0000 1.1.1.1
+++ src/org/netbeans/mdr/storagemodel/CompositeCollection.java 11 Jul 2002 09:26:54 -0000 1.3
@@ -23,8 +23,8 @@
import org.netbeans.mdr.util.*;
/**
- * Instances of CompositeCollection
are collections uniting several
- * other collections. The methods of this class must be called in the following
+ * Instances of CompositeCollection
are immutable collections uniting
+ * several other collections. The methods of this class must be called in the following
* order:
*
* It is not allowed to add further collections after any of the accessors has + * been called.
+ * + *Because the collections added using @link addCollection(Collection} are added
+ * as is and their members are accessed only, when to be returned by methods of
+ * this class resp. its {@link Iterator}, instances of CompositeCollection
+ * are live if and only if all of the composed collections are live.
[XXX]: Put this class into org.netbeans.mdr.util
+ * package.
MdrStorage
using factory storageClass
- * and parameters properties
. Creates a default storage, if the
- * storageClass
is not a
+ /** Creates a new MdrStorage
using factory storageFactoryClassName
+ * and parameters params
. Creates a default storage, if the
+ * storageFactoryClassName
is not a
* {@link org.netbeans.mdr.persistence.StorageFactory} or cannot be instantiated.
*
* @param repository
- * @param storageClass fully qualified name of class implementing
+ * @param storageFactoryClassName fully qualified name of class implementing
* {@link org.netbeans.mdr.persistence.StorageFactory}
- * @param properties parameters for storage creation
+ * @param params parameters for storage creation
* @exception DebugException if the storage cannot be created
*/
- public MdrStorage(NBMDRepositoryImpl repository, String storageClass, Map properties) {
+ public MdrStorage(NBMDRepositoryImpl repository, String storageFactoryClassName, Map params) {
this.storages = new HashMap();
this.nullMofId = new HashMap();
this.objects = new HashMap();
@@ -223,10 +379,12 @@
this.valuesObjects = new HashMap();
this.repository = repository;
+
+ this.params = params;
StorageFactory storageFactory = null;
try {
// try to instantiate storage factory (its class name was passed as storageClass argument)
- Class storageFactoryClass = Class.forName(storageClass);
+ Class storageFactoryClass = Class.forName(storageFactoryClassName);
// does the class implement StorageFactory interface?
if (StorageFactory.class.isAssignableFrom(storageFactoryClass)) {
// yes - create new instance
@@ -234,7 +392,7 @@
} 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");
+ throw new Exception("class "+storageFactoryClassName+" does not implement StorageFactory");
}
} catch (Exception e) {
// in case the passed StorageFactory class could not be created, create default implementation
@@ -246,7 +404,7 @@
try {
// create storage passing the parameters to the factory method
- this.bootStorage = storageFactory.createStorage(properties);
+ this.bootStorage = storageFactory.createStorage(params);
// cache the NULL MOFID of the boot storage
this.bootNullMofId = storageFactory.createNullMOFID();
} catch (StorageException e) {
@@ -256,7 +414,7 @@
// create the utilities for storage management
eventNotifier = new EventNotifier();
- repositoryMutex = new TransactionMutex(this, eventNotifier);
+ repositoryMutex = new TransactionMutex(this, eventNotifier, repository);
}
/* -------------------------------------------------------------------- */
@@ -329,7 +487,6 @@
/* -- 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.
@@ -910,7 +1067,7 @@
*
* @param context
* @param indexName
- * @return the index for the given attribute or null
*/
+ * @return the index for the given attribute or null
*/
private MultivaluedIndex getAdditionalIndex(String context, String indexName) {
try {
Storage storage = getStorageByMofId(context);
@@ -1234,7 +1391,7 @@
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;
@@ -1255,7 +1412,7 @@
}
bootStorage.dropIndex(oldAttributeIndex.getName());
}
- */
+ */
Object key;
String newValue;
@@ -1515,7 +1672,7 @@
private String getContextAssocEndIndexName(String context, String assocMofId, int end) {
return PREFIX_ASSOC_END + context + ":" + assocMofId + end;
}
-
+
public Storage getStorageByMofId(String mofId) {
String storageId = getStorageIdFromMofId(mofId);
if (storageId == null) {
@@ -1564,13 +1721,13 @@
/** Transient support **/
void registerTransientObjectsContainer(String mofId, TransientStorableClass tsc) {
- org.netbeans.mdr.storagemodel.transientimpl.TransientObjectResolverIndex tir = (org.netbeans.mdr.storagemodel.transientimpl.TransientObjectResolverIndex)
- this.objects.get (org.netbeans.mdr.storagemodel.transientimpl.MOFID.TRANSIENT_STORAGE_PREFIX);
+ org.netbeans.mdr.storagemodel.transientimpl.TransientObjectResolverIndex tir = (org.netbeans.mdr.storagemodel.transientimpl.TransientObjectResolverIndex)
+ this.objects.get(org.netbeans.mdr.storagemodel.transientimpl.MOFID.TRANSIENT_STORAGE_PREFIX);
if (tir == null) {
- tir = new org.netbeans.mdr.storagemodel.transientimpl.TransientObjectResolverIndex ();
- this.objects.put (org.netbeans.mdr.storagemodel.transientimpl.MOFID.TRANSIENT_STORAGE_PREFIX, tir);
+ tir = new org.netbeans.mdr.storagemodel.transientimpl.TransientObjectResolverIndex();
+ this.objects.put(org.netbeans.mdr.storagemodel.transientimpl.MOFID.TRANSIENT_STORAGE_PREFIX, tir);
}
- tir.register (mofId, tsc);
+ tir.register(mofId, tsc);
}
void unregisterTransientObjectsContainer(String mofId) throws StorageException {
Index: src/org/netbeans/mdr/storagemodel/StorableAssociation.java
===================================================================
RCS file: /usr/local/cvs/case/netbeans/mdr/src/org/netbeans/mdr/storagemodel/StorableAssociation.java,v
retrieving revision 1.1.1.2
retrieving revision 1.5
diff -u -r1.1.1.2 -r1.5
--- src/org/netbeans/mdr/storagemodel/StorableAssociation.java 10 Jul 2002 08:05:48 -0000 1.1.1.2
+++ src/org/netbeans/mdr/storagemodel/StorableAssociation.java 12 Jul 2002 10:02:58 -0000 1.5
@@ -150,7 +150,7 @@
if (((Boolean) getMetaObject().getAttribute(MOFConstants.SH_MODEL_ASSOCIATION_IS_DERIVED)).booleanValue() || TagSupport.getTagValue(getMetaObject(), INTERCEPTABLE_TAG_ID, "").equals("true"))
return BaseObjectHandler.resolveImplementation(TagSupport.getImplFullName(getMetaObject(), TagSupport.ASSOCIATION));
else
- return AssociationHandler.class;
+ return getMdrStorage().getAssociationHandlerClass();
}
/** Returns multiplicity of the first association end.
@@ -246,26 +246,14 @@
}
/**
+ * Returns immutable, live collection of all links managed by this association
+ * proxy.
+ *
* @throws StorageException
- * @return
+ * @return immutable, live collection of all links
*/
public Collection getAllLinks() throws StorageException {
- ArrayList allLinks = new ArrayList ();
-
- for (Iterator it = bIndex.keySet().iterator (); it.hasNext();) {
- String a = (String) it.next();
- if (isMultivaluedB()) {
- Collection bees = getMdrStorage().getObjectsFromIndex((MultivaluedIndex) bIndex, a);
- for (Iterator it2 = bees.iterator (); it2.hasNext();){
- AssociationLink oneLink = new AssociationLink((StorableObject) getMdrStorage().getObject(a), (StorableObject) it2.next());
- allLinks.add(oneLink);
- }
- } else {
- AssociationLink oneLink = new AssociationLink((StorableObject) getMdrStorage().getObject(a), (StorableObject) getMdrStorage().getObjectFromIndexIfExists((SinglevaluedIndex) bIndex, a));
- allLinks.add(oneLink);
- }
- }
- return Collections.unmodifiableCollection(allLinks);
+ return new LinkSetCollection();
}
/**
@@ -567,5 +555,155 @@
e.printStackTrace();
throw new RuntimeException();
}
+ }
+
+ /* --------------------------------------------------------------------- */
+ /* -- LinkSetCollection (inner class) ---------------------------------- */
+ /* --------------------------------------------------------------------- */
+
+ protected class LinkSetCollection extends AbstractCollection {
+
+ public Iterator iterator() {
+ return new LinkSetIterator();
+ }
+
+ public int size() {
+ int size = 0;
+ LinkSetIterator it = new LinkSetIterator();
+ it.initCheck();
+ while (it.b != null) {
+ size++;
+ it.fetchNext();
+ }
+ return size;
+ }
+ }
+
+ /* --------------------------------------------------------------------- */
+ /* -- LinkSetIterator (inner class) ------------------------------------ */
+ /* --------------------------------------------------------------------- */
+
+ protected class LinkSetIterator implements Iterator {
+
+ boolean initialized = false;
+
+ /**
+ * Iterator through all instances at the a-side of this association or
+ * null
before the first access or if a storage problem
+ * occured.
+ */
+ Iterator as = null;
+
+ /**
+ * MOF ID of the current instance at the a side. null
+ * only before the first call to fetchNext()
.
+ */
+ String aID = null;
+
+ /**
+ * Object with ID aID
or null
if not yet
+ * retrieved.
+ */
+ StorableObject a = null;
+
+ /**
+ * If the association if multi-valued at b's end, bs
+ * contains the iterator for the b's associated with the current a.
+ * Shall only be accessed inside fetchNext()
.
+ */
+ Iterator bs = null;
+
+ /**
+ * The current b object, null
initially and after the
+ * last link has been retrieved.
+ */
+ StorableObject b = null;
+
+ private void initCheck() {
+ if ( ! initialized ) {
+ initialized = true;
+ try {
+ as = bIndex.keySet().iterator();
+ } catch ( StorageException se ) {
+ // [XXX]: probably throw a DebugException here
+ as = null;
+ }
+ fetchNext();
+ }
+ }
+
+ private void fetchNext() {
+ if ( as == null ) {
+ return;
+ }
+ b = null;
+ // check if there is yet another b for the current a
+ if ( bs != null ) {
+ if ( bs.hasNext() ) {
+ b = (StorableObject) bs.next();
+ return;
+ }
+ }
+
+ try {
+ // fetch the next a
+ while ( as.hasNext() ) {
+ aID = (String) as.next();
+ a = null;
+ // fetch the first b for the given a, if exists
+ if ( isMultivaluedB() ) {
+ bs = getMdrStorage().getObjectsFromIndex((MultivaluedIndex) bIndex, aID).iterator();
+ if ( bs.hasNext() ) {
+ b = (StorableObject) bs.next();
+ }
+ } else {
+ b = (StorableObject) getMdrStorage().getObjectFromIndexIfExists((SinglevaluedIndex) bIndex, aID);
+ }
+ // check, if a b was found, return, if yes
+ if ( b != null ) {
+ return;
+ }
+ }
+ } catch (StorageException se) {
+ // [XXX]: probably throw a DebugException here
+ as = null;
+ b = null;
+ }
+
+ // there are not more links !
+ return;
+ }
+
+ public boolean hasNext() {
+ initCheck();
+ return b != null;
+ }
+
+ public Object next() {
+ initCheck();
+ if ( b == null ) {
+ throw new NoSuchElementException();
+ }
+ if ( a == null ) {
+ try {
+ a = (StorableObject) getMdrStorage().getObject(aID);
+ } catch (StorageException se) {
+ // {XXX]: better exception handling
+ se.printStackTrace();
+ throw new DebugException();
+ }
+ }
+ AssociationLink link = new AssociationLink(a,b);
+ fetchNext();
+ return link;
+ }
+
+ /**
+ * operation not supported
+ */
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+
}
}
Index: src/org/netbeans/mdr/storagemodel/StorableClass.java
===================================================================
RCS file: /usr/local/cvs/case/netbeans/mdr/src/org/netbeans/mdr/storagemodel/StorableClass.java,v
retrieving revision 1.1.1.3
retrieving revision 1.5
diff -u -r1.1.1.3 -r1.5
--- src/org/netbeans/mdr/storagemodel/StorableClass.java 18 Jul 2002 08:37:28 -0000 1.1.1.3
+++ src/org/netbeans/mdr/storagemodel/StorableClass.java 18 Jul 2002 10:06:32 -0000 1.5
@@ -224,9 +224,13 @@
return (DatatypeDescriptor) datatypes.get(name);
}
- /** Returns all instances of MOF class represented by this proxy within the current context.
+ /** Returns immutable, live collection of all instances of MOF class
+ * represented by this proxy.
+ *
+ * @param subclasses if true
also the instances of sub-classes
+ * will be returned, otherwise only the instances of the current class
+ * @return collection of instances of this class (and its sub-classes)
* @throws StorageException problem in storage
- * @return collection of instances
*/
public Collection allObjects(boolean subclasses) throws StorageException {
if (subclasses) {
@@ -240,10 +244,18 @@
}
}
+ /**
+ * Adds the instances of this class and its super-classes to result
+ * and adds the MOF IDs of all visited class proxies to visited
.
+ * Instances of a class already being a member of visited
are
+ * not added to result
a second time.
+ *
+ * @param result the collection where to add the instances
+ * @param visited MOF IDs of class proxies already visited
+ */
private void collectObjects(CompositeCollection result, Set visited) throws StorageException {
- if (!visited.contains(getMofId())) {
+ if (visited.add(getMofId())) {
result.addCollection(allObjects(false));
- visited.add(getMofId());
for (Iterator it = subclasses.iterator(); it.hasNext();) {
((StorableClass) getMdrStorage().getObject((String) it.next())).collectObjects(result, visited);
}
@@ -449,6 +461,9 @@
visited.add(getMofId());
}
+ /**
+ * Returns the super-class for generated handler classes.
+ */
public Class getClassSuperclass() throws StorageException, ClassNotFoundException {
if (classSuperclass == null) {
synchronized (superclassMutex) {
@@ -485,6 +500,23 @@
return false;
}
+ /**
+ * Returns the implementation super-class for the generated handler.
+ *
+ * If the class has derived or inceptable members, {@link + * TagSupport#getImplFullName(StorableObject, int)} determines the class + * name.
+ * + *If this model class has model super-classes then the return value + * depends on if there is a most specific implementation class among the + * implementation classes of those super-classes. If yes, this most + * specific implementation class is returned, otherwise {@link + * TagSupport#getImplFullName(StorableObject, int)} determines the class + * name.
+ * + *If non of the cases above applies, ClassProxyHandler.class
+ * is returned as default value.
[XXX]: Probably this method should be used to a test utility + * class ?!
+ */ + public static String prettyPrintMask(int mask) { + StringBuffer buf = new StringBuffer(); + if ( (mask & AttributeEvent.EVENT_ATTRIBUTE_ADD) == AttributeEvent.EVENT_ATTRIBUTE_ADD ) buf.append("IAA "); + if ( (mask & AttributeEvent.EVENT_ATTRIBUTE_REMOVE) == AttributeEvent.EVENT_ATTRIBUTE_REMOVE ) buf.append("IAR "); + if ( (mask & AttributeEvent.EVENT_ATTRIBUTE_SET) == AttributeEvent.EVENT_ATTRIBUTE_SET ) buf.append("IAS "); + if ( (mask & AttributeEvent.EVENT_CLASSATTR_ADD) == AttributeEvent.EVENT_CLASSATTR_ADD ) buf.append("CAA "); + if ( (mask & AttributeEvent.EVENT_CLASSATTR_REMOVE) == AttributeEvent.EVENT_CLASSATTR_REMOVE ) buf.append("CAR "); + if ( (mask & AttributeEvent.EVENT_CLASSATTR_SET) == AttributeEvent.EVENT_CLASSATTR_SET ) buf.append("CAS "); + if ( (mask & InstanceEvent.EVENT_INSTANCE_CREATE) == InstanceEvent.EVENT_INSTANCE_CREATE ) buf.append("IC "); + if ( (mask & InstanceEvent.EVENT_INSTANCE_DELETE) == InstanceEvent.EVENT_INSTANCE_DELETE ) buf.append("ID "); + if ( (mask & AssociationEvent.EVENT_ASSOCIATION_ADD) == AssociationEvent.EVENT_ASSOCIATION_ADD ) buf.append("AA "); + if ( (mask & AssociationEvent.EVENT_ASSOCIATION_REMOVE) == AssociationEvent.EVENT_ASSOCIATION_REMOVE ) buf.append("AR "); + if ( (mask & AssociationEvent.EVENT_ASSOCIATION_SET) == AssociationEvent.EVENT_ASSOCIATION_SET ) buf.append("AS "); + if ( (mask & ExtentEvent.EVENT_EXTENT_CREATE) == ExtentEvent.EVENT_EXTENT_CREATE ) buf.append("EC "); + if ( (mask & ExtentEvent.EVENT_EXTENT_DELETE) == ExtentEvent.EVENT_EXTENT_DELETE ) buf.append("ED "); + if ( (mask & TransactionEvent.EVENT_TRANSACTION_COMMIT) == TransactionEvent.EVENT_TRANSACTION_COMMIT ) buf.append("TC "); + if ( (mask & TransactionEvent.EVENT_TRANSACTION_ROLLBACK) == TransactionEvent.EVENT_TRANSACTION_ROLLBACK ) buf.append("TR "); + if ( (mask & TransactionEvent.EVENT_TRANSACTION_START) == TransactionEvent.EVENT_TRANSACTION_START ) buf.append("TS "); + if ( buf.length() > 0 ) buf.deleteCharAt(buf.length()-1); + return buf.toString(); + } + + /* -------------------------------------------------------------------- */ + /* -- Public attributes ----------------------------------------------- */ + /* -------------------------------------------------------------------- */ + + public final Association ASSOCIATION = new Association(); + public final Clazz CLASS = new Clazz(); + public final Instance INSTANCE = new Instance(); + public final Package PACKAGE = new Package(); + public final Repository REPOSITORY = new Repository(); + + /* -------------------------------------------------------------------- */ + /* -- Private attributes ---------------------------------------------- */ + /* -------------------------------------------------------------------- */ + + /** + * Thread for the dispatching of events after transaction success. + */ + private final Thread dispatcher = new Thread(new EventsDelivery()); + + /** + * Maps: event => instance ofQueuedListenerSet
.
+ */
+ private final Hashtable queuedListenerMap = new Hashtable();
+
+ /**
+ * Queue for the events of the currently running write transaction.
+ * The events are stored to inform their listeners either about
+ * rollback or success.
+ */
+ private final LinkedList localQueue = new LinkedList();
+
+ /**
+ * Queue for the events of successfully finished transactions, the
+ * listeners of which still have to be informed.
+ */
+ private final LinkedList globalQueue = new LinkedList();
+
+ /* -------------------------------------------------------------------- */
+ /* -- Constructor (public) -------------------------------------------- */
+ /* -------------------------------------------------------------------- */
+
+ /**
+ * Starts the dispatcher thread as daemon.
+ */
+ public EventNotifier() {
+ dispatcher.setDaemon(true);
+ dispatcher.start();
+ }
+
+ /* -------------------------------------------------------------------- */
+ /* -- Methods to fire events at transaction commit or rollback time --- */
+ /* -------------------------------------------------------------------- */
+
+ /**
+ * Calls {@link MDRPreChangeListener.changeCancelled(MDRChangeEvent)} for
+ * all pre-change listeners on event
to inform them
+ * about cancelling the event.
+ */
+ public void fireCancelled(MDRChangeEvent event) {
+ localQueue.remove(event);
+ QueuedListenerSet collected = (QueuedListenerSet) queuedListenerMap.remove(event);
+ if (collected == null) {
+ System.err.println("Change cancelled event not corresponding to any planned change event.");
+ Thread.dumpStack();
+ return;
+ }
+ // fire changeCancelled event
+ for (QueuedListenerSet.PreListenerIterator it = collected.preListenerIterator(); it.hasNext();) {
+ try {
+ it.next().changeCancelled(event);
+ } catch (RuntimeException e) {
+ // log the exception
+ e.printStackTrace();
+ }
+ }
+ }
+
+ /**
+ * Calls {@link MDRPreChangeListener.changeCancelled(MDRChangeEvent)}
+ * on all pre-change listeners of all events of the transaction to be
+ * rolled back.
+ */
+ public void fireCancelled() {
+ while (!localQueue.isEmpty()) {
+ MDRChangeEvent event = (MDRChangeEvent) localQueue.getFirst();
+ fireCancelled(event);
+ }
+ }
+
+ /**
+ * Enqueues all events of a transaction successfully finished to inform
+ * the listeners in a separate thread.
+ */
+ public void fireChanged() {
+ synchronized (globalQueue) {
+ globalQueue.addAll(localQueue);
+ globalQueue.notify();
+ }
+ localQueue.clear();
+ }
+
+ /* -------------------------------------------------------------------- */
+ /* -- EventNotifier.EventDelivery (inner class, private) -------------- */
+ /* -------------------------------------------------------------------- */
+
+ /**
+ * Runnable to be executed by the event dispatcher thread. Waits on the
+ * global queue if it is empty. Informs the listeners on queued events.
+ * Catches all exceptions and logs the stack trace.
+ *
+ * Returns if a queued change event was not planned before (i.e. does
+ * not correspond to an entry in {@link #changeListeners}.
+ */
+ private class EventsDelivery implements Runnable {
/**
- * Maps: event => set of change listeners.
+ *
*/
- private final Hashtable changeListeners = new Hashtable();
+ public void run() {
+ QueuedListenerSet collected;
+ MDRChangeEvent event;
+
+ while (true) {
+ synchronized (globalQueue) {
+ while (globalQueue.isEmpty()) {
+ try {
+ globalQueue.wait();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ collected = (QueuedListenerSet) queuedListenerMap.remove(event = (MDRChangeEvent) globalQueue.removeFirst());
+ }
+ if (collected == null) {
+ System.err.println("Change event not corresponding to any planned change event.");
+ Thread.dumpStack();
+ return;
+ }
+ for (QueuedListenerSet.AllListenerIterator it = collected.allListenerIterator(); it.hasNext();) {
+ try {
+ it.next().change(event);
+ } catch (RuntimeException e) {
+ // log the exception
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+ }
+
+ /* -------------------------------------------------------------------- */
+ /* -- EventNotifier.Abstract (inner class, public abstract) ----------- */
+ /* -------------------------------------------------------------------- */
+
+ /**
+ * This class and its derived classes are used to enqueue all changes into
+ * the local queue and to fire the pre-change events.
+ */
+ public abstract class Abstract {
+ /**
+ * Maps repository objects to instances of RegisteredListenerSet
.
+ */
+ private final HashMap RegisteredListenerSets = new HashMap();
+
+ /**
+ * Adds listener
to source
for event types
+ * matching mask
.
+ */
+ public void addListener(MDRChangeListener listener, int mask, Object source) {
+ //System.out.println("-- CALLED: addListener on " + source + " with " + prettyPrintMask(mask));
+ if ( (listener == null) || (mask == 0) ) return;
+
+ synchronized (RegisteredListenerSets) {
+ RegisteredListenerSet value = (RegisteredListenerSet) RegisteredListenerSets.get(source);
+ if ( value == null ) {
+ value = new RegisteredListenerSet();
+ RegisteredListenerSets.put(source, value);
+ }
+ value.addListener(listener, mask);
+ }
+ }
+
+ /**
+ * Removes listener
from source
for all event types.
+ */
+ public void removeListener(MDRChangeListener listener, Object source) {
+ if ( listener == null ) return;
+
+ synchronized (RegisteredListenerSets) {
+ RegisteredListenerSet value = (RegisteredListenerSet) RegisteredListenerSets.get(source);
+ if ( value != null ) {
+ value.removeListener(listener);
+ if ( value.isEmpty() ) {
+ RegisteredListenerSets.remove(source);
+ }
+ }
+ }
+ }
+
+ /**
+ * Removes listener
from source
for event types
+ * matching mask
.
+ */
+ public void removeListener(MDRChangeListener listener, int mask, Object source) {
+ if ( (listener == null) || (mask == 0) ) return;
+
+ synchronized (RegisteredListenerSets) {
+ RegisteredListenerSet value = (RegisteredListenerSet) RegisteredListenerSets.get(source);
+ if ( value != null ) {
+ value.removeListener(listener, mask);
+ if ( value.isEmpty() ) {
+ RegisteredListenerSets.remove(source);
+ }
+ }
+ }
+ }
+
+ /** Informs pre-change listeners about the given event. Internally the
+ * event is stored together with its pre-change listeners and change
+ * listeners to allow further event processing at transaction rollback
+ * resp. commit time.
+ *
+ * @param current The source object of this event.
+ * @param event Event object.
+ * @exception DebugException if the event was already fired
+ */
+ public void firePlannedChange(Object current, MDRChangeEvent event) {
+ //System.out.println("-- CALLED: firePlannedChange on " + current + " with type " + prettyPrintType(event));
+ localQueue.addLast(event);
+ // collect all listeners
+ QueuedListenerSet queuedListeners = new QueuedListenerSet(event);
+ collectListeners(current, event, queuedListeners);
+ for (QueuedListenerSet.PreListenerIterator it = queuedListeners.preListenerIterator(); it.hasNext();) {
+ try {
+ it.next().plannedChange(event);
+ } catch (RuntimeException e) {
+ // log the exception
+ e.printStackTrace();
+ }
+ }
+ if (queuedListenerMap.put(event,queuedListeners) != null) {
+ throw new DebugException("Same event fired twice.");
+ }
+ }
/**
- * Queue for the events of the currently running write transaction.
- * The events are stored to inform their listeners either about
- * rollback or success.
- */
- private final LinkedList localQueue = new LinkedList();
+ * Collects the listeners for the given event
on object
+ * current
. This method has to be overwritten by derived
+ * classes to inform listeners on objects to which the events are
+ * propagated. Overwriting methods shall call this method first and
+ * then add any further listeners.
+ *
+ * @param current the object on which the event was fired
+ * @param event the event
+ * @param post if false
, listeners implementing
+ * {@link org.netbeans.api.mdr.events.MDRPreChangeListener} are
+ * collected, otherwise listeners implementing only
+ * {@link org.netbeans.api.mdr.events.MDRChangeListener}
+ * @param preChange the set where the pre-change listeners are collected
+ * @param postChange the set where the post-change only listeners are collected
+ */
+ protected void collectListeners(Object current, MDRChangeEvent event, QueuedListenerSet queuedListeners) {
+ // fire event on all listeners registered on this object
+ synchronized (RegisteredListenerSets) {
+ RegisteredListenerSet value = (RegisteredListenerSet) RegisteredListenerSets.get(current);
+ if (value != null) {
+ value.collectListeners(queuedListeners);
+ }
+ }
+ }
+ }
+
+ /* -------------------------------------------------------------------- */
+ /* -- EventNotifier.Assocation (inner class, public) ------------------ */
+ /* -------------------------------------------------------------------- */
+
+ /**
+ * Handles events for associations.
+ */
+ public final class Association extends Abstract {
+ private Association() {
+ super();
+ }
+
+ public void addListener(MDRChangeListener listener, int mask, Object source) {
+ super.addListener(listener, mask & EventNotifier.EVENTMASK_BY_ASSOCIATION, source);
+ }
+ public void removeListener(MDRChangeListener listener, int mask, Object source) {
+ super.removeListener(listener, mask & EventNotifier.EVENTMASK_BY_ASSOCIATION, source);
+ }
+
+ /**
+ * Adds listeners on the instances participating in the association link
+ * added resp. removed and on the owning package.
+ */
+ protected void collectListeners(Object current, MDRChangeEvent event, QueuedListenerSet queuedListeners) {
+ super.collectListeners(current, event, queuedListeners);
+
+ // fire event on all listeners registered on instances that were affected
+ if (event instanceof AssociationEvent) {
+ AssociationEvent assocEvent = (AssociationEvent) event;
+ if (assocEvent.getFixedElement() != null) INSTANCE.collectListeners(assocEvent.getFixedElement(), event, queuedListeners);
+ if (assocEvent.getOldElement() != null) INSTANCE.collectListeners(assocEvent.getOldElement(), event, queuedListeners);
+ if (assocEvent.getNewElement() != null) INSTANCE.collectListeners(assocEvent.getNewElement(), event, queuedListeners);
+ }
+
+ // fire event on the immediate package extent
+ PACKAGE.collectListeners(((RefAssociation) current).refImmediatePackage(), event, queuedListeners);
+ }
+ }
+
+ /* -------------------------------------------------------------------- */
+ /* -- EventNotifier.Clazz (inner class, public) ----------------------- */
+ /* -------------------------------------------------------------------- */
+
+ /**
+ * Handles events for class proxies.
+ */
+ public final class Clazz extends Abstract {
+ private Clazz() {
+ super();
+ }
+
+ public void addListener(MDRChangeListener listener, int mask, Object source) {
+ super.addListener(listener, mask & EventNotifier.EVENTMASK_BY_CLASS, source);
+ }
+ public void removeListener(MDRChangeListener listener, int mask, Object source) {
+ super.removeListener(listener, mask & EventNotifier.EVENTMASK_BY_CLASS, source);
+ }
+
+ /**
+ * Adds listeners on the owning package.
+ */
+ protected void collectListeners(Object current, MDRChangeEvent event, QueuedListenerSet queuedListeners) {
+ super.collectListeners(current, event, queuedListeners);
+ PACKAGE.collectListeners(((RefClass) current).refImmediatePackage(), event, queuedListeners);
+ }
+ }
+
+ /* -------------------------------------------------------------------- */
+ /* -- EventNotifier.Instance (inner class, public) -------------------- */
+ /* -------------------------------------------------------------------- */
+
+ /**
+ * Handles events for instances.
+ */
+ public final class Instance extends Abstract {
+ private Instance() {
+ super();
+ }
+
+ public void addListener(MDRChangeListener listener, int mask, Object source) {
+ super.addListener(listener, mask & EventNotifier.EVENTMASK_BY_INSTANCE, source);
+ }
+ public void removeListener(MDRChangeListener listener, int mask, Object source) {
+ super.removeListener(listener, mask & EventNotifier.EVENTMASK_BY_INSTANCE, source);
+ }
+
+ /**
+ * Adds listeners on the owning class proxy.
+ */
+ protected void collectListeners(Object current, MDRChangeEvent event, QueuedListenerSet queuedListeners) {
+ super.collectListeners(current, event, queuedListeners);
+ CLASS.collectListeners(((RefObject) current).refClass(), event, queuedListeners);
+ }
+ }
+
+ /* -------------------------------------------------------------------- */
+ /* -- EventNotifier.Package (inner class, public) --------------------- */
+ /* -------------------------------------------------------------------- */
+
+ /**
+ * Handles events for packages.
+ */
+ public final class Package extends Abstract {
+ private Package() {
+ super();
+ }
+
+ public void addListener(MDRChangeListener listener, int mask, Object source) {
+ super.addListener(listener, mask & EventNotifier.EVENTMASK_BY_PACKAGE, source);
+ }
+ public void removeListener(MDRChangeListener listener, int mask, Object source) {
+ super.removeListener(listener, mask & EventNotifier.EVENTMASK_BY_PACKAGE, source);
+ }
+
+ /**
+ * Adds listeners on the owning package resp., if this package is
+ * outermost, on the repository.
+ */
+ protected void collectListeners(Object current, MDRChangeEvent event, QueuedListenerSet queuedListeners) {
+ super.collectListeners(current, event, queuedListeners);
+ RefPackage immediate = ((RefPackage) current).refImmediatePackage();
+ if (immediate != null) {
+ collectListeners(immediate, event, queuedListeners);
+ } else {
+ REPOSITORY.collectListeners(((BaseObjectHandler) current)._getDelegate().getMdrStorage(), event, queuedListeners);
+ }
+ }
+ }
+
+ /* -------------------------------------------------------------------- */
+ /* -- EventNotifier.Repository (inner class, public) ------------------ */
+ /* -------------------------------------------------------------------- */
+
+ /**
+ * Handles events for repositories.
+ */
+ public final class Repository extends Abstract {
+ private Repository() {
+ super();
+ }
+
+ public void addListener(MDRChangeListener listener, int mask, Object source) {
+ super.addListener(listener, mask & EventNotifier.EVENTMASK_BY_REPOSITORY, source);
+ }
+ public void removeListener(MDRChangeListener listener, int mask, Object source) {
+ super.removeListener(listener, mask & EventNotifier.EVENTMASK_BY_REPOSITORY, source);
+ }
+ }
+
+ /* ===================================================================== */
+ /* == INNER CLASS CONTAINING OPTIMIZED/OPTIMIZABLE DATASTRUCTURES ====== */
+ /* == FOR LISTENER MANAGEMENT ========================================== */
+ /* ===================================================================== */
+ Index: src/org/netbeans/mdr/util/ImplClass.java
===================================================================
RCS file: /usr/local/cvs/case/netbeans/mdr/src/org/netbeans/mdr/util/ImplClass.java,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -r1.1.1.1 -r1.2
--- src/org/netbeans/mdr/util/ImplClass.java 2 Jul 2002 07:35:30 -0000 1.1.1.1
+++ src/org/netbeans/mdr/util/ImplClass.java 4 Jul 2002 12:50:46 -0000 1.2
@@ -24,6 +24,8 @@
* @version
*/
public abstract class ImplClass {
+
+ /* Suffix for the names of implementation classes. */
protected static final String classNameSuffix = "$Impl";
private static final ProtectionDomain pd;
Index: src/org/netbeans/mdr/util/TransactionMutex.java
===================================================================
RCS file: /usr/local/cvs/case/netbeans/mdr/src/org/netbeans/mdr/util/TransactionMutex.java,v
retrieving revision 1.1.1.1
retrieving revision 1.3
diff -u -r1.1.1.1 -r1.3
--- src/org/netbeans/mdr/util/TransactionMutex.java 2 Jul 2002 07:35:30 -0000 1.1.1.1
+++ src/org/netbeans/mdr/util/TransactionMutex.java 11 Jul 2002 09:41:27 -0000 1.3
@@ -13,6 +13,8 @@
package org.netbeans.mdr.util;
import java.util.HashMap;
+import org.netbeans.api.mdr.events.TransactionEvent;
+import org.netbeans.mdr.NBMDRepositoryImpl;
import org.netbeans.mdr.storagemodel.MdrStorage;
import org.netbeans.mdr.persistence.StorageException;
@@ -52,14 +54,18 @@
// events notifier
private final EventNotifier notifier;
+ // the repository (used as event source for transaction events)
+ private final NBMDRepositoryImpl repository;
+
/* -------------------------------------------------------------------- */
/* -- Constructor (public) -------------------------------------------- */
/* -------------------------------------------------------------------- */
/** Creates new TransactionMutex */
- public TransactionMutex(MdrStorage storage, EventNotifier notifier) {
+ public TransactionMutex(MdrStorage storage, EventNotifier notifier, NBMDRepositoryImpl repository) {
this.storage = storage;
this.notifier = notifier;
+ this.repository = repository;
}
/* -------------------------------------------------------------------- */
@@ -107,8 +113,15 @@
}
if (writeAccess || counter > 0) {
+ if ( counter == 0 ) {
+ writer = thread;
+ TransactionEvent event = new TransactionEvent(
+ repository,
+ TransactionEvent.EVENT_TRANSACTION_START
+ );
+ notifier.REPOSITORY.firePlannedChange(storage, event);
+ }
counter++;
- writer = thread;
} else {
Counter rCount = (Counter) readers.get(thread);
if (rCount == null) {
@@ -129,7 +142,7 @@
/**
* Leave a transaction. If an outermost (i.e. not nested) write
* transaction is left, the listeners are informed and the transaction
- * is committed resp. rolled back. Finally all waiting thread are
+ * is committed resp. rolled back. Finally all waiting threads are
* notified.
*
* @param fail false
indicates transaction
@@ -146,11 +159,21 @@
// left the last write lock -> commit/rollback and send events
try {
if (this.fail) {
+ TransactionEvent event = new TransactionEvent(
+ repository,
+ TransactionEvent.EVENT_TRANSACTION_ROLLBACK
+ );
+ notifier.REPOSITORY.firePlannedChange(storage, event);
notifier.fireCancelled();
storage.rollback();
Thread.dumpStack();
System.out.println("rolled back!");
} else {
+ TransactionEvent event = new TransactionEvent(
+ repository,
+ TransactionEvent.EVENT_TRANSACTION_COMMIT
+ );
+ notifier.REPOSITORY.firePlannedChange(storage, event);
notifier.fireChanged();
storage.commit();
//System.out.println("commited");
@@ -189,7 +212,7 @@
/* -------------------------------------------------------------------- */
/**
- * Instances Counter
are integer with {@link #dec() decrement}
+ * Instances Counter
are integers with {@link #dec() decrement}
* and {@link #inc() increment} methods.
*/
private static class Counter {
Index: src/org/netbeans/modules/mdrexplorer/looks/MDREventHandler.java
===================================================================
RCS file: /usr/local/cvs/case/netbeans/mdr/src/org/netbeans/modules/mdrexplorer/looks/MDREventHandler.java,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -r1.1.1.1 -r1.2
--- src/org/netbeans/modules/mdrexplorer/looks/MDREventHandler.java 2 Jul 2002 07:35:32 -0000 1.1.1.1
+++ src/org/netbeans/modules/mdrexplorer/looks/MDREventHandler.java 11 Jul 2002 09:26:54 -0000 1.2
@@ -26,24 +26,55 @@
import org.netbeans.api.looks.Look;
/**
+ * Instances of MDREventHandler
are event handlers which listen
+ * on repository changes on behalf of {@link org.netbeans.api.looks.LookNodeSubstitutes
+ * node substitutes}. They manage a map from repository objects to node substitutes
+ * to be able to access the node substitute for a given repository object. Looks
+ * have to register their node subsitutes by calling {@link #addNodeSubstitute(Look.NodeSubstitute)}
+ * or {@link #addNodeSubstitute(Object, Look.NodeSubstitute)} from within
+ * {@link org.netbeans.api.looks.Look#attachTo(ook.NodeSubstitute)}.
*
+ * @deprecated register NodeSubstitutes directly on repository objects instead, see
+ * issue 25186
* @author Tomas Zezula
*/
public class MDREventHandler implements MDRPreChangeListener {
+ /* --------------------------------------------------------------------- */
+ /* -- Attributes ------------------------------------------------------- */
+ /* --------------------------------------------------------------------- */
+
+ /**
+ * Maps repository content to node substitutes.
+ */
private HashMap registeredNodeSubstitutes;
+
+ /**
+ * Map storing the parents of objects to be deleted. After an object has
+ * been deleted, its parent node is not accessible any more. Nevertheless it
+ * must be refreshed to reflect the deletion of the node representing the object.
+ * Hence the parents of the objects to be deleted are stored in the map.
+ */
private HashMap pendingEvents;
private ReferenceQueue queue;
private MDRepository repository;
+ /* --------------------------------------------------------------------- */
+ /* -- Constructor ------------------------------------------------------ */
+ /* --------------------------------------------------------------------- */
+
public MDREventHandler (MDRepository repository) {
this.queue = new ReferenceQueue();
this.registeredNodeSubstitutes = new HashMap();
this.pendingEvents = new HashMap();
this.repository = repository;
- this.repository.addListener(this);
+ this.repository.addListener(this, MDRChangeEvent.EVENTMASK_ALL);
}
+ /* --------------------------------------------------------------------- */
+ /* -- Management of NodeSubstitutes ------------------------------------ */
+ /* --------------------------------------------------------------------- */
+
public synchronized void addNodeSubstitute(Look.NodeSubstitute substitute) {
if (substitute == null)
return;
@@ -56,32 +87,25 @@
this.registeredNodeSubstitutes.put(key, new WeakReference(substitute,this.queue));
}
- /** This method is called when the node was garbage collected. You shoud
- * unregister from all objects where this object was registered as a
- * listener.
- */
-
- /** This method gets called if a planned change (which was already announced
- * by calling {@link #plannedChange} was cancelled (e.g. the operation that was
- * going to perform the change failed). This method is called synchronously by
- * the operation that tried to perform the change.
- * Any run-time exception thrown by the implementation of this method should - * not affect the events dispatching (i.e. it should be ignored by the event source). - * @param e Object describing the cancelled change (has to be the same instance - * as passed to the {@link #plannedChange} method). - */ - public void changeCancelled(MDRChangeEvent e) { - if ((e.getType() & 2) == 2) { - this.pendingEvents.remove(e.getSource()); + private synchronized Look.NodeSubstitute getNodeSubstituteForObject(Object object) { + if (object ==null) + return null; + Reference ref = (Reference) this.registeredNodeSubstitutes.get(object); + if (ref == null) { + return null; // Not registered object } + Look.NodeSubstitute substitute = (Look.NodeSubstitute) ref.get(); + return substitute; } - /** This method gets called when a repository change is planned to occur. - * Any operation that performs a change in MDR has to fire this notification - * synchronously on each registered pre-change listener before the change is performed.
- * Any run-time exception thrown by the implementation of this method should - * not affect the events dispatching (i.e. it should be ignored by the event source). - * @param e Object describing the planned change. + /* --------------------------------------------------------------------- */ + /* -- Implements org.netbeans.api.mdr.MDRPreChangeListener ------------- */ + /* --------------------------------------------------------------------- */ + + /** + * Handles deletion events only. Stores the parents of objects to be deleted. + * This is necessary to refresh parent nodes when the object to be deleted + * has been deleted. */ public void plannedChange(MDRChangeEvent e) { if ((e.getType() & ExtentEvent.EVENT_EXTENT_DELETE) == ExtentEvent.EVENT_EXTENT_DELETE) { @@ -107,16 +131,18 @@ } } - /** This method gets called after a repository change is performed. This method - * is called asynchronously. - * If a listener implements {@link MDRPreChangeListener} which is a descedant - * of this interface, the event object passed to this method must be the same - * instance as the event object previously passed to the corresponding - * {@link MDRPreChangeListener#plannedChange} method call of the listener.
- * Any run-time exception thrown by the implementation of this method should
- * not affect the events dispatching (i.e. it should be ignored by the event source).
- *
- * @param e Object describing the performed change.
+ /**
+ * Removes the information stored for the pending event e
.
+ * @see #plannedChange(MDRChangeEvent)
+ */
+ public void changeCancelled(MDRChangeEvent e) {
+ if ((e.getType() & 2) == 2) {
+ this.pendingEvents.remove(e.getSource());
+ }
+ }
+
+ /**
+ * Refreshes the nodes affected by e
.
*/
public void change(MDRChangeEvent e) {
if ((e.getType() & ExtentEvent.EVENT_EXTENT_CREATE) == ExtentEvent.EVENT_EXTENT_CREATE) {
@@ -171,6 +197,14 @@
}
}
+ /* --------------------------------------------------------------------- */
+ /* -- Clean-up dangling map entries ------------------------------------ */
+ /* --------------------------------------------------------------------- */
+
+ /**
+ * Removes entries with garbage collected values from the map associating
+ * repository objects with node substitutes.
+ */
synchronized void flushReferenceQueue() {
if (this.queue.poll()!=null) {
Iterator values = this.registeredNodeSubstitutes.values().iterator();
@@ -184,17 +218,6 @@
}
}
-
- private synchronized Look.NodeSubstitute getNodeSubstituteForObject(Object object) {
- if (object ==null)
- return null;
- Reference ref = (Reference) this.registeredNodeSubstitutes.get(object);
- if (ref == null) {
- return null; // Not registered object
- }
- Look.NodeSubstitute substitute = (Look.NodeSubstitute) ref.get();
- return substitute;
- }
}
Index: test/build-qa-functional.xml
===================================================================
RCS file: /usr/local/cvs/case/netbeans/mdr/test/build-qa-functional.xml,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -r1.1.1.1 -r1.2
--- test/build-qa-functional.xml 2 Jul 2002 07:35:41 -0000 1.1.1.1
+++ test/build-qa-functional.xml 2 Jul 2002 16:31:01 -0000 1.2
@@ -158,7 +158,7 @@