123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330 |
- /*
- * Copyright 2000-2014 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.server;
-
- import java.io.InputStream;
- import java.io.Serializable;
- import java.lang.annotation.Annotation;
- import java.lang.annotation.Inherited;
- import java.util.logging.Level;
- import java.util.logging.Logger;
-
- import com.vaadin.annotations.PreserveOnRefresh;
- import com.vaadin.annotations.Push;
- import com.vaadin.annotations.Theme;
- import com.vaadin.annotations.Title;
- import com.vaadin.annotations.Widgetset;
- import com.vaadin.shared.communication.PushMode;
- import com.vaadin.shared.ui.ui.Transport;
- import com.vaadin.ui.UI;
-
- public abstract class UIProvider implements Serializable {
-
- /* Default widgetset name to look for */
- private static final String APP_WIDGETSET_NAME = "AppWidgetset";
-
- public abstract Class<? extends UI> getUIClass(UIClassSelectionEvent event);
-
- public UI createInstance(UICreateEvent event) {
- try {
- return event.getUIClass().newInstance();
- } catch (InstantiationException e) {
- throw new RuntimeException("Could not instantiate UI class", e);
- } catch (IllegalAccessException e) {
- throw new RuntimeException("Could not access UI class", e);
- }
- }
-
- /**
- * Helper to get an annotation for a class. If the annotation is not present
- * on the target class, its super classes and directly implemented
- * interfaces are also searched for the annotation. Interfaces implemented
- * by superclasses are not taken into account.
- * <p>
- * Note that searching implemented interfaces for {@code @Inherited}
- * annotations and searching for superclasses for non-inherited annotations
- * do not follow the standard semantics and are supported for backwards
- * compatibility. Future versions of the framework might only support the
- * standard semantics of {@code @Inherited}.
- *
- * @param clazz
- * the 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<?> clazz,
- Class<T> annotationType) {
- // Don't discover hierarchy if annotation is inherited
- if (annotationType.getAnnotation(Inherited.class) != null) {
- T annotation = clazz.getAnnotation(annotationType);
- if (annotation != null) {
- return annotation;
- }
- } else {
- // Find from the class hierarchy
- Class<?> currentType = clazz;
- while (currentType != Object.class) {
- T annotation = currentType.getAnnotation(annotationType);
- if (annotation != null) {
- return annotation;
- } else {
- currentType = currentType.getSuperclass();
- }
- }
- }
-
- // Find from a directly implemented interface
- for (Class<?> iface : clazz.getInterfaces()) {
- T annotation = iface.getAnnotation(annotationType);
- if (annotation != null) {
- return annotation;
- }
- }
-
- return null;
- }
-
- /**
- * Finds the theme to use for a specific UI. If no specific theme is
- * required, <code>null</code> is returned.
- * <p>
- * The default implementation checks for a @{@link Theme} annotation on the
- * UI class.
- *
- * @param event
- * the UI create event with information about the UI and the
- * current request.
- * @return the name of the theme, or <code>null</code> if the default theme
- * should be used
- *
- */
- public String getTheme(UICreateEvent event) {
- Theme uiTheme = getAnnotationFor(event.getUIClass(), 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>
- * This method uses the Widgetset definition priority order from
- * {@link #getWidgetsetInfo(UICreateEvent)}.
- * <p>
- * <strong>Note:</strong> This method exists only for backwards
- * compatibility and overriding it won't have the effect it used to.
- *
- * @param event
- * the UI create event with information about the UI and the
- * current request.
- * @return the name of the widgetset, or <code>null</code> if the default
- * widgetset should be used
- * @deprecated This method has been replaced by
- * {@link #getWidgetsetInfo(UICreateEvent)} in 7.7
- */
- @Deprecated
- public String getWidgetset(UICreateEvent event) {
- WidgetsetInfo widgetsetInfo = getWidgetsetInfo(event);
- return widgetsetInfo != null ? widgetsetInfo.getWidgetsetName() : 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 following order of priority for
- * finding the widgetset information:
- * <ul>
- * <li>@{@link Widgetset} annotation if it is defined for the UI class</li>
- * <li>The class AppWidgetset if one exists in the default package</li>
- * <li>A widgetset called AppWidgetset if there is an AppWidgetset.gwt.xml
- * file in the default package</li>
- * <li>null to use the default widgetset otherwise</li>
- * </ul>
- *
- * @since 7.7
- *
- * @param event
- * the UI create event with information about the UI and the
- * current request.
- * @return the widgetset info, or <code>null</code> if the default widgetset
- * should be used
- */
- public WidgetsetInfo getWidgetsetInfo(UICreateEvent event) {
- Widgetset uiWidgetset = getAnnotationFor(event.getUIClass(),
- Widgetset.class);
-
- // First case: We have an @Widgetset annotation, use that
- if (uiWidgetset != null) {
- return new WidgetsetInfoImpl(uiWidgetset.value());
- }
-
- // Second case: We might have an init parameter, use that
- String initParameterWidgetSet = event.getService()
- .getDeploymentConfiguration().getWidgetset(null);
- if (initParameterWidgetSet != null) {
- return new WidgetsetInfoImpl(initParameterWidgetSet);
- }
-
- // Find the class AppWidgetset in the default package if one exists
- WidgetsetInfo info = getWidgetsetClassInfo();
-
- // Third case: we have a generated class called APP_WIDGETSET_NAME
- if (info != null) {
- return info;
- }
-
- // Fourth case: we have an AppWidgetset.gwt.xml file
- else {
- InputStream resource = event.getUIClass()
- .getResourceAsStream("/" + APP_WIDGETSET_NAME + ".gwt.xml");
- if (resource != null) {
- return new WidgetsetInfoImpl(false, null, APP_WIDGETSET_NAME);
- }
- }
-
- // fourth case: we are using the default widgetset
- return null;
- }
-
- private Class<WidgetsetInfo> findWidgetsetClass() {
- try {
- // We cannot naively use Class.forname without getting the correct
- // classloader
- // FIXME This might still fail with osgi
- ClassLoader tccl = VaadinService.getCurrent().getClassLoader();
- Class<?> c = Class.forName(APP_WIDGETSET_NAME, true, tccl);
-
- // if not implementing the interface, possibly a @WebListener class
- // from an earlier version - ignore it
- if (WidgetsetInfo.class.isAssignableFrom(c)) {
- return (Class<WidgetsetInfo>) c;
- }
- } catch (ClassNotFoundException e) {
- // ClassNotFound is a normal case
- }
- return null;
- }
-
- private WidgetsetInfo getWidgetsetClassInfo() {
- Class<WidgetsetInfo> cls = findWidgetsetClass();
- if (cls != null) {
- try {
- return cls.newInstance();
- } catch (InstantiationException e) {
- getLogger().log(Level.INFO,
- "Unexpected trying to instantiate class "
- + cls.getName(),
- e);
- } catch (IllegalAccessException e) {
- getLogger().log(Level.INFO,
- "Unexpected trying to access class " + cls.getName(),
- e);
- }
- }
- return null;
- }
-
- /**
- * 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.
- * <p>
- * Whenever a preserved UI is reused, its
- * {@link UI#refresh(com.vaadin.server.VaadinRequest) refresh} method is
- * invoked by the framework first.
- *
- *
- * @param event
- * the UI create event with information about the UI and the
- * current request.
- *
- * @return <code>true</code>if the same UI instance should be reused e.g.
- * when the browser window is refreshed.
- */
- public boolean isPreservedOnRefresh(UICreateEvent event) {
- PreserveOnRefresh preserveOnRefresh = getAnnotationFor(
- event.getUIClass(), PreserveOnRefresh.class);
- return preserveOnRefresh != null;
- }
-
- public String getPageTitle(UICreateEvent event) {
- Title titleAnnotation = getAnnotationFor(event.getUIClass(),
- Title.class);
- if (titleAnnotation == null) {
- return null;
- } else {
- return titleAnnotation.value();
- }
- }
-
- /**
- * Finds the {@link PushMode} to use for a specific UI. If no specific push
- * mode is required, <code>null</code> is returned.
- * <p>
- * The default implementation uses the @{@link Push} annotation if it's
- * defined for the UI class.
- *
- * @param event
- * the UI create event with information about the UI and the
- * current request.
- * @return the push mode to use, or <code>null</code> if the default push
- * mode should be used
- *
- */
- public PushMode getPushMode(UICreateEvent event) {
- Push push = getAnnotationFor(event.getUIClass(), Push.class);
- if (push == null) {
- return null;
- } else {
- return push.value();
- }
- }
-
- /**
- * Finds the {@link Transport} to use for a specific UI. If no transport is
- * defined, <code>null</code> is returned.
- * <p>
- * The default implementation uses the @{@link Push} annotation if it's
- * defined for the UI class.
- *
- * @param event
- * the UI create event with information about the UI and the
- * current request.
- * @return the transport type to use, or <code>null</code> if the default
- * transport type should be used
- */
- public Transport getPushTransport(UICreateEvent event) {
- Push push = getAnnotationFor(event.getUIClass(), Push.class);
- if (push == null) {
- return null;
- } else {
- return push.transport();
- }
- }
-
- private static final Logger getLogger() {
- return Logger.getLogger(UIProvider.class.getName());
- }
-
- }
|