You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commons-dev@ws.apache.org by Jeff Barrett <ba...@us.ibm.com> on 2009/04/03 15:44:57 UTC
Re: svn commit: r757453 - in /webservices/commons/trunk/modules/XmlSchema/src: main/java/org/apache/ws/commons/schema/SchemaBuilder.java
test/java/tests/SchemaBuilderCacheTest.java
Hi Daniel,
+1 to both those suggestions.
Thanks,
Jeff
IBM Software Group - WebSphere Web Services Development
Phone: (512) 286-5256 or TieLine: 363-5256
Internet e-mail and Sametime ID: barrettj@us.ibm.com
From:
Daniel Kulp <dk...@apache.org>
To:
commons-dev@ws.apache.org
Cc:
woodroy@apache.org
Date:
03/23/2009 12:25 PM
Subject:
Re: svn commit: r757453 - in
/webservices/commons/trunk/modules/XmlSchema/src:
main/java/org/apache/ws/commons/schema/SchemaBuilder.java
test/java/tests/SchemaBuilderCacheTest.java
Couple questions about this commit:
1) Why not just use a ThreadLocal<Map<....>> instead of mimicking one with
a
HashMap based on thread id? That way, if the Thread goes away before
someone
clears it, we know the the data will get garbage collected.
2) Collections.synchronizedMap(new Hashtable<String,
SoftReference<XmlSchema>>())
Uh..... Hashtable is already synchronized. Should that be a HashMap?
Dan
On Mon March 23 2009 1:14:57 pm woodroy@apache.org wrote:
> Author: woodroy
> Date: Mon Mar 23 17:14:56 2009
> New Revision: 757453
>
> URL: http://svn.apache.org/viewvc?rev=757453&view=rev
> Log:
> Update initCache and clearCache to account for multi-threaded case.
> Essentially, one thread could change the static 'resolvedSchema'
variable
> from null to non-null after another thread found the value to be null.
>
> Contributor: Jeff Barrett via Roy Wood
>
>
> Added:
>
>
webservices/commons/trunk/modules/XmlSchema/src/test/java/tests/SchemaBuild
>erCacheTest.java Modified:
>
>
webservices/commons/trunk/modules/XmlSchema/src/main/java/org/apache/ws/com
>mons/schema/SchemaBuilder.java
>
> Modified:
>
webservices/commons/trunk/modules/XmlSchema/src/main/java/org/apache/ws/com
>mons/schema/SchemaBuilder.java URL:
>
http://svn.apache.org/viewvc/webservices/commons/trunk/modules/XmlSchema/sr
>c/main/java/org/apache/ws/commons/schema/SchemaBuilder.java?rev=757453&r1=75
>7452&r2=757453&view=diff
>
===========================================================================
>=== ---
>
webservices/commons/trunk/modules/XmlSchema/src/main/java/org/apache/ws/com
>mons/schema/SchemaBuilder.java (original) +++
>
webservices/commons/trunk/modules/XmlSchema/src/main/java/org/apache/ws/com
>mons/schema/SchemaBuilder.java Mon Mar 23 17:14:56 2009 @@ -24,6 +24,7 @@
> import java.util.Collections;
> import java.util.HashMap;
> import java.util.HashSet;
> +import java.util.Hashtable;
> import java.util.List;
> import java.util.Map;
> import java.util.Set;
> @@ -66,7 +67,8 @@
> * initialize resolvedSchemas to non-null Clearing of cache is done
by
> calling clearCache() which will * clear and nullify resolvedSchemas
> */
> - private static Map<String, SoftReference<XmlSchema>>
resolvedSchemas;
> +
> + private static Map<String, Map<String, SoftReference<XmlSchema>>>
> resolvedSchemas; private static final String[] RESERVED_ATTRIBUTES_LIST
=
> {"name", "type", "default", @@ -109,16 +111,108 @@
> currentSchema = new XmlSchema();
> }
>
> +
> + /**
> + * Setup the cache to be used by the current thread of execution.
> Multiple + * threads can use the cache, and each one must call this
> method at + * some point prior to attempting to resolve the first
> schema, or the cache + * will not be used on that thread.
> + *
> + * IMPORTANT: The thread MUST call clearCache() when it is done
with
> the + * schemas or a large amount of memory may remain in-use.
> + */
> + public static synchronized void initCache() {
> +
> + if (resolvedSchemas == null) {
> + resolvedSchemas =
> + Collections.synchronizedMap(new HashMap<String,
Map<String,
> SoftReference<XmlSchema>>>()); + }
> +
> + String threadID =
String.valueOf(Thread.currentThread().getId());
> +
> + Map<String, SoftReference<XmlSchema>> threadResolvedSchemas =
> + resolvedSchemas.get(threadID);
> +
> + // If there is no entry yet for this thread ID, then create one
> + if (threadResolvedSchemas == null) {
> + threadResolvedSchemas = Collections.synchronizedMap(new
> Hashtable<String, SoftReference<XmlSchema>>()); +
> resolvedSchemas.put(threadID, threadResolvedSchemas); +
> + }
> + }
> +
> + /**
> + * Remove any entries from the cache for the current thread.
Entries
> for + * other threads are not altered.
> + */
> public static synchronized void clearCache() {
> if (resolvedSchemas != null) {
> - resolvedSchemas.clear(); // necessary?
> - resolvedSchemas = null;
> + String threadID =
> String.valueOf(Thread.currentThread().getId()); + // If there
> are entries for this thread ID, then clear them and + //
remove
> the entry
> + Map<String, SoftReference<XmlSchema>> threadResolvedSchemas
=
> + resolvedSchemas.get(threadID);
> +
> + if (threadResolvedSchemas != null) {
> + threadResolvedSchemas.clear();
> + resolvedSchemas.remove(threadID);
> + }
> + }
> + }
> +
> + /**
> + * Return a cached schema if one exists for this thread. In order
for
> schemas to be cached + * the thread must have done an initCache()
> previously.
> + * The parameters are used to construct a key used to lookup the
> schema + * @param targetNamespace
> + * @param schemaLocation
> + * @param baseUri
> + * @return The cached schema if one exists for this thread or null.
> + */
> + private XmlSchema getCachedSchema(String targetNamespace,
> + String schemaLocation, String baseUri) {
> +
> + XmlSchema resolvedSchema = null;
> +
> + if (resolvedSchemas != null) { // cache is initialized, use it
> + String threadID =
> String.valueOf(Thread.currentThread().getId()); + Map<String,
> SoftReference<XmlSchema>> threadResolvedSchemas = +
> resolvedSchemas.get(threadID);
> + if (threadResolvedSchemas != null) {
> + // Not being very smart about this at the moment. One
> could, for example, + // see that the schemaLocation or
> baseUri is the same as another, but differs + // only by
a
> trailing slash. As it is now, we assume a single character difference +
> // means it's a schema that has yet to be resolved. +
> String schemaKey = targetNamespace + schemaLocation + baseUri; +
> SoftReference<XmlSchema> softref =
> threadResolvedSchemas.get(schemaKey); + if (softref !=
null)
> {
> + resolvedSchema = softref.get();
> + }
> + }
> }
> + return resolvedSchema;
> }
>
> - public static synchronized void initCache() {
> - if (resolvedSchemas == null) {
> - resolvedSchemas = Collections.synchronizedMap(new
> HashMap<String, SoftReference<XmlSchema>>()); + /**
> + * Add an XmlSchema to the cache if the current thread has the
cache
> enabled. + * The first three parameters are used to construct a key
> + * @param targetNamespace
> + * @param schemaLocation
> + * @param baseUri
> + * This parameter is the value put under the key (if the cache is
> enabled) + * @param readSchema
> + */
> + private void putCachedSchema(String targetNamespace, String
> schemaLocation, + String baseUri, XmlSchema readSchema) {
> +
> + if (resolvedSchemas != null) {
> + String threadID =
> String.valueOf(Thread.currentThread().getId()); + Map<String,
> SoftReference<XmlSchema>> threadResolvedSchemas = +
> resolvedSchemas.get(threadID);
> + if (threadResolvedSchemas != null) {
> + String schemaKey = targetNamespace + schemaLocation +
> baseUri; + threadResolvedSchemas.put(schemaKey, new
> SoftReference<XmlSchema>(readSchema)); + }
> }
> }
>
> @@ -917,22 +1011,10 @@
> XmlSchema resolveXmlSchema(String targetNamespace, String
> schemaLocation, String baseUri, TargetNamespaceValidator validator) {
>
> - String schemaKey = null;
> - if (resolvedSchemas != null) { // cache is initialized, use it
> - // Not being very smart about this at the moment. One
could,
> for example, - // see that the schemaLocation or baseUri is
the
> same as another, but differs - // only by a trailing slash.
As
> it is now, we assume a single character difference - // means
> it's a schema that has yet to be resolved.
> - schemaKey = Thread.currentThread().getId() +
targetNamespace +
> schemaLocation + baseUri; - SoftReference<XmlSchema> softref
=
> resolvedSchemas.get(schemaKey); - if (softref != null) {
> - XmlSchema resolvedSchema = softref.get();
> - if (resolvedSchema != null) {
> - return resolvedSchema;
> - }
> - }
> + if (getCachedSchema(targetNamespace, schemaLocation, baseUri)
!=
> null) { + return getCachedSchema(targetNamespace,
> schemaLocation, baseUri); }
> -
> +
> // use the entity resolver provided if the schema location is
> present null if (schemaLocation != null && !"".equals(schemaLocation)) {
> InputSource source =
> collection.getSchemaResolver().resolveEntity(targetNamespace, @@ -958,9
> +1040,7 @@
> collection.push(key);
> try {
> XmlSchema readSchema = collection.read(source,
null,
> validator); - if (resolvedSchemas != null) {
> - resolvedSchemas.put(schemaKey, new
> SoftReference<XmlSchema>(readSchema)); - }
> + putCachedSchema(targetNamespace, schemaLocation,
> baseUri, readSchema); return readSchema;
> } catch (Exception e) {
> throw new RuntimeException(e);
>
> Added:
>
webservices/commons/trunk/modules/XmlSchema/src/test/java/tests/SchemaBuild
>erCacheTest.java URL:
>
http://svn.apache.org/viewvc/webservices/commons/trunk/modules/XmlSchema/sr
>c/test/java/tests/SchemaBuilderCacheTest.java?rev=757453&view=auto
>
===========================================================================
>=== ---
>
webservices/commons/trunk/modules/XmlSchema/src/test/java/tests/SchemaBuild
>erCacheTest.java (added) +++
>
webservices/commons/trunk/modules/XmlSchema/src/test/java/tests/SchemaBuild
>erCacheTest.java Mon Mar 23 17:14:56 2009 @@ -0,0 +1,424 @@
> +/*
> + * Licensed to the Apache Software Foundation (ASF) under one
> + * or more contributor license agreements. See the NOTICE file
> + * distributed with this work for additional information
> + * regarding copyright ownership. The ASF licenses this file
> + * to you under the Apache License, Version 2.0 (the
> + * "License"); you may not use this file except in compliance
> + * with the License. You may obtain a copy of the License at
> + *
> + * http://www.apache.org/licenses/LICENSE-2.0
> + *
> + * Unless required by applicable law or agreed to in writing,
> + * software distributed under the License is distributed on an
> + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
> + * KIND, either express or implied. See the License for the
> + * specific language governing permissions and limitations
> + * under the License.
> + */
> +
> +
> +package tests;
> +
> +import java.lang.ref.SoftReference;
> +import java.lang.reflect.Field;
> +import java.util.Hashtable;
> +import java.util.Map;
> +
> +import javax.xml.parsers.DocumentBuilderFactory;
> +
> +import org.apache.ws.commons.schema.SchemaBuilder;
> +import org.apache.ws.commons.schema.XmlSchema;
> +import org.apache.ws.commons.schema.XmlSchemaCollection;
> +import org.w3c.dom.Document;
> +
> +import org.junit.Assert;
> +import org.junit.Test;
> +import org.junit.Ignore;
> +
> +/**
> + * Test the resolved Schema cache.
> + */
> +public class SchemaBuilderCacheTest extends Assert {
> +
> + /**
> + * Test that if the cache is not initialized, then it should not be
> used when a schema is read. + * @throws Exception
> + */
> + @Test
> + public void testResolveCacheUninitialized() throws Exception {
> + Document doc = setupDocument();
> + XmlSchemaCollection schemaCol = setupXmlSchemaCollection();
> + XmlSchema schema = schemaCol.read(doc,null);
> + assertNotNull(schema);
> +
> + // If the cache is not in use, then it should be null
> + assertNull(getResolvedSchemasHashtable());
> + }
> +
> + /**
> + * Test if the cache is initialized it will be populated when a
schema
> is read and it will + * be cleared when the clearCache method is
> called.
> + * @throws Exception
> + */
> + @Test
> + public void testResolveCacheInitialized() throws Exception {
> + try {
> + SchemaBuilder.initCache();
> + Document doc = setupDocument();
> + XmlSchemaCollection schemaCol = setupXmlSchemaCollection();
> + XmlSchema schema = schemaCol.read(doc, null);
> + assertNotNull(schema);
> +
> + // If the cache is in use, it should not be null and there
> should + // be an entry for this thread ID
> + assertNotNull(getResolvedSchemasHashtable());
> + Map<String, SoftReference<XmlSchema>> threadHT =
> getThreadResolvedSchemaHashtable(); + assertNotNull(threadHT);
> + assertFalse(threadHT.isEmpty());
> + assertEquals(1, threadHT.size());
> +
> + // After clearing the cache, there should be no entry for
this
> thread ID, and + // the hashtable should not be null
> + SchemaBuilder.clearCache();
> + assertNotNull(getResolvedSchemasHashtable());
> + assertNull(getThreadResolvedSchemaHashtable());
> + System.out.println("Line 13");
> + } finally {
> + resetResolvedSchemasHashtable();
> + }
> +
> + // If the cache is enabled, then it should be non-null
> + }
> +
> + /**
> + * Test that threads can not affect the cache for other threads.
> + */
> + @Test
> + public void testMultithreadCache() {
> + try {
> + MultithreadUpdateLockMonitor testMonitor = new
> MultithreadUpdateLockMonitor(); +
> startupTestThreads(testMonitor);
> +
> + if (testMonitor.t1Exception != null) {
> + fail("Thread T1 encountred an error: "
> + + testMonitor.t1Exception.toString());
> + }
> + if (testMonitor.t2Exception != null) {
> + fail("Thread T2 encountred an error: "
> + + testMonitor.t2Exception.toString());
> + }
> + if (testMonitor.t3Exception != null) {
> + fail("Thread T3 encountred an error: "
> + + testMonitor.t3Exception.toString());
> + }
> + } finally {
> + resetResolvedSchemasHashtable();
> + }
> + }
> +
> +
>
//=========================================================================
>===================== + // Utility Methods
> +
>
//=========================================================================
>===================== +
> + static Document setupDocument() {
> + DocumentBuilderFactory documentBuilderFactory =
> DocumentBuilderFactory.newInstance(); +
> documentBuilderFactory.setNamespaceAware(true);
> + Document doc;
> + try {
> + doc = documentBuilderFactory.newDocumentBuilder().
> + parse(Resources.asURI("importBase.xsd"));
> + } catch (Exception e) {
> + throw new RuntimeException(e);
> + }
> + return doc;
> + }
> +
> + static XmlSchemaCollection setupXmlSchemaCollection() {
> + XmlSchemaCollection schemaCol = new XmlSchemaCollection();
> + schemaCol.setBaseUri(Resources.TEST_RESOURCES);
> + return schemaCol;
> + }
> +
> + /**
> + * Override the protection on the resolvedSchemas attribute in the
> SchemaBuilder class + * and return its current value.
> + * @return value of Hashtable resolvedSchemas, which may be null
> + * @throws Exception If there are problems with Java reflection
> (should not happen) + */
> + static Map<String, Map<String, SoftReference<XmlSchema>>>
> getResolvedSchemasHashtable(){ + Map<String, Map<String,
> SoftReference<XmlSchema>>> ht = null; + try {
> + Field field =
> SchemaBuilder.class.getDeclaredField("resolvedSchemas"); +
> field.setAccessible(true);
> + ht = (Map<String, Map<String,
> SoftReference<XmlSchema>>>)field.get(null); + } catch (Exception
e)
> {
> + throw new RuntimeException(e);
> + }
> + return ht;
> + }
> +
> + /**
> + * Return the Hashtable for the current thread or null if there is
not
> one. + * @return
> + */
> + static Map<String, SoftReference<XmlSchema>>
> getThreadResolvedSchemaHashtable() { + Map<String,
> SoftReference<XmlSchema>> threadHashtable = null; + Map<String,
> Map<String, SoftReference<XmlSchema>>> ht =
getResolvedSchemasHashtable();
> + if (ht != null) {
> + String threadID =
> String.valueOf(Thread.currentThread().getId()); +
> threadHashtable = (Map<String, SoftReference<XmlSchema>>)
ht.get(threadID);
> + }
> + return threadHashtable;
> + }
> +
> + /**
> + * Set the resolvedSchemas collection to null. This should be done
in
> a finally block + * of any tests that cause an
SchemaBuilder.initCache
> to be done to cleanup for the next + * test.
> + */
> + static void resetResolvedSchemasHashtable() {
> + try {
> + Field field =
> SchemaBuilder.class.getDeclaredField("resolvedSchemas"); +
> field.setAccessible(true);
> + Map<String, Map<String, SoftReference<XmlSchema>>> ht =
> (Map<String, Map<String, SoftReference<XmlSchema>>>) field.get(null); +
> if (ht != null) {
> + ht.clear();
> + field.set(null, null);
> + }
> + }catch (Exception e) {
> + throw new RuntimeException(e);
> + }
> + }
> +
> + // Amount of time the testcase should wait on the test threads
before
> timing out + private static int THREAD_TIMEOUT = 90000;
> +
> + /**
> + * Configure and start the test threads for the multi-threaded
> testing. The threads will + * perform various tests between
themselves
> such as clearing cache in one thread and making + * sure the cache
used
> by a different thread is not affected. A monitor is used to control +
> * the synchonization between the threads and for communicating faliures
> back to the test + * method.
> + *
> + * See thed Runnable classes for details on the tests performed.
> + *
> + * @param testMonitor Used to synchronize the tests between the
> threads + */
> + private void startupTestThreads(MultithreadUpdateLockMonitor
> testMonitor) { + TestingRunnable1 testRunnable1 = new
> TestingRunnable1();
> + testRunnable1.testMonitor = testMonitor;
> +
> + TestingRunnable2 testRunnable2 = new TestingRunnable2();
> + testRunnable2.testMonitor = testMonitor;
> +
> + TestingRunnable3 testRunnable3 = new TestingRunnable3();
> + testRunnable3.testMonitor = testMonitor;
> +
> + Thread thread1 = new Thread(testRunnable1);
> + Thread thread2 = new Thread(testRunnable2);
> + Thread thread3 = new Thread(testRunnable3);
> +
> + thread1.start();
> + thread2.start();
> + thread3.start();
> +
> + // Join the threads to wait for their completion, specifying a
> timeout to prevent + // a testcase hang if something goes wrong
with
> the threads. + try {
> + thread1.join(THREAD_TIMEOUT);
> + thread2.join(THREAD_TIMEOUT);
> + thread3.join(THREAD_TIMEOUT);
> + } catch (InterruptedException e) {
> + e.printStackTrace();
> + fail("Unable to join to testing threads");
> + }
> + }
> +}
> +
> +/**
> + * Monitor used to control synchronization between the testing threads
and
> communicate failures + * back to the test method.
> + */
> +class MultithreadUpdateLockMonitor {
> + boolean t1SetupComplete = false;
> + boolean t2SetupComplete = false;
> + Exception t1Exception = null;
> + Exception t2Exception = null;
> + Exception t3Exception = null;
> +}
>
+//========================================================================
>========================= +// Test execution threads
>
+//========================================================================
>========================= +/**
> + * Thread 1 will do the following
> + * - Initialize the cache and verify it was used during a read
> + * - Unblock Thread 2
> + * - Wait until Thread 2 unblocks it
> + * - Verify that the clearCache done by Thread 2 did not affect this
> Thread's cache. + */
> +@Ignore
> +class TestingRunnable1 implements Runnable {
> +
> + MultithreadUpdateLockMonitor testMonitor = null;
> +
> + public void run() {
> + SchemaBuilder.initCache();
> + Document doc = SchemaBuilderCacheTest.setupDocument();
> + XmlSchemaCollection schemaCol =
> SchemaBuilderCacheTest.setupXmlSchemaCollection(); + XmlSchema
> schema = schemaCol.read(doc, null);
> + if (schema == null) {
> + testMonitor.t1Exception = new Exception("Schema was null");
> + }
> +
> + // If the cache is in use, it should not be null and there
should
> be an entry for this + // Thread
> + if (SchemaBuilderCacheTest.getResolvedSchemasHashtable() ==
null)
> { + testMonitor.t1Exception = new Exception("resolvedSchemas
was
> null"); + }
> + Map<String, SoftReference<XmlSchema>> threadHT =
> SchemaBuilderCacheTest.getThreadResolvedSchemaHashtable(); + if
> (threadHT == null ) {
> + testMonitor.t1Exception = new Exception("Thread
> resolvedSchemas was null"); + }
> +
> + if (threadHT.isEmpty()) {
> + testMonitor.t1Exception = new Exception("Thread
> resolvedSchemas was empty"); + }
> +
> + synchronized(testMonitor) {
> + testMonitor.t1SetupComplete = true;
> + testMonitor.notifyAll();
> + while (!testMonitor.t2SetupComplete) {
> + try {
> + testMonitor.wait();
> + } catch (InterruptedException e) {
> + e.printStackTrace();
> + testMonitor.t1Exception = new RuntimeException(e);
> + throw (RuntimeException) testMonitor.t1Exception;
> + }
> + }
> + }
> +
> + // After the other thread does a reset, the cache for this
thread
> should NOT be null + if
> (SchemaBuilderCacheTest.getResolvedSchemasHashtable() == null) { +
> testMonitor.t1Exception = new Exception("resolvedSchemas was null
after
> reset"); + }
> + threadHT =
> SchemaBuilderCacheTest.getThreadResolvedSchemaHashtable(); + if
> (threadHT == null ) {
> + testMonitor.t1Exception = new Exception("Thread
> resolvedSchemas was null after clear"); + }
> +
> + if (threadHT.isEmpty()) {
> + testMonitor.t1Exception = new Exception("Thread
> resolvedSchemas was empty after clear"); + }
> +
> + // Issue our a clear on this TID, and now there should be no
> entires for it + SchemaBuilder.clearCache();
> + if (SchemaBuilderCacheTest.getResolvedSchemasHashtable() ==
null)
> { + testMonitor.t1Exception = new Exception("resolvedSchemas
was
> null after clear on TID"); + }
> +
> + threadHT =
> SchemaBuilderCacheTest.getThreadResolvedSchemaHashtable(); + if
> (threadHT != null ) {
> + testMonitor.t1Exception = new Exception("Thread
> resolvedSchemas was not null after clear"); + }
> + }
> +}
> +
> +/**
> + * Thread 2 will:
> + * - Block until released by Thread 1
> + * - Initialize the cache then make sure it was used for a resolve on
this
> thread + * - clear the cache and make sure the entries for this Thread a
> removed + * - Unblock Thread 1 to make sure the clear did not affect it
> + */
> +@Ignore
> +class TestingRunnable2 implements Runnable {
> +
> + MultithreadUpdateLockMonitor testMonitor = null;
> +
> + public void run() {
> + synchronized (testMonitor) {
> + while (!testMonitor.t1SetupComplete) {
> + try {
> + testMonitor.wait();
> + } catch (InterruptedException e) {
> + e.printStackTrace();
> + testMonitor.t2Exception = new RuntimeException(e);
> + throw (RuntimeException) testMonitor.t2Exception;
> + }
> + }
> + }
> + SchemaBuilder.initCache();
> + Document doc = SchemaBuilderCacheTest.setupDocument();
> + XmlSchemaCollection schemaCol =
> SchemaBuilderCacheTest.setupXmlSchemaCollection(); + XmlSchema
> schema = schemaCol.read(doc, null);
> + if (schema == null) {
> + testMonitor.t2Exception = new Exception("Schema was null");
> + }
> +
> + // If the cache is in use, it should not be null.
> + if (SchemaBuilderCacheTest.getResolvedSchemasHashtable() ==
null)
> { + testMonitor.t2Exception = new Exception("resolvedSchemas
was
> null"); + }
> + Map<String, SoftReference<XmlSchema>> threadHT =
> SchemaBuilderCacheTest.getThreadResolvedSchemaHashtable(); + if
> (threadHT == null ) {
> + testMonitor.t2Exception = new Exception("Thread
> resolvedSchemas was null"); + }
> + if (threadHT.isEmpty()) {
> + testMonitor.t2Exception = new Exception("Thread
> resolvedSchemas was empty"); + }
> +
> + // Issue our a clear on this TID, and now there should be no
> entires for it + SchemaBuilder.clearCache();
> + if (SchemaBuilderCacheTest.getResolvedSchemasHashtable() ==
null)
> { + testMonitor.t2Exception = new Exception("resolvedSchemas
was
> null after clear on TID"); + }
> +
> + threadHT =
> SchemaBuilderCacheTest.getThreadResolvedSchemaHashtable(); + if
> (threadHT != null ) {
> + testMonitor.t2Exception = new Exception("Thread
> resolvedSchemas was not null after clear"); + }
> +
> + synchronized (testMonitor) {
> + testMonitor.t2SetupComplete = true;
> + testMonitor.notifyAll();
> + }
> + }
> +}
> +
> +/**
> + * Test that the init done by Thread 1 does NOT cause the cache to be
used
> by this thread + * which did not do an init.
> + */
> +@Ignore
> +class TestingRunnable3 implements Runnable {
> + MultithreadUpdateLockMonitor testMonitor = null;
> +
> + public void run() {
> + synchronized (testMonitor) {
> + while (!testMonitor.t1SetupComplete) {
> + try {
> + testMonitor.wait();
> + } catch (InterruptedException e) {
> + e.printStackTrace();
> + testMonitor.t3Exception = new RuntimeException(e);
> + throw (RuntimeException) testMonitor.t2Exception;
> + }
> + }
> + }
> + Document doc = SchemaBuilderCacheTest.setupDocument();
> + XmlSchemaCollection schemaCol =
> SchemaBuilderCacheTest.setupXmlSchemaCollection(); + XmlSchema
> schema = schemaCol.read(doc, null);
> + if (schema == null) {
> + testMonitor.t3Exception = new Exception("Schema was null");
> + }
> + Map<String, SoftReference<XmlSchema>> threadHT =
> SchemaBuilderCacheTest.getThreadResolvedSchemaHashtable(); + if
> (threadHT != null ) {
> + testMonitor.t3Exception = new Exception("Thread
> resolvedSchemas was not null"); + }
> +
> +
> + }
> +
> +}
--
Daniel Kulp
dkulp@apache.org
http://www.dankulp.com/blog