Browse Source

Add RootProvider for Root selection without custom Application (#8159)

tags/7.0.0.beta1
Leif Åstrand 11 years ago
parent
commit
72d9cc9ec0

+ 24
- 46
server/src/com/vaadin/Application.java View File

@@ -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

+ 35
- 0
server/src/com/vaadin/terminal/AbstractRootProvider.java View File

@@ -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);
}
}
}

+ 51
- 0
server/src/com/vaadin/terminal/DefaultRootProvider.java View File

@@ -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;
}
}

+ 29
- 0
server/src/com/vaadin/terminal/RootProvider.java View File

@@ -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);
}

+ 2
- 0
server/src/com/vaadin/terminal/gwt/server/ApplicationServlet.java View File

@@ -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) {

+ 13
- 5
tests/server-side/com/vaadin/tests/server/component/root/CustomRootClassLoader.java View File

@@ -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

+ 14
- 19
tests/testbench/com/vaadin/launcher/ApplicationRunnerServlet.java View File

@@ -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;
@@ -39,23 +41,6 @@ import com.vaadin.ui.Root;
@SuppressWarnings("serial")
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 {

+ 11
- 5
tests/testbench/com/vaadin/tests/application/RefreshStatePreserve.java View File

@@ -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

+ 12
- 3
tests/testbench/com/vaadin/tests/components/root/RootsInMultipleTabs.java View File

@@ -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

Loading…
Cancel
Save