aboutsummaryrefslogtreecommitdiffstats
path: root/server/src/main/java/com/vaadin/ui/Dependency.java
blob: 6557590c0899b5f76dbd776a4a398daae44cd67a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
/*
 * Copyright 2000-2016 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.ui;

import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.List;

import com.vaadin.annotations.HtmlImport;
import com.vaadin.annotations.JavaScript;
import com.vaadin.annotations.StyleSheet;
import com.vaadin.server.ClientConnector;
import com.vaadin.server.DependencyFilter;
import com.vaadin.server.DependencyFilter.FilterContext;
import com.vaadin.server.LegacyCommunicationManager;
import com.vaadin.server.VaadinService;

/**
 * Represents a stylesheet or JavaScript to include on the page.
 *
 * @author Vaadin Ltd
 * @since 8.0
 */
public class Dependency implements Serializable {
    /**
     * The type of dependency.
     */
    public enum Type {
        STYLESHEET(StyleSheet.class), //
        JAVASCRIPT(JavaScript.class), //
        HTMLIMPORT(HtmlImport.class);

        private Class<? extends Annotation> annotationType;

        private Type(Class<? extends Annotation> annotationType) {
            this.annotationType = annotationType;
        }
    }

    private final Type type;
    private final String url;

    /**
     * Creates a new dependency of the given type, to be loaded from the given
     * URL.
     * <p>
     * The URL is passed through the translation mechanism before loading, so
     * custom protocols such as "vaadin://" can be used.
     *
     * @param type
     *            the type of dependency, not <code>null</code>
     * @param url
     *            the URL to load the dependency from, not <code>null</code>
     */
    public Dependency(Type type, String url) {
        if (url == null) {
            throw new IllegalArgumentException("url cannot be null");
        }
        assert type != null;
        this.type = type;
        this.url = url;
    }

    /**
     * Gets the untranslated URL for the dependency.
     *
     * @return the URL for the dependency
     */
    public String getUrl() {
        return url;
    }

    /**
     * Gets the type of the dependency.
     *
     * @return the type of the dependency
     */
    public Type getType() {
        return type;
    }

    /**
     * Finds all the URLs defined for the given class using annotations for the
     * given type, registers the URLs to the communication manager and adds the
     * registered dependencies to the given list.
     *
     * @param type
     *            the type of dependencies to look for
     * @param cls
     *            the class to scan
     * @param manager
     *            a reference to the communication manager which tracks
     *            dependencies
     * @param dependencies
     *            the list to add registered dependencies to
     *
     * @return a stream of resource URLs in the order defined by the annotations
     */
    @SuppressWarnings("deprecation")
    private static void findAndRegisterResources(Type type,
            Class<? extends ClientConnector> cls,
            LegacyCommunicationManager manager, List<Dependency> dependencies) {
        Annotation[] annotations = cls
                .getAnnotationsByType(type.annotationType);
        if (annotations != null) {
            for (Annotation annotation : annotations) {
                String[] resources;
                if (annotation instanceof StyleSheet) {
                    resources = ((StyleSheet) annotation).value();
                } else if (annotation instanceof JavaScript) {
                    resources = ((JavaScript) annotation).value();
                } else if (annotation instanceof HtmlImport) {
                    resources = ((HtmlImport) annotation).value();
                } else {
                    throw new IllegalArgumentException(
                            "Unknown annotation type: "
                                    + annotation.annotationType().getName());
                }

                for (String resource : resources) {
                    String url = manager.registerDependency(resource, cls);
                    dependencies.add(new Dependency(type, url));
                }
            }
        }
    }

    /**
     * Finds all the URLs defined for the given classes, registers the URLs to
     * the communication manager and returns the registered dependencies.
     * <p>
     * The returned collection contains all types of dependencies for each class
     * in the given list in the order the classes are in the list, i.e. all
     * dependencies for the first class before all dependencies for the next
     * class.
     * <p>
     * JavaScript dependencies are returned before HTML imports.
     *
     * @param connectorTypes
     *            the collection of connector classes to scan
     * @param manager
     *            a reference to the communication manager which tracks
     *            dependencies
     * @return the list of found dependencies
     */
    @SuppressWarnings("deprecation")
    private static List<Dependency> findDependencies(
            List<Class<? extends ClientConnector>> connectorTypes,
            LegacyCommunicationManager manager) {
        List<Dependency> dependencies = new ArrayList<>();

        for (Class<? extends ClientConnector> connectorType : connectorTypes) {
            findAndRegisterResources(Type.JAVASCRIPT, connectorType, manager,
                    dependencies);
            findAndRegisterResources(Type.HTMLIMPORT, connectorType, manager,
                    dependencies);
            findAndRegisterResources(Type.STYLESHEET, connectorType, manager,
                    dependencies);
        }

        return dependencies;
    }

    /**
     * Finds all the URLs defined for the given classes, registers the URLs to
     * the communication manager, passes the registered dependencies through any
     * defined filters and returns the filtered collection of dependencies to
     * load.
     *
     * @since 8.1
     * @param connectorTypes
     *            the collection of connector classes to scan
     * @param manager
     *            a reference to the communication manager which tracks
     *            dependencies
     * @param context
     *            the context information for the filtering operation
     * @return the list of found and filtered dependencies
     */
    public static List<Dependency> findDependencies(
            List<Class<? extends ClientConnector>> connectorTypes,
            LegacyCommunicationManager manager, FilterContext context) {
        List<Dependency> dependencies = findDependencies(connectorTypes,
                manager);
        VaadinService service = context.getService();
        for (DependencyFilter filter : service.getDependencyFilters()) {
            dependencies = filter.filter(dependencies, context);
        }
        return dependencies;
    }

}