You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tapestry.apache.org by hl...@apache.org on 2007/03/05 18:36:19 UTC
svn commit: r514746 - in /tapestry/tapestry5:
tapestry-core/trunk/src/main/java/org/apache/tapestry/
tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/
tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/
tapestry-io...
Author: hlship
Date: Mon Mar 5 09:36:17 2007
New Revision: 514746
URL: http://svn.apache.org/viewvc?view=rev&rev=514746
Log:
TAPESTRY-1291: Tighten up some synchronized collection access and add additional tests and checks for threading errors.
Added:
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/LaunchCrusherTest.java
Modified:
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/TapestryFilter.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentClassResolverImpl.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InternalModule.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/LinkFactoryImpl.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/IntegrationTests.java
tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/RegistryBuilder.java
tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/IOCMessages.java
tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/ModuleImpl.java
tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/OrIdMatcher.java
tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/RegistryImpl.java
tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/ClassFactoryClassPool.java
tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/CtClassSource.java
tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/test/TestBase.java
tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/util/CaseInsensitiveMap.java
tapestry/tapestry5/tapestry-ioc/trunk/src/main/resources/org/apache/tapestry/ioc/internal/IOCStrings.properties
tapestry/tapestry5/tapestry-ioc/trunk/src/test/java/org/apache/tapestry/ioc/util/CaseInsensitiveMapTest.java
tapestry/tapestry5/tapestry-test/trunk/src/main/java/org/apache/tapestry/test/AbstractIntegrationTestSuite.java
tapestry/tapestry5/tapestry-test/trunk/src/main/java/org/apache/tapestry/test/ErrorReportingCommandProcessor.java
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/TapestryFilter.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/TapestryFilter.java?view=diff&rev=514746&r1=514745&r2=514746
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/TapestryFilter.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/TapestryFilter.java Mon Mar 5 09:36:17 2007
@@ -58,7 +58,9 @@
* defined by the <code>tapestry.app-package</code> context init parameter and the application
* name is the capitalization of the filter name (as specified in web.xml).
*/
- public final void init(FilterConfig filterConfig) throws ServletException
+ // Why synchronized? To tell the JVM to flush out any changes (such as the creation of the Registry) that
+ // occur within this method. It's just that runtime behavior has gotten strange.
+ public synchronized final void init(FilterConfig filterConfig) throws ServletException
{
_config = filterConfig;
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentClassResolverImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentClassResolverImpl.java?view=diff&rev=514746&r1=514745&r2=514746
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentClassResolverImpl.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentClassResolverImpl.java Mon Mar 5 09:36:17 2007
@@ -222,7 +222,7 @@
* mapping from logical name to class name
* @return the located class name or null
*/
- private String locate(String logicalName, Map<String, String> logicalNameToClassName)
+ private synchronized String locate(String logicalName, Map<String, String> logicalNameToClassName)
{
rebuild();
@@ -237,7 +237,7 @@
return result;
}
- public String resolvePageClassNameToPageName(String pageClassName)
+ public synchronized String resolvePageClassNameToPageName(String pageClassName)
{
rebuild();
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InternalModule.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InternalModule.java?view=diff&rev=514746&r1=514745&r2=514746
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InternalModule.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InternalModule.java Mon Mar 5 09:36:17 2007
@@ -314,13 +314,13 @@
@Contribute("tapestry.ioc.FactoryDefaults")
public static void contributeFactoryDefaults(MappedConfiguration<String, String> configuration)
{
- // Remember this is request-to-request time, presumably it'll take the developer more than
+ // Remember this is request-to-request time, presumably it'll take the developer more than
// one second to make a change, save it, and switch back to the browser.
-
+
configuration.add("tapestry.file-check-interval", "1000"); // 1 second
configuration.add("tapestry.supported-locales", "en");
configuration.add("tapestry.default-cookie-max-age", "604800"); // One week
-
+
configuration.add("tapestry.start-page-name", "start");
// This is designed to make it easy to keep syncrhonized with script.aculo.ous. As we
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/LinkFactoryImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/LinkFactoryImpl.java?view=diff&rev=514746&r1=514745&r2=514746
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/LinkFactoryImpl.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/LinkFactoryImpl.java Mon Mar 5 09:36:17 2007
@@ -24,11 +24,11 @@
import java.util.List;
import java.util.Map;
-import org.apache.commons.codec.net.URLCodec;
import org.apache.tapestry.ComponentEventHandler;
import org.apache.tapestry.Link;
import org.apache.tapestry.TapestryConstants;
import org.apache.tapestry.internal.InternalConstants;
+import org.apache.tapestry.internal.TapestryInternalUtils;
import org.apache.tapestry.internal.structure.ComponentPageElement;
import org.apache.tapestry.internal.structure.Page;
import org.apache.tapestry.ioc.services.TypeCoercer;
@@ -54,9 +54,6 @@
private final StrategyRegistry<PassivateContextHandler> _registry;
- // URLCodec is thread-safe and sharable.
- private final URLCodec _urlCodec = new URLCodec();
-
private interface PassivateContextHandler<T>
{
void handle(T result, List context);
@@ -156,19 +153,12 @@
StringBuilder builder = new StringBuilder();
- try
+ for (int i = 0; i < activationContext.length; i++)
{
- for (int i = 0; i < activationContext.length; i++)
- {
- if (i > 0)
- builder.append("/");
+ if (i > 0)
+ builder.append("/");
- builder.append(_urlCodec.encode(activationContext[i]));
- }
- }
- catch (Exception ex)
- {
- throw new RuntimeException(ex);
+ builder.append(TapestryInternalUtils.urlEncode(activationContext[i]));
}
link.addParameter(InternalConstants.PAGE_CONTEXT_NAME, builder.toString());
Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/IntegrationTests.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/IntegrationTests.java?view=diff&rev=514746&r1=514745&r2=514746
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/IntegrationTests.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/IntegrationTests.java Mon Mar 5 09:36:17 2007
@@ -31,7 +31,7 @@
* my system, Skype is listening on localhost:80.
*/
@Test(timeOut = 50000, sequential = true, groups =
-{ "integration" })
+{ "integration" }, enabled=true)
public class IntegrationTests extends AbstractIntegrationTestSuite
{
@Test
Added: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/LaunchCrusherTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/LaunchCrusherTest.java?view=auto&rev=514746
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/LaunchCrusherTest.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/LaunchCrusherTest.java Mon Mar 5 09:36:17 2007
@@ -0,0 +1,171 @@
+package org.apache.tapestry.integration;
+
+import static java.lang.String.format;
+import static org.apache.tapestry.ioc.internal.util.CollectionFactory.newList;
+
+import java.io.BufferedInputStream;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.util.List;
+import java.util.concurrent.CyclicBarrier;
+
+import org.apache.tapestry.ioc.internal.util.InternalUtils;
+import org.apache.tapestry.test.JettyRunner;
+import org.testng.Assert;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+/**
+ * Tapestry seems least stable at initial startup (all those proxies and generated code). So we're
+ * giving it a crushing just as it starts up.
+ */
+public class LaunchCrusherTest extends Assert
+{
+ // Jetty's default thread pool max size is 256. If you push this number too high, you get connection reset by peer
+ // errors (I think Jetty reject requests when there's no available thread, after a short timeout).
+ private static final int THREAD_COUNT = 50;
+
+ /** The port on which the internal copy of Jetty is executed. */
+ public static final int JETTY_PORT = 9999;
+
+ private JettyRunner _jetty;
+
+ private final CyclicBarrier _barrier = new CyclicBarrier(THREAD_COUNT + 1);
+
+ class Worker implements Runnable
+ {
+ private String _name;
+
+ private String _content;
+
+ public synchronized String getContent()
+ {
+ return _content;
+ }
+
+ public void run()
+ {
+ _name = Thread.currentThread().getName();
+
+ System.out.printf("[%s] waiting ...\n", _name);
+
+ try
+ {
+ _barrier.await();
+
+ URL url = new URL(format("http://localhost:%d/", JETTY_PORT));
+
+ readContent(url);
+
+ _barrier.await();
+ }
+ catch (Exception ex)
+ {
+ throw new RuntimeException(ex);
+ }
+ }
+
+ private void readContent(URL url)
+ {
+ System.out.printf("[%s] reading ...\n", _name);
+
+ try
+ {
+ InputStream is = url.openStream();
+ InputStreamReader reader = new InputStreamReader(new BufferedInputStream(is));
+
+ StringBuilder builder = new StringBuilder();
+
+ char[] buffer = new char[10000];
+
+ while (true)
+ {
+ int length = reader.read(buffer);
+
+ if (length < 0)
+ break;
+
+ builder.append(buffer, 0, length);
+ }
+
+ reader.close();
+
+ synchronized (this)
+ {
+ _content = builder.toString();
+ }
+
+ System.out.printf("[%s] done.\n", _name);
+ }
+ catch (Exception ex)
+ {
+ System.out.printf("[%s] fail: %s.\n", _name, ex.toString());
+
+ synchronized (this)
+ {
+ _content = "[" + ex.toString() + "]";
+ }
+ }
+ }
+ }
+
+ @BeforeClass
+ public void setup()
+ {
+ _jetty = new JettyRunner("/", JETTY_PORT, "src/test/app1");
+ }
+
+ @AfterClass
+ public void cleanup()
+ {
+ _jetty.stop();
+ }
+
+ @Test
+ public void crushing_number_of_threads_at_startup() throws Exception
+ {
+ Worker[] workers = new Worker[THREAD_COUNT];
+
+ for (int i = 0; i < THREAD_COUNT; i++)
+ {
+ workers[i] = new Worker();
+
+ new Thread(workers[i]).start();
+ }
+
+ _barrier.await();
+
+ System.out.printf("%d threads started\n", THREAD_COUNT);
+
+ _barrier.await();
+
+ String expected = workers[0].getContent();
+ String failureContent = null;
+ List<Integer> failures = newList();
+
+ System.out.printf("*****\n%s\n*****\n", expected);
+
+ for (int i = 1; i < THREAD_COUNT; i++)
+ {
+ String actual = workers[i].getContent();
+
+ if (!actual.equals(expected))
+ {
+ failures.add(i);
+
+ if (failureContent == null)
+ failureContent = actual;
+
+ }
+ }
+
+ if (failureContent != null)
+ {
+ System.err.println("Failures in thread(s): " + InternalUtils.join(failures));
+
+ assertEquals(failureContent, expected);
+ }
+ }
+}
Modified: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/RegistryBuilder.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/RegistryBuilder.java?view=diff&rev=514746&r1=514745&r2=514746
==============================================================================
--- tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/RegistryBuilder.java (original)
+++ tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/RegistryBuilder.java Mon Mar 5 09:36:17 2007
@@ -46,7 +46,7 @@
/**
* Service implementation overrides, keyed on service id. Service implementations are most
* useful when perfroming integration tests on services. As one service can bring in another, we
- * have to stop at a certain "bounary" services by provide stub/ mock objects as their
+ * have to stop at a certain "boundary" services by provide stub/ mock objects as their
* implementations.
*/
private final Map<String, Object> _serviceOverrides = newCaseInsensitiveMap();
Modified: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/IOCMessages.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/IOCMessages.java?view=diff&rev=514746&r1=514745&r2=514746
==============================================================================
--- tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/IOCMessages.java (original)
+++ tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/IOCMessages.java Mon Mar 5 09:36:17 2007
@@ -1,4 +1,4 @@
-// Copyright 2006 The Apache Software Foundation
+// Copyright 2006, 2007 The Apache Software Foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -12,8 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package org.apache.tapestry.ioc.internal;
-
+package org.apache.tapestry.ioc.internal;
+
import static org.apache.tapestry.ioc.internal.util.InternalUtils.asString;
import static org.apache.tapestry.ioc.services.ClassFabUtils.getJavaClassName;
@@ -27,265 +27,265 @@
import org.apache.tapestry.ioc.Messages;
import org.apache.tapestry.ioc.def.ContributionDef;
import org.apache.tapestry.ioc.def.ServiceDef;
+import org.apache.tapestry.ioc.internal.util.InternalUtils;
import org.apache.tapestry.ioc.internal.util.MessagesImpl;
-
-public final class IOCMessages
-{
- private static final Messages MESSAGES = MessagesImpl.forClass(IOCMessages.class);
-
- private IOCMessages()
- {
- }
-
- static String buildMethodConflict(Method conflict, String existing)
- {
- return MESSAGES.format("build-method-conflict", asString(conflict), existing);
- }
-
- static String buildMethodWrongReturnType(Method method)
- {
- return MESSAGES.format("build-method-wrong-return-type", asString(method), method
- .getReturnType().getCanonicalName());
- }
-
- static String decoratorMethodWrongReturnType(Method method)
- {
- return MESSAGES.format("decorator-method-wrong-return-type", asString(method), method
- .getReturnType().getCanonicalName());
- }
-
- static String noSuchModule(String moduleId)
- {
- return MESSAGES.format("no-such-module", moduleId);
- }
-
- static String missingService(String serviceId)
- {
- return MESSAGES.format("missing-service", serviceId);
- }
-
- public static String builderLocked()
- {
- return MESSAGES.get("builder-locked");
- }
-
- public static String moduleIdConflict(String id)
- {
- return MESSAGES.format("module-id-conflict", id);
- }
-
- static String serviceWrongInterface(String serviceId, Class actualInterface,
- Class requestedInterface)
- {
- return MESSAGES.format(
- "service-wrong-interface",
- serviceId,
- actualInterface.getName(),
- requestedInterface.getName());
- }
-
- static String instantiateBuilderError(Class builderClass, String moduleId, Throwable cause)
- {
- return MESSAGES
- .format("instantiate-builder-error", builderClass.getName(), moduleId, cause);
- }
-
- static String builderMethodError(Method method, String serviceId, Throwable cause)
- {
- return MESSAGES.format("builder-method-error", asString(method), serviceId, cause);
- }
-
- static String decoratorMethodError(Method method, String serviceId, Throwable cause)
- {
- return MESSAGES.format("decorator-method-error", asString(method), serviceId, cause);
- }
-
- static String builderMethodReturnedNull(Method method, String serviceId)
- {
- return MESSAGES.format("builder-method-returned-null", asString(method), serviceId);
- }
-
- static String serviceIsPrivate(String serviceId)
- {
- return MESSAGES.format("service-is-private", serviceId);
- }
-
- static String noServiceMatchesType(Class serviceInterface)
- {
- return MESSAGES.format("no-service-matches-type", serviceInterface.getName());
- }
-
- static String manyServiceMatches(Class serviceInterface, List<String> ids)
- {
- StringBuilder buffer = new StringBuilder();
-
- for (int i = 0; i < ids.size(); i++)
- {
- if (i > 0)
- buffer.append(", ");
-
- buffer.append(ids.get(i));
- }
-
- return MESSAGES.format(
- "many-service-matches",
- serviceInterface.getName(),
- ids.size(),
- buffer.toString());
- }
-
- static String unknownLifecycle(String name)
- {
- return MESSAGES.format("unknown-lifecycle", name);
- }
-
- static String decoratorMethodNeedsDelegateParameter(Method method)
- {
- return MESSAGES.format("decorator-method-needs-delegate-parameter", asString(method));
- }
-
- static String decoratorReturnedWrongType(Method method, String serviceId, Object returned,
- Class serviceInterface)
- {
- return MESSAGES.format(
- "decorator-returned-wrong-type",
- asString(method),
- serviceId,
- returned,
- serviceInterface.getName());
- }
-
- static String creatingService(String serviceId)
- {
- return MESSAGES.format("creating-service", serviceId);
- }
-
- static String invokingMethod(Method method)
- {
- return MESSAGES.format("invoking-method", asString(method));
- }
-
- static String invokingMethod(ContributionDef def)
- {
- // The toString() of a contribution def is the name of the method.
- return MESSAGES.format("invoking-method", def);
- }
-
- static String recursiveServiceBuild(ServiceDef def)
- {
- return MESSAGES.format("recursive-service-build", def.getServiceId(), def.toString());
- }
-
- static String contributionWrongReturnType(Method method)
- {
- return MESSAGES.format(
- "contribution-wrong-return-type",
- asString(method),
- getJavaClassName(method.getReturnType()));
- }
-
- static String tooManyContributionParameters(Method method)
- {
- return MESSAGES.format("too-many-contribution-parameters", asString(method));
- }
-
- static String noContributionParameter(Method method)
- {
- return MESSAGES.format("no-contribution-parameter", asString(method));
- }
-
- static String contributionMethodError(Method method, Throwable cause)
- {
- return MESSAGES.format("contribution-method-error", asString(method), cause);
- }
-
- static String contributionWasNull(String serviceId, ContributionDef def)
- {
- return MESSAGES.format("contribution-was-null", serviceId, def);
- }
-
- static String contributionKeyWasNull(String serviceId, ContributionDef def)
- {
- return MESSAGES.format("contribution-key-was-null", serviceId, def);
- }
-
- static String contributionWrongValueType(String serviceId, ContributionDef def,
- Class actualClass, Class expectedClass)
- {
- return MESSAGES.format("contribution-wrong-value-type", serviceId, def, actualClass
- .getName(), expectedClass.getName());
- }
-
- static String contributionWrongKeyType(String serviceId, ContributionDef def,
- Class actualClass, Class expectedClass)
- {
- return MESSAGES.format(
- "contribution-wrong-key-type",
- serviceId,
- def,
- actualClass.getName(),
- expectedClass.getName());
- }
-
- static String tooManyConfigurationParameters(Method method)
- {
- return MESSAGES.format("too-many-configuration-parameters", asString(method));
- }
-
- static String genericTypeNotSupported(Type type)
- {
- return MESSAGES.format("generic-type-not-supported", type);
- }
-
- static String contributionDuplicateKey(String serviceId, ContributionDef contributionDef,
- ContributionDef existingDef)
- {
- return MESSAGES.format(
- "contribution-duplicate-key",
- serviceId,
- contributionDef,
- existingDef);
- }
-
- static String errorBuildingService(String serviceId, ServiceDef serviceDef, Throwable cause)
- {
- return MESSAGES.format("error-building-service", serviceId, serviceDef, cause);
- }
-
- static String noPublicConstructors(String moduleId, Class moduleBuilderClass)
- {
- return MESSAGES.format("no-public-constructors", moduleId, moduleBuilderClass.getName());
- }
-
- static String tooManyPublicConstructors(String moduleId, Class moduleBuilderClass,
- Constructor constructor)
- {
- return MESSAGES.format("too-many-public-constructors", moduleId, moduleBuilderClass
- .getName(), constructor);
- }
-
- static String recursiveModuleConstructor(String moduleId, Class builderClass,
- Constructor constructor)
- {
- return MESSAGES.format(
- "recursive-module-constructor",
- moduleId,
- builderClass.getName(),
- constructor);
- }
-
- static String registryShutdown(String serviceId)
- {
- return MESSAGES.format("registry-shutdown", serviceId);
- }
-
- static String constructedConfiguration(Collection result)
- {
- return MESSAGES.format("constructed-configuration", result);
- }
-
- static String constructedConfiguration(Map result)
- {
- return MESSAGES.format("constructed-configuration", result);
- }
-}
+
+public final class IOCMessages
+{
+ private static final Messages MESSAGES = MessagesImpl.forClass(IOCMessages.class);
+
+ private IOCMessages()
+ {
+ }
+
+ static String buildMethodConflict(Method conflict, String existing)
+ {
+ return MESSAGES.format("build-method-conflict", asString(conflict), existing);
+ }
+
+ static String buildMethodWrongReturnType(Method method)
+ {
+ return MESSAGES.format("build-method-wrong-return-type", asString(method), method
+ .getReturnType().getCanonicalName());
+ }
+
+ static String decoratorMethodWrongReturnType(Method method)
+ {
+ return MESSAGES.format("decorator-method-wrong-return-type", asString(method), method
+ .getReturnType().getCanonicalName());
+ }
+
+ static String noSuchModule(String moduleId, Collection<String> moduleIds)
+ {
+ return MESSAGES.format("no-such-module", moduleId, InternalUtils.joinSorted(moduleIds));
+ }
+
+ static String missingService(String serviceId)
+ {
+ return MESSAGES.format("missing-service", serviceId);
+ }
+
+ public static String builderLocked()
+ {
+ return MESSAGES.get("builder-locked");
+ }
+
+ public static String moduleIdConflict(String id)
+ {
+ return MESSAGES.format("module-id-conflict", id);
+ }
+
+ static String serviceWrongInterface(String serviceId, Class actualInterface,
+ Class requestedInterface)
+ {
+ return MESSAGES.format(
+ "service-wrong-interface",
+ serviceId,
+ actualInterface.getName(),
+ requestedInterface.getName());
+ }
+
+ static String instantiateBuilderError(Class builderClass, String moduleId, Throwable cause)
+ {
+ return MESSAGES
+ .format("instantiate-builder-error", builderClass.getName(), moduleId, cause);
+ }
+
+ static String builderMethodError(Method method, String serviceId, Throwable cause)
+ {
+ return MESSAGES.format("builder-method-error", asString(method), serviceId, cause);
+ }
+
+ static String decoratorMethodError(Method method, String serviceId, Throwable cause)
+ {
+ return MESSAGES.format("decorator-method-error", asString(method), serviceId, cause);
+ }
+
+ static String builderMethodReturnedNull(Method method, String serviceId)
+ {
+ return MESSAGES.format("builder-method-returned-null", asString(method), serviceId);
+ }
+
+ static String serviceIsPrivate(String serviceId)
+ {
+ return MESSAGES.format("service-is-private", serviceId);
+ }
+
+ static String noServiceMatchesType(Class serviceInterface)
+ {
+ return MESSAGES.format("no-service-matches-type", serviceInterface.getName());
+ }
+
+ static String manyServiceMatches(Class serviceInterface, List<String> ids)
+ {
+ StringBuilder buffer = new StringBuilder();
+
+ for (int i = 0; i < ids.size(); i++)
+ {
+ if (i > 0) buffer.append(", ");
+
+ buffer.append(ids.get(i));
+ }
+
+ return MESSAGES.format(
+ "many-service-matches",
+ serviceInterface.getName(),
+ ids.size(),
+ buffer.toString());
+ }
+
+ static String unknownLifecycle(String name)
+ {
+ return MESSAGES.format("unknown-lifecycle", name);
+ }
+
+ static String decoratorMethodNeedsDelegateParameter(Method method)
+ {
+ return MESSAGES.format("decorator-method-needs-delegate-parameter", asString(method));
+ }
+
+ static String decoratorReturnedWrongType(Method method, String serviceId, Object returned,
+ Class serviceInterface)
+ {
+ return MESSAGES.format(
+ "decorator-returned-wrong-type",
+ asString(method),
+ serviceId,
+ returned,
+ serviceInterface.getName());
+ }
+
+ static String creatingService(String serviceId)
+ {
+ return MESSAGES.format("creating-service", serviceId);
+ }
+
+ static String invokingMethod(Method method)
+ {
+ return MESSAGES.format("invoking-method", asString(method));
+ }
+
+ static String invokingMethod(ContributionDef def)
+ {
+ // The toString() of a contribution def is the name of the method.
+ return MESSAGES.format("invoking-method", def);
+ }
+
+ static String recursiveServiceBuild(ServiceDef def)
+ {
+ return MESSAGES.format("recursive-service-build", def.getServiceId(), def.toString());
+ }
+
+ static String contributionWrongReturnType(Method method)
+ {
+ return MESSAGES.format(
+ "contribution-wrong-return-type",
+ asString(method),
+ getJavaClassName(method.getReturnType()));
+ }
+
+ static String tooManyContributionParameters(Method method)
+ {
+ return MESSAGES.format("too-many-contribution-parameters", asString(method));
+ }
+
+ static String noContributionParameter(Method method)
+ {
+ return MESSAGES.format("no-contribution-parameter", asString(method));
+ }
+
+ static String contributionMethodError(Method method, Throwable cause)
+ {
+ return MESSAGES.format("contribution-method-error", asString(method), cause);
+ }
+
+ static String contributionWasNull(String serviceId, ContributionDef def)
+ {
+ return MESSAGES.format("contribution-was-null", serviceId, def);
+ }
+
+ static String contributionKeyWasNull(String serviceId, ContributionDef def)
+ {
+ return MESSAGES.format("contribution-key-was-null", serviceId, def);
+ }
+
+ static String contributionWrongValueType(String serviceId, ContributionDef def,
+ Class actualClass, Class expectedClass)
+ {
+ return MESSAGES.format("contribution-wrong-value-type", serviceId, def, actualClass
+ .getName(), expectedClass.getName());
+ }
+
+ static String contributionWrongKeyType(String serviceId, ContributionDef def,
+ Class actualClass, Class expectedClass)
+ {
+ return MESSAGES.format(
+ "contribution-wrong-key-type",
+ serviceId,
+ def,
+ actualClass.getName(),
+ expectedClass.getName());
+ }
+
+ static String tooManyConfigurationParameters(Method method)
+ {
+ return MESSAGES.format("too-many-configuration-parameters", asString(method));
+ }
+
+ static String genericTypeNotSupported(Type type)
+ {
+ return MESSAGES.format("generic-type-not-supported", type);
+ }
+
+ static String contributionDuplicateKey(String serviceId, ContributionDef contributionDef,
+ ContributionDef existingDef)
+ {
+ return MESSAGES.format(
+ "contribution-duplicate-key",
+ serviceId,
+ contributionDef,
+ existingDef);
+ }
+
+ static String errorBuildingService(String serviceId, ServiceDef serviceDef, Throwable cause)
+ {
+ return MESSAGES.format("error-building-service", serviceId, serviceDef, cause);
+ }
+
+ static String noPublicConstructors(String moduleId, Class moduleBuilderClass)
+ {
+ return MESSAGES.format("no-public-constructors", moduleId, moduleBuilderClass.getName());
+ }
+
+ static String tooManyPublicConstructors(String moduleId, Class moduleBuilderClass,
+ Constructor constructor)
+ {
+ return MESSAGES.format("too-many-public-constructors", moduleId, moduleBuilderClass
+ .getName(), constructor);
+ }
+
+ static String recursiveModuleConstructor(String moduleId, Class builderClass,
+ Constructor constructor)
+ {
+ return MESSAGES.format(
+ "recursive-module-constructor",
+ moduleId,
+ builderClass.getName(),
+ constructor);
+ }
+
+ static String registryShutdown(String serviceId)
+ {
+ return MESSAGES.format("registry-shutdown", serviceId);
+ }
+
+ static String constructedConfiguration(Collection result)
+ {
+ return MESSAGES.format("constructed-configuration", result);
+ }
+
+ static String constructedConfiguration(Map result)
+ {
+ return MESSAGES.format("constructed-configuration", result);
+ }
+}
Modified: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/ModuleImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/ModuleImpl.java?view=diff&rev=514746&r1=514745&r2=514746
==============================================================================
--- tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/ModuleImpl.java (original)
+++ tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/ModuleImpl.java Mon Mar 5 09:36:17 2007
@@ -1,4 +1,4 @@
-// Copyright 2006 The Apache Software Foundation
+// Copyright 2006, 2007 The Apache Software Foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -49,9 +49,6 @@
import org.apache.tapestry.ioc.services.RegistryShutdownListener;
import org.apache.tapestry.ioc.util.BodyBuilder;
-/**
- *
- */
public class ModuleImpl implements Module
{
private final InternalRegistry _registry;
@@ -64,8 +61,15 @@
private final static String INTERNAL_MODULE_ID = "tapestry.ioc";
+ /**
+ * A single mutex, shared by all modules, that serializes creation of services across all
+ * threads. This is a bit draconian, but appears to be necessary. Fortunately, service creation
+ * is a very tiny part of any individual service's lifecycle.
+ */
+ private static final Object MUTEX = new Object();
+
// Set to true when invoking the module constructor. Used to
- // detect endless loops caused by irresponsible dependencies into
+ // detect endless loops caused by irresponsible dependencies in
// the constructor.
private boolean _insideConstructor;
@@ -154,27 +158,31 @@
return result;
}
- // Why synchronized here? Two reasons. First, with some lifecycle models (or perhaps in some
- // scenarios using interceptors), we may try to acquire the write lock a second time and the
- // @Concurrent.Write annotation doesn't currently support that. Second, I'm concerned about
- // multiple threads building services simultaneously, and getting into a thread deadlock. Of
- // course, this isn't a solution for that ... we may need a global mutex to handle that specific
- // case! Alternately, I've thought about creating a "service creation" thread at startup and
- // queuing service creation requests to that thread, and blocking the local thread.
-
- private synchronized Object findOrCreate(ServiceDef def)
+ /**
+ * Locates the service proxy for a particular service (from the service definition).
+ * <p>
+ * Access is synchronized via {@link #MUTEX}.
+ *
+ * @param def
+ * defines the service
+ * @return the service proxy
+ */
+ private Object findOrCreate(ServiceDef def)
{
- String key = def.getServiceId();
+ synchronized (MUTEX)
+ {
+ String key = def.getServiceId();
- Object result = _services.get(key);
+ Object result = _services.get(key);
- if (result == null)
- {
- result = create(def);
- _services.put(key, result);
- }
+ if (result == null)
+ {
+ result = create(def);
+ _services.put(key, result);
+ }
- return result;
+ return result;
+ }
}
public void eagerLoadServices()
@@ -195,8 +203,8 @@
}
/**
- * Creates the service and updates the cache of created services. Method is called from
- * synchronized block.
+ * Creates the service and updates the cache of created services. Access is synchronized via
+ * {@link #MUTEX}.
*/
private Object create(ServiceDef def)
{
@@ -228,11 +236,7 @@
creator = new OneShotServiceCreator(def, creator);
- Object service = createProxy(resources, creator, def.isEagerLoad());
-
- _services.put(serviceId, service);
-
- return service;
+ return createProxy(resources, creator, def.isEagerLoad());
}
catch (Exception ex)
{
@@ -240,13 +244,17 @@
}
}
- public synchronized Object getModuleBuilder()
+ public Object getModuleBuilder()
{
- if (_moduleBuilder == null) _moduleBuilder = instantiateModuleBuilder();
+ synchronized (MUTEX)
+ {
+ if (_moduleBuilder == null) _moduleBuilder = instantiateModuleBuilder();
- return _moduleBuilder;
+ return _moduleBuilder;
+ }
}
+ /** Access synchronized by MUTEX. */
private Object instantiateModuleBuilder()
{
Class builderClass = _moduleDef.getBuilderClass();
Modified: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/OrIdMatcher.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/OrIdMatcher.java?view=diff&rev=514746&r1=514745&r2=514746
==============================================================================
--- tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/OrIdMatcher.java (original)
+++ tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/OrIdMatcher.java Mon Mar 5 09:36:17 2007
@@ -29,7 +29,7 @@
public OrIdMatcher(Collection<IdMatcher> matchers)
{
- _matchers = matchers.toArray(new IdMatcher[0]);
+ _matchers = matchers.toArray(new IdMatcher[matchers.size()]);
}
public boolean matches(String id)
Modified: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/RegistryImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/RegistryImpl.java?view=diff&rev=514746&r1=514745&r2=514746
==============================================================================
--- tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/RegistryImpl.java (original)
+++ tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/RegistryImpl.java Mon Mar 5 09:36:17 2007
@@ -1,4 +1,4 @@
-// Copyright 2006 The Apache Software Foundation
+// Copyright 2006, 2007 The Apache Software Foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -192,7 +192,7 @@
_registryShutdownHub.fireRegistryDidShutdown();
}
- /** Internal access, usualy from another module. */
+ /** Internal access, usually from another module. */
public <T> T getService(String serviceId, Class<T> serviceInterface, Module module)
{
_lock.check();
@@ -268,7 +268,8 @@
Module module = _modules.get(moduleId);
- if (module == null) throw new RuntimeException(IOCMessages.noSuchModule(moduleId));
+ if (module == null)
+ throw new RuntimeException(IOCMessages.noSuchModule(moduleId, _modules.keySet()));
return module;
}
@@ -493,6 +494,11 @@
public List<ServiceDecorator> findDecoratorsForService(ServiceDef serviceDef)
{
_lock.check();
+
+ // This simply should never happen, yet we're seeing it. This falls into the
+ // category of "scary things that happen in multi-threaded applications".
+
+ assert serviceDef != null;
Log log = getLog(serviceDef.getServiceId());
Modified: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/ClassFactoryClassPool.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/ClassFactoryClassPool.java?view=diff&rev=514746&r1=514745&r2=514746
==============================================================================
--- tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/ClassFactoryClassPool.java (original)
+++ tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/ClassFactoryClassPool.java Mon Mar 5 09:36:17 2007
@@ -80,7 +80,7 @@
_loader = loader;
}
- public ClassLoader getLoader()
+ public synchronized ClassLoader getLoader()
{
return _loader;
}
Modified: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/CtClassSource.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/CtClassSource.java?view=diff&rev=514746&r1=514745&r2=514746
==============================================================================
--- tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/CtClassSource.java (original)
+++ tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/CtClassSource.java Mon Mar 5 09:36:17 2007
@@ -40,7 +40,7 @@
/**
* Returns the number of classes (and interfaces) created by this source.
*/
- public int getCreatedClassCount()
+ public synchronized int getCreatedClassCount()
{
return _createdClassCount;
}
Modified: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/test/TestBase.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/test/TestBase.java?view=diff&rev=514746&r1=514745&r2=514746
==============================================================================
--- tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/test/TestBase.java (original)
+++ tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/test/TestBase.java Mon Mar 5 09:36:17 2007
@@ -40,7 +40,7 @@
*/
public class TestBase extends Assert
{
- private class ThreadLocalControl extends ThreadLocal<IMocksControl>
+ private static class ThreadLocalControl extends ThreadLocal<IMocksControl>
{
@Override
protected IMocksControl initialValue()
Modified: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/util/CaseInsensitiveMap.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/util/CaseInsensitiveMap.java?view=diff&rev=514746&r1=514745&r2=514746
==============================================================================
--- tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/util/CaseInsensitiveMap.java (original)
+++ tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/util/CaseInsensitiveMap.java Mon Mar 5 09:36:17 2007
@@ -14,6 +14,7 @@
package org.apache.tapestry.ioc.util;
+import java.io.Serializable;
import java.util.AbstractMap;
import java.util.AbstractSet;
import java.util.ConcurrentModificationException;
@@ -34,14 +35,18 @@
* @param <V>
* the type of value stored
*/
-public class CaseInsensitiveMap<V> extends AbstractMap<String, V> implements Map<String, V>
+public class CaseInsensitiveMap<V> extends AbstractMap<String, V> implements Serializable
{
+ private static final long serialVersionUID = 3362718337611953298L;
+
private static final int NULL_HASH = Integer.MIN_VALUE;
private static final int DEFAULT_SIZE = 20;
- private static class CIMEntry<V> implements Map.Entry<String, V>
+ private static class CIMEntry<V> implements Map.Entry<String, V>, Serializable
{
+ private static final long serialVersionUID = 6713986085221148350L;
+
private String _key;
private final int _hashCode;
Modified: tapestry/tapestry5/tapestry-ioc/trunk/src/main/resources/org/apache/tapestry/ioc/internal/IOCStrings.properties
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/main/resources/org/apache/tapestry/ioc/internal/IOCStrings.properties?view=diff&rev=514746&r1=514745&r2=514746
==============================================================================
--- tapestry/tapestry5/tapestry-ioc/trunk/src/main/resources/org/apache/tapestry/ioc/internal/IOCStrings.properties (original)
+++ tapestry/tapestry5/tapestry-ioc/trunk/src/main/resources/org/apache/tapestry/ioc/internal/IOCStrings.properties Mon Mar 5 09:36:17 2007
@@ -22,7 +22,7 @@
missing-service=Service '%s' does not exist.
builder-locked=The Registry Builder has created the Registry, further operations are not allowed.
module-id-conflict=Module '%s' has already been defined. The duplicate definition will be ignored.
-no-such-module=Module '%s' does not exist. Please ensure that the JAR file for the module is on the classpath.
+no-such-module=Module '%s' does not exist. Please ensure that the JAR file for the module is on the classpath. Available modules: %s.
service-wrong-interface=Service '%s' implements interface %s, which is not compatible with the requested type %s.
instantiate-builder-error=Unable to instantiate class %s as builder for module '%s': %s
builder-method-error=Error invoking service builder method %s (for service '%s'): %s
Modified: tapestry/tapestry5/tapestry-ioc/trunk/src/test/java/org/apache/tapestry/ioc/util/CaseInsensitiveMapTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/test/java/org/apache/tapestry/ioc/util/CaseInsensitiveMapTest.java?view=diff&rev=514746&r1=514745&r2=514746
==============================================================================
--- tapestry/tapestry5/tapestry-ioc/trunk/src/test/java/org/apache/tapestry/ioc/util/CaseInsensitiveMapTest.java (original)
+++ tapestry/tapestry5/tapestry-ioc/trunk/src/test/java/org/apache/tapestry/ioc/util/CaseInsensitiveMapTest.java Mon Mar 5 09:36:17 2007
@@ -16,6 +16,10 @@
import static org.apache.tapestry.ioc.internal.util.CollectionFactory.newCaseInsensitiveMap;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
import java.util.Arrays;
import java.util.Collections;
import java.util.ConcurrentModificationException;
@@ -309,6 +313,30 @@
Collections.sort(keys);
assertEquals(keys, Arrays.asList("barney", "betty", "fred", "wilma"));
+ }
+
+ @Test
+ public void serialize_deserialize() throws Exception
+ {
+ Map<String, String> map = newCaseInsensitiveMap();
+
+ map.put("fred", "flintstone");
+ map.put("barney", "rubble");
+ map.put("wilma", "flinstone");
+ map.put("betty", "rubble");
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ ObjectOutputStream oos = new ObjectOutputStream(baos);
+
+ oos.writeObject(map);
+ oos.close();
+
+ ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
+ ObjectInputStream ois = new ObjectInputStream(bais);
+
+ Map<String, String> copy = (Map<String, String>) ois.readObject();
+
+ assertEquals(copy, map);
}
@SuppressWarnings("unchecked")
Modified: tapestry/tapestry5/tapestry-test/trunk/src/main/java/org/apache/tapestry/test/AbstractIntegrationTestSuite.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-test/trunk/src/main/java/org/apache/tapestry/test/AbstractIntegrationTestSuite.java?view=diff&rev=514746&r1=514745&r2=514746
==============================================================================
--- tapestry/tapestry5/tapestry-test/trunk/src/main/java/org/apache/tapestry/test/AbstractIntegrationTestSuite.java (original)
+++ tapestry/tapestry5/tapestry-test/trunk/src/main/java/org/apache/tapestry/test/AbstractIntegrationTestSuite.java Mon Mar 5 09:36:17 2007
@@ -37,7 +37,8 @@
* jumping all over your web application in an unpredictable order.
* <p>
* This class implements the {@link Selenium} interface, and delegates all those methods to the
- * {@link DefaultSelenium} instance it creates.
+ * {@link DefaultSelenium} instance it creates. It also extends the normal exception reporting for
+ * any failed command or query to produce a more detailed report to the main console.
*
* @see JettyRunner
*/
@@ -413,6 +414,8 @@
public void open(String url)
{
_selenium.open(url);
+
+ waitForPageToLoad(PAGE_LOAD_TIMEOUT);
}
public void refresh()
@@ -483,6 +486,14 @@
public void waitForPageToLoad(String timeout)
{
_selenium.waitForPageToLoad(timeout);
+ }
+
+ /**
+ * Waits the default time for the page to load.
+ */
+ public void waitForPageToLoad()
+ {
+ waitForPageToLoad(PAGE_LOAD_TIMEOUT);
}
public void waitForPopUp(String windowID, String timeout)
Modified: tapestry/tapestry5/tapestry-test/trunk/src/main/java/org/apache/tapestry/test/ErrorReportingCommandProcessor.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-test/trunk/src/main/java/org/apache/tapestry/test/ErrorReportingCommandProcessor.java?view=diff&rev=514746&r1=514745&r2=514746
==============================================================================
--- tapestry/tapestry5/tapestry-test/trunk/src/main/java/org/apache/tapestry/test/ErrorReportingCommandProcessor.java (original)
+++ tapestry/tapestry5/tapestry-test/trunk/src/main/java/org/apache/tapestry/test/ErrorReportingCommandProcessor.java Mon Mar 5 09:36:17 2007
@@ -29,11 +29,14 @@
_delegate = delegate;
}
+ private static final String BORDER = "**********************************************************************";
+
private void reportError(String command, String[] args, RuntimeException ex)
{
StringBuilder builder = new StringBuilder();
- builder.append("Seleninum failure processing comamnd ");
+ builder.append(BORDER);
+ builder.append("\nSeleninum failure processing comamnd ");
builder.append(command);
builder.append("(");
@@ -53,7 +56,8 @@
builder.append(_delegate.getString("getHtmlSource", new String[] {}));
builder.append("\n");
-
+ builder.append(BORDER);
+
System.err.println(builder.toString());
}