You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sis.apache.org by de...@apache.org on 2012/10/11 16:55:42 UTC
svn commit: r1397093 - in /sis/trunk: ./
sis-metadata/src/main/java/org/apache/sis/metadata/
sis-utility/src/main/java/org/apache/sis/internal/util/
sis-utility/src/main/java/org/apache/sis/util/collection/
sis-utility/src/main/java/org/apache/sis/util...
Author: desruisseaux
Date: Thu Oct 11 14:55:41 2012
New Revision: 1397093
URL: http://svn.apache.org/viewvc?rev=1397093&view=rev
Log:
Merge from the JDK6 branch.
Added:
sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/util/Executors.java
- copied unchanged from r1397091, sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/internal/util/Executors.java
sis/trunk/sis-utility/src/main/java/org/apache/sis/util/collection/Cache.java
- copied unchanged from r1397091, sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/util/collection/Cache.java
sis/trunk/sis-utility/src/main/java/org/apache/sis/util/collection/CacheEntries.java
- copied unchanged from r1397091, sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/util/collection/CacheEntries.java
sis/trunk/sis-utility/src/main/java/org/apache/sis/util/collection/CheckedArrayList.java
- copied unchanged from r1397091, sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/util/collection/CheckedArrayList.java
sis/trunk/sis-utility/src/main/java/org/apache/sis/util/collection/CheckedHashMap.java
- copied unchanged from r1397091, sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/util/collection/CheckedHashMap.java
sis/trunk/sis-utility/src/main/java/org/apache/sis/util/collection/CheckedHashSet.java
- copied unchanged from r1397091, sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/util/collection/CheckedHashSet.java
sis/trunk/sis-utility/src/main/java/org/apache/sis/util/collection/SynchronizedIterator.java
- copied unchanged from r1397091, sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/util/collection/SynchronizedIterator.java
sis/trunk/sis-utility/src/test/java/org/apache/sis/test/TestUtilities.java
- copied unchanged from r1397091, sis/branches/JDK6/sis-utility/src/test/java/org/apache/sis/test/TestUtilities.java
sis/trunk/sis-utility/src/test/java/org/apache/sis/util/collection/CacheTest.java
- copied unchanged from r1397091, sis/branches/JDK6/sis-utility/src/test/java/org/apache/sis/util/collection/CacheTest.java
Modified:
sis/trunk/ (props changed)
sis/trunk/sis-metadata/src/main/java/org/apache/sis/metadata/ModifiableMetadata.java
sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/util/DaemonThread.java
sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/util/ReferenceQueueConsumer.java
sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/util/Threads.java
sis/trunk/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java
sis/trunk/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties
sis/trunk/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties
sis/trunk/sis-utility/src/test/java/org/apache/sis/test/TestCase.java
sis/trunk/sis-utility/src/test/java/org/apache/sis/test/suite/UtilityTestSuite.java
sis/trunk/sis-utility/src/test/java/org/apache/sis/util/collection/WeakHashSetTest.java
sis/trunk/sis-utility/src/test/java/org/apache/sis/util/collection/WeakValueHashMapTest.java
Propchange: sis/trunk/
------------------------------------------------------------------------------
Merged /sis/branches/JDK7:r1395069-1397090
Merged /sis/branches/JDK6:r1395070-1397091
Modified: sis/trunk/sis-metadata/src/main/java/org/apache/sis/metadata/ModifiableMetadata.java
URL: http://svn.apache.org/viewvc/sis/trunk/sis-metadata/src/main/java/org/apache/sis/metadata/ModifiableMetadata.java?rev=1397093&r1=1397092&r2=1397093&view=diff
==============================================================================
--- sis/trunk/sis-metadata/src/main/java/org/apache/sis/metadata/ModifiableMetadata.java (original)
+++ sis/trunk/sis-metadata/src/main/java/org/apache/sis/metadata/ModifiableMetadata.java Thu Oct 11 14:55:41 2012
@@ -16,15 +16,18 @@
*/
package org.apache.sis.metadata;
-import java.util.ArrayList;
import java.util.Set;
import java.util.List;
import java.util.Collection;
import java.util.Collections;
-import java.util.LinkedHashSet;
import java.util.NoSuchElementException;
-
+import net.jcip.annotations.ThreadSafe;
import org.opengis.util.CodeList;
+import org.apache.sis.util.collection.CheckedHashSet;
+import org.apache.sis.util.collection.CheckedArrayList;
+
+import static org.apache.sis.util.collection.Collections.isNullOrEmpty;
+import static org.apache.sis.util.collection.Collections.hashMapCapacity;
/**
@@ -71,6 +74,7 @@ import org.opengis.util.CodeList;
* @version 0.3
* @module
*/
+@ThreadSafe
public abstract class ModifiableMetadata {
/**
* Constructs an initially empty metadata.
@@ -116,8 +120,8 @@ public abstract class ModifiableMetadata
* <ul>
* <li>Invokes {@link #checkWritePermission()} in order to ensure that this metadata is
* modifiable.</li>
- * <li>If {@code source} is {@linkplain XCollections#isNullOrEmpty(Collection) null or
- * empty}, returns {@code null} (meaning that the metadata is not provided).</li>
+ * <li>If {@code source} is null or empty, returns {@code null}
+ * (meaning that the metadata attribute is not provided).</li>
* <li>If {@code target}Â is null, creates a new {@link List}.</li>
* <li>Copies the content of the given {@code source} into the target.</li>
* </ul>
@@ -140,13 +144,13 @@ public abstract class ModifiableMetadata
// See the comments in copyCollection(...) for implementation notes.
if (source != target) {
checkWritePermission();
- if (source == null) {
+ if (isNullOrEmpty(source)) {
target = null;
} else {
if (target != null) {
target.clear();
} else {
- target = new ArrayList<E>(source.size());
+ target = new MutableList<E>(elementType, source.size());
}
target.addAll(source);
}
@@ -161,8 +165,8 @@ public abstract class ModifiableMetadata
* <ul>
* <li>Invokes {@link #checkWritePermission()} in order to ensure that this metadata is
* modifiable.</li>
- * <li>If {@code source} is {@linkplain XCollections#isNullOrEmpty(Collection) null or
- * empty}, returns {@code null} (meaning that the metadata is not provided).</li>
+ * <li>If {@code source} is null or empty, returns {@code null}
+ * (meaning that the metadata attribute is not provided).</li>
* <li>If {@code target}Â is null, creates a new {@link Set}.</li>
* <li>Copies the content of the given {@code source} into the target.</li>
* </ul>
@@ -185,13 +189,13 @@ public abstract class ModifiableMetadata
// See the comments in copyCollection(...) for implementation notes.
if (source != target) {
checkWritePermission();
- if (source == null) {
+ if (isNullOrEmpty(source)) {
target = null;
} else {
if (target != null) {
target.clear();
} else {
- target = new LinkedHashSet<E>(source.size());
+ target = new MutableSet<E>(elementType, source.size());
}
target.addAll(source);
}
@@ -206,8 +210,8 @@ public abstract class ModifiableMetadata
* <ul>
* <li>Invokes {@link #checkWritePermission()} in order to ensure that this metadata is
* modifiable.</li>
- * <li>If {@code source} is {@linkplain XCollections#isNullOrEmpty(Collection) null or
- * empty}, returns {@code null} (meaning that the metadata is not provided).</li>
+ * <li>If {@code source} is null or empty, returns {@code null}
+ * (meaning that the metadata attribute is not provided).</li>
* <li>If {@code target}Â is null, creates a new {@link Set} or a new {@link List}
* depending on the value returned by {@link #collectionType(Class)}.</li>
* <li>Copies the content of the given {@code source} into the target.</li>
@@ -240,7 +244,7 @@ public abstract class ModifiableMetadata
*/
if (source != target) {
checkWritePermission();
- if (source == null) {
+ if (isNullOrEmpty(source)) {
target = null;
} else {
if (target != null) {
@@ -248,9 +252,9 @@ public abstract class ModifiableMetadata
} else {
final int capacity = source.size();
if (useSet(elementType)) {
- target = new LinkedHashSet<E>(capacity);
+ target = new MutableSet<E>(elementType, capacity);
} else {
- target = new ArrayList<E>(capacity);
+ target = new MutableList<E>(elementType, capacity);
}
}
target.addAll(source);
@@ -276,7 +280,7 @@ public abstract class ModifiableMetadata
return c;
}
if (isModifiable()) {
- return new ArrayList<E>();
+ return new MutableList<E>(elementType);
}
return Collections.emptyList();
}
@@ -298,7 +302,7 @@ public abstract class ModifiableMetadata
return c;
}
if (isModifiable()) {
- return new LinkedHashSet<E>();
+ return new MutableSet<E>(elementType);
}
return Collections.emptySet();
}
@@ -332,13 +336,13 @@ public abstract class ModifiableMetadata
final boolean isModifiable = isModifiable();
if (useSet(elementType)) {
if (isModifiable) {
- return new LinkedHashSet<E>();
+ return new MutableSet<E>(elementType);
} else {
return Collections.emptySet();
}
} else {
if (isModifiable) {
- return new ArrayList<E>();
+ return new MutableList<E>(elementType);
} else {
return Collections.emptyList();
}
@@ -346,6 +350,58 @@ public abstract class ModifiableMetadata
}
/**
+ * A checked set synchronized on the enclosing {@link ModifiableMetadata}.
+ * Used for mutable sets only.
+ */
+ private final class MutableSet<E> extends CheckedHashSet<E> {
+ private static final long serialVersionUID = 2337350768744454264L;
+
+ public MutableSet(Class<E> type) {
+ super(type, 4); // Use a small capacity because we typically have few elements.
+ }
+
+ public MutableSet(Class<E> type, int capacity) {
+ super(type, hashMapCapacity(capacity));
+ }
+
+ @Override
+ protected Object getLock() {
+ return ModifiableMetadata.this;
+ }
+
+ @Override
+ protected void checkWritePermission() throws UnsupportedOperationException {
+ ModifiableMetadata.this.checkWritePermission();
+ }
+ }
+
+ /**
+ * A checked list synchronized on the enclosing {@link ModifiableMetadata}.
+ * Used for mutable lists only.
+ */
+ private final class MutableList<E> extends CheckedArrayList<E> {
+ private static final long serialVersionUID = -5016778173550153002L;
+
+ public MutableList(Class<E> type) {
+ super(type, 4); // Use a small capacity because we typically have few elements.
+ }
+
+ public MutableList(Class<E> type, int capacity) {
+ super(type, capacity);
+ }
+
+ @Override
+ protected Object getLock() {
+ return ModifiableMetadata.this;
+ }
+
+ @Override
+ protected void checkWritePermission() throws UnsupportedOperationException {
+ ModifiableMetadata.this.checkWritePermission();
+ }
+ }
+
+ /**
* Returns {@code true} if we should use a {@link Set} instead than a {@link List}
* for elements of the given type.
*/
Modified: sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/util/DaemonThread.java
URL: http://svn.apache.org/viewvc/sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/util/DaemonThread.java?rev=1397093&r1=1397092&r2=1397093&view=diff
==============================================================================
--- sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/util/DaemonThread.java (original)
+++ sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/util/DaemonThread.java Thu Oct 11 14:55:41 2012
@@ -133,7 +133,7 @@ abstract class DaemonThread extends Thre
for (DaemonThread thread=first; thread!=null; thread=thread.previous) {
final long delay = stopWaitingAt - System.nanoTime();
if (delay <= 0) break;
- thread.join(delay);
+ thread.join(delay / 1000000); // Convert nanoseconds to milliseconds.
}
}
Modified: sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/util/ReferenceQueueConsumer.java
URL: http://svn.apache.org/viewvc/sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/util/ReferenceQueueConsumer.java?rev=1397093&r1=1397092&r2=1397093&view=diff
==============================================================================
--- sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/util/ReferenceQueueConsumer.java (original)
+++ sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/util/ReferenceQueueConsumer.java Thu Oct 11 14:55:41 2012
@@ -77,13 +77,15 @@ public final class ReferenceQueueConsume
/**
* Constructs a new thread as a daemon thread. This thread will be sleeping most of the time.
- * It will run only only a few nanoseconds every time a new {@link Reference} is enqueded.
+ * It will run only only a few nanoseconds every time a new {@link Reference} is enqueued.
+ *
+ * {@note We give to this thread a priority higher than the normal one since this thread shall
+ * execute only tasks to be completed very shortly. Quick execution of those tasks is at the
+ * benefit of the rest of the system, since they make more resources available sooner.}
*/
private ReferenceQueueConsumer(final DaemonThread lastCreatedDaemon) {
- super(Threads.RESOURCE_DISPOSERS, "ReferenceQueueConsumer", lastCreatedDaemon);
+ super(Threads.DAEMONS, "ReferenceQueueConsumer", lastCreatedDaemon);
setPriority(Thread.MAX_PRIORITY - 2);
- // The above line sets the priority to the maximal value allowed by the
- // RESOURCE_DISPOSERS group, which is actually lower than MAX_PRIORITY.
}
/**
Modified: sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/util/Threads.java
URL: http://svn.apache.org/viewvc/sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/util/Threads.java?rev=1397093&r1=1397092&r2=1397093&view=diff
==============================================================================
--- sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/util/Threads.java (original)
+++ sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/util/Threads.java Thu Oct 11 14:55:41 2012
@@ -16,6 +16,8 @@
*/
package org.apache.sis.internal.util;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.ExecutorService;
import org.apache.sis.util.Static;
import org.apache.sis.util.logging.Logging;
@@ -25,6 +27,11 @@ import org.apache.sis.util.logging.Loggi
* used in SIS. Their intend is to bring some order in debugger informations, by grouping the
* threads created by SIS together under the same parent tree node.
*
+ * {@section Note on dependencies}
+ * This class shall not depend on {@link Executors} or {@link ReferenceQueueConsumer}, because
+ * initialization of those classes create new threads or threaded executor. But it is okay to
+ * have dependencies the other way around.
+ *
* @author Martin Desruisseaux (Geomatys)
* @since 0.3 (derived from geotk-3.03)
* @version 0.3
@@ -36,7 +43,7 @@ final class Threads extends Static {
* as possible to the root of all thread groups (i.e. not as an application thread subgroup).
* The intend is to separate the library thread groups from the user application thread groups.
*/
- private static final ThreadGroup SIS;
+ static final ThreadGroup SIS;
static {
ThreadGroup parent = Thread.currentThread().getThreadGroup();
try {
@@ -52,14 +59,9 @@ final class Threads extends Static {
}
/**
- * The group of threads for resources disposal. We give them a priority slightly higher
- * than the normal one since this group shall contain only tasks to be completed very
- * quickly, and the benefit of executing those tasks soon is more resources made available.
- */
- static final ThreadGroup RESOURCE_DISPOSERS = new ThreadGroup(SIS, "ResourceDisposers") {
- /* Constructor */ {
- setMaxPriority(Thread.NORM_PRIORITY + 3);
- }
+ * The sub-group for daemon threads, usually for resources disposal.
+ */
+ static final ThreadGroup DAEMONS = new ThreadGroup(SIS, "Daemons") {
@Override public void uncaughtException(final Thread thread, final Throwable exception) {
Logging.severeException(Logging.getLogger("org.apache.sis"), thread.getClass(), "run", exception);
}
@@ -73,6 +75,13 @@ final class Threads extends Static {
static DaemonThread lastCreatedDaemon;
/**
+ * Executor to shutdown. This is a copy of the {@link Executors#DAEMON_TASKS} field,
+ * copied here only when the {@link Executors} class is loaded and initialized. We
+ * do that way for avoiding dependency from {@code Threads} to {@code Executors}.
+ */
+ static ExecutorService executor;
+
+ /**
* Do not allows instantiation of this class.
*/
private Threads() {
@@ -91,6 +100,20 @@ final class Threads extends Static {
* we were waiting for the daemon threads to die.
*/
static synchronized void shutdown(final long stopWaitingAt) throws InterruptedException {
+ if (executor != null) {
+ executor.shutdown();
+ /*
+ * Wait for work completion. In theory this is not necessary since the daemon
+ * tasks are only house-cleaning work. We nevertheless wait for their completion
+ * as a safety. There tasks are supposed to be short.
+ */
+ final long delay = stopWaitingAt - System.nanoTime();
+ if (delay > 0) {
+ executor.awaitTermination(delay, TimeUnit.NANOSECONDS);
+ // Even if the tasks didn't completed, continue without waiting for them.
+ // We can not log at this point, since the logging framework may be shutdown.
+ }
+ }
DaemonThread.killAll(lastCreatedDaemon, stopWaitingAt);
}
}
Modified: sis/trunk/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java
URL: http://svn.apache.org/viewvc/sis/trunk/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java?rev=1397093&r1=1397092&r2=1397093&view=diff
==============================================================================
--- sis/trunk/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java (original)
+++ sis/trunk/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java Thu Oct 11 14:55:41 2012
@@ -51,6 +51,11 @@ public final class Errors extends Indexe
public static final int EmptyArgument_1 = 1;
/**
+ * Argument â{0}â can not be an instance of â{1}â.
+ */
+ public static final int IllegalArgumentClass_2 = 17;
+
+ /**
* Argument â{0}â can not be an instance of â{1}â. Expected an instance of â{2}â or derived
* type.
*/
@@ -112,6 +117,11 @@ public final class Errors extends Indexe
public static final int NullArgument_1 = 0;
/**
+ * Recursive call while creating an object for the â{0}â key.
+ */
+ public static final int RecursiveCreateCallForKey_1 = 18;
+
+ /**
* Argument â{0}â has {1} dimensions, while {2} was expected.
*/
public static final int UnexpectedArgumentDimension_3 = 5;
Modified: sis/trunk/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties
URL: http://svn.apache.org/viewvc/sis/trunk/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties?rev=1397093&r1=1397092&r2=1397093&view=diff
==============================================================================
--- sis/trunk/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties (original)
+++ sis/trunk/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties Thu Oct 11 14:55:41 2012
@@ -16,6 +16,7 @@
#
EmptyArgument_1 = Argument \u2018{0}\u2019 shall not be empty.
IllegalArgument_1 = Illegal value for argument \u2018{0}\u2019.
+IllegalArgumentClass_2 = Argument \u2018{0}\u2019 can not be an instance of \u2018{1}\u2019.
IllegalArgumentClass_3 = Argument \u2018{0}\u2019 can not be an instance of \u2018{1}\u2019. Expected an instance of \u2018{2}\u2019 or derived type.
IllegalArgumentValue_2 = Argument \u2018{0}\u2019 can not take the \u201c{1}\u201d value.
IllegalBitsPattern_1 = Illegal bits pattern: {0}.
@@ -27,6 +28,7 @@ NegativeArgument_2 = Argume
NotANumber_1 = Argument \u2018{0}\u2019 shall not be NaN (Not-a-Number).
NotAPrimitiveWrapper_1 = Class \u2018{0}\u2019 is not a primitive type wrapper.
NullArgument_1 = Argument \u2018{0}\u2019 shall not be null.
+RecursiveCreateCallForKey_1 = Recursive call while creating an object for the \u201c{0}\u201d key.
UnexpectedArgumentDimension_3 = Argument \u2018{0}\u2019 has {1} dimensions, while {2} was expected.
ValueAlreadyDefined_1 = A value is already defined for \u201c{0}\u201d.
ValueNotGreaterThanZero_2 = Value \u2018{0}\u2019={1} is invalid. Expected a number greater than 0.
Modified: sis/trunk/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties
URL: http://svn.apache.org/viewvc/sis/trunk/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties?rev=1397093&r1=1397092&r2=1397093&view=diff
==============================================================================
--- sis/trunk/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties (original)
+++ sis/trunk/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties Thu Oct 11 14:55:41 2012
@@ -16,6 +16,7 @@
#
EmptyArgument_1 = L\u2019argument \u2018{0}\u2019 ne doit pas \u00eatre vide.
IllegalArgument_1 = Valeur ill\u00e9gale pour l\u2019argument \u2018{0}\u2019.
+IllegalArgumentClass_2 = L\u2019argument \u2018{0}\u2019 ne peut pas \u00eatre de type \u2018{1}\u2019.
IllegalArgumentClass_3 = L\u2019argument \u2018{0}\u2019 ne peut pas \u00eatre de type \u2018{1}\u2019. Une instance de \u2018{2}\u2019 ou d\u2019un type d\u00e9riv\u00e9 \u00e9tait attendue.
IllegalArgumentValue_2 = L\u2019argument \u2018{0}\u2019 n\u2019accepte pas la valeur \u201c{1}\u201d.
IllegalBitsPattern_1 = Pattern de bits invalide: {0}.
@@ -27,6 +28,7 @@ NegativeArgument_2 = L\u201
NotANumber_1 = L\u2019argument \u2018{0}\u2019 ne doit pas \u00eatre NaN (Not-a-Number).
NotAPrimitiveWrapper_1 = La classe \u2018{0}\u2019 n\u2019est pas un adaptateur d\u2019un type primitif.
NullArgument_1 = L\u2019argument \u2018{0}\u2019 ne doit pas \u00eatre nul.
+RecursiveCreateCallForKey_1 = Appel r\u00e9cursif lors de la cr\u00e9ation d\u2019un objet pour la cl\u00e9 \u201c{0}\u201d.
UnexpectedArgumentDimension_3 = L\u2019argument \u2018{0}\u2019 a {1} dimensions, alors qu\u2019on en attendait {2}.
ValueAlreadyDefined_1 = Une valeur est d\u00e9j\u00e0 d\u00e9finie pour \u201c{0}\u201d.
ValueNotGreaterThanZero_2 = La valeur \u2018{0}\u2019={1} n\u2019est pas valide. On attendait un nombre positif non-nul.
Modified: sis/trunk/sis-utility/src/test/java/org/apache/sis/test/TestCase.java
URL: http://svn.apache.org/viewvc/sis/trunk/sis-utility/src/test/java/org/apache/sis/test/TestCase.java?rev=1397093&r1=1397092&r2=1397093&view=diff
==============================================================================
--- sis/trunk/sis-utility/src/test/java/org/apache/sis/test/TestCase.java (original)
+++ sis/trunk/sis-utility/src/test/java/org/apache/sis/test/TestCase.java Thu Oct 11 14:55:41 2012
@@ -16,22 +16,15 @@
*/
package org.apache.sis.test;
-import java.util.Date;
-import java.util.Locale;
-import java.util.TimeZone;
import java.util.logging.Logger;
import java.util.logging.Handler;
import java.util.logging.ConsoleHandler;
-import java.text.DateFormat;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
import java.io.Console;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
-import org.apache.sis.util.ArgumentChecks;
import org.apache.sis.util.logging.Logging;
import org.junit.After;
@@ -129,54 +122,12 @@ public abstract strictfp class TestCase
}
/**
- * Date parser and formatter using the {@code "yyyy-MM-dd HH:mm:ss"} pattern
- * and UTC time zone.
- */
- private static final DateFormat dateFormat;
- static {
- dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CANADA);
- dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
- dateFormat.setLenient(false);
- };
-
- /**
* Creates a new test case.
*/
protected TestCase() {
}
/**
- * Parses the date for the given string using the {@code "yyyy-MM-dd HH:mm:ss"} pattern
- * in UTC timezone.
- *
- * @param date The date as a {@link String}.
- * @return The date as a {@link Date}.
- */
- public static Date date(final String date) {
- ArgumentChecks.ensureNonNull("date", date);
- try {
- synchronized (dateFormat) {
- return dateFormat.parse(date);
- }
- } catch (ParseException e) {
- throw new AssertionError(e);
- }
- }
-
- /**
- * Formats the given date using the {@code "yyyy-MM-dd HH:mm:ss"} pattern in UTC timezone.
- *
- * @param date The date to format.
- * @return The date as a {@link String}.
- */
- public static String format(final Date date) {
- ArgumentChecks.ensureNonNull("date", date);
- synchronized (dateFormat) {
- return dateFormat.format(date);
- }
- }
-
- /**
* If verbose output is enabled, flushes the {@link #out} stream after each test.
* The stream will be flushed to the {@linkplain System#console() console} if
* available, or to the {@linkplain System#out standard output stream} otherwise.
Modified: sis/trunk/sis-utility/src/test/java/org/apache/sis/test/suite/UtilityTestSuite.java
URL: http://svn.apache.org/viewvc/sis/trunk/sis-utility/src/test/java/org/apache/sis/test/suite/UtilityTestSuite.java?rev=1397093&r1=1397092&r2=1397093&view=diff
==============================================================================
--- sis/trunk/sis-utility/src/test/java/org/apache/sis/test/suite/UtilityTestSuite.java (original)
+++ sis/trunk/sis-utility/src/test/java/org/apache/sis/test/suite/UtilityTestSuite.java Thu Oct 11 14:55:41 2012
@@ -44,10 +44,11 @@ import org.junit.runners.Suite;
org.apache.sis.util.type.TypesTest.class,
org.apache.sis.util.type.SimpleInternationalStringTest.class,
org.apache.sis.util.type.DefaultInternationalStringTest.class,
+ org.apache.sis.math.MathFunctionsTest.class,
org.apache.sis.internal.util.ReferenceQueueConsumerTest.class,
org.apache.sis.util.collection.WeakHashSetTest.class,
org.apache.sis.util.collection.WeakValueHashMapTest.class,
- org.apache.sis.math.MathFunctionsTest.class
+ org.apache.sis.util.collection.CacheTest.class
})
public final strictfp class UtilityTestSuite extends TestSuite {
}
Modified: sis/trunk/sis-utility/src/test/java/org/apache/sis/util/collection/WeakHashSetTest.java
URL: http://svn.apache.org/viewvc/sis/trunk/sis-utility/src/test/java/org/apache/sis/util/collection/WeakHashSetTest.java?rev=1397093&r1=1397092&r2=1397093&view=diff
==============================================================================
--- sis/trunk/sis-utility/src/test/java/org/apache/sis/util/collection/WeakHashSetTest.java (original)
+++ sis/trunk/sis-utility/src/test/java/org/apache/sis/util/collection/WeakHashSetTest.java Thu Oct 11 14:55:41 2012
@@ -18,12 +18,14 @@ package org.apache.sis.util.collection;
import java.util.HashSet;
import java.util.Random;
+import java.util.concurrent.Callable;
import org.apache.sis.test.TestCase;
import org.apache.sis.test.DependsOnMethod;
import org.apache.sis.test.TestConfiguration;
import org.junit.Test;
import static org.apache.sis.test.Assert.*;
+import static org.apache.sis.test.TestUtilities.waitForGarbageCollection;
/**
@@ -48,7 +50,8 @@ public final strictfp class WeakHashSetT
/**
* Tests the {@link WeakHashSet} using strong references.
- * The tested {@link WeakHashSet} should behave like a standard {@link Set} object.
+ * The tested {@code WeakHashSet} shall behave like a standard {@link HashSet},
+ * except for element order.
*/
@Test
public void testStrongReferences() {
@@ -150,22 +153,21 @@ public final strictfp class WeakHashSetT
* happen too often, we may turn off the "allow garbage collector dependent tests" flag.
*/
if (TestConfiguration.allowGarbageCollectorDependentTests()) {
- int retry = 4;
- do { // Do our best to lets GC finish its work.
- Thread.sleep(50);
- System.gc();
- } while (--retry >= 0 && weakSet.size() != strongSet.size());
+ waitForGarbageCollection(new Callable<Boolean>() {
+ @Override public Boolean call() {
+ return weakSet.size() == strongSet.size();
+ }
+ });
assertSetEquals(strongSet, weakSet);
/*
* Clearing all strong references should make the set empty.
*/
strongSet.clear();
- retry = 4;
- do { // Do our best to lets GC finish its work.
- assertTrue("Expected an empty set.", --retry >= 0);
- Thread.sleep(50);
- System.gc();
- } while (!weakSet.isEmpty());
+ assertTrue("Expected an empty set.", waitForGarbageCollection(new Callable<Boolean>() {
+ @Override public Boolean call() {
+ return weakSet.isEmpty();
+ }
+ }));
}
}
}
Modified: sis/trunk/sis-utility/src/test/java/org/apache/sis/util/collection/WeakValueHashMapTest.java
URL: http://svn.apache.org/viewvc/sis/trunk/sis-utility/src/test/java/org/apache/sis/util/collection/WeakValueHashMapTest.java?rev=1397093&r1=1397092&r2=1397093&view=diff
==============================================================================
--- sis/trunk/sis-utility/src/test/java/org/apache/sis/util/collection/WeakValueHashMapTest.java (original)
+++ sis/trunk/sis-utility/src/test/java/org/apache/sis/util/collection/WeakValueHashMapTest.java Thu Oct 11 14:55:41 2012
@@ -16,14 +16,17 @@
*/
package org.apache.sis.util.collection;
+import java.util.Map;
import java.util.HashMap;
import java.util.Random;
+import java.util.concurrent.Callable;
import org.apache.sis.test.TestCase;
import org.apache.sis.test.TestConfiguration;
import org.apache.sis.test.DependsOnMethod;
import org.junit.Test;
import static org.apache.sis.test.Assert.*;
+import static org.apache.sis.test.TestUtilities.waitForGarbageCollection;
/**
@@ -48,13 +51,24 @@ public final strictfp class WeakValueHas
/**
* Tests the {@link WeakValueHashMap} using strong references.
- * The tested {@link WeakValueHashMap} should behave like a standard {@link Map} object.
+ * The tested {@code WeakValueHashMap} shall behave like a standard {@link HashMap},
+ * except for element order.
*/
@Test
public void testStrongReferences() {
+ testStrongReferences(new WeakValueHashMap<Integer,Integer>(Integer.class));
+ }
+
+ /**
+ * Implementation of the {@link #testStrongReferences()} method,
+ * to be reused by {@link CacheTest}.
+ *
+ * @param weakMap The map implementation to test.
+ */
+ static void testStrongReferences(final Map<Integer,Integer> weakMap) {
final Random random = new Random();
for (int pass=0; pass<NUM_RETRY; pass++) {
- final WeakValueHashMap<Integer,Integer> weakMap = new WeakValueHashMap<Integer,Integer>(Integer.class);
+ weakMap.clear();
final HashMap<Integer,Integer> strongMap = new HashMap<Integer,Integer>();
for (int i=0; i<SAMPLE_SIZE; i++) {
final Integer key = random.nextInt(SAMPLE_SIZE);
@@ -84,9 +98,19 @@ public final strictfp class WeakValueHas
@Test
@DependsOnMethod("testStrongReferences")
public void testWeakReferences() throws InterruptedException {
+ testWeakReferences(new WeakValueHashMap<Integer,Integer>(Integer.class));
+ }
+
+ /**
+ * Implementation of the {@link #testWeakReferences()} method,
+ * to be reused by {@link CacheTest}.
+ *
+ * @param weakMap The map implementation to test.
+ */
+ static void testWeakReferences(final Map<Integer,Integer> weakMap) throws InterruptedException {
final Random random = new Random();
for (int pass=0; pass<NUM_RETRY; pass++) {
- final WeakValueHashMap<Integer,Integer> weakMap = new WeakValueHashMap<Integer,Integer>(Integer.class);
+ weakMap.clear();
final HashMap<Integer,Integer> strongMap = new HashMap<Integer,Integer>();
for (int i=0; i<SAMPLE_SIZE; i++) {
// We really want new instances here.
@@ -133,22 +157,21 @@ public final strictfp class WeakValueHas
* happen too often, we may turn off the "allow garbage collector dependent tests" flag.
*/
if (TestConfiguration.allowGarbageCollectorDependentTests()) {
- int retry = 4;
- do { // Do our best to lets GC finish its work.
- Thread.sleep(50);
- System.gc();
- } while (--retry >= 0 && weakMap.size() != strongMap.size());
+ waitForGarbageCollection(new Callable<Boolean>() {
+ @Override public Boolean call() {
+ return weakMap.size() == strongMap.size();
+ }
+ });
assertMapEquals(strongMap, weakMap);
/*
* Clearing all strong references should make the map empty.
*/
strongMap.clear();
- retry = 4;
- do { // Do our best to lets GC finish its work.
- assertTrue("Expected an empty map.", --retry >= 0);
- Thread.sleep(50);
- System.gc();
- } while (!weakMap.isEmpty());
+ assertTrue("Expected an empty map.", waitForGarbageCollection(new Callable<Boolean>() {
+ @Override public Boolean call() {
+ return weakMap.isEmpty();
+ }
+ }));
}
}
}