You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

BrowserWindowOpener.java 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370
  1. /*
  2. * Copyright 2000-2016 Vaadin Ltd.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License"); you may not
  5. * use this file except in compliance with the License. You may obtain a copy of
  6. * the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  12. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  13. * License for the specific language governing permissions and limitations under
  14. * the License.
  15. */
  16. package com.vaadin.server;
  17. import java.util.Collections;
  18. import java.util.Set;
  19. import com.vaadin.shared.ApplicationConstants;
  20. import com.vaadin.shared.ui.BrowserWindowOpenerState;
  21. import com.vaadin.ui.AbstractComponent;
  22. import com.vaadin.ui.UI;
  23. /**
  24. * Component extension that opens a browser popup window when the extended
  25. * component is clicked.
  26. *
  27. * @author Vaadin Ltd
  28. * @since 7.0.0
  29. */
  30. public class BrowserWindowOpener extends AbstractExtension {
  31. private static class BrowserWindowOpenerUIProvider extends UIProvider {
  32. private final String path;
  33. private final Class<? extends UI> uiClass;
  34. public BrowserWindowOpenerUIProvider(Class<? extends UI> uiClass,
  35. String path) {
  36. this.path = ensureInitialSlash(path);
  37. this.uiClass = uiClass;
  38. }
  39. private static String ensureInitialSlash(String path) {
  40. if (path == null) {
  41. return null;
  42. } else if (!path.startsWith("/")) {
  43. return '/' + path;
  44. } else {
  45. return path;
  46. }
  47. }
  48. @Override
  49. public Class<? extends UI> getUIClass(UIClassSelectionEvent event) {
  50. String requestPathInfo = event.getRequest().getPathInfo();
  51. if (path.equals(requestPathInfo)) {
  52. return uiClass;
  53. } else {
  54. return null;
  55. }
  56. }
  57. }
  58. private final BrowserWindowOpenerUIProvider uiProvider;
  59. /**
  60. * Creates a window opener that will open windows containing the provided UI
  61. * class
  62. *
  63. * @param uiClass
  64. * the UI class that should be opened when the extended component
  65. * is clicked
  66. */
  67. public BrowserWindowOpener(Class<? extends UI> uiClass) {
  68. this(uiClass, generateUIClassUrl(uiClass));
  69. }
  70. /**
  71. * Creates a window opener that will open windows containing the provided UI
  72. * using the provided path
  73. *
  74. * @param uiClass
  75. * the UI class that should be opened when the extended component
  76. * is clicked
  77. * @param path
  78. * the path that the UI should be bound to
  79. */
  80. public BrowserWindowOpener(Class<? extends UI> uiClass, String path) {
  81. // Create a Resource with a translated URL going to the VaadinService
  82. this(new ExternalResource(
  83. ApplicationConstants.APP_PROTOCOL_PREFIX + path),
  84. new BrowserWindowOpenerUIProvider(uiClass, path));
  85. }
  86. /**
  87. * Creates a window opener that will open windows to the provided URL
  88. *
  89. * @param url
  90. * the URL to open in the window
  91. */
  92. public BrowserWindowOpener(String url) {
  93. this(new ExternalResource(url));
  94. }
  95. /**
  96. * Creates a window opener that will open window to the provided resource
  97. *
  98. * @param resource
  99. * the resource to open in the window
  100. */
  101. public BrowserWindowOpener(Resource resource) {
  102. this(resource, null);
  103. }
  104. private BrowserWindowOpener(Resource resource,
  105. BrowserWindowOpenerUIProvider uiProvider) {
  106. this.uiProvider = uiProvider;
  107. setResource(BrowserWindowOpenerState.locationResource, resource);
  108. }
  109. public void extend(AbstractComponent target) {
  110. super.extend(target);
  111. }
  112. /**
  113. * Sets the provided URL {@code url} for this instance. The {@code url} will
  114. * be opened in a new browser window/tab when the extended component is
  115. * clicked.
  116. *
  117. * @since 7.4
  118. *
  119. * @param url
  120. * URL to open
  121. */
  122. public void setUrl(String url) {
  123. setResource(new ExternalResource(url));
  124. }
  125. /**
  126. * Sets the provided {@code resource} for this instance. The
  127. * {@code resource} will be opened in a new browser window/tab when the
  128. * extended component is clicked.
  129. *
  130. * @since 7.4
  131. *
  132. * @param resource
  133. * resource to open
  134. */
  135. public void setResource(Resource resource) {
  136. setResource(BrowserWindowOpenerState.locationResource, resource);
  137. }
  138. /**
  139. * Returns the resource for this instance.
  140. *
  141. * @since 7.4
  142. *
  143. * @return resource to open browser window
  144. */
  145. public Resource getResource() {
  146. return getResource(BrowserWindowOpenerState.locationResource);
  147. }
  148. /**
  149. * Returns the URL for this BrowserWindowOpener instance. Returns
  150. * {@code null} if this instance is not URL resource based (a non URL based
  151. * resource has been set for it).
  152. *
  153. * @since 7.4
  154. *
  155. * @return URL to open in the new browser window/tab when the extended
  156. * component is clicked
  157. */
  158. public String getUrl() {
  159. Resource resource = getResource();
  160. if (resource instanceof ExternalResource) {
  161. return ((ExternalResource) resource).getURL();
  162. }
  163. return null;
  164. }
  165. /**
  166. * Sets the target window name that will be used. If a window has already
  167. * been opened with the same name, the contents of that window will be
  168. * replaced instead of opening a new window. If the name is
  169. * <code>null</code> or <code>"_blank"</code>, a new window will always be
  170. * opened.
  171. *
  172. * @param windowName
  173. * the target name for the window
  174. */
  175. public void setWindowName(String windowName) {
  176. getState().target = windowName;
  177. }
  178. /**
  179. * Gets the target window name.
  180. *
  181. * @see #setWindowName(String)
  182. *
  183. * @return the window target string
  184. */
  185. public String getWindowName() {
  186. return getState(false).target;
  187. }
  188. // Avoid breaking url to multiple lines
  189. // @formatter:off
  190. /**
  191. * Sets the features for opening the window. See e.g.
  192. * {@link https://developer.mozilla.org/en-US/docs/DOM/window.open#Position_and_size_features}
  193. * for a description of the commonly supported features.
  194. *
  195. * @param features a string with window features, or <code>null</code> to use the default features.
  196. */
  197. // @formatter:on
  198. public void setFeatures(String features) {
  199. getState().features = features;
  200. }
  201. /**
  202. * Gets the window features.
  203. *
  204. * @see #setFeatures(String)
  205. * @return
  206. */
  207. public String getFeatures() {
  208. return getState(false).features;
  209. }
  210. @Override
  211. protected BrowserWindowOpenerState getState() {
  212. return (BrowserWindowOpenerState) super.getState();
  213. }
  214. @Override
  215. protected BrowserWindowOpenerState getState(boolean markAsDirty) {
  216. return (BrowserWindowOpenerState) super.getState(markAsDirty);
  217. }
  218. @Override
  219. public void attach() {
  220. super.attach();
  221. if (uiProvider != null
  222. && !getSession().getUIProviders().contains(uiProvider)) {
  223. getSession().addUIProvider(uiProvider);
  224. }
  225. }
  226. @Override
  227. public void detach() {
  228. if (uiProvider != null) {
  229. getSession().removeUIProvider(uiProvider);
  230. }
  231. super.detach();
  232. }
  233. private static String generateUIClassUrl(Class<? extends UI> uiClass) {
  234. return "popup/" + uiClass.getSimpleName();
  235. }
  236. /**
  237. * Sets a URI fragment that will be added to the URI opened in the window.
  238. * If the window is opened to contain a Vaadin UI, the fragment will be
  239. * available using {@link Page#getUriFragment()} on the Page instance of the
  240. * new UI.
  241. * <p>
  242. * The default value is <code>null</code>.
  243. *
  244. * @param uriFragment
  245. * the URI fragment string that should be included in the opened
  246. * URI, or <code>null</code> to preserve the original fragment of
  247. * the URI.
  248. */
  249. public void setUriFragment(String uriFragment) {
  250. getState().uriFragment = uriFragment;
  251. }
  252. /**
  253. * Gets that URI fragment configured for opened windows.
  254. *
  255. * @return the URI fragment string, or <code>null</code> if no fragment is
  256. * configured.
  257. *
  258. * @see #setUriFragment(String)
  259. */
  260. public String getUriFragment() {
  261. return getState(false).uriFragment;
  262. }
  263. /**
  264. * Sets a parameter that will be added to the query string of the opened
  265. * URI. If the window is opened to contain a Vaadin UI, the parameter will
  266. * be available using {@link VaadinRequest#getParameter(String)} e.g. using
  267. * the request instance passed to {@link UI#init(VaadinRequest)}.
  268. * <p>
  269. * Setting a parameter with the same name as a previously set parameter will
  270. * replace the previous value.
  271. *
  272. * @param name
  273. * the name of the parameter to add, not <code>null</code>
  274. * @param value
  275. * the value of the parameter to add, not <code>null</code>
  276. *
  277. * @see #removeParameter(String)
  278. * @see #getParameterNames()
  279. * @see #getParameter(String)
  280. */
  281. public void setParameter(String name, String value) {
  282. if (name == null || value == null) {
  283. throw new IllegalArgumentException("Null not allowed");
  284. }
  285. getState().parameters.put(name, value);
  286. }
  287. /**
  288. * Removes a parameter that has been set using
  289. * {@link #setParameter(String, String)}. Removing a parameter that has not
  290. * been set has no effect.
  291. *
  292. * @param name
  293. * the name of the parameter to remove, not <code>null</code>
  294. *
  295. * @see #setParameter(String, String)
  296. */
  297. public void removeParameter(String name) {
  298. if (name == null) {
  299. throw new IllegalArgumentException("Null not allowed");
  300. }
  301. getState().parameters.remove(name);
  302. }
  303. /**
  304. * Gets the names of all parameters set using
  305. * {@link #setParameter(String, String)}.
  306. *
  307. * @return an unmodifiable set of parameter names
  308. *
  309. * @see #setParameter(String, String)
  310. * @see #getParameter(String)
  311. */
  312. public Set<String> getParameterNames() {
  313. return Collections.unmodifiableSet(getState().parameters.keySet());
  314. }
  315. /**
  316. * Gets the value of a parameter set using
  317. * {@link #setParameter(String, String)}. If there is no parameter with the
  318. * given name, <code>null</code> is returned.
  319. *
  320. * @param name
  321. * the name of the parameter to get, not <code>null</code>
  322. * @return the value of the parameter, or <code>null</code> there is no
  323. * parameter
  324. *
  325. * @see #setParameter(String, String)
  326. * @see #getParameter(String)
  327. */
  328. public String getParameter(String name) {
  329. if (name == null) {
  330. throw new IllegalArgumentException("Null not allowed");
  331. }
  332. return getState(false).parameters.get(name);
  333. }
  334. }