@@ -153,15 +153,11 @@ | |||
var bootstrapApp = function(mayDefer) { | |||
var themeUri = getConfig('themeUri'); | |||
if (themeUri) { | |||
loadTheme(themeUri); | |||
} | |||
loadTheme(themeUri); | |||
var widgetsetBase = getConfig('widgetsetBase'); | |||
var widgetset = getConfig('widgetset'); | |||
if (widgetset && widgetsetBase) { | |||
loadWidgetset(widgetsetBase, widgetset); | |||
} | |||
loadWidgetset(widgetsetBase, widgetset); | |||
if (getConfig('uidl') === undefined) { | |||
if (mayDefer) { |
@@ -28,7 +28,6 @@ import java.util.Collections; | |||
import java.util.Enumeration; | |||
import java.util.EventObject; | |||
import java.util.HashMap; | |||
import java.util.HashSet; | |||
import java.util.Iterator; | |||
import java.util.LinkedList; | |||
import java.util.List; | |||
@@ -36,14 +35,15 @@ import java.util.Locale; | |||
import java.util.Map; | |||
import java.util.Map.Entry; | |||
import java.util.Properties; | |||
import java.util.Set; | |||
import java.util.logging.Level; | |||
import java.util.logging.Logger; | |||
import java.util.regex.Matcher; | |||
import java.util.regex.Pattern; | |||
import com.vaadin.annotations.EagerInit; | |||
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; | |||
@@ -210,15 +210,16 @@ 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} | |||
* | |||
* @see #getWindow(String) | |||
* @see Application#getUI(WrappedRequest) | |||
*/ | |||
@Override | |||
public UI.LegacyWindow getUI(WrappedRequest request) { | |||
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; | |||
if (pathInfo != null && pathInfo.length() > 0) { | |||
@@ -235,6 +236,19 @@ 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 | |||
public Class<? extends UI> getUIClass(WrappedRequest request) { | |||
return getUIInstance(request).getClass(); | |||
} | |||
/** | |||
* Sets the application's theme. | |||
* <p> | |||
@@ -269,9 +283,9 @@ public class Application implements Terminal.ErrorListener, Serializable { | |||
* <p> | |||
* {@inheritDoc} | |||
*/ | |||
@Override | |||
public String getThemeForUI(UI uI) { | |||
public String getThemeForUI(WrappedRequest request, | |||
Class<? extends UI> uiClass) { | |||
return theme; | |||
} | |||
@@ -476,15 +490,6 @@ public class Application implements Terminal.ErrorListener, Serializable { | |||
private final EventRouter eventRouter = new EventRouter(); | |||
/** | |||
* Keeps track of which uIs have been inited. | |||
* <p> | |||
* TODO Investigate whether this might be derived from the different states | |||
* in getUIForRrequest. | |||
* </p> | |||
*/ | |||
private Set<Integer> initedUIs = new HashSet<Integer>(); | |||
private List<UIProvider> uiProviders = new LinkedList<UIProvider>(); | |||
private GlobalResourceHandler globalResourceHandler; | |||
@@ -1577,67 +1582,98 @@ public class Application implements Terminal.ErrorListener, Serializable { | |||
} | |||
/** | |||
* Gets a UI for a request for which no UI is already known. This method is | |||
* called when the framework processes a request that does not originate | |||
* from an existing UI instance. This typically happens when a host page is | |||
* requested. | |||
* | |||
* Gets the UI class for a request for which no UI is already known. This | |||
* method is called when the framework processes a request that does not | |||
* originate from an existing UI instance. This typically happens when a | |||
* host page is requested. | |||
* <p> | |||
* Subclasses of Application may override this method to provide custom | |||
* logic for choosing how to create a suitable UI or for picking an already | |||
* created UI. If an existing UI is picked, care should be taken to avoid | |||
* keeping the same UI open in multiple browser windows, as that will cause | |||
* the states to go out of sync. | |||
* </p> | |||
* | |||
* logic for choosing what kind of UI to use. | |||
* <p> | |||
* If {@link BrowserDetails} are required to create a UI, the implementation | |||
* can throw a {@link UIRequiresMoreInformationException} exception. In this | |||
* case, the framework will instruct the browser to send the additional | |||
* details, whereupon this method is invoked again with the browser details | |||
* present in the wrapped request. Throwing the exception if the browser | |||
* details are already available is not supported. | |||
* </p> | |||
* The default implementation in {@link Application} uses the | |||
* {@value #UI_PARAMETER} parameter from web.xml for finding the name of the | |||
* UI class. If {@link DeploymentConfiguration#getClassLoader()} does not | |||
* return <code>null</code>, the returned {@link ClassLoader} is used for | |||
* loading the UI class. Otherwise the {@link ClassLoader} used to load this | |||
* class is used. | |||
* | |||
* <p> | |||
* The default implementation in {@link Application} creates a new instance | |||
* of the UI class returned by {@link #getUIClassName(WrappedRequest)}, | |||
* which in turn uses the {@value #UI_PARAMETER} parameter from web.xml. If | |||
* {@link DeploymentConfiguration#getClassLoader()} for the request returns | |||
* a {@link ClassLoader}, it is used for loading the UI class. Otherwise the | |||
* {@link ClassLoader} used to load this class is used. | |||
* </p> | |||
* | |||
* @param request | |||
* the wrapped request for which a UI is needed | |||
* @return a UI instance to use for the request | |||
* @throws UIRequiresMoreInformationException | |||
* may be thrown by an implementation to indicate that | |||
* {@link BrowserDetails} are required to create a UI | |||
* | |||
* @see #getUIClassName(WrappedRequest) | |||
* @see UI | |||
* @see UIRequiresMoreInformationException | |||
* @see WrappedRequest#getBrowserDetails() | |||
* | |||
* @since 7.0 | |||
*/ | |||
protected UI getUI(WrappedRequest request) | |||
throws UIRequiresMoreInformationException { | |||
// Iterate in reverse order - test check newest provider first | |||
for (int i = uiProviders.size() - 1; i >= 0; i--) { | |||
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 provider.instantiateUI(this, uiClass, request); | |||
return uiClass; | |||
} | |||
} | |||
throw new RuntimeException( | |||
"No UI provider returned an UI class for request"); | |||
} | |||
/** | |||
* Creates an UI instance for a request for which no UI is already known. | |||
* This method is called when the framework processes a request that does | |||
* not originate from an existing UI instance. This typically happens when a | |||
* host page is requested. | |||
* <p> | |||
* Subclasses of Application may override this method to provide custom | |||
* logic for choosing how to create a suitable UI or for picking an already | |||
* created UI. If an existing UI is picked, care should be taken to avoid | |||
* keeping the same UI open in multiple browser windows, as that will cause | |||
* the states to go out of sync. | |||
* </p> | |||
* | |||
* @param request | |||
* @param uiClass | |||
* @return | |||
*/ | |||
protected <T extends UI> T createUIInstance(WrappedRequest request, | |||
Class<T> uiClass) { | |||
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> providerClass = provider.getUIClass(this, | |||
request); | |||
if (providerClass != null) { | |||
if (providerClass != uiClass) { | |||
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; | |||
} | |||
return uiClass.cast(provider.instantiateUI(this, uiClass, | |||
request)); | |||
} | |||
} | |||
throw new RuntimeException( | |||
"No UI providers available or providers are not able to find UI instance"); | |||
"No UI provider created an UI instance for request"); | |||
} | |||
/** | |||
@@ -1653,8 +1689,9 @@ public class Application implements Terminal.ErrorListener, Serializable { | |||
* | |||
* @since 7.0 | |||
*/ | |||
public String getThemeForUI(UI uI) { | |||
Theme uiTheme = getAnnotationFor(uI.getClass(), Theme.class); | |||
public String getThemeForUI(WrappedRequest request, | |||
Class<? extends UI> uiClass) { | |||
Theme uiTheme = getAnnotationFor(uiClass, Theme.class); | |||
if (uiTheme != null) { | |||
return uiTheme.value(); | |||
} else { | |||
@@ -1665,18 +1702,22 @@ public class Application implements Terminal.ErrorListener, Serializable { | |||
/** | |||
* 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. | |||
* | |||
* TODO Tell what the default implementation does once it does something. | |||
* | |||
* @param uI | |||
* the UI to get a widgetset for | |||
* @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(UI uI) { | |||
Widgetset uiWidgetset = getAnnotationFor(uI.getClass(), Widgetset.class); | |||
public String getWidgetsetForUI(WrappedRequest request, | |||
Class<? extends UI> uiClass) { | |||
Widgetset uiWidgetset = getAnnotationFor(uiClass, Widgetset.class); | |||
if (uiWidgetset != null) { | |||
return uiWidgetset.value(); | |||
} else { | |||
@@ -1818,8 +1859,6 @@ public class Application implements Terminal.ErrorListener, Serializable { | |||
*/ | |||
private static final ThreadLocal<Application> currentApplication = new ThreadLocal<Application>(); | |||
private boolean uiPreserved = false; | |||
/** | |||
* Gets the currently used application. The current application is | |||
* automatically defined when processing requests to the server. In other | |||
@@ -1894,17 +1933,12 @@ public class Application implements Terminal.ErrorListener, Serializable { | |||
* @param request | |||
* the request for which a UI is desired | |||
* @return a UI belonging to the request | |||
* @throws UIRequiresMoreInformationException | |||
* if no existing UI could be found and creating a new UI | |||
* requires additional information from the browser | |||
* | |||
* @see #getUI(WrappedRequest) | |||
* @see UIRequiresMoreInformationException | |||
* @see #createUI(WrappedRequest) | |||
* | |||
* @since 7.0 | |||
*/ | |||
public UI getUIForRequest(WrappedRequest request) | |||
throws UIRequiresMoreInformationException { | |||
public UI getUIForRequest(WrappedRequest request) { | |||
UI uI = UI.getCurrent(); | |||
if (uI != null) { | |||
return uI; | |||
@@ -1917,69 +1951,75 @@ public class Application implements Terminal.ErrorListener, Serializable { | |||
&& browserDetails.getUriFragment() != null; | |||
uI = uIs.get(uiId); | |||
Class<? extends UI> uiClass = null; | |||
if (uI == null && hasBrowserDetails | |||
&& !retainOnRefreshUIs.isEmpty()) { | |||
uiClass = getUIClass(request); | |||
if (uI == null && isUiPreserved()) { | |||
// Check for a known UI | |||
if (!retainOnRefreshUIs.isEmpty()) { | |||
Integer retainedUIId; | |||
if (!hasBrowserDetails) { | |||
throw new UIRequiresMoreInformationException(); | |||
} else { | |||
String windowName = browserDetails.getWindowName(); | |||
retainedUIId = retainOnRefreshUIs.get(windowName); | |||
} | |||
@SuppressWarnings("null") | |||
String windowName = browserDetails.getWindowName(); | |||
Integer retainedUIId = retainOnRefreshUIs.get(windowName); | |||
if (retainedUIId != null) { | |||
if (retainedUIId != null) { | |||
UI retainedUI = uIs.get(retainedUIId); | |||
// We've had the same UI instance in a window with this | |||
// name, but should we still use it? | |||
if (retainedUI.getClass() == uiClass) { | |||
uiId = retainedUIId; | |||
uI = uIs.get(uiId); | |||
uI = retainedUI; | |||
} else { | |||
getLogger().info( | |||
"Not using retained UI in " + windowName | |||
+ " because retained UI was of type " | |||
+ retainedUIId.getClass() + " but " | |||
+ uiClass | |||
+ " is expected for the request."); | |||
} | |||
} | |||
} | |||
if (uI == null) { | |||
// Throws exception if UI can not yet be created | |||
uI = getUI(request); | |||
} // end synchronized block | |||
// Initialize some fields for a newly created UI | |||
if (uI.getApplication() == null) { | |||
uI.setApplication(this); | |||
} | |||
if (uI.getUIId() < 0) { | |||
UI.setCurrent(uI); | |||
if (uiId == null) { | |||
// Get the next id if none defined | |||
uiId = Integer.valueOf(nextUIId++); | |||
} | |||
uI.setUIId(uiId.intValue()); | |||
uIs.put(uiId, uI); | |||
} | |||
} | |||
return uI; | |||
} | |||
// Set thread local here so it is available in init | |||
UI.setCurrent(uI); | |||
public UI createUI(WrappedRequest request) { | |||
Class<? extends UI> uiClass = getUIClass(request); | |||
if (!initedUIs.contains(uiId)) { | |||
boolean initRequiresBrowserDetails = isUiPreserved() | |||
|| !uI.getClass().isAnnotationPresent(EagerInit.class); | |||
if (!initRequiresBrowserDetails || hasBrowserDetails) { | |||
uI.doInit(request); | |||
UI ui = createUIInstance(request, uiClass); | |||
// Remember that this UI has been initialized | |||
initedUIs.add(uiId); | |||
// Initialize some fields for a newly created UI | |||
if (ui.getApplication() == null) { | |||
ui.setApplication(this); | |||
} | |||
// Get the next id | |||
Integer uiId = Integer.valueOf(nextUIId++); | |||
// init() might turn on preserve so do this afterwards | |||
if (isUiPreserved()) { | |||
// Remember this UI | |||
String windowName = request.getBrowserDetails() | |||
.getWindowName(); | |||
retainOnRefreshUIs.put(windowName, uiId); | |||
} | |||
} | |||
uIs.put(uiId, ui); | |||
// Set thread local here so it is available in init | |||
UI.setCurrent(ui); | |||
ui.doInit(request, uiId.intValue()); | |||
if (isUiPreserved(request, uiClass)) { | |||
// Remember this UI | |||
String windowName = request.getBrowserDetails().getWindowName(); | |||
if (windowName == null) { | |||
getLogger().warning( | |||
"There is no window.name available for UI " + uiClass | |||
+ " that should be preserved."); | |||
} else { | |||
retainOnRefreshUIs.put(windowName, uiId); | |||
} | |||
} // end synchronized block | |||
} | |||
return uI; | |||
return ui; | |||
} | |||
/** | |||
@@ -2002,54 +2042,23 @@ public class Application implements Terminal.ErrorListener, Serializable { | |||
return uiId; | |||
} | |||
/** | |||
* Sets 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. | |||
* <p> | |||
* NOTE that you should avoid turning this feature on/off on-the-fly when | |||
* the UI is already shown, as it might not be retained as intended. | |||
* </p> | |||
* | |||
* @param uiPreserved | |||
* <code>true</code>if the same UI instance should be reused e.g. | |||
* when the browser window is refreshed. | |||
*/ | |||
public void setUiPreserved(boolean uiPreserved) { | |||
this.uiPreserved = uiPreserved; | |||
if (!uiPreserved) { | |||
retainOnRefreshUIs.clear(); | |||
} | |||
} | |||
/** | |||
* 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() { | |||
return uiPreserved; | |||
} | |||
/** | |||
* Checks whether there's a pending initialization for the UI with the given | |||
* id. | |||
* | |||
* @param uiId | |||
* UI id to check for | |||
* @return <code>true</code> of the initialization is pending, | |||
* <code>false</code> if the UI id is not registered or if the UI | |||
* has already been initialized | |||
* | |||
* @see #getUIForRequest(WrappedRequest) | |||
*/ | |||
public boolean isUIInitPending(int uiId) { | |||
return !initedUIs.contains(Integer.valueOf(uiId)); | |||
public boolean isUiPreserved(WrappedRequest request, | |||
Class<? extends UI> uiClass) { | |||
PreserveOnRefresh preserveOnRefresh = getAnnotationFor(uiClass, | |||
PreserveOnRefresh.class); | |||
return preserveOnRefresh != null; | |||
} | |||
/** | |||
@@ -2268,4 +2277,20 @@ 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(); | |||
} | |||
} | |||
public boolean isEagerInit(WrappedRequest request, | |||
Class<? extends UI> uiClass) { | |||
EagerInit eagerInit = getAnnotationFor(uiClass, EagerInit.class); | |||
return eagerInit != null; | |||
} | |||
} |
@@ -1,37 +0,0 @@ | |||
/* | |||
* 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; | |||
import com.vaadin.server.WrappedRequest; | |||
import com.vaadin.server.WrappedRequest.BrowserDetails; | |||
/** | |||
* Exception that is thrown to indicate that creating or initializing the UI | |||
* requires information detailed from the web browser ({@link BrowserDetails}) | |||
* to be present. | |||
* | |||
* This exception may not be thrown if that information is already present in | |||
* the current WrappedRequest. | |||
* | |||
* @see Application#getUI(WrappedRequest) | |||
* @see WrappedRequest#getBrowserDetails() | |||
* | |||
* @since 7.0 | |||
*/ | |||
public class UIRequiresMoreInformationException extends Exception { | |||
// Nothing of interest here | |||
} |
@@ -0,0 +1,28 @@ | |||
/* | |||
* 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.annotations; | |||
import java.lang.annotation.ElementType; | |||
import java.lang.annotation.Retention; | |||
import java.lang.annotation.RetentionPolicy; | |||
import java.lang.annotation.Target; | |||
@Target(ElementType.TYPE) | |||
@Retention(RetentionPolicy.RUNTIME) | |||
public @interface PreserveOnRefresh { | |||
} |
@@ -0,0 +1,38 @@ | |||
/* | |||
* 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.annotations; | |||
import java.lang.annotation.ElementType; | |||
import java.lang.annotation.Retention; | |||
import java.lang.annotation.RetentionPolicy; | |||
import java.lang.annotation.Target; | |||
import com.vaadin.ui.UI; | |||
/** | |||
* Defines the HTML page title for a {@link UI}. | |||
*/ | |||
@Retention(RetentionPolicy.RUNTIME) | |||
@Target(ElementType.TYPE) | |||
public @interface Title { | |||
/** | |||
* Gets the HTML title that should be used if the UI is used on it's own. | |||
* | |||
* @return a page title string | |||
*/ | |||
public String value(); | |||
} |
@@ -56,7 +56,6 @@ import com.liferay.portal.kernel.util.PropsUtil; | |||
import com.vaadin.Application; | |||
import com.vaadin.Application.ApplicationStartEvent; | |||
import com.vaadin.Application.SystemMessages; | |||
import com.vaadin.UIRequiresMoreInformationException; | |||
import com.vaadin.server.AbstractCommunicationManager.Callback; | |||
import com.vaadin.ui.UI; | |||
@@ -501,12 +500,7 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet | |||
// Both action requests and render requests are ok | |||
// without a UI as they render the initial HTML | |||
// and then do a second request | |||
try { | |||
uI = application | |||
.getUIForRequest(wrappedRequest); | |||
} catch (UIRequiresMoreInformationException e) { | |||
// Ignore problem and continue without UI | |||
} | |||
uI = application.getUIForRequest(wrappedRequest); | |||
break; | |||
case BROWSER_DETAILS: | |||
// Should not try to find a UI here as the | |||
@@ -902,7 +896,6 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet | |||
throws PortletException { | |||
try { | |||
final Application application = getApplicationClass().newInstance(); | |||
application.setUiPreserved(true); | |||
return application; | |||
} catch (final IllegalAccessException e) { | |||
throw new PortletException("getNewApplication failed", e); |
@@ -60,13 +60,11 @@ import javax.servlet.http.HttpServletResponse; | |||
import com.vaadin.Application; | |||
import com.vaadin.Application.SystemMessages; | |||
import com.vaadin.UIRequiresMoreInformationException; | |||
import com.vaadin.annotations.JavaScript; | |||
import com.vaadin.annotations.StyleSheet; | |||
import com.vaadin.external.json.JSONArray; | |||
import com.vaadin.external.json.JSONException; | |||
import com.vaadin.external.json.JSONObject; | |||
import com.vaadin.server.BootstrapHandler.BootstrapContext; | |||
import com.vaadin.server.ComponentSizeValidator.InvalidLayout; | |||
import com.vaadin.server.RpcManager.RpcInvocationException; | |||
import com.vaadin.server.StreamVariable.StreamingEndEvent; | |||
@@ -1512,7 +1510,7 @@ public abstract class AbstractCommunicationManager implements Serializable { | |||
} | |||
private String getTheme(UI uI) { | |||
String themeName = uI.getApplication().getThemeForUI(uI); | |||
String themeName = uI.getTheme(); | |||
String requestThemeName = getRequestTheme(); | |||
if (requestThemeName != null) { | |||
@@ -2410,36 +2408,22 @@ public abstract class AbstractCommunicationManager implements Serializable { | |||
WrappedResponse response, Application application) | |||
throws IOException { | |||
// if we do not yet have a currentUI, it should be initialized | |||
// shortly, and we should send the initial UIDL | |||
boolean sendUIDL = UI.getCurrent() == null; | |||
assert UI.getCurrent() == null; | |||
try { | |||
CombinedRequest combinedRequest = new CombinedRequest(request); | |||
UI uI = application.getUIForRequest(combinedRequest); | |||
response.setContentType("application/json; charset=UTF-8"); | |||
// Use the same logic as for determined UIs | |||
BootstrapHandler bootstrapHandler = getBootstrapHandler(); | |||
BootstrapContext context = bootstrapHandler.createContext( | |||
combinedRequest, response, application, uI.getUIId()); | |||
String widgetset = context.getWidgetsetName(); | |||
String theme = context.getThemeName(); | |||
String themeUri = bootstrapHandler.getThemeUri(context, theme); | |||
UI uI = application.getUIForRequest(combinedRequest); | |||
if (uI == null) { | |||
uI = application.createUI(combinedRequest); | |||
} | |||
// TODO These are not required if it was only the init of the UI | |||
// that was delayed | |||
JSONObject params = new JSONObject(); | |||
params.put("widgetset", widgetset); | |||
params.put("themeUri", themeUri); | |||
// UI id might have changed based on e.g. window.name | |||
params.put(UIConstants.UI_ID_PARAMETER, uI.getUIId()); | |||
if (sendUIDL) { | |||
String initialUIDL = getInitialUIDL(combinedRequest, uI); | |||
params.put("uidl", initialUIDL); | |||
} | |||
String initialUIDL = getInitialUIDL(combinedRequest, uI); | |||
params.put("uidl", initialUIDL); | |||
// NOTE! GateIn requires, for some weird reason, getOutputStream | |||
// to be used instead of getWriter() (it seems to interpret | |||
@@ -2452,10 +2436,6 @@ public abstract class AbstractCommunicationManager implements Serializable { | |||
// NOTE GateIn requires the buffers to be flushed to work | |||
outWriter.flush(); | |||
out.flush(); | |||
} catch (UIRequiresMoreInformationException e) { | |||
// Requiring more information at this point is not allowed | |||
// TODO handle in a better way | |||
throw new RuntimeException(e); | |||
} catch (JSONException e) { | |||
// TODO Auto-generated catch block | |||
e.printStackTrace(); |
@@ -21,6 +21,7 @@ import java.util.List; | |||
import org.jsoup.nodes.Node; | |||
import com.vaadin.Application; | |||
import com.vaadin.ui.UI; | |||
/** | |||
* A representation of a bootstrap fragment being generated. The bootstrap | |||
@@ -37,7 +38,7 @@ public class BootstrapFragmentResponse extends BootstrapResponse { | |||
* Crate a new bootstrap fragment response. | |||
* | |||
* @see BootstrapResponse#BootstrapResponse(BootstrapHandler, | |||
* WrappedRequest, Application, Integer) | |||
* WrappedRequest, Application, Class) | |||
* | |||
* @param handler | |||
* the bootstrap handler that is firing the event | |||
@@ -47,16 +48,16 @@ public class BootstrapFragmentResponse extends BootstrapResponse { | |||
* @param application | |||
* the application for which the bootstrap page should be | |||
* generated | |||
* @param uiId | |||
* the generated id of the UI that will be displayed on the page | |||
* @param uiClass | |||
* the class of the UI that will be displayed on the page | |||
* @param fragmentNodes | |||
* a mutable list containing the DOM nodes that will make up the | |||
* application HTML | |||
*/ | |||
public BootstrapFragmentResponse(BootstrapHandler handler, | |||
WrappedRequest request, Application application, Integer uiId, | |||
List<Node> fragmentNodes) { | |||
super(handler, request, application, uiId); | |||
WrappedRequest request, Application application, | |||
Class<? extends UI> uiClass, List<Node> fragmentNodes) { | |||
super(handler, request, application, uiClass); | |||
this.fragmentNodes = fragmentNodes; | |||
} | |||
@@ -37,12 +37,10 @@ import org.jsoup.nodes.Node; | |||
import org.jsoup.parser.Tag; | |||
import com.vaadin.Application; | |||
import com.vaadin.UIRequiresMoreInformationException; | |||
import com.vaadin.external.json.JSONException; | |||
import com.vaadin.external.json.JSONObject; | |||
import com.vaadin.shared.ApplicationConstants; | |||
import com.vaadin.shared.Version; | |||
import com.vaadin.shared.ui.ui.UIConstants; | |||
import com.vaadin.ui.UI; | |||
public abstract class BootstrapHandler implements RequestHandler { | |||
@@ -74,30 +72,20 @@ public abstract class BootstrapHandler implements RequestHandler { | |||
return bootstrapResponse.getApplication(); | |||
} | |||
public Integer getUIId() { | |||
return bootstrapResponse.getUIId(); | |||
} | |||
public UI getUI() { | |||
return bootstrapResponse.getUI(); | |||
public Class<? extends UI> getUIClass() { | |||
return bootstrapResponse.getUiClass(); | |||
} | |||
public String getWidgetsetName() { | |||
if (widgetsetName == null) { | |||
UI uI = getUI(); | |||
if (uI != null) { | |||
widgetsetName = getWidgetsetForUI(this); | |||
} | |||
widgetsetName = getWidgetsetForUI(this); | |||
} | |||
return widgetsetName; | |||
} | |||
public String getThemeName() { | |||
if (themeName == null) { | |||
UI uI = getUI(); | |||
if (uI != null) { | |||
themeName = findAndEscapeThemeName(this); | |||
} | |||
themeName = findAndEscapeThemeName(this); | |||
} | |||
return themeName; | |||
} | |||
@@ -120,23 +108,11 @@ public abstract class BootstrapHandler implements RequestHandler { | |||
WrappedRequest request, WrappedResponse response) | |||
throws IOException { | |||
// TODO Should all urls be handled here? | |||
Integer uiId = null; | |||
try { | |||
UI uI = application.getUIForRequest(request); | |||
if (uI == null) { | |||
writeError(response, new Throwable("No UI found")); | |||
return true; | |||
} | |||
Class<? extends UI> uiClass = application.getUIClass(request); | |||
uiId = Integer.valueOf(uI.getUIId()); | |||
} catch (UIRequiresMoreInformationException e) { | |||
// Just keep going without uiId | |||
} | |||
try { | |||
BootstrapContext context = createContext(request, response, | |||
application, uiId); | |||
application, uiClass); | |||
setupMainDiv(context); | |||
BootstrapFragmentResponse fragmentResponse = context | |||
@@ -166,8 +142,8 @@ public abstract class BootstrapHandler implements RequestHandler { | |||
Map<String, Object> headers = new LinkedHashMap<String, Object>(); | |||
Document document = Document.createShell(""); | |||
BootstrapPageResponse pageResponse = new BootstrapPageResponse( | |||
this, request, context.getApplication(), context.getUIId(), | |||
document, headers); | |||
this, request, context.getApplication(), | |||
context.getUIClass(), document, headers); | |||
List<Node> fragmentNodes = fragmentResponse.getFragmentNodes(); | |||
Element body = document.body(); | |||
for (Node node : fragmentNodes) { | |||
@@ -242,10 +218,11 @@ public abstract class BootstrapHandler implements RequestHandler { | |||
head.appendElement("meta").attr("http-equiv", "X-UA-Compatible") | |||
.attr("content", "chrome=1"); | |||
UI uI = context.getUI(); | |||
String title = ((uI == null || uI.getCaption() == null) ? "" : uI | |||
.getCaption()); | |||
head.appendElement("title").appendText(title); | |||
String title = context.getApplication().getPageTitleForUI( | |||
context.getRequest(), context.getUIClass()); | |||
if (title != null) { | |||
head.appendElement("title").appendText(title); | |||
} | |||
head.appendElement("style").attr("type", "text/css") | |||
.appendText("html, body {height:100%;margin:0;}"); | |||
@@ -267,11 +244,12 @@ public abstract class BootstrapHandler implements RequestHandler { | |||
body.addClass(ApplicationConstants.GENERATED_BODY_CLASSNAME); | |||
} | |||
public BootstrapContext createContext(WrappedRequest request, | |||
WrappedResponse response, Application application, Integer uiId) { | |||
private BootstrapContext createContext(WrappedRequest request, | |||
WrappedResponse response, Application application, | |||
Class<? extends UI> uiClass) { | |||
BootstrapContext context = new BootstrapContext(response, | |||
new BootstrapFragmentResponse(this, request, application, uiId, | |||
new ArrayList<Node>())); | |||
new BootstrapFragmentResponse(this, request, application, | |||
uiClass, new ArrayList<Node>())); | |||
return context; | |||
} | |||
@@ -290,10 +268,10 @@ public abstract class BootstrapHandler implements RequestHandler { | |||
protected abstract String getApplicationId(BootstrapContext context); | |||
public String getWidgetsetForUI(BootstrapContext context) { | |||
UI uI = context.getUI(); | |||
WrappedRequest request = context.getRequest(); | |||
String widgetset = uI.getApplication().getWidgetsetForUI(uI); | |||
String widgetset = context.getApplication().getWidgetsetForUI( | |||
context.getRequest(), context.getUIClass()); | |||
if (widgetset == null) { | |||
widgetset = request.getDeploymentConfiguration() | |||
.getConfiguredWidgetset(request); | |||
@@ -413,14 +391,9 @@ public abstract class BootstrapHandler implements RequestHandler { | |||
protected JSONObject getApplicationParameters(BootstrapContext context) | |||
throws JSONException, PaintException { | |||
Application application = context.getApplication(); | |||
Integer uiId = context.getUIId(); | |||
JSONObject appConfig = new JSONObject(); | |||
if (uiId != null) { | |||
appConfig.put(UIConstants.UI_ID_PARAMETER, uiId); | |||
} | |||
if (context.getThemeName() != null) { | |||
appConfig.put("themeUri", | |||
getThemeUri(context, context.getThemeName())); | |||
@@ -433,18 +406,18 @@ public abstract class BootstrapHandler implements RequestHandler { | |||
appConfig.put("widgetset", context.getWidgetsetName()); | |||
if (uiId == null || application.isUIInitPending(uiId.intValue())) { | |||
appConfig.put("initialPath", context.getRequest() | |||
.getRequestPathInfo()); | |||
Map<String, String[]> parameterMap = context.getRequest() | |||
.getParameterMap(); | |||
appConfig.put("initialParams", parameterMap); | |||
} else { | |||
if (application.isEagerInit(context.getRequest(), context.getUIClass())) { | |||
throw new RuntimeException( | |||
"Eager UI init is currently not supported"); | |||
// write the initial UIDL into the config | |||
appConfig.put("uidl", | |||
getInitialUIDL(context.getRequest(), context.getUI())); | |||
// appConfig.put("uidl", | |||
// getInitialUIDL(context.getRequest(), context.getUI())); | |||
} | |||
appConfig.put("initialPath", context.getRequest().getRequestPathInfo()); | |||
Map<String, String[]> parameterMap = context.getRequest() | |||
.getParameterMap(); | |||
appConfig.put("initialParams", parameterMap); | |||
return appConfig; | |||
} | |||
@@ -532,7 +505,8 @@ public abstract class BootstrapHandler implements RequestHandler { | |||
* @return | |||
*/ | |||
public String getThemeName(BootstrapContext context) { | |||
return context.getApplication().getThemeForUI(context.getUI()); | |||
return context.getApplication().getThemeForUI(context.getRequest(), | |||
context.getUIClass()); | |||
} | |||
/** | |||
@@ -561,21 +535,4 @@ public abstract class BootstrapHandler implements RequestHandler { | |||
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, | |||
e.getLocalizedMessage()); | |||
} | |||
/** | |||
* Gets the initial UIDL message to send to the client. | |||
* | |||
* @param request | |||
* the originating request | |||
* @param ui | |||
* the UI for which the UIDL should be generated | |||
* @return a string with the initial UIDL message | |||
* @throws PaintException | |||
* if an exception occurs while painting the components | |||
* @throws JSONException | |||
* if an exception occurs while formatting the output | |||
*/ | |||
protected abstract String getInitialUIDL(WrappedRequest request, UI ui) | |||
throws PaintException, JSONException; | |||
} |
@@ -21,6 +21,7 @@ import java.util.Map; | |||
import org.jsoup.nodes.Document; | |||
import com.vaadin.Application; | |||
import com.vaadin.ui.UI; | |||
/** | |||
* A representation of a bootstrap page being generated. The bootstrap page | |||
@@ -39,7 +40,7 @@ public class BootstrapPageResponse extends BootstrapResponse { | |||
* Crate a new bootstrap page response. | |||
* | |||
* @see BootstrapResponse#BootstrapResponse(BootstrapHandler, | |||
* WrappedRequest, Application, Integer) | |||
* WrappedRequest, Application, Class) | |||
* | |||
* @param handler | |||
* the bootstrap handler that is firing the event | |||
@@ -49,17 +50,18 @@ public class BootstrapPageResponse extends BootstrapResponse { | |||
* @param application | |||
* the application for which the bootstrap page should be | |||
* generated | |||
* @param uiId | |||
* the generated id of the UI that will be displayed on the page | |||
* @param uiClass | |||
* the class of the UI that will be displayed on the page | |||
* @param document | |||
* the DOM document making up the HTML page | |||
* @param headers | |||
* a map into which header data can be added | |||
*/ | |||
public BootstrapPageResponse(BootstrapHandler handler, | |||
WrappedRequest request, Application application, Integer uiId, | |||
Document document, Map<String, Object> headers) { | |||
super(handler, request, application, uiId); | |||
WrappedRequest request, Application application, | |||
Class<? extends UI> uiClass, Document document, | |||
Map<String, Object> headers) { | |||
super(handler, request, application, uiClass); | |||
this.headers = headers; | |||
this.document = document; | |||
} |
@@ -19,7 +19,6 @@ package com.vaadin.server; | |||
import java.util.EventObject; | |||
import com.vaadin.Application; | |||
import com.vaadin.UIRequiresMoreInformationException; | |||
import com.vaadin.ui.UI; | |||
/** | |||
@@ -32,7 +31,7 @@ import com.vaadin.ui.UI; | |||
public abstract class BootstrapResponse extends EventObject { | |||
private final WrappedRequest request; | |||
private final Application application; | |||
private final Integer uiId; | |||
private final Class<? extends UI> uiClass; | |||
/** | |||
* Creates a new bootstrap event. | |||
@@ -45,15 +44,15 @@ public abstract class BootstrapResponse extends EventObject { | |||
* @param application | |||
* the application for which the bootstrap page should be | |||
* generated | |||
* @param uiId | |||
* the generated id of the UI that will be displayed on the page | |||
* @param uiClass | |||
* the class of the UI that will be displayed on the page | |||
*/ | |||
public BootstrapResponse(BootstrapHandler handler, WrappedRequest request, | |||
Application application, Integer uiId) { | |||
Application application, Class<? extends UI> uiClass) { | |||
super(handler); | |||
this.request = request; | |||
this.application = application; | |||
this.uiId = uiId; | |||
this.uiClass = uiClass; | |||
} | |||
/** | |||
@@ -89,32 +88,13 @@ public abstract class BootstrapResponse extends EventObject { | |||
} | |||
/** | |||
* Gets the UI id that has been generated for this response. Please note | |||
* that if {@link Application#isUiPreserved()} is enabled, a previously | |||
* created UI with a different id might eventually end up being used. | |||
* Gets the class of the UI that will be displayed on the generated | |||
* bootstrap page. | |||
* | |||
* @return the UI id | |||
* @return the class of the UI | |||
*/ | |||
public Integer getUIId() { | |||
return uiId; | |||
public Class<? extends UI> getUiClass() { | |||
return uiClass; | |||
} | |||
/** | |||
* Gets the UI for which this page is being rendered, if available. Some | |||
* features of the framework will postpone the UI selection until after the | |||
* bootstrap page has been rendered and required information from the | |||
* browser has been sent back. This method will return <code>null</code> if | |||
* no UI instance is yet available. | |||
* | |||
* @see Application#isUiPreserved() | |||
* @see Application#getUI(WrappedRequest) | |||
* @see UIRequiresMoreInformationException | |||
* | |||
* @return The UI that will be displayed in the page being generated, or | |||
* <code>null</code> if all required information is not yet | |||
* available. | |||
*/ | |||
public UI getUI() { | |||
return UI.getCurrent(); | |||
} | |||
} |
@@ -22,7 +22,6 @@ import java.net.URL; | |||
import javax.servlet.ServletContext; | |||
import com.vaadin.Application; | |||
import com.vaadin.external.json.JSONException; | |||
import com.vaadin.ui.UI; | |||
/** | |||
@@ -107,12 +106,6 @@ public class CommunicationManager extends AbstractCommunicationManager { | |||
} | |||
return themeName; | |||
} | |||
@Override | |||
protected String getInitialUIDL(WrappedRequest request, UI uI) | |||
throws PaintException, JSONException { | |||
return CommunicationManager.this.getInitialUIDL(request, uI); | |||
} | |||
}; | |||
} | |||
@@ -17,14 +17,13 @@ | |||
package com.vaadin.server; | |||
import com.vaadin.Application; | |||
import com.vaadin.UIRequiresMoreInformationException; | |||
import com.vaadin.ui.UI; | |||
public class DefaultUIProvider extends AbstractUIProvider { | |||
@Override | |||
public Class<? extends UI> getUIClass(Application application, | |||
WrappedRequest request) throws UIRequiresMoreInformationException { | |||
WrappedRequest request) { | |||
Object uiClassNameObj = application | |||
.getProperty(Application.UI_PARAMETER); | |||
@@ -137,13 +137,6 @@ public class PortletCommunicationManager extends AbstractCommunicationManager { | |||
null); | |||
} | |||
@Override | |||
protected String getInitialUIDL(WrappedRequest request, UI uI) | |||
throws PaintException, JSONException { | |||
return PortletCommunicationManager.this.getInitialUIDL(request, | |||
uI); | |||
} | |||
@Override | |||
protected JSONObject getApplicationParameters( | |||
BootstrapContext context) throws JSONException, |
@@ -17,12 +17,11 @@ | |||
package com.vaadin.server; | |||
import com.vaadin.Application; | |||
import com.vaadin.UIRequiresMoreInformationException; | |||
import com.vaadin.ui.UI; | |||
public interface UIProvider { | |||
public Class<? extends UI> getUIClass(Application application, | |||
WrappedRequest request) throws UIRequiresMoreInformationException; | |||
WrappedRequest request); | |||
public UI instantiateUI(Application application, Class<? extends UI> type, | |||
WrappedRequest request); |
@@ -26,8 +26,6 @@ import javax.portlet.PortletRequest; | |||
import javax.servlet.ServletRequest; | |||
import javax.servlet.http.HttpServletRequest; | |||
import com.vaadin.Application; | |||
import com.vaadin.UIRequiresMoreInformationException; | |||
import com.vaadin.annotations.EagerInit; | |||
import com.vaadin.ui.UI; | |||
@@ -218,11 +216,8 @@ public interface WrappedRequest extends Serializable { | |||
* for instance using javascript in the browser. | |||
* | |||
* This information is only guaranteed to be available in some special | |||
* cases, for instance when | |||
* {@link Application#getUIForRequest(WrappedRequest)} is called again after | |||
* throwing {@link UIRequiresMoreInformationException} or in | |||
* {@link UI#init(WrappedRequest)} for a UI class not annotated with | |||
* {@link EagerInit} | |||
* cases, for instance in {@link UI#init(WrappedRequest)} for a UI class not | |||
* annotated with {@link EagerInit} | |||
* | |||
* @return the browser details, or <code>null</code> if details are not | |||
* available |
@@ -85,7 +85,7 @@ import com.vaadin.tools.ReflectTools; | |||
* </p> | |||
* | |||
* @see #init(WrappedRequest) | |||
* @see Application#getUI(WrappedRequest) | |||
* @see Application#createUI(WrappedRequest) | |||
* | |||
* @since 7.0 | |||
*/ | |||
@@ -98,7 +98,6 @@ public abstract class UI extends AbstractComponentContainer implements | |||
* window in Vaadin 6 with {@link com.vaadin.Application.LegacyApplication} | |||
*/ | |||
@Deprecated | |||
@EagerInit | |||
public static class LegacyWindow extends UI { | |||
private String name; | |||
@@ -709,28 +708,6 @@ public abstract class UI extends AbstractComponentContainer implements | |||
} | |||
} | |||
/** | |||
* Sets the id of this UI within its application. The UI id is used to route | |||
* requests to the right UI. | |||
* <p> | |||
* This method is mainly intended for internal use by the framework. | |||
* </p> | |||
* | |||
* @param uiId | |||
* the id of this UI | |||
* | |||
* @throws IllegalStateException | |||
* if the UI id has already been set | |||
* | |||
* @see #getUIId() | |||
*/ | |||
public void setUIId(int uiId) { | |||
if (this.uiId != -1) { | |||
throw new IllegalStateException("UI id has already been defined"); | |||
} | |||
this.uiId = uiId; | |||
} | |||
/** | |||
* Gets the id of the UI, used to identify this UI within its application | |||
* when processing requests. The UI id should be present in every request to | |||
@@ -748,8 +725,8 @@ public abstract class UI extends AbstractComponentContainer implements | |||
* Adds a window as a subwindow inside this UI. To open a new browser window | |||
* or tab, you should instead use {@link open(Resource)} with an url | |||
* pointing to this application and ensure | |||
* {@link Application#getUI(WrappedRequest)} returns an appropriate UI for | |||
* the request. | |||
* {@link Application#createUI(WrappedRequest)} returns an appropriate UI | |||
* for the request. | |||
* | |||
* @param window | |||
* @throws IllegalArgumentException | |||
@@ -831,6 +808,8 @@ public abstract class UI extends AbstractComponentContainer implements | |||
private boolean resizeLazy = false; | |||
private String theme; | |||
/** | |||
* This method is used by Component.Focusable objects to request focus to | |||
* themselves. Focus renders must be handled at window level (instead of | |||
@@ -959,8 +938,16 @@ public abstract class UI extends AbstractComponentContainer implements | |||
* | |||
* @param request | |||
* the initialization request | |||
* @param uiId | |||
* the id of the new ui | |||
*/ | |||
public void doInit(WrappedRequest request) { | |||
public void doInit(WrappedRequest request, int uiId) { | |||
if (this.uiId != -1) { | |||
throw new IllegalStateException("UI id has already been defined"); | |||
} | |||
this.uiId = uiId; | |||
theme = getApplication().getThemeForUI(request, getClass()); | |||
getPage().init(request); | |||
// Call the init overridden by the application developer | |||
@@ -1352,4 +1339,13 @@ public abstract class UI extends AbstractComponentContainer implements | |||
public void setLastUidlRequestTime(long lastUidlRequest) { | |||
this.lastUidlRequest = lastUidlRequest; | |||
} | |||
/** | |||
* Gets the theme that was used when the UI was initialized. | |||
* | |||
* @return the theme name | |||
*/ | |||
public String getTheme() { | |||
return theme; | |||
} | |||
} |
@@ -10,7 +10,6 @@ import org.easymock.EasyMock; | |||
import com.vaadin.Application; | |||
import com.vaadin.Application.ApplicationStartEvent; | |||
import com.vaadin.UIRequiresMoreInformationException; | |||
import com.vaadin.server.DefaultUIProvider; | |||
import com.vaadin.server.DeploymentConfiguration; | |||
import com.vaadin.server.WrappedRequest; | |||
@@ -56,8 +55,11 @@ public class CustomUIClassLoader extends TestCase { | |||
application.start(new ApplicationStartEvent(null, | |||
createConfigurationMock(), null)); | |||
UI uI = application.getUIForRequest(createRequestMock(null)); | |||
assertTrue(uI instanceof MyUI); | |||
DefaultUIProvider uiProvider = new DefaultUIProvider(); | |||
Class<? extends UI> uiClass = uiProvider.getUIClass(application, | |||
createRequestMock(null)); | |||
assertEquals(MyUI.class, uiClass); | |||
} | |||
private static DeploymentConfiguration createConfigurationMock() { | |||
@@ -101,9 +103,11 @@ public class CustomUIClassLoader extends TestCase { | |||
application.start(new ApplicationStartEvent(null, | |||
createConfigurationMock(), null)); | |||
UI uI = application | |||
.getUIForRequest(createRequestMock(loggingClassLoader)); | |||
assertTrue(uI instanceof MyUI); | |||
DefaultUIProvider uiProvider = new DefaultUIProvider(); | |||
Class<? extends UI> uiClass = uiProvider.getUIClass(application, | |||
createRequestMock(loggingClassLoader)); | |||
assertEquals(MyUI.class, uiClass); | |||
assertEquals(1, loggingClassLoader.requestedClasses.size()); | |||
assertEquals(MyUI.class.getName(), | |||
loggingClassLoader.requestedClasses.get(0)); | |||
@@ -112,10 +116,6 @@ public class CustomUIClassLoader extends TestCase { | |||
private Application createStubApplication() { | |||
return new Application() { | |||
{ | |||
addUIProvider(new DefaultUIProvider()); | |||
} | |||
@Override | |||
public String getProperty(String name) { | |||
if (name.equals(UI_PARAMETER)) { | |||
@@ -124,14 +124,6 @@ public class CustomUIClassLoader extends TestCase { | |||
return super.getProperty(name); | |||
} | |||
} | |||
@Override | |||
public UI getUIForRequest(WrappedRequest request) | |||
throws UIRequiresMoreInformationException { | |||
// Always create a new root for testing (can't directly use | |||
// getRoot as it's protected) | |||
return getUI(request); | |||
} | |||
}; | |||
} | |||
} |
@@ -30,7 +30,6 @@ import javax.servlet.http.HttpServletRequest; | |||
import javax.servlet.http.HttpServletResponse; | |||
import com.vaadin.Application; | |||
import com.vaadin.UIRequiresMoreInformationException; | |||
import com.vaadin.server.AbstractApplicationServlet; | |||
import com.vaadin.server.AbstractUIProvider; | |||
import com.vaadin.server.WrappedHttpServletRequest; | |||
@@ -116,8 +115,7 @@ public class ApplicationRunnerServlet extends AbstractApplicationServlet { | |||
@Override | |||
public Class<? extends UI> getUIClass( | |||
Application application, WrappedRequest request) | |||
throws UIRequiresMoreInformationException { | |||
Application application, WrappedRequest request) { | |||
return (Class<? extends UI>) classToRun; | |||
} | |||
}); |
@@ -1,7 +1,7 @@ | |||
package com.vaadin.tests.application; | |||
import com.vaadin.Application; | |||
import com.vaadin.UIRequiresMoreInformationException; | |||
import com.vaadin.annotations.PreserveOnRefresh; | |||
import com.vaadin.server.AbstractUIProvider; | |||
import com.vaadin.server.WrappedRequest; | |||
import com.vaadin.tests.components.AbstractTestApplication; | |||
@@ -9,6 +9,7 @@ import com.vaadin.ui.Label; | |||
import com.vaadin.ui.UI; | |||
public class RefreshStatePreserve extends AbstractTestApplication { | |||
@PreserveOnRefresh | |||
public static class RefreshStateUI extends UI { | |||
@Override | |||
public void init(WrappedRequest request) { | |||
@@ -22,12 +23,10 @@ public class RefreshStatePreserve extends AbstractTestApplication { | |||
@Override | |||
public void init() { | |||
super.init(); | |||
setUiPreserved(true); | |||
addUIProvider(new AbstractUIProvider() { | |||
@Override | |||
public Class<? extends UI> getUIClass(Application application, | |||
WrappedRequest request) | |||
throws UIRequiresMoreInformationException { | |||
WrappedRequest request) { | |||
return RefreshStateUI.class; | |||
} | |||
}); |
@@ -1,9 +1,9 @@ | |||
package com.vaadin.tests.application; | |||
import com.vaadin.Application; | |||
import com.vaadin.UIRequiresMoreInformationException; | |||
import com.vaadin.server.DownloadStream; | |||
import com.vaadin.server.PaintException; | |||
import com.vaadin.server.UIProvider; | |||
import com.vaadin.server.WrappedRequest; | |||
import com.vaadin.tests.components.AbstractTestApplication; | |||
import com.vaadin.tests.integration.FlagSeResource; | |||
@@ -73,12 +73,19 @@ public class ThreadLocalInstances extends AbstractTestApplication { | |||
@Override | |||
public void init() { | |||
reportCurrentStatus("app init"); | |||
} | |||
addUIProvider(new UIProvider() { | |||
@Override | |||
public UI instantiateUI(Application application, | |||
Class<? extends UI> type, WrappedRequest request) { | |||
return mainWindow; | |||
} | |||
@Override | |||
protected UI getUI(WrappedRequest request) | |||
throws UIRequiresMoreInformationException { | |||
return mainWindow; | |||
@Override | |||
public Class<? extends UI> getUIClass(Application application, | |||
WrappedRequest request) { | |||
return mainWindow.getClass(); | |||
} | |||
}); | |||
} | |||
@Override |
@@ -1,6 +1,7 @@ | |||
package com.vaadin.tests.components.loginform; | |||
import com.vaadin.Application; | |||
import com.vaadin.server.AbstractUIProvider; | |||
import com.vaadin.server.WrappedRequest; | |||
import com.vaadin.ui.LoginForm; | |||
import com.vaadin.ui.LoginForm.LoginEvent; | |||
@@ -12,11 +13,17 @@ import com.vaadin.ui.UI.LegacyWindow; | |||
public class LoginFormWithMultipleWindows extends Application { | |||
@Override | |||
protected UI getUI(WrappedRequest request) { | |||
return new LoginFormWindow(); | |||
public void init() { | |||
addUIProvider(new AbstractUIProvider() { | |||
@Override | |||
public Class<? extends UI> getUIClass(Application application, | |||
WrappedRequest request) { | |||
return LoginFormWindow.class; | |||
} | |||
}); | |||
} | |||
public class LoginFormWindow extends LegacyWindow { | |||
public static class LoginFormWindow extends LegacyWindow { | |||
public LoginFormWindow() { | |||
super(); | |||
@@ -1,10 +1,10 @@ | |||
package com.vaadin.tests.components.ui; | |||
import com.vaadin.UIRequiresMoreInformationException; | |||
import com.vaadin.Application; | |||
import com.vaadin.annotations.EagerInit; | |||
import com.vaadin.server.ExternalResource; | |||
import com.vaadin.server.UIProvider; | |||
import com.vaadin.server.WrappedRequest; | |||
import com.vaadin.server.WrappedRequest.BrowserDetails; | |||
import com.vaadin.shared.ui.label.ContentMode; | |||
import com.vaadin.tests.components.AbstractTestApplication; | |||
import com.vaadin.ui.Label; | |||
@@ -22,23 +22,33 @@ public class LazyInitUIs extends AbstractTestApplication { | |||
} | |||
@Override | |||
public UI getUI(WrappedRequest request) | |||
throws UIRequiresMoreInformationException { | |||
public void init() { | |||
addUIProvider(new UIProvider() { | |||
@Override | |||
public UI instantiateUI(Application application, | |||
Class<? extends UI> type, WrappedRequest request) { | |||
return getUI(request); | |||
} | |||
@Override | |||
public Class<? extends UI> getUIClass(Application application, | |||
WrappedRequest request) { | |||
return getUI(request).getClass(); | |||
} | |||
}); | |||
} | |||
private UI getUI(WrappedRequest request) { | |||
if (request.getParameter("lazyCreate") != null) { | |||
// UI created on second request | |||
BrowserDetails browserDetails = request.getBrowserDetails(); | |||
if (browserDetails == null | |||
|| browserDetails.getUriFragment() == null) { | |||
throw new UIRequiresMoreInformationException(); | |||
} else { | |||
UI uI = new UI() { | |||
@Override | |||
protected void init(WrappedRequest request) { | |||
addComponent(getRequestInfo("LazyCreateUI", request)); | |||
} | |||
}; | |||
return uI; | |||
} | |||
UI uI = new UI() { | |||
@Override | |||
protected void init(WrappedRequest request) { | |||
addComponent(getRequestInfo("LazyCreateUI", request)); | |||
} | |||
}; | |||
return uI; | |||
} else if (request.getParameter("eagerInit") != null) { | |||
// UI inited on first request | |||
return new EagerInitUI(); |
@@ -1,7 +1,6 @@ | |||
package com.vaadin.tests.components.ui; | |||
import com.vaadin.Application; | |||
import com.vaadin.UIRequiresMoreInformationException; | |||
import com.vaadin.server.AbstractUIProvider; | |||
import com.vaadin.server.WrappedRequest; | |||
import com.vaadin.tests.components.AbstractTestApplication; | |||
@@ -26,8 +25,7 @@ public class UIsInMultipleTabs extends AbstractTestApplication { | |||
addUIProvider(new AbstractUIProvider() { | |||
@Override | |||
public Class<? extends UI> getUIClass(Application application, | |||
WrappedRequest request) | |||
throws UIRequiresMoreInformationException { | |||
WrappedRequest request) { | |||
return TabUI.class; | |||
} | |||
}); |
@@ -16,9 +16,10 @@ | |||
package com.vaadin.tests.minitutorials.v7a1; | |||
import com.vaadin.annotations.PreserveOnRefresh; | |||
import com.vaadin.server.WrappedRequest; | |||
import com.vaadin.ui.UI; | |||
import com.vaadin.ui.TextField; | |||
import com.vaadin.ui.UI; | |||
/** | |||
* Mini tutorial code for | |||
@@ -28,6 +29,7 @@ import com.vaadin.ui.TextField; | |||
* @author Vaadin Ltd | |||
* @since 7.0.0 | |||
*/ | |||
@PreserveOnRefresh | |||
public class CreatingPreserveState extends UI { | |||
private static int windowCounter = 0; | |||
@@ -36,7 +38,6 @@ public class CreatingPreserveState extends UI { | |||
TextField tf = new TextField("Window #" + (++windowCounter)); | |||
tf.setImmediate(true); | |||
getContent().addComponent(tf); | |||
getApplication().setUiPreserved(true); | |||
} | |||
} |
@@ -17,10 +17,9 @@ | |||
package com.vaadin.tests.minitutorials.v7a1; | |||
import com.vaadin.Application; | |||
import com.vaadin.UIRequiresMoreInformationException; | |||
import com.vaadin.server.UIProvider; | |||
import com.vaadin.server.WebBrowser; | |||
import com.vaadin.server.WrappedRequest; | |||
import com.vaadin.server.WrappedRequest.BrowserDetails; | |||
import com.vaadin.ui.Label; | |||
import com.vaadin.ui.UI; | |||
@@ -35,21 +34,32 @@ import com.vaadin.ui.UI; | |||
public class DifferentFeaturesForDifferentClients extends Application { | |||
@Override | |||
protected UI getUI(WrappedRequest request) | |||
throws UIRequiresMoreInformationException { | |||
BrowserDetails browserDetails = request.getBrowserDetails(); | |||
// This is a limitation of 7.0.0.alpha1 that there is no better way to | |||
// check if WebBrowser has been fully initialized | |||
if (browserDetails.getUriFragment() == null) { | |||
throw new UIRequiresMoreInformationException(); | |||
} | |||
public void init() { | |||
super.init(); | |||
addUIProvider(new UIProvider() { | |||
@Override | |||
public Class<? extends UI> getUIClass(Application application, | |||
WrappedRequest request) { | |||
// could also use browser version etc. | |||
if (request.getHeader("user-agent").contains("mobile")) { | |||
return TouchRoot.class; | |||
} else { | |||
return DefaultRoot.class; | |||
} | |||
} | |||
// could also use screen size, browser version etc. | |||
if (browserDetails.getWebBrowser().isTouchDevice()) { | |||
return new TouchRoot(); | |||
} else { | |||
return new DefaultRoot(); | |||
} | |||
// Must override as default implementation isn't allowed to | |||
// instantiate our non-public classes | |||
@Override | |||
public UI instantiateUI(Application application, | |||
Class<? extends UI> type, WrappedRequest request) { | |||
try { | |||
return type.newInstance(); | |||
} catch (Exception e) { | |||
throw new RuntimeException(e); | |||
} | |||
} | |||
}); | |||
} | |||
} | |||
@@ -42,9 +42,8 @@ public class TestAddonContextListener implements AddonContextListener { | |||
} | |||
private boolean shouldModify(BootstrapResponse response) { | |||
UI uI = response.getUI(); | |||
boolean shouldModify = uI != null | |||
&& uI.getClass() == BootstrapModifyUI.class; | |||
Class<? extends UI> uiClass = response.getUiClass(); | |||
boolean shouldModify = uiClass == BootstrapModifyUI.class; | |||
return shouldModify; | |||
} | |||