summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLeif Åstrand <leif@vaadin.com>2012-08-20 19:19:47 +0300
committerLeif Åstrand <leif@vaadin.com>2012-08-20 19:20:09 +0300
commit72d9cc9ec098952dfdb03708f808da555307e78d (patch)
treed2e97757e8a1ecdcf25cfec3b066c87a2db6c791
parent0dfdb151913a13e929a65c4dd8b5987c9edd06d5 (diff)
downloadvaadin-framework-72d9cc9ec098952dfdb03708f808da555307e78d.tar.gz
vaadin-framework-72d9cc9ec098952dfdb03708f808da555307e78d.zip
Add RootProvider for Root selection without custom Application (#8159)
-rw-r--r--server/src/com/vaadin/Application.java70
-rw-r--r--server/src/com/vaadin/terminal/AbstractRootProvider.java35
-rw-r--r--server/src/com/vaadin/terminal/DefaultRootProvider.java51
-rw-r--r--server/src/com/vaadin/terminal/RootProvider.java29
-rw-r--r--server/src/com/vaadin/terminal/gwt/server/ApplicationServlet.java2
-rw-r--r--tests/server-side/com/vaadin/tests/server/component/root/CustomRootClassLoader.java18
-rw-r--r--tests/testbench/com/vaadin/launcher/ApplicationRunnerServlet.java33
-rw-r--r--tests/testbench/com/vaadin/tests/application/RefreshStatePreserve.java16
-rw-r--r--tests/testbench/com/vaadin/tests/components/root/RootsInMultipleTabs.java15
9 files changed, 191 insertions, 78 deletions
diff --git a/server/src/com/vaadin/Application.java b/server/src/com/vaadin/Application.java
index b120c8455a..d2924eb716 100644
--- a/server/src/com/vaadin/Application.java
+++ b/server/src/com/vaadin/Application.java
@@ -32,6 +32,7 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.LinkedList;
+import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
@@ -56,6 +57,7 @@ import com.vaadin.terminal.ApplicationResource;
import com.vaadin.terminal.CombinedRequest;
import com.vaadin.terminal.DeploymentConfiguration;
import com.vaadin.terminal.RequestHandler;
+import com.vaadin.terminal.RootProvider;
import com.vaadin.terminal.Terminal;
import com.vaadin.terminal.VariableOwner;
import com.vaadin.terminal.WrappedRequest;
@@ -503,6 +505,8 @@ public class Application implements Terminal.ErrorListener, Serializable {
*/
private Set<Integer> initedRoots = new HashSet<Integer>();
+ private List<RootProvider> rootProviders = new LinkedList<RootProvider>();
+
/**
* Gets the user of the application.
*
@@ -1873,55 +1877,21 @@ public class Application implements Terminal.ErrorListener, Serializable {
*/
protected Root getRoot(WrappedRequest request)
throws RootRequiresMoreInformationException {
- String rootClassName = getRootClassName(request);
- try {
- ClassLoader classLoader = request.getDeploymentConfiguration()
- .getClassLoader();
- if (classLoader == null) {
- classLoader = getClass().getClassLoader();
- }
- Class<? extends Root> rootClass = Class.forName(rootClassName,
- true, classLoader).asSubclass(Root.class);
- try {
- Root root = rootClass.newInstance();
- return root;
- } catch (Exception e) {
- throw new RuntimeException("Could not instantiate root class "
- + rootClassName, e);
+
+ // Iterate in reverse order - test check newest provider first
+ for (int i = rootProviders.size() - 1; i >= 0; i--) {
+ RootProvider provider = rootProviders.get(i);
+
+ Class<? extends Root> rootClass = provider.getRootClass(this,
+ request);
+
+ if (rootClass != null) {
+ return provider.instantiateRoot(this, rootClass, request);
}
- } catch (ClassNotFoundException e) {
- throw new RuntimeException("Could not load root class "
- + rootClassName, e);
}
- }
- /**
- * Provides the name of the <code>Root</code> class that should be used for
- * a request. The class must have an accessible no-args constructor.
- * <p>
- * The default implementation uses the {@value #ROOT_PARAMETER} parameter
- * from web.xml.
- * </p>
- * <p>
- * This method is mainly used by the default implementation of
- * {@link #getRoot(WrappedRequest)}. If you override that method with your
- * own functionality, the results of this method might not be used.
- * </p>
- *
- * @param request
- * the request for which a new root is required
- * @return the name of the root class to use
- *
- * @since 7.0
- */
- protected String getRootClassName(WrappedRequest request) {
- Object rootClassNameObj = getProperties().get(ROOT_PARAMETER);
- if (rootClassNameObj instanceof String) {
- return (String) rootClassNameObj;
- } else {
- throw new RuntimeException("No " + ROOT_PARAMETER
- + " defined in web.xml");
- }
+ throw new RuntimeException(
+ "No root providers available or providers are not able to find root instance");
}
/**
@@ -2169,6 +2139,14 @@ public class Application implements Terminal.ErrorListener, Serializable {
return configuration.isProductionMode();
}
+ public void addRootProvider(RootProvider rootProvider) {
+ rootProviders.add(rootProvider);
+ }
+
+ public void removeRootProvider(RootProvider rootProvider) {
+ rootProviders.remove(rootProvider);
+ }
+
/**
* Finds the {@link Root} to which a particular request belongs. If the
* request originates from an existing Root, that root is returned. In other
diff --git a/server/src/com/vaadin/terminal/AbstractRootProvider.java b/server/src/com/vaadin/terminal/AbstractRootProvider.java
new file mode 100644
index 0000000000..0b63003440
--- /dev/null
+++ b/server/src/com/vaadin/terminal/AbstractRootProvider.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2011 Vaadin Ltd.
+ *
+ * Licensed 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 com.vaadin.terminal;
+
+import com.vaadin.Application;
+import com.vaadin.ui.Root;
+
+public abstract class AbstractRootProvider implements RootProvider {
+
+ @Override
+ public Root instantiateRoot(Application application,
+ Class<? extends Root> type, WrappedRequest request) {
+ try {
+ return type.newInstance();
+ } catch (InstantiationException e) {
+ throw new RuntimeException("Could not instantiate root class", e);
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException("Could not access root class", e);
+ }
+ }
+}
diff --git a/server/src/com/vaadin/terminal/DefaultRootProvider.java b/server/src/com/vaadin/terminal/DefaultRootProvider.java
new file mode 100644
index 0000000000..cbf8c98828
--- /dev/null
+++ b/server/src/com/vaadin/terminal/DefaultRootProvider.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2011 Vaadin Ltd.
+ *
+ * Licensed 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 com.vaadin.terminal;
+
+import com.vaadin.Application;
+import com.vaadin.RootRequiresMoreInformationException;
+import com.vaadin.ui.Root;
+
+public class DefaultRootProvider extends AbstractRootProvider {
+
+ @Override
+ public Class<? extends Root> getRootClass(Application application,
+ WrappedRequest request) throws RootRequiresMoreInformationException {
+ Object rootClassNameObj = application
+ .getProperty(Application.ROOT_PARAMETER);
+
+ if (rootClassNameObj instanceof String) {
+ String rootClassName = rootClassNameObj.toString();
+
+ ClassLoader classLoader = request.getDeploymentConfiguration()
+ .getClassLoader();
+ if (classLoader == null) {
+ classLoader = getClass().getClassLoader();
+ }
+ try {
+ Class<? extends Root> rootClass = Class.forName(rootClassName,
+ true, classLoader).asSubclass(Root.class);
+
+ return rootClass;
+ } catch (ClassNotFoundException e) {
+ throw new RuntimeException("Could not find root class", e);
+ }
+ }
+
+ return null;
+ }
+}
diff --git a/server/src/com/vaadin/terminal/RootProvider.java b/server/src/com/vaadin/terminal/RootProvider.java
new file mode 100644
index 0000000000..476cf1bd78
--- /dev/null
+++ b/server/src/com/vaadin/terminal/RootProvider.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2011 Vaadin Ltd.
+ *
+ * Licensed 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 com.vaadin.terminal;
+
+import com.vaadin.Application;
+import com.vaadin.RootRequiresMoreInformationException;
+import com.vaadin.ui.Root;
+
+public interface RootProvider {
+ public Class<? extends Root> getRootClass(Application application,
+ WrappedRequest request) throws RootRequiresMoreInformationException;
+
+ public Root instantiateRoot(Application application,
+ Class<? extends Root> type, WrappedRequest request);
+}
diff --git a/server/src/com/vaadin/terminal/gwt/server/ApplicationServlet.java b/server/src/com/vaadin/terminal/gwt/server/ApplicationServlet.java
index 06bc70872d..52885f3fbb 100644
--- a/server/src/com/vaadin/terminal/gwt/server/ApplicationServlet.java
+++ b/server/src/com/vaadin/terminal/gwt/server/ApplicationServlet.java
@@ -20,6 +20,7 @@ import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import com.vaadin.Application;
+import com.vaadin.terminal.DefaultRootProvider;
import com.vaadin.terminal.gwt.server.ServletPortletHelper.ApplicationClassException;
/**
@@ -69,6 +70,7 @@ public class ApplicationServlet extends AbstractApplicationServlet {
// Creates a new application instance
try {
final Application application = getApplicationClass().newInstance();
+ application.addRootProvider(new DefaultRootProvider());
return application;
} catch (final IllegalAccessException e) {
diff --git a/tests/server-side/com/vaadin/tests/server/component/root/CustomRootClassLoader.java b/tests/server-side/com/vaadin/tests/server/component/root/CustomRootClassLoader.java
index fa730515a2..74770f8652 100644
--- a/tests/server-side/com/vaadin/tests/server/component/root/CustomRootClassLoader.java
+++ b/tests/server-side/com/vaadin/tests/server/component/root/CustomRootClassLoader.java
@@ -6,15 +6,16 @@ import java.util.Properties;
import junit.framework.TestCase;
+import org.easymock.EasyMock;
+
import com.vaadin.Application;
import com.vaadin.Application.ApplicationStartEvent;
import com.vaadin.RootRequiresMoreInformationException;
+import com.vaadin.terminal.DefaultRootProvider;
import com.vaadin.terminal.DeploymentConfiguration;
import com.vaadin.terminal.WrappedRequest;
import com.vaadin.ui.Root;
-import org.easymock.EasyMock;
-
public class CustomRootClassLoader extends TestCase {
/**
@@ -111,10 +112,17 @@ public class CustomRootClassLoader extends TestCase {
private Application createStubApplication() {
return new Application() {
+ {
+ addRootProvider(new DefaultRootProvider());
+ }
+
@Override
- protected String getRootClassName(WrappedRequest request) {
- // Always use the same root class
- return MyRoot.class.getName();
+ public String getProperty(String name) {
+ if (name.equals(ROOT_PARAMETER)) {
+ return MyRoot.class.getName();
+ } else {
+ return super.getProperty(name);
+ }
}
@Override
diff --git a/tests/testbench/com/vaadin/launcher/ApplicationRunnerServlet.java b/tests/testbench/com/vaadin/launcher/ApplicationRunnerServlet.java
index 6b7b36c3f3..bb37082d30 100644
--- a/tests/testbench/com/vaadin/launcher/ApplicationRunnerServlet.java
+++ b/tests/testbench/com/vaadin/launcher/ApplicationRunnerServlet.java
@@ -30,6 +30,8 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.vaadin.Application;
+import com.vaadin.RootRequiresMoreInformationException;
+import com.vaadin.terminal.AbstractRootProvider;
import com.vaadin.terminal.WrappedRequest;
import com.vaadin.terminal.gwt.server.AbstractApplicationServlet;
import com.vaadin.terminal.gwt.server.WrappedHttpServletRequest;
@@ -40,23 +42,6 @@ import com.vaadin.ui.Root;
public class ApplicationRunnerServlet extends AbstractApplicationServlet {
/**
- * Internal implementation of an application with a dynamically selected
- * Root implementation;
- */
- private static class RootRunnerApplication extends Application {
- private final Class<?> runnableClass;
-
- private RootRunnerApplication(Class<?> runnableClass) {
- this.runnableClass = runnableClass;
- }
-
- @Override
- protected String getRootClassName(WrappedRequest request) {
- return runnableClass.getCanonicalName();
- }
- }
-
- /**
* The name of the application class currently used. Only valid within one
* request.
*/
@@ -126,7 +111,17 @@ public class ApplicationRunnerServlet extends AbstractApplicationServlet {
try {
final Class<?> classToRun = getClassToRun();
if (Root.class.isAssignableFrom(classToRun)) {
- return new RootRunnerApplication(classToRun);
+ Application application = new Application();
+ application.addRootProvider(new AbstractRootProvider() {
+
+ @Override
+ public Class<? extends Root> getRootClass(
+ Application application, WrappedRequest request)
+ throws RootRequiresMoreInformationException {
+ return (Class<? extends Root>) classToRun;
+ }
+ });
+ return application;
} else if (Application.class.isAssignableFrom(classToRun)) {
return (Application) classToRun.newInstance();
} else {
@@ -221,7 +216,7 @@ public class ApplicationRunnerServlet extends AbstractApplicationServlet {
throws ClassNotFoundException {
Class<?> classToRun = getClassToRun();
if (Root.class.isAssignableFrom(classToRun)) {
- return RootRunnerApplication.class;
+ return Application.class;
} else if (Application.class.isAssignableFrom(classToRun)) {
return classToRun.asSubclass(Application.class);
} else {
diff --git a/tests/testbench/com/vaadin/tests/application/RefreshStatePreserve.java b/tests/testbench/com/vaadin/tests/application/RefreshStatePreserve.java
index 36a793bd6d..bd2aea3756 100644
--- a/tests/testbench/com/vaadin/tests/application/RefreshStatePreserve.java
+++ b/tests/testbench/com/vaadin/tests/application/RefreshStatePreserve.java
@@ -1,5 +1,8 @@
package com.vaadin.tests.application;
+import com.vaadin.Application;
+import com.vaadin.RootRequiresMoreInformationException;
+import com.vaadin.terminal.AbstractRootProvider;
import com.vaadin.terminal.WrappedRequest;
import com.vaadin.tests.components.AbstractTestApplication;
import com.vaadin.ui.Label;
@@ -20,11 +23,14 @@ public class RefreshStatePreserve extends AbstractTestApplication {
public void init() {
super.init();
setRootPreserved(true);
- }
-
- @Override
- protected String getRootClassName(WrappedRequest request) {
- return RefreshStateRoot.class.getName();
+ addRootProvider(new AbstractRootProvider() {
+ @Override
+ public Class<? extends Root> getRootClass(Application application,
+ WrappedRequest request)
+ throws RootRequiresMoreInformationException {
+ return RefreshStateRoot.class;
+ }
+ });
}
@Override
diff --git a/tests/testbench/com/vaadin/tests/components/root/RootsInMultipleTabs.java b/tests/testbench/com/vaadin/tests/components/root/RootsInMultipleTabs.java
index c3b20c5e7c..ae3182401d 100644
--- a/tests/testbench/com/vaadin/tests/components/root/RootsInMultipleTabs.java
+++ b/tests/testbench/com/vaadin/tests/components/root/RootsInMultipleTabs.java
@@ -1,5 +1,8 @@
package com.vaadin.tests.components.root;
+import com.vaadin.Application;
+import com.vaadin.RootRequiresMoreInformationException;
+import com.vaadin.terminal.AbstractRootProvider;
import com.vaadin.terminal.WrappedRequest;
import com.vaadin.tests.components.AbstractTestApplication;
import com.vaadin.ui.Label;
@@ -19,9 +22,15 @@ public class RootsInMultipleTabs extends AbstractTestApplication {
}
}
- @Override
- protected String getRootClassName(WrappedRequest request) {
- return TabRoot.class.getName();
+ public RootsInMultipleTabs() {
+ addRootProvider(new AbstractRootProvider() {
+ @Override
+ public Class<? extends Root> getRootClass(Application application,
+ WrappedRequest request)
+ throws RootRequiresMoreInformationException {
+ return TabRoot.class;
+ }
+ });
}
@Override