Adding JMCR-Stable version
[Benchmarks_CSolver.git] / JMCR-Stable / real-world application / MyDerby-10.3 / java / engine / org / apache / derby / impl / sql / depend / BasicDependencyManager.java
diff --git a/JMCR-Stable/real-world application/MyDerby-10.3/java/engine/org/apache/derby/impl/sql/depend/BasicDependencyManager.java b/JMCR-Stable/real-world application/MyDerby-10.3/java/engine/org/apache/derby/impl/sql/depend/BasicDependencyManager.java
new file mode 100644 (file)
index 0000000..ee7b50c
--- /dev/null
@@ -0,0 +1,1388 @@
+/*\r
+\r
+   Derby - Class org.apache.derby.impl.sql.depend.BasicDependencyManager\r
+\r
+   Licensed to the Apache Software Foundation (ASF) under one or more\r
+   contributor license agreements.  See the NOTICE file distributed with\r
+   this work for additional information regarding copyright ownership.\r
+   The ASF licenses this file to you under the Apache License, Version 2.0\r
+   (the "License"); you may not use this file except in compliance with\r
+   the License.  You may obtain a copy of the License at\r
+\r
+      http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+   Unless required by applicable law or agreed to in writing, software\r
+   distributed under the License is distributed on an "AS IS" BASIS,\r
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+   See the License for the specific language governing permissions and\r
+   limitations under the License.\r
+\r
+ */\r
+\r
+package org.apache.derby.impl.sql.depend;\r
+\r
+import java.util.Enumeration;\r
+import java.util.Hashtable;\r
+import java.util.List;\r
+import java.util.ListIterator;\r
+\r
+import org.apache.derby.catalog.DependableFinder;\r
+import org.apache.derby.catalog.UUID;\r
+import org.apache.derby.iapi.error.StandardException;\r
+import org.apache.derby.iapi.services.context.ContextManager;\r
+import org.apache.derby.iapi.services.io.FormatableBitSet;\r
+import org.apache.derby.iapi.services.sanity.SanityManager;\r
+import org.apache.derby.iapi.sql.compile.CompilerContext;\r
+import org.apache.derby.iapi.sql.compile.Parser;\r
+import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;\r
+import org.apache.derby.iapi.sql.conn.StatementContext;\r
+import org.apache.derby.iapi.sql.depend.Dependency;\r
+import org.apache.derby.iapi.sql.depend.DependencyManager;\r
+import org.apache.derby.iapi.sql.depend.Dependent;\r
+import org.apache.derby.iapi.sql.depend.Provider;\r
+import org.apache.derby.iapi.sql.depend.ProviderInfo;\r
+import org.apache.derby.iapi.sql.depend.ProviderList;\r
+import org.apache.derby.iapi.sql.dictionary.DataDictionary;\r
+import org.apache.derby.iapi.sql.dictionary.DependencyDescriptor;\r
+import org.apache.derby.iapi.sql.dictionary.SchemaDescriptor;\r
+import org.apache.derby.iapi.sql.dictionary.TableDescriptor;\r
+import org.apache.derby.iapi.sql.dictionary.ViewDescriptor;\r
+import org.apache.derby.iapi.store.access.TransactionController;\r
+import org.apache.derby.impl.sql.compile.CreateViewNode;\r
+\r
+/**\r
+       The dependency manager tracks needs that dependents have of providers.\r
+ */\r
+\r
+public class BasicDependencyManager implements DependencyManager {\r
+  \r
+    /**\r
+     * DataDictionary for this database.\r
+     */\r
+    private final DataDictionary dd;\r
+    \r
+    /**\r
+     * Map of in-memory dependencies for Dependents.\r
+     * In-memory means that one or both of the Dependent\r
+     * or Provider are non-persistent (isPersistent() returns false).\r
+     * \r
+     * Key is the UUID of the Dependent (from getObjectID()).\r
+     * Value is a List containing Dependency objects, each\r
+     * of whihc links the same Dependent to a Provider.\r
+     * Dependency objects in the List are unique.\r
+     * \r
+     */\r
+    private final Hashtable dependents = new Hashtable();\r
+    \r
+    /**\r
+     * Map of in-memory dependencies for Providers.\r
+     * In-memory means that one or both of the Dependent\r
+     * or Provider are non-persistent (isPersistent() returns false).\r
+     * \r
+     * Key is the UUID of the Provider (from getObjectID()).\r
+     * Value is a List containing Dependency objects, each\r
+     * of which links the same Provider to a Dependent.\r
+     * Dependency objects in the List are unique.\r
+     * \r
+     */    \r
+    private final Hashtable providers = new Hashtable();\r
+\r
+\r
+       //\r
+       // DependencyManager interface\r
+       //\r
+\r
+       /**\r
+               adds a dependency from the dependent on the provider.\r
+               This will be considered to be the default type of\r
+               dependency, when dependency types show up.\r
+               <p>\r
+               Implementations of addDependency should be fast --\r
+               performing alot of extra actions to add a dependency would\r
+               be a detriment.\r
+\r
+               @param d the dependent\r
+               @param p the provider\r
+\r
+               @exception StandardException thrown if something goes wrong\r
+        */\r
+       public void addDependency(Dependent d, Provider p, ContextManager cm) \r
+               throws StandardException {\r
+               addDependency(d, p, cm, null);\r
+       }\r
+       \r
+       private void addDependency(Dependent d, Provider p, ContextManager cm, \r
+                       TransactionController tc) throws StandardException {\r
+\r
+               //synchronized(this) //Jeff Huang\r
+               {\r
+                       Dependency dy = new BasicDependency(d, p);\r
+\r
+                       /* Dependencies are either in-memory or stored, but not both */\r
+                       if (! d.isPersistent() || ! p.isPersistent())\r
+                       {\r
+                               /* Duplicate dependencies are not added to the lists.\r
+                                * If we find that the dependency we are trying to add in\r
+                                * one list is a duplicate, then it should be a duplicate in the\r
+                                * other list.\r
+                                */\r
+                               boolean addedToDeps = false;\r
+                               boolean addedToProvs = false;\r
+                               \r
+                               addedToDeps = addDependencyToTable(dependents, d.getObjectID(), dy);\r
+                               if (addedToDeps)\r
+                               {\r
+                                       addedToProvs = addDependencyToTable(providers, p.getObjectID(), dy);\r
+                               }\r
+                               else if (SanityManager.DEBUG)\r
+                               {\r
+                                       addedToProvs = addDependencyToTable(providers, p.getObjectID(), dy);\r
+                               }\r
+\r
+                               /* Dependency should have been added to both or neither */\r
+                               if (SanityManager.DEBUG)\r
+                               {\r
+                    if (addedToDeps != addedToProvs)\r
+                    {\r
+                        SanityManager.THROWASSERT(\r
+                            "addedToDeps (" + addedToDeps + \r
+                            ") and addedToProvs (" +\r
+                            addedToProvs + ") are expected to agree");\r
+                    }\r
+                               }\r
+\r
+                               /* Add the dependency to the StatementContext, so that\r
+                               * it can be cleared on a pre-execution error.\r
+                               */\r
+                               StatementContext sc = (StatementContext) cm.getContext(org.apache.derby.iapi.reference.ContextId.LANG_STATEMENT);\r
+                               sc.addDependency(dy);\r
+                       }\r
+                       else\r
+                       {\r
+                               /* Add a stored dependency */\r
+                               LanguageConnectionContext       lcc = getLanguageConnectionContext(cm);\r
+                               DependencyDescriptor            dependencyDescriptor;\r
+                               boolean wait = (tc == null);\r
+                       \r
+                               dependencyDescriptor = new DependencyDescriptor(d, p);\r
+\r
+                               /* We can finally call the DataDictionary to store the dependency */\r
+                               dd.addDescriptor(dependencyDescriptor, null,\r
+                                                                DataDictionary.SYSDEPENDS_CATALOG_NUM, true,\r
+                                                                ((wait)?lcc.getTransactionExecute():tc), wait);\r
+                       }\r
+               }\r
+       }\r
+\r
+       /**\r
+               drops a single dependency\r
+\r
+               @param d the dependent\r
+               @param p the provider\r
+\r
+               @exception StandardException thrown if something goes wrong\r
+        */\r
+       private void dropDependency(LanguageConnectionContext lcc, Dependent d, Provider p) throws StandardException\r
+       {\r
+               if (SanityManager.DEBUG) {\r
+                       // right now, this routine isn't called for in-memory dependencies\r
+                       if (! d.isPersistent() || ! p.isPersistent())\r
+                       {\r
+                               SanityManager.NOTREACHED();\r
+                       }\r
+               }\r
+\r
+               DependencyDescriptor dependencyDescriptor = new DependencyDescriptor(d, p);\r
+\r
+               dd.dropStoredDependency( dependencyDescriptor, \r
+                                                                lcc.getTransactionExecute() );\r
+       }\r
+\r
+\r
+       /**\r
+               mark all dependencies on the named provider as invalid.\r
+               When invalidation types show up, this will use the default\r
+               invalidation type. The dependencies will still exist once\r
+               they are marked invalid; clearDependencies should be used\r
+               to remove dependencies that a dependent has or provider gives.\r
+               <p>\r
+               Implementations of this can take a little time, but are not\r
+               really expected to recompile things against any changes\r
+               made to the provider that caused the invalidation. The\r
+               dependency system makes no guarantees about the state of\r
+               the provider -- implementations can call this before or\r
+               after actually changing the provider to its new state.\r
+               <p>\r
+               Implementations should throw StandardException\r
+               if the invalidation should be disallowed.\r
+\r
+               @param p the provider\r
+               @param action   The action causing the invalidate\r
+\r
+               @exception StandardException thrown if unable to make it invalid\r
+        */\r
+       public void invalidateFor(Provider p, int action,\r
+                                 LanguageConnectionContext lcc)\r
+                throws StandardException\r
+       {\r
+               /*\r
+               ** Non-persistent dependencies are stored in memory, and need to\r
+               ** use "synchronized" to ensure their lists don't change while\r
+               ** the invalidation is taking place.  Persistent dependencies are\r
+               ** stored in the data dictionary, and we should *not* do anything\r
+               ** transactional (like reading from a system table) from within\r
+               ** a synchronized method, as it could cause deadlock.\r
+               **\r
+               ** Presumably, the transactional locking in the data dictionary\r
+               ** is enough to protect us, so that we don't have to put any\r
+               ** synchronization in the DependencyManager.\r
+               */\r
+               if (p.isPersistent())\r
+                       coreInvalidateFor(p, action, lcc);\r
+               else {\r
+                       synchronized (this) {\r
+                               coreInvalidateFor(p, action, lcc);\r
+                       }\r
+               }\r
+       }\r
+\r
+       /**\r
+        * A version of invalidateFor that does not provide synchronization among\r
+        * invalidators.  If parameter "forSync" is true, it also provides\r
+        * synchronization on the dependents.  Currently, this means synchronizing\r
+        * on the prepared statements, which might be being executed on other\r
+        * threads.\r
+        * @param p                     provider\r
+        * @param action        The action causing the invalidate\r
+        * @param lcc           Language connection context\r
+        *\r
+        * @exception StandardException         Thrown on error.\r
+        */\r
+       private void coreInvalidateFor(Provider p, int action, LanguageConnectionContext lcc)\r
+               throws StandardException\r
+       {\r
+               List list = getDependents(p);\r
+               if (list == null)\r
+               {\r
+                       return;\r
+               }\r
+\r
+\r
+               // affectedCols is passed in from table descriptor provider to indicate\r
+               // which columns it cares; subsetCols is affectedCols' intersection\r
+               // with column bit map found in the provider of SYSDEPENDS line to\r
+               // find out which columns really matter.  If SYSDEPENDS line's\r
+               // dependent is view (or maybe others), provider is table, yet it \r
+               // doesn't have column bit map because the view was created in a\r
+               // previous version of server which doesn't support column dependency,\r
+               // and we really want it to have (such as in drop column), in any case\r
+               // if we passed in table descriptor to this function with a bit map,\r
+               // we really need this, we generate the bitmaps on the fly and update\r
+               // SYSDEPENDS\r
+\r
+               FormatableBitSet affectedCols = null, subsetCols = null;\r
+               if (p instanceof TableDescriptor)\r
+               {\r
+                       affectedCols = ((TableDescriptor) p).getReferencedColumnMap();\r
+                       if (affectedCols != null)\r
+                               subsetCols = new FormatableBitSet(affectedCols.getLength());\r
+               }\r
+\r
+               {\r
+                       StandardException noInvalidate = null;\r
+                       // We cannot use an iterator here as the invalidations can remove\r
+                       // entries from this list. \r
+                       for (int ei = list.size() - 1; ei >= 0; ei--)\r
+                       {\r
+                               if (ei >= list.size())\r
+                                       continue;\r
+                               Dependency dependency = (Dependency) list.get(ei);\r
+\r
+                               Dependent dep = dependency.getDependent();\r
+\r
+                               if (affectedCols != null)\r
+                               {\r
+                                       TableDescriptor td = (TableDescriptor) dependency.getProvider();\r
+                                       FormatableBitSet providingCols = td.getReferencedColumnMap();\r
+                                       if (providingCols == null)\r
+                                       {\r
+                                               if (dep instanceof ViewDescriptor)\r
+                                               {\r
+                                                       ViewDescriptor vd = (ViewDescriptor) dep;\r
+                                                       SchemaDescriptor compSchema;\r
+                                                       compSchema = dd.getSchemaDescriptor(vd.getCompSchemaId(), null);\r
+                                                       CompilerContext newCC = lcc.pushCompilerContext(compSchema);\r
+                                                       Parser  pa = newCC.getParser();\r
+\r
+                                                       // Since this is always nested inside another SQL\r
+                                                       // statement, so topLevel flag should be false\r
+                                                       CreateViewNode cvn = (CreateViewNode)pa.parseStatement(\r
+                                                                                               vd.getViewText());\r
+\r
+                                                       // need a current dependent for bind\r
+                                                       newCC.setCurrentDependent(dep);\r
+                                                       cvn.bindStatement();\r
+                                                       ProviderInfo[] providerInfos = cvn.getProviderInfo();\r
+                                                       lcc.popCompilerContext(newCC);\r
+\r
+                                                       boolean         interferent = false;\r
+                                                       for (int i = 0; i < providerInfos.length; i++)\r
+                                                       {\r
+                                                               Provider provider = null;\r
+                                                                       provider = (Provider) providerInfos[i].\r
+                                                                                                       getDependableFinder().\r
+                                                                                                       getDependable(dd,\r
+                                                                                                       providerInfos[i].getObjectId());\r
+                                                               if (provider instanceof TableDescriptor)\r
+                                                               {\r
+                                                                       TableDescriptor tab = (TableDescriptor)provider;\r
+                                                                       FormatableBitSet colMap = tab.getReferencedColumnMap();\r
+                                                                       if (colMap == null)\r
+                                                                               continue;\r
+                                                                       // if later on an error is raised such as in\r
+                                                                       // case of interference, this dependency line\r
+                                                                       // upgrade will not happen due to rollback\r
+                                                                       tab.setReferencedColumnMap(null);\r
+                                                                       dropDependency(lcc, vd, tab);\r
+                                                                       tab.setReferencedColumnMap(colMap);\r
+                                                                       addDependency(vd, tab, lcc.getContextManager());\r
+\r
+                                                                       if (tab.getObjectID().equals(td.getObjectID()))\r
+                                                                       {\r
+                                                                               System.arraycopy(affectedCols.getByteArray(), 0, \r
+                                                                                       subsetCols.getByteArray(), 0, \r
+                                                                                       affectedCols.getLengthInBytes());\r
+                                                                               subsetCols.and(colMap);\r
+                                                                               if (subsetCols.anySetBit() != -1)\r
+                                                                               {\r
+                                                                                       interferent = true;\r
+                                                                                       ((TableDescriptor) p).setReferencedColumnMap(subsetCols);\r
+                                                                               }\r
+                                                                       }\r
+                                                               }       // if provider instanceof TableDescriptor\r
+                                                       }       // for providerInfos\r
+                                                       if (! interferent)\r
+                                                               continue;\r
+                                               }       // if dep instanceof ViewDescriptor\r
+                                               else\r
+                                                       ((TableDescriptor) p).setReferencedColumnMap(null);\r
+                                       }       // if providingCols == null\r
+                                       else\r
+                                       {\r
+                                               System.arraycopy(affectedCols.getByteArray(), 0, subsetCols.getByteArray(), 0, affectedCols.getLengthInBytes());\r
+                                               subsetCols.and(providingCols);\r
+                                               if (subsetCols.anySetBit() == -1)\r
+                                                       continue;\r
+                                               ((TableDescriptor) p).setReferencedColumnMap(subsetCols);\r
+                                       }\r
+                               }\r
+\r
+                               // generate a list of invalidations that fail.\r
+                               try {\r
+                                       dep.prepareToInvalidate(p, action, lcc);\r
+                               } catch (StandardException sqle) {\r
+\r
+                                       if (noInvalidate == null) {\r
+                                               noInvalidate = sqle;\r
+                                       } else {\r
+                                               try {\r
+                                                       sqle.initCause(noInvalidate);\r
+                                                       noInvalidate = sqle;\r
+                                               } catch (IllegalStateException ise) {\r
+                                                       // We weren't able to chain the exceptions. That's\r
+                                                       // OK, since we always have the first exception we\r
+                                                       // caught. Just skip the current exception.\r
+                                               }\r
+                                       }\r
+                               }\r
+                               if (noInvalidate == null) {\r
+\r
+                                       if (affectedCols != null)\r
+                                               ((TableDescriptor) p).setReferencedColumnMap(affectedCols);\r
+\r
+                                       // REVISIT: future impl will want to mark the individual\r
+                                       // dependency as invalid as well as the dependent...\r
+                                       dep.makeInvalid(action, lcc);\r
+                               }\r
+                       }\r
+\r
+                       if (noInvalidate != null)\r
+                               throw noInvalidate;\r
+               }\r
+       }\r
+\r
+       /**\r
+               Erases all of the dependencies the dependent has, be they\r
+               valid or invalid, of any dependency type.  This action is\r
+               usually performed as the first step in revalidating a\r
+               dependent; it first erases all the old dependencies, then\r
+               revalidates itself generating a list of new dependencies,\r
+               and then marks itself valid if all its new dependencies are\r
+               valid.\r
+               <p>\r
+               There might be a future want to clear all dependencies for\r
+               a particular provider, e.g. when destroying the provider.\r
+               However, at present, they are assumed to stick around and\r
+               it is the responsibility of the dependent to erase them when\r
+               revalidating against the new version of the provider.\r
+               <p>\r
+               clearDependencies will delete dependencies if they are\r
+               stored; the delete is finalized at the next commit.\r
+\r
+               @param d the dependent\r
+        *\r
+        * @exception StandardException         Thrown on failure\r
+        */\r
+       public void clearDependencies(LanguageConnectionContext lcc, Dependent d) throws StandardException {\r
+               clearDependencies(lcc, d, null);\r
+       }\r
+\r
+       /**\r
+        * @inheritDoc\r
+        */\r
+       public void clearDependencies(LanguageConnectionContext lcc, \r
+                                                                       Dependent d, TransactionController tc) throws StandardException {\r
+               List deps = (List) dependents.get(d.getObjectID());\r
+\r
+               synchronized(this)\r
+               {\r
+                       /* Remove all the stored dependencies */\r
+                       if (d.isPersistent())\r
+                       {\r
+                               boolean wait = (tc == null);\r
+                               \r
+                               dd.dropDependentsStoredDependencies(d.getObjectID(),\r
+                                                               ((wait)?lcc.getTransactionExecute():tc),\r
+                                                               wait);\r
+                       }\r
+\r
+                       /* Now remove the in-memory dependencies */\r
+\r
+                       if (deps == null) return; // already removed\r
+\r
+                       // go through the list notifying providers to remove\r
+                       // the dependency from their lists\r
+                       for (ListIterator depsIterator = deps.listIterator();\r
+                               depsIterator.hasNext(); ) {\r
+\r
+                               Dependency dy = (Dependency)depsIterator.next();\r
+                               clearProviderDependency(dy.getProviderKey(), dy);\r
+                       }\r
+\r
+                       dependents.remove(d.getObjectID());\r
+               }\r
+       }\r
+\r
+       /**\r
+        * Clear the specified in memory dependency.\r
+        * This is useful for clean-up when an exception occurs.\r
+        * (We clear all in-memory dependencies added in the current\r
+        * StatementContext.)\r
+        */\r
+       public void clearInMemoryDependency(Dependency dy)\r
+       {\r
+               synchronized(this)\r
+               {\r
+                       List deps =\r
+                               (List) dependents.get(dy.getDependent().getObjectID());\r
+\r
+                       // NOTE - this is a NEGATIVE Sanity mode check, in sane mode we continue\r
+                       // to ensure the dependency manager is consistent.\r
+                       if (!SanityManager.DEBUG) {\r
+                               // dependency has already been removed\r
+                               if (deps == null)\r
+                                       return;\r
+                       }\r
+\r
+                       List provs =\r
+                               (List) providers.get(dy.getProvider().getObjectID());\r
+\r
+                       if (SanityManager.DEBUG)\r
+                       {\r
+                               // if both are null then everything is OK\r
+                               if ((deps != null) || (provs != null)) {\r
+\r
+                                       // ensure that the Dependency dy is either\r
+                                       // in both lists or in neither. Even if dy\r
+                                       // is out of the list we can have non-null\r
+                                       // deps and provs here because other dependencies\r
+                                       // with the the same providers or dependents can exist\r
+\r
+                                       //\r
+                                       int depCount = 0;\r
+                                       if (deps != null) {\r
+                                               for (int ci = 0; ci < deps.size(); ci++) {\r
+                                                       if (dy.equals(deps.get(ci)))\r
+                                                               depCount++;\r
+                                               }\r
+                                       }\r
+\r
+                                       int provCount = 0;\r
+                                       if (provs != null) {\r
+                                               for (int ci = 0; ci < provs.size(); ci++) {\r
+                                                       if (dy.equals(provs.get(ci)))\r
+                                                               provCount++;\r
+                                               }\r
+                                       }\r
+\r
+                                       if (depCount != provCount) {\r
+                                               SanityManager.THROWASSERT("Dependency count mismatch count in deps: " + depCount +\r
+                                                       ", count in provs " + provCount +\r
+                                                       ", dy.getDependent().getObjectID() = " + dy.getDependent().getObjectID() +\r
+                                                       ", dy.getProvider().getObjectID() = " + dy.getProvider().getObjectID());\r
+                                       }\r
+                               }\r
+\r
+                               // dependency has already been removed,\r
+                               // matches code that is protected by !DEBUG above\r
+                               if (deps == null)\r
+                                       return;\r
+                       }\r
+\r
+                       // dependency has already been removed\r
+                       if (provs == null)\r
+                               return;\r
+\r
+\r
+                       deps.remove(dy);\r
+                       if (deps.size() == 0)\r
+                               dependents.remove(dy.getDependent().getObjectID());\r
+                       provs.remove(dy);\r
+                       if (provs.size() == 0)\r
+                               providers.remove(dy.getProvider().getObjectID());\r
+               }\r
+       }\r
+\r
+\r
+       /**\r
+        * @see DependencyManager#getAllProviders\r
+        *\r
+        * @exception StandardException         Thrown on error\r
+        */\r
+//     public SList getAllProviders(Dependent dependent)\r
+//                                                     throws StandardException\r
+//     {\r
+//             synchronized(this)\r
+//             {\r
+//                     SList list = getProviders(dependent);\r
+//                     return list;\r
+//             }\r
+//     }\r
+\r
+       /**\r
+        * @see DependencyManager#getAllProviderInfos\r
+        *\r
+        * @exception StandardException         Thrown on error\r
+        */\r
+/*     public ProviderInfo[] getAllProviderInfos(Dependent dependent)\r
+                                                       throws StandardException\r
+       {\r
+               synchronized(this)\r
+               {\r
+                       ProviderInfo[]  retval;\r
+                       SList list = getProviders(dependent);\r
+                       retval = new ProviderInfo[list.size()];\r
+                       if (list == null)\r
+                       {\r
+                               return retval;\r
+                       }\r
+                       \r
+                       int piCtr = 0;\r
+\r
+                       Enumeration enum = list.elements();\r
+                       while (enum != null && enum.hasMoreElements())\r
+                       {\r
+                               Dependency dep = (Dependency) enum.nextElement();\r
+\r
+                               retval[piCtr++] = new BasicProviderInfo(\r
+                                                                               dep.getProvider().getObjectID(),\r
+                                                                               dep.getProvider().getDependableFinder(),\r
+                                                                               dep.getProvider().getObjectName()\r
+                                                                               );\r
+                       }\r
+\r
+                       return retval;\r
+               }\r
+       }\r
+*/\r
+\r
+       /**\r
+        * @see DependencyManager#getPersistentProviderInfos\r
+        *\r
+        * @exception StandardException         Thrown on error\r
+        */\r
+       public synchronized ProviderInfo[] getPersistentProviderInfos(Dependent dependent)\r
+                                                       throws StandardException\r
+       {\r
+               List list = getProviders(dependent);\r
+               if (list == null)\r
+               {\r
+                       return EMPTY_PROVIDER_INFO;\r
+               }\r
+\r
+               java.util.ArrayList pih = new java.util.ArrayList();\r
+\r
+               for (ListIterator depsIterator = list.listIterator();\r
+                                       depsIterator.hasNext(); ) \r
+               {\r
+                       Dependency dep = (Dependency) depsIterator.next();\r
+\r
+                       if (dep.getProvider().isPersistent())\r
+                       {\r
+                               pih.add(new BasicProviderInfo(\r
+                                                                       dep.getProvider().getObjectID(),\r
+                                                                       dep.getProvider().getDependableFinder(),\r
+                                                                       dep.getProvider().getObjectName()\r
+                                                                       ));\r
+                       }\r
+               }\r
+\r
+\r
+               return (ProviderInfo[]) pih.toArray(EMPTY_PROVIDER_INFO);\r
+       }\r
+\r
+       private static final ProviderInfo[] EMPTY_PROVIDER_INFO = new ProviderInfo[0];\r
+\r
+       /**\r
+        * @see DependencyManager#getPersistentProviderInfos\r
+        *\r
+        * @exception StandardException         Thrown on error\r
+        */\r
+       public ProviderInfo[] getPersistentProviderInfos(ProviderList pl)\r
+                                                       throws StandardException\r
+       {\r
+               Enumeration e = pl.elements();\r
+               int                     numProviders = 0;\r
+               ProviderInfo[]  retval;\r
+\r
+               /*\r
+               ** We make 2 passes - the first to count the number of persistent\r
+               ** providers and the second to populate the array of ProviderInfos.\r
+               */\r
+               while (e != null && e.hasMoreElements())\r
+               {\r
+                       Provider prov = (Provider) e.nextElement();\r
+\r
+                       if (prov.isPersistent())\r
+                       {\r
+                               numProviders++;\r
+                       }\r
+               }\r
+\r
+               e = pl.elements();\r
+               retval = new ProviderInfo[numProviders];\r
+               int piCtr = 0;\r
+               while (e != null && e.hasMoreElements())\r
+               {\r
+                       Provider prov = (Provider) e.nextElement();\r
+\r
+                       if (prov.isPersistent())\r
+                       {\r
+                               retval[piCtr++] = new BasicProviderInfo(\r
+                                                                       prov.getObjectID(),\r
+                                                                       prov.getDependableFinder(),\r
+                                                                       prov.getObjectName()\r
+                                                                       );\r
+                       }\r
+               }\r
+\r
+               return retval;\r
+       }\r
+\r
+       /**\r
+        * @see DependencyManager#clearColumnInfoInProviders\r
+        *\r
+        * @param pl            provider list\r
+        *\r
+        * @exception StandardException         Thrown on error\r
+        */\r
+       public void clearColumnInfoInProviders(ProviderList pl)\r
+                                       throws StandardException\r
+       {\r
+               Enumeration e = pl.elements();\r
+               while (e.hasMoreElements())\r
+               {\r
+                       Provider pro = (Provider) e.nextElement();\r
+                       if (pro instanceof TableDescriptor)\r
+                               ((TableDescriptor) pro).setReferencedColumnMap(null);\r
+               }\r
+       }\r
+\r
+       /**\r
+        * Copy dependencies from one dependent to another.\r
+        *\r
+        * @param copy_From the dependent to copy from  \r
+        * @param copyTo the dependent to copy to\r
+        * @param persistentOnly only copy persistent dependencies\r
+        * @param cm            Current ContextManager\r
+        *\r
+        * @exception StandardException         Thrown on error.\r
+        */\r
+       public void copyDependencies(Dependent  copy_From, \r
+                                                               Dependent       copyTo,\r
+                                                               boolean         persistentOnly,\r
+                                                               ContextManager cm) throws StandardException\r
+       {\r
+               copyDependencies(copy_From, copyTo, persistentOnly, cm, null);\r
+       }\r
+       \r
+       /**\r
+        * @inheritDoc \r
+        */\r
+       public synchronized void copyDependencies(\r
+                                                                       Dependent       copy_From, \r
+                                                                       Dependent       copyTo,\r
+                                                                       boolean         persistentOnly,\r
+                                                                       ContextManager cm,\r
+                                                                       TransactionController tc)\r
+               throws StandardException\r
+       {\r
+\r
+               List list = getProviders(copy_From);\r
+               if (list == null)\r
+                       return;\r
+\r
+               for (ListIterator depsIterator = list.listIterator(); depsIterator.hasNext(); ) \r
+               {\r
+                       Provider provider = ((Dependency) depsIterator.next()).getProvider();\r
+                               \r
+                       if (!persistentOnly || provider.isPersistent())\r
+                       {\r
+                               this.addDependency(copyTo, provider, cm, tc);\r
+                       }\r
+               }\r
+       }\r
+\r
+                                       \r
+       /**\r
+        * Returns a string representation of the SQL action, hence no\r
+        * need to internationalize, which is causing the invokation\r
+        * of the Dependency Manager.\r
+        *\r
+        * @param action                The action\r
+        *\r
+        * @return String       The String representation\r
+        */\r
+       public String getActionString(int action)\r
+       {\r
+               switch (action)\r
+               {\r
+                       case ALTER_TABLE:\r
+                               return "ALTER TABLE";\r
+\r
+                       case RENAME: //for rename table and column\r
+                               return "RENAME";\r
+\r
+                       case RENAME_INDEX:\r
+                               return "RENAME INDEX";\r
+\r
+                       case COMPILE_FAILED:\r
+                               return "COMPILE FAILED";\r
+\r
+                       case DROP_TABLE:\r
+                               return "DROP TABLE";\r
+\r
+                       case DROP_INDEX:\r
+                               return "DROP INDEX";\r
+\r
+                       case DROP_VIEW:\r
+                               return "DROP VIEW";\r
+\r
+                       case CREATE_INDEX:\r
+                               return "CREATE INDEX";\r
+\r
+                       case ROLLBACK:\r
+                               return "ROLLBACK";\r
+\r
+                       case CHANGED_CURSOR:\r
+                               return "CHANGED CURSOR";\r
+\r
+                       case CREATE_CONSTRAINT:\r
+                               return "CREATE CONSTRAINT";\r
+\r
+                       case DROP_CONSTRAINT:\r
+                               return "DROP CONSTRAINT";\r
+\r
+                       case DROP_METHOD_ALIAS:\r
+                               return "DROP ROUTINE";\r
+\r
+                       case PREPARED_STATEMENT_RELEASE:\r
+                               return "PREPARED STATEMENT RELEASE";\r
+\r
+                       case DROP_SPS:\r
+                               return "DROP STORED PREPARED STATEMENT";\r
+\r
+                       case USER_RECOMPILE_REQUEST:\r
+                               return "USER REQUESTED INVALIDATION";\r
+\r
+                       case BULK_INSERT:\r
+                               return "BULK INSERT";\r
+\r
+                   case CREATE_VIEW:\r
+                               return "CREATE_VIEW";\r
\r
+                       case DROP_JAR:\r
+                               return "DROP_JAR";\r
+\r
+                       case REPLACE_JAR:\r
+                               return "REPLACE_JAR";\r
+\r
+                       case SET_CONSTRAINTS_ENABLE:\r
+                               return "SET_CONSTRAINTS_ENABLE";\r
+\r
+                       case SET_CONSTRAINTS_DISABLE:\r
+                               return "SET_CONSTRAINTS_DISABLE";\r
+\r
+                       case INTERNAL_RECOMPILE_REQUEST:\r
+                               return "INTERNAL RECOMPILE REQUEST";\r
+\r
+                       case CREATE_TRIGGER:\r
+                               return "CREATE TRIGGER";\r
+\r
+                       case DROP_TRIGGER:\r
+                               return "DROP TRIGGER";\r
+\r
+                       case SET_TRIGGERS_ENABLE:\r
+                               return "SET TRIGGERS ENABLED";\r
+\r
+                       case SET_TRIGGERS_DISABLE:\r
+                               return "SET TRIGGERS DISABLED";\r
+\r
+                       case MODIFY_COLUMN_DEFAULT:\r
+                               return "MODIFY COLUMN DEFAULT";\r
+\r
+                       case COMPRESS_TABLE:\r
+                               return "COMPRESS TABLE";\r
+\r
+                       case DROP_COLUMN:\r
+                               return "DROP COLUMN";\r
+\r
+                       case DROP_COLUMN_RESTRICT:\r
+                               return "DROP COLUMN RESTRICT";\r
+\r
+                   case DROP_STATISTICS:\r
+                               return "DROP STATISTICS";\r
+\r
+                       case UPDATE_STATISTICS:\r
+                               return "UPDATE STATISTICS";\r
+\r
+                   case TRUNCATE_TABLE:\r
+                           return "TRUNCATE TABLE";\r
+\r
+                   case DROP_SYNONYM:\r
+                           return "DROP SYNONYM";\r
+\r
+                   case REVOKE_PRIVILEGE:\r
+                           return "REVOKE PRIVILEGE";\r
+\r
+                   case REVOKE_PRIVILEGE_RESTRICT:\r
+                           return "REVOKE PRIVILEGE RESTRICT";\r
+                                                  \r
+                       default:\r
+                               if (SanityManager.DEBUG)\r
+                               {\r
+                                       SanityManager.THROWASSERT("getActionString() passed an invalid value (" + action + ")");\r
+                               }\r
+                               // NOTE: This is not internationalized because we should never\r
+                               // reach here.\r
+                               return "UNKNOWN";\r
+               }\r
+       }\r
+\r
+       /**\r
+        * Count the number of active dependencies, both stored and in memory,\r
+        * in the system.\r
+        *\r
+        * @return int          The number of active dependencies in the system.\r
+\r
+               @exception StandardException thrown if something goes wrong\r
+        */\r
+       public int countDependencies()\r
+               throws StandardException\r
+       {\r
+               synchronized(this)\r
+               {\r
+                       int numDependencies = 0;\r
+                       Enumeration deps = dependents.elements();\r
+                       Enumeration provs = providers.elements();\r
+                       List storedDeps = dd.getAllDependencyDescriptorsList();\r
+\r
+                       /* Count the in memory dependencies */\r
+                       while (deps.hasMoreElements())\r
+                       {\r
+                               numDependencies += ((List) deps.nextElement()).size();\r
+                       }\r
+\r
+                       while (provs.hasMoreElements())\r
+                       {\r
+                               numDependencies += ((List) provs.nextElement()).size();\r
+                       }\r
+\r
+                       /* Add in the stored dependencies */\r
+                       numDependencies += storedDeps.size();\r
+\r
+                       return numDependencies;\r
+               }\r
+       }\r
+\r
+       /**\r
+        * Dump out debugging info on all of the dependencies currently\r
+        * within the system.\r
+        *\r
+        * @return String       Debugging info on the dependencies.\r
+        *                                      (null if SanityManger.DEBUG is false)\r
+\r
+        * @exception StandardException thrown if something goes wrong\r
+        * @exception java.sql.SQLException thrown if something goes wrong\r
+        */\r
+       public String dumpDependencies() throws StandardException, java.sql.SQLException\r
+       {\r
+               synchronized(this)\r
+               {\r
+                       boolean foundInMemory = false;\r
+                       boolean foundStored = false;\r
+                       StringBuffer debugBuf = new StringBuffer();\r
+\r
+                       if (SanityManager.DEBUG)\r
+                       {\r
+                               Enumeration deps = dependents.keys();\r
+                               UUID[]          depKeys = new UUID[dependents.size()];\r
+\r
+                               /* Record the in memory dependencies */\r
+                               for (int i = 0; deps.hasMoreElements(); i++)\r
+                               {\r
+                                       /*\r
+                                       ** Get all the keys and sort them, so that they will always\r
+                                       ** be printed in the same order (we have tests that canonize\r
+                                       ** the order of printing the dependencies, and since the key\r
+                                       ** is a UUID, the order they are returned from\r
+                                       ** hasMoreElements() changes from run to run).\r
+                                       */\r
+                                       depKeys[i] = (UUID) deps.nextElement();\r
+                               }\r
+\r
+                               /* Do a bubble sort - there aren't likely to be many elements */\r
+                               bubbleSort(depKeys);\r
+\r
+                               /* Iterate through the sorted keys */\r
+                               for (int i = 0; i < depKeys.length; i++)\r
+                               {\r
+                                       List depsSList = (List) dependents.get(depKeys[i]);\r
+\r
+                                       for (ListIterator depsIterator = depsSList.listIterator();\r
+                                               depsIterator.hasNext(); ) \r
+                                       {\r
+                                               Dependency dy = (Dependency)depsIterator.next();\r
+\r
+                                               if (! foundInMemory)\r
+                                               {\r
+                                                       debugBuf.append("In Memory Dependencies:\n");\r
+                                                       foundInMemory = true;\r
+                                               }\r
+\r
+                                               debugBuf.append(dy.getDependent().toString() +\r
+                                                                               ", type " + \r
+                                                                               dy.getDependent().getClassType() +\r
+                                                                               ", " +\r
+                                                                               " is dependent on " +\r
+                                                                               dy.getProvider().getObjectName() + \r
+                                                                               ", type " +\r
+                                                                               dy.getProvider().getClassType() +\r
+                                                                               "\n");\r
+                                       }\r
+                               }\r
+\r
+                               /* Record the in memory dependencies */\r
+                               Enumeration provs = providers.keys();\r
+                               UUID[]          provKeys = new UUID[providers.size()];\r
+                               for (int i = 0; provs.hasMoreElements(); i++)\r
+                               {\r
+                                       /*\r
+                                       ** Get all the keys and sort them, so that they will always\r
+                                       ** be printed in the same order (we have tests that canonize\r
+                                       ** the order of printing the dependencies, and since the key\r
+                                       ** is a UUID, the order they are returned from\r
+                                       ** hasMoreElements() changes from run to run).\r
+                                       */\r
+                                       provKeys[i] = (UUID) provs.nextElement();\r
+                               }\r
+\r
+                               /* Do a bubble sort - there aren't likely to be many elements */\r
+                               bubbleSort(provKeys);\r
+\r
+                               /* Iterate through the sorted keys */\r
+                               for (int i = 0; i < provKeys.length; i++)\r
+                               {\r
+                                       List depsSList = (List) providers.get(provKeys[i]);\r
+\r
+                                       for (ListIterator depsIterator = depsSList.listIterator();\r
+                                               depsIterator.hasNext(); ) \r
+                                       {\r
+\r
+                                               Dependency dy = (Dependency)depsIterator.next();\r
+\r
+                                               if (! foundInMemory)\r
+                                               {\r
+                                                       debugBuf.append("In Memory Dependencies:\n");\r
+                                                       foundInMemory = true;\r
+                                               }\r
+\r
+                                               debugBuf.append( \r
+                                                                               dy.getProvider().toString() + \r
+                                                                               ", type " +\r
+                                                                               dy.getProvider().getClassType() +\r
+                                                                               ", provides for " +\r
+                                                                               dy.getDependent().getObjectName() +\r
+                                                                               ", type " +\r
+                                                                               dy.getDependent().getClassType() +\r
+                                                                               "\n");\r
+                                       }\r
+                               }\r
+                               /* Record the stored dependencies in sorted order to avoid\r
+                                  ordering problems in canons. Also the dependencyDescriptor.getUUID()\r
+                                  in this list is not unique, hence the sort on the output string values instead\r
+                               */\r
+                               List storedDeps = dd.getAllDependencyDescriptorsList();\r
+\r
+                               String[] dependStr = new String[storedDeps.size()];\r
+\r
+                               int i = 0;\r
+                               for (ListIterator depsIterator = storedDeps.listIterator();\r
+                                        depsIterator.hasNext(); )\r
+                               {\r
+                                       DependencyDescriptor dependDescr =\r
+                        (DependencyDescriptor) depsIterator.next();\r
+\r
+                                       if (! foundStored)\r
+                                       {\r
+                                               debugBuf.append("Stored Dependencies:\n");\r
+                                               foundStored = true;\r
+                                       }\r
+                    \r
+                    DependableFinder providerFinder = dependDescr.getProviderFinder();\r
+                    DependableFinder dependentFinder = dependDescr.getDependentFinder();\r
+                    \r
+\r
+                                       dependStr[i++] =\r
+                        providerFinder.getDependable(dd, dependDescr.getProviderID()).getObjectName() +\r
+                        ", type " + providerFinder.getSQLObjectType() +\r
+                        ", provides for " +\r
+                        dependentFinder.getDependable(dd, dependDescr.getUUID()).getObjectName() +\r
+                        ", type " + dependentFinder.getSQLObjectType() +\r
+                        "\n";\r
+                               }\r
+\r
+                               // sort stored dependencies; dependStr\r
+                               for (i = 0; i < dependStr.length; i++)\r
+                               {\r
+                                       for (int j = i + 1; j < dependStr.length; j++)\r
+                                       {\r
+                                               if (dependStr[i].compareTo(dependStr[j]) > 0)\r
+                                               {\r
+                                                       String save = dependStr[i];\r
+                                                       dependStr[i] = dependStr[j];\r
+                                                       dependStr[j] = save;\r
+                                               }\r
+                                       }\r
+                               }\r
+\r
+                               for(i=0; i < dependStr.length; i++)\r
+                                               debugBuf.append(dependStr[i]);\r
+\r
+\r
+                       }\r
+\r
+                       return debugBuf.toString();\r
+               }\r
+       }\r
+\r
+       //\r
+       // class interface\r
+       //\r
+       public BasicDependencyManager(DataDictionary dd) {\r
+        this.dd = dd;\r
+       }\r
+\r
+       //\r
+       // class implementation\r
+       //\r
+\r
+       /**\r
+        * Add a new dependency to the specified table if it does not\r
+        * already exist in that table.\r
+        *\r
+        * @return boolean              Whether or not the dependency get added.\r
+        */\r
+       private boolean addDependencyToTable(Hashtable table, \r
+               Object key, Dependency dy) {\r
+\r
+               List deps = (List) table.get(key);\r
+               if (deps == null) {\r
+                       deps = newSList();\r
+                       deps.add(dy);\r
+                       table.put(key, deps);\r
+               }\r
+               else {\r
+                       /* Make sure that we're not adding a duplicate dependency */\r
+                       UUID    provKey = dy.getProvider().getObjectID();\r
+                       UUID    depKey = dy.getDependent().getObjectID();\r
+\r
+                       for (ListIterator depsIT = deps.listIterator();  depsIT.hasNext(); )\r
+                       {\r
+                               Dependency curDY = (Dependency)depsIT.next();\r
+                               if (curDY.getProvider().getObjectID().equals(provKey) &&\r
+                                       curDY.getDependent().getObjectID().equals(depKey))\r
+                               {\r
+                                       return false;\r
+                               }\r
+                       }\r
+\r
+                       deps.add(dy);\r
+               }\r
+\r
+               if (SanityManager.DEBUG) {\r
+\r
+                       if (SanityManager.DEBUG_ON("memoryLeakTrace")) {\r
+\r
+                               if (table.size() > 100)\r
+                                       System.out.println("memoryLeakTrace:BasicDependencyManager:table " + table.size());\r
+                               if (deps.size() > 50)\r
+                                       System.out.println("memoryLeakTrace:BasicDependencyManager:deps " + deps.size());\r
+                       }\r
+               }\r
+\r
+               return true;\r
+       }\r
+\r
+       /**\r
+        * removes a dependency for a given provider. assumes\r
+        * that the dependent removal is being dealt with elsewhere.\r
+        * Won't assume that the dependent only appears once in the list.\r
+        */\r
+       protected void clearProviderDependency(UUID p, Dependency d) {\r
+               List deps = (List) providers.get(p);\r
+\r
+               if (deps == null)\r
+                       return;\r
+\r
+               deps.remove(d);\r
+\r
+               if (deps.size() == 0)\r
+                       providers.remove(p);\r
+       }\r
+\r
+       /**\r
+        * Replace the DependencyDescriptors in an List with Dependencys.\r
+        *\r
+        * @param storedList    The List of DependencyDescriptors representing\r
+        *                                              stored dependencies.\r
+        * @param providerForList The provider if this list is being created\r
+        *                        for a list of dependents. Null otherwise.\r
+        * \r
+        * @return List         The converted List\r
+        *\r
+        * @exception StandardException thrown if something goes wrong\r
+        */\r
+       private List getDependencyDescriptorList(List storedList,\r
+                       Provider providerForList)\r
+               throws StandardException\r
+       {\r
+               if (storedList.size() != 0)\r
+               {\r
+                       /* For each DependencyDescriptor, we need to instantiate\r
+                        * object descriptors of the appropriate type for both\r
+                        * the dependent and provider, create a Dependency with\r
+                        * that Dependent and Provider and substitute the Dependency\r
+                        * back into the same place in the List\r
+                        * so that the call gets an enumerations of Dependencys.\r
+                        */\r
+                       for (ListIterator depsIterator = storedList.listIterator();\r
+                                depsIterator.hasNext(); ) \r
+                       {\r
+                               Dependent                       tempD;\r
+                               Provider                        tempP;\r
+                               DependableFinder        finder = null;\r
+\r
+                               DependencyDescriptor depDesc = (DependencyDescriptor) depsIterator.next();\r
+\r
+                                       finder = depDesc.getDependentFinder();\r
+                                       tempD = (Dependent) finder.getDependable(dd, depDesc.getUUID() );\r
+\r
+                                       if (providerForList != null)\r
+                                       {\r
+                                               // Use the provider being passed in.\r
+                                               tempP = providerForList;\r
+                                               \r
+                                               // Sanity check the object identifiers match.\r
+                                               if (SanityManager.DEBUG) {\r
+                                                       if (!tempP.getObjectID().equals(depDesc.getProviderID()))\r
+                                                       {\r
+                                                               SanityManager.THROWASSERT("mismatch providers");\r
+                                                       }\r
+                                               }\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               finder = depDesc.getProviderFinder();\r
+                                               tempP = (Provider) finder.getDependable(dd, depDesc.getProviderID() );\r
+                                               \r
+                                       }\r
+\r
+                               depsIterator.set(new BasicDependency(tempD, tempP));\r
+                       }\r
+               }\r
+\r
+               return storedList;\r
+       }\r
+\r
+       /**\r
+        * Returns the LanguageConnectionContext to use.\r
+        *\r
+        * @param cm    Current ContextManager\r
+        *\r
+        * @return LanguageConnectionContext    The LanguageConnectionContext to use.\r
+        */\r
+       private LanguageConnectionContext getLanguageConnectionContext(ContextManager cm)\r
+       {\r
+               // find the language context.\r
+               return (LanguageConnectionContext) cm.getContext(LanguageConnectionContext.CONTEXT_ID);\r
+       }\r
+\r
+       /**\r
+        * Do a bubble sort on the given array of UUIDs.  This sorts by the\r
+        * String values of the UUIDs.  It's slow, but it doesn't matter\r
+        * because this is only for testing and debugging.  Sorting by\r
+        * UUID.toString() always gives the same order because, within a\r
+        * single boot of the system, UUIDs are distinguished only by a\r
+        * sequence number.\r
+        *\r
+        * @param uuids         The array of UUIDs to sort.\r
+        */\r
+       private void bubbleSort(UUID[] uuids)\r
+       {\r
+               if (SanityManager.DEBUG)\r
+               {\r
+                       for (int i = 0; i < uuids.length; i++)\r
+                       {\r
+                               for (int j = i + 1; j < uuids.length; j++)\r
+                               {\r
+                                       if (uuids[i].toString().compareTo(uuids[j].toString()) > 0)\r
+                                       {\r
+                                               UUID    save = uuids[i];\r
+                                               uuids[i] = uuids[j];\r
+                                               uuids[j] = save;\r
+                                       }\r
+                               }\r
+                       }\r
+               }\r
+       }\r
+\r
+       /**\r
+               Returns an enumeration of all dependencies that this\r
+               dependent has with any provider (even\r
+               invalid ones). Includes all dependency types.\r
+\r
+               @param d the dependent\r
+\r
+               @exception StandardException thrown if something goes wrong\r
+        */\r
+       private List getProviders (Dependent d) throws StandardException {\r
+\r
+               List deps = (List) dependents.get(d.getObjectID());\r
+\r
+               /* If the Dependent is not persistent, then we only have to\r
+               * worry about in-memory dependencies.  Otherwise, we have to\r
+               * integrate the 2.\r
+               */\r
+               if (! d.isPersistent())\r
+               {\r
+                       return (deps == null? null : deps);\r
+               }\r
+               else\r
+               {\r
+                       if (deps == null)\r
+                       {\r
+                               deps = newSList();\r
+                       }\r
+                       else\r
+                       {\r
+                               deps = newSList(deps);\r
+                       }\r
+\r
+                       /* Now we need to add any persistent dependencies to the\r
+                       * list before returning\r
+                       */\r
+                       List storedList = getDependencyDescriptorList(\r
+                                                               dd.getDependentsDescriptorList(\r
+                                                                                               d.getObjectID().toString()\r
+                                                                                                                       ),\r
+                                                               (Provider) null\r
+                                                                                                       );\r
+\r
+                       if (storedList.size() > 0)\r
+                       {\r
+                               deps.addAll(0, storedList);\r
+                       }\r
+\r
+                       return deps;\r
+               }\r
+       }\r
+\r
+       /**\r
+               Returns an enumeration of all dependencies that this\r
+               provider is supporting for any dependent at all (even\r
+               invalid ones). Includes all dependency types.\r
+\r
+               @param p the provider\r
+\r
+               @exception StandardException thrown if something goes wrong\r
+        */\r
+       private List getDependents (Provider p) \r
+                       throws StandardException {\r
+\r
+               List deps = (List) providers.get(p.getObjectID());\r
+\r
+               /* If the Provider is not persistent, then we only have to\r
+               * worry about in-memory dependencies.  Otherwise, we have to\r
+               * integrate the 2.\r
+               */\r
+               if (! p.isPersistent())\r
+               {\r
+                       return deps;\r
+               }\r
+               else\r
+               {\r
+                       if (deps == null)\r
+                       {\r
+                               deps = newSList();\r
+                       }\r
+                       else\r
+                       {\r
+                               deps = newSList(deps);\r
+                       }\r
+\r
+                       /* Now we need to add any persistent dependencies to the\r
+                       * list before returning\r
+                       */\r
+                       List storedList = getDependencyDescriptorList(\r
+                                                               dd.getProvidersDescriptorList(\r
+                                                                                               p.getObjectID().toString()\r
+                                                                                                                       ),\r
+                                                       p\r
+                                                                                                       );\r
+                       if (storedList.size() > 0)\r
+                       {\r
+                               deps.addAll(0, storedList);\r
+                       }\r
+\r
+                       return deps;\r
+               }\r
+       }\r
+\r
+       private static List newSList() {\r
+               return java.util.Collections.synchronizedList(new java.util.LinkedList());\r
+       }\r
+       private static List newSList(List list) {\r
+               return java.util.Collections.synchronizedList(new java.util.LinkedList(list));\r
+       }\r
+}\r