summaryrefslogtreecommitdiffstats
path: root/server
diff options
context:
space:
mode:
authorLeif Åstrand <leif@vaadin.com>2012-09-04 11:15:53 +0300
committerLeif Åstrand <leif@vaadin.com>2012-09-05 11:39:31 +0300
commitaa913676e513170244169352dd97d6b583b50065 (patch)
treef1c0f70d0ca822261af860c285630e2401f0a4b8 /server
parent65240f403416efc82fb5ff9efce682291d426e89 (diff)
downloadvaadin-framework-aa913676e513170244169352dd97d6b583b50065.tar.gz
vaadin-framework-aa913676e513170244169352dd97d6b583b50065.zip
Move UI class info querying to UIProvider (#9402)
Diffstat (limited to 'server')
-rw-r--r--server/src/com/vaadin/Application.java290
-rw-r--r--server/src/com/vaadin/server/AbstractUIProvider.java83
-rw-r--r--server/src/com/vaadin/server/BootstrapHandler.java15
-rw-r--r--server/src/com/vaadin/server/UIProvider.java53
-rw-r--r--server/src/com/vaadin/ui/UI.java3
5 files changed, 255 insertions, 189 deletions
diff --git a/server/src/com/vaadin/Application.java b/server/src/com/vaadin/Application.java
index 9498534b4a..36a8db83a1 100644
--- a/server/src/com/vaadin/Application.java
+++ b/server/src/com/vaadin/Application.java
@@ -18,7 +18,6 @@ package com.vaadin;
import java.io.IOException;
import java.io.Serializable;
-import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.net.SocketException;
import java.net.URL;
@@ -40,15 +39,12 @@ import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-import com.vaadin.annotations.PreserveOnRefresh;
-import com.vaadin.annotations.Theme;
-import com.vaadin.annotations.Title;
-import com.vaadin.annotations.Widgetset;
import com.vaadin.data.util.converter.Converter;
import com.vaadin.data.util.converter.ConverterFactory;
import com.vaadin.data.util.converter.DefaultConverterFactory;
import com.vaadin.event.EventRouter;
import com.vaadin.server.AbstractErrorMessage;
+import com.vaadin.server.AbstractUIProvider;
import com.vaadin.server.ApplicationContext;
import com.vaadin.server.BootstrapFragmentResponse;
import com.vaadin.server.BootstrapListener;
@@ -193,6 +189,47 @@ public class Application implements Terminal.ErrorListener, Serializable {
this.mainWindow = mainWindow;
}
+ @Override
+ public void start(ApplicationStartEvent event) {
+ super.start(event);
+ addUIProvider(new AbstractUIProvider() {
+ @Override
+ public Class<? extends UI> getUIClass(Application application,
+ WrappedRequest request) {
+ if (application == LegacyApplication.this) {
+ UI uiInstance = getUIInstance(request);
+ if (uiInstance != null) {
+ return uiInstance.getClass();
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public UI createInstance(Application application,
+ Class<? extends UI> type, WrappedRequest request) {
+ return getUIInstance(request);
+ }
+
+ @Override
+ public String getThemeForUI(WrappedRequest request,
+ Class<? extends UI> uiClass) {
+ return theme;
+ }
+
+ @Override
+ public String getPageTitleForUI(WrappedRequest request,
+ Class<? extends UI> uiClass) {
+ UI uiInstance = getUIInstance(request);
+ if (uiInstance != null) {
+ return uiInstance.getCaption();
+ } else {
+ return super.getPageTitleForUI(request, uiClass);
+ }
+ }
+ });
+ }
+
/**
* Gets the mainWindow of the application.
*
@@ -210,19 +247,6 @@ public class Application implements Terminal.ErrorListener, Serializable {
return mainWindow;
}
- /**
- * This implementation simulates the way of finding a window for a
- * request by extracting a window name from the requested path and
- * passes that name to {@link #getWindow(String)}.
- * <p>
- * {@inheritDoc}
- */
- @Override
- protected <T extends UI> T createUIInstance(WrappedRequest request,
- Class<T> uiClass) {
- return uiClass.cast(getUIInstance(request));
- }
-
private UI getUIInstance(WrappedRequest request) {
String pathInfo = request.getRequestPathInfo();
String name = null;
@@ -261,19 +285,6 @@ public class Application implements Terminal.ErrorListener, Serializable {
}
/**
- * This implementation simulates the way of finding a window for a
- * request by extracting a window name from the requested path and
- * passes that name to {@link #getWindow(String)}.
- *
- * <p>
- * {@inheritDoc}
- */
- @Override
- public Class<? extends UI> getUIClass(WrappedRequest request) {
- return getUIInstance(request).getClass();
- }
-
- /**
* Sets the application's theme.
* <p>
* Note that this theme can be overridden for a specific UI with
@@ -302,18 +313,6 @@ public class Application implements Terminal.ErrorListener, Serializable {
}
/**
- * This implementation returns the theme that has been set using
- * {@link #setTheme(String)}
- * <p>
- * {@inheritDoc}
- */
- @Override
- public String getThemeForUI(WrappedRequest request,
- Class<? extends UI> uiClass) {
- return theme;
- }
-
- /**
* <p>
* Gets a UI by name. Returns <code>null</code> if the application is
* not running or it does not contain a window corresponding to the
@@ -1601,23 +1600,8 @@ public class Application implements Terminal.ErrorListener, Serializable {
* @since 7.0
*/
public Class<? extends UI> getUIClass(WrappedRequest request) {
- // Iterate in reverse order - check newest provider first
- int providersSize = uiProviders.size();
- if (providersSize == 0) {
- throw new IllegalStateException("There are no UI providers");
- }
- for (int i = providersSize - 1; i >= 0; i--) {
- UIProvider provider = uiProviders.get(i);
-
- Class<? extends UI> uiClass = provider.getUIClass(this, request);
-
- if (uiClass != null) {
- return uiClass;
- }
- }
-
- throw new RuntimeException(
- "No UI provider returned an UI class for request");
+ UIProvider uiProvider = getUiProvider(request, null);
+ return uiProvider.getUIClass(this, request);
}
/**
@@ -1639,6 +1623,59 @@ public class Application implements Terminal.ErrorListener, Serializable {
*/
protected <T extends UI> T createUIInstance(WrappedRequest request,
Class<T> uiClass) {
+ UIProvider uiProvider = getUiProvider(request, uiClass);
+ return uiClass.cast(uiProvider.createInstance(this, uiClass, request));
+ }
+
+ /**
+ * Gets the {@link UIProvider} that should be used for a request. The
+ * selection can further be restricted by also requiring the UI provider to
+ * support a specific UI class.
+ *
+ * @see UIProvider
+ * @see #addUIProvider(UIProvider)
+ *
+ * @param request
+ * the request for which to get an UI provider
+ * @param uiClass
+ * the UI class for which a provider is required, or
+ * <code>null</code> to use the first UI provider supporting the
+ * request.
+ * @return an UI provider supporting the request (and the UI class if
+ * provided).
+ *
+ * @since 7.0.0
+ */
+ public UIProvider getUiProvider(WrappedRequest request, Class<?> uiClass) {
+ UIProvider provider = (UIProvider) request
+ .getAttribute(UIProvider.class.getName());
+ if (provider != null) {
+ // Cached provider found, verify that it's a sensible selection
+ Class<? extends UI> providerClass = provider.getUIClass(this,
+ request);
+ if (uiClass == null && providerClass != null) {
+ // Use it if it gives any answer if no specific class is
+ // required
+ return provider;
+ } else if (uiClass == providerClass) {
+ // Use it if it gives the expected UI class
+ return provider;
+ } else {
+ // Don't keep it cached if it doesn't match the expectations
+ request.setAttribute(UIProvider.class.getName(), null);
+ }
+ }
+
+ // Iterate all current providers if no matching cached provider found
+ provider = doGetUiProvider(request, uiClass);
+
+ // Cache the found provider
+ request.setAttribute(UIProvider.class.getName(), provider);
+
+ return provider;
+ }
+
+ private UIProvider doGetUiProvider(WrappedRequest request, Class<?> uiClass) {
int providersSize = uiProviders.size();
if (providersSize == 0) {
throw new IllegalStateException("There are no UI providers");
@@ -1649,108 +1686,25 @@ public class Application implements Terminal.ErrorListener, Serializable {
Class<? extends UI> providerClass = provider.getUIClass(this,
request);
+ // If we found something
if (providerClass != null) {
- if (providerClass != uiClass) {
+ if (uiClass == null) {
+ // Not looking for anything particular -> anything is ok
+ return provider;
+ } else if (providerClass == uiClass) {
+ // Looking for a specific provider -> only use if matching
+ return provider;
+ } else {
getLogger().warning(
"Mismatching UI classes. Expected " + uiClass
+ " but got " + providerClass + " from "
+ provider);
- // Try with next provider if we didn't get the expected
- // class
- continue;
+ // Continue looking
}
- return uiClass.cast(provider.createInstance(this, uiClass,
- request));
}
}
- throw new RuntimeException(
- "No UI provider created an UI instance for request");
- }
-
- /**
- * Finds the theme to use for a specific UI. If no specific theme is
- * required, <code>null</code> is returned.
- *
- * TODO Tell what the default implementation does once it does something.
- *
- * @param uI
- * the UI to get a theme for
- * @return the name of the theme, or <code>null</code> if the default theme
- * should be used
- *
- * @since 7.0
- */
- public String getThemeForUI(WrappedRequest request,
- Class<? extends UI> uiClass) {
- Theme uiTheme = getAnnotationFor(uiClass, Theme.class);
- if (uiTheme != null) {
- return uiTheme.value();
- } else {
- return null;
- }
- }
-
- /**
- * Finds the widgetset to use for a specific UI. If no specific widgetset is
- * required, <code>null</code> is returned.
- * <p>
- * The default implementation uses the @{@link Widgetset} annotation if it's
- * defined for the UI class.
- *
- * @param request
- * the wrapped request for which to get a widgetset
- * @param uiClass
- * the UI class to get a widgetset for
- * @return the name of the widgetset, or <code>null</code> if the default
- * widgetset should be used
- *
- * @since 7.0
- */
- public String getWidgetsetForUI(WrappedRequest request,
- Class<? extends UI> uiClass) {
- Widgetset uiWidgetset = getAnnotationFor(uiClass, Widgetset.class);
- if (uiWidgetset != null) {
- return uiWidgetset.value();
- } else {
- return null;
- }
- }
-
- /**
- * Helper to get an annotation for a class. If the annotation is not present
- * on the target class, it's superclasses and implemented interfaces are
- * also searched for the annotation.
- *
- * @param type
- * the target class from which the annotation should be found
- * @param annotationType
- * the annotation type to look for
- * @return an annotation of the given type, or <code>null</code> if the
- * annotation is not present on the class
- */
- private static <T extends Annotation> T getAnnotationFor(Class<?> type,
- Class<T> annotationType) {
- // Find from the class hierarchy
- Class<?> currentType = type;
- while (currentType != Object.class) {
- T annotation = currentType.getAnnotation(annotationType);
- if (annotation != null) {
- return annotation;
- } else {
- currentType = currentType.getSuperclass();
- }
- }
-
- // Find from an implemented interface
- for (Class<?> iface : type.getInterfaces()) {
- T annotation = iface.getAnnotation(annotationType);
- if (annotation != null) {
- return annotation;
- }
- }
-
- return null;
+ throw new RuntimeException("No UI provider found for request");
}
/**
@@ -1999,7 +1953,7 @@ public class Application implements Terminal.ErrorListener, Serializable {
ui.doInit(request, uiId.intValue());
- if (isUiPreserved(request, uiClass)) {
+ if (getUiProvider(request, uiClass).isUiPreserved(request, uiClass)) {
// Remember this UI
String windowName = request.getBrowserDetails().getWindowName();
if (windowName == null) {
@@ -2035,25 +1989,6 @@ public class Application implements Terminal.ErrorListener, Serializable {
}
/**
- * Checks whether the same UI state should be reused if the framework can
- * detect that the application is opened in a browser window where it has
- * previously been open. The framework attempts to discover this by checking
- * the value of window.name in the browser.
- *
- * @param request
- * @param uiClass
- *
- * @return <code>true</code>if the same UI instance should be reused e.g.
- * when the browser window is refreshed.
- */
- public boolean isUiPreserved(WrappedRequest request,
- Class<? extends UI> uiClass) {
- PreserveOnRefresh preserveOnRefresh = getAnnotationFor(uiClass,
- PreserveOnRefresh.class);
- return preserveOnRefresh != null;
- }
-
- /**
* Gets all the uIs of this application. This includes uIs that have been
* requested but not yet initialized. Please note, that uIs are not
* automatically removed e.g. if the browser window is closed and that there
@@ -2270,13 +2205,4 @@ public class Application implements Terminal.ErrorListener, Serializable {
return globalResourceHandler;
}
- public String getPageTitleForUI(WrappedRequest request,
- Class<? extends UI> uiClass) {
- Title titleAnnotation = getAnnotationFor(uiClass, Title.class);
- if (titleAnnotation == null) {
- return null;
- } else {
- return titleAnnotation.value();
- }
- }
}
diff --git a/server/src/com/vaadin/server/AbstractUIProvider.java b/server/src/com/vaadin/server/AbstractUIProvider.java
index 59ce31891d..49f8e3ec77 100644
--- a/server/src/com/vaadin/server/AbstractUIProvider.java
+++ b/server/src/com/vaadin/server/AbstractUIProvider.java
@@ -16,7 +16,13 @@
package com.vaadin.server;
+import java.lang.annotation.Annotation;
+
import com.vaadin.Application;
+import com.vaadin.annotations.PreserveOnRefresh;
+import com.vaadin.annotations.Theme;
+import com.vaadin.annotations.Title;
+import com.vaadin.annotations.Widgetset;
import com.vaadin.ui.UI;
public abstract class AbstractUIProvider implements UIProvider {
@@ -32,4 +38,81 @@ public abstract class AbstractUIProvider implements UIProvider {
throw new RuntimeException("Could not access root class", e);
}
}
+
+ /**
+ * Helper to get an annotation for a class. If the annotation is not present
+ * on the target class, it's superclasses and implemented interfaces are
+ * also searched for the annotation.
+ *
+ * @param type
+ * the target class from which the annotation should be found
+ * @param annotationType
+ * the annotation type to look for
+ * @return an annotation of the given type, or <code>null</code> if the
+ * annotation is not present on the class
+ */
+ protected static <T extends Annotation> T getAnnotationFor(Class<?> type,
+ Class<T> annotationType) {
+ // Find from the class hierarchy
+ Class<?> currentType = type;
+ while (currentType != Object.class) {
+ T annotation = currentType.getAnnotation(annotationType);
+ if (annotation != null) {
+ return annotation;
+ } else {
+ currentType = currentType.getSuperclass();
+ }
+ }
+
+ // Find from an implemented interface
+ for (Class<?> iface : type.getInterfaces()) {
+ T annotation = iface.getAnnotation(annotationType);
+ if (annotation != null) {
+ return annotation;
+ }
+ }
+
+ return null;
+ }
+
+ @Override
+ public String getThemeForUI(WrappedRequest request,
+ Class<? extends UI> uiClass) {
+ Theme uiTheme = getAnnotationFor(uiClass, Theme.class);
+ if (uiTheme != null) {
+ return uiTheme.value();
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ public String getWidgetsetForUI(WrappedRequest request,
+ Class<? extends UI> uiClass) {
+ Widgetset uiWidgetset = getAnnotationFor(uiClass, Widgetset.class);
+ if (uiWidgetset != null) {
+ return uiWidgetset.value();
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ public boolean isUiPreserved(WrappedRequest request,
+ Class<? extends UI> uiClass) {
+ PreserveOnRefresh preserveOnRefresh = getAnnotationFor(uiClass,
+ PreserveOnRefresh.class);
+ return preserveOnRefresh != null;
+ }
+
+ @Override
+ public String getPageTitleForUI(WrappedRequest request,
+ Class<? extends UI> uiClass) {
+ Title titleAnnotation = getAnnotationFor(uiClass, Title.class);
+ if (titleAnnotation == null) {
+ return null;
+ } else {
+ return titleAnnotation.value();
+ }
+ }
}
diff --git a/server/src/com/vaadin/server/BootstrapHandler.java b/server/src/com/vaadin/server/BootstrapHandler.java
index a1438312b6..4d200b5063 100644
--- a/server/src/com/vaadin/server/BootstrapHandler.java
+++ b/server/src/com/vaadin/server/BootstrapHandler.java
@@ -218,8 +218,9 @@ public abstract class BootstrapHandler implements RequestHandler {
head.appendElement("meta").attr("http-equiv", "X-UA-Compatible")
.attr("content", "chrome=1");
- String title = context.getApplication().getPageTitleForUI(
- context.getRequest(), context.getUIClass());
+ String title = context.getApplication()
+ .getUiProvider(context.getRequest(), context.getUIClass())
+ .getPageTitleForUI(context.getRequest(), context.getUIClass());
if (title != null) {
head.appendElement("title").appendText(title);
}
@@ -270,8 +271,9 @@ public abstract class BootstrapHandler implements RequestHandler {
public String getWidgetsetForUI(BootstrapContext context) {
WrappedRequest request = context.getRequest();
- String widgetset = context.getApplication().getWidgetsetForUI(
- context.getRequest(), context.getUIClass());
+ String widgetset = context.getApplication()
+ .getUiProvider(context.getRequest(), context.getUIClass())
+ .getWidgetsetForUI(context.getRequest(), context.getUIClass());
if (widgetset == null) {
widgetset = request.getDeploymentConfiguration()
.getConfiguredWidgetset(request);
@@ -497,8 +499,9 @@ public abstract class BootstrapHandler implements RequestHandler {
* @return
*/
public String getThemeName(BootstrapContext context) {
- return context.getApplication().getThemeForUI(context.getRequest(),
- context.getUIClass());
+ return context.getApplication()
+ .getUiProvider(context.getRequest(), context.getUIClass())
+ .getThemeForUI(context.getRequest(), context.getUIClass());
}
/**
diff --git a/server/src/com/vaadin/server/UIProvider.java b/server/src/com/vaadin/server/UIProvider.java
index ea73a705ea..60b79cdbb9 100644
--- a/server/src/com/vaadin/server/UIProvider.java
+++ b/server/src/com/vaadin/server/UIProvider.java
@@ -17,6 +17,7 @@
package com.vaadin.server;
import com.vaadin.Application;
+import com.vaadin.annotations.Widgetset;
import com.vaadin.ui.UI;
public interface UIProvider {
@@ -25,4 +26,56 @@ public interface UIProvider {
public UI createInstance(Application application, Class<? extends UI> type,
WrappedRequest request);
+
+ public String getPageTitleForUI(WrappedRequest request,
+ Class<? extends UI> uiClass);
+
+ /**
+ * Checks whether the same UI state should be reused if the framework can
+ * detect that the application is opened in a browser window where it has
+ * previously been open. The framework attempts to discover this by checking
+ * the value of window.name in the browser.
+ *
+ * @param request
+ * @param uiClass
+ *
+ * @return <code>true</code>if the same UI instance should be reused e.g.
+ * when the browser window is refreshed.
+ */
+ public boolean isUiPreserved(WrappedRequest request,
+ Class<? extends UI> uiClass);
+
+ /**
+ * Finds the widgetset to use for a specific UI. If no specific widgetset is
+ * required, <code>null</code> is returned.
+ * <p>
+ * The default implementation uses the @{@link Widgetset} annotation if it's
+ * defined for the UI class.
+ *
+ * @param request
+ * the wrapped request for which to get a widgetset
+ * @param uiClass
+ * the UI class to get a widgetset for
+ * @return the name of the widgetset, or <code>null</code> if the default
+ * widgetset should be used
+ *
+ */
+ public String getWidgetsetForUI(WrappedRequest request,
+ Class<? extends UI> uiClass);
+
+ /**
+ * Finds the theme to use for a specific UI. If no specific theme is
+ * required, <code>null</code> is returned.
+ *
+ * TODO Tell what the default implementation does once it does something.
+ *
+ * @param uI
+ * the UI to get a theme for
+ * @return the name of the theme, or <code>null</code> if the default theme
+ * should be used
+ *
+ */
+ public String getThemeForUI(WrappedRequest request,
+ Class<? extends UI> uiClass);
+
}
diff --git a/server/src/com/vaadin/ui/UI.java b/server/src/com/vaadin/ui/UI.java
index ee4cb9fd2c..7ae4e6bda3 100644
--- a/server/src/com/vaadin/ui/UI.java
+++ b/server/src/com/vaadin/ui/UI.java
@@ -940,7 +940,8 @@ public abstract class UI extends AbstractComponentContainer implements
throw new IllegalStateException("UI id has already been defined");
}
this.uiId = uiId;
- theme = getApplication().getThemeForUI(request, getClass());
+ theme = getApplication().getUiProvider(request, getClass())
+ .getThemeForUI(request, getClass());
getPage().init(request);