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 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389
  1. /*
  2. * Copyright 2000-2018 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. /**
  110. * Add this extension to the target component.
  111. *
  112. * @param target
  113. * the component to attach this extension to
  114. */
  115. public void extend(AbstractComponent target) {
  116. super.extend(target);
  117. }
  118. /**
  119. * Add this extension to the {@code EventTrigger}.
  120. *
  121. * @param eventTrigger
  122. * the trigger to attach this extension to
  123. *
  124. * @since
  125. */
  126. public void extend(EventTrigger eventTrigger) {
  127. super.extend(eventTrigger.getConnector());
  128. getState().partInformation = eventTrigger.getPartInformation();
  129. }
  130. /**
  131. * Sets the provided URL {@code url} for this instance. The {@code url} will
  132. * be opened in a new browser window/tab when the extended component is
  133. * clicked.
  134. *
  135. * @since 7.4
  136. *
  137. * @param url
  138. * URL to open
  139. */
  140. public void setUrl(String url) {
  141. setResource(new ExternalResource(url));
  142. }
  143. /**
  144. * Sets the provided {@code resource} for this instance. The
  145. * {@code resource} will be opened in a new browser window/tab when the
  146. * extended component is clicked.
  147. *
  148. * @since 7.4
  149. *
  150. * @param resource
  151. * resource to open
  152. */
  153. public void setResource(Resource resource) {
  154. setResource(BrowserWindowOpenerState.locationResource, resource);
  155. }
  156. /**
  157. * Returns the resource for this instance.
  158. *
  159. * @since 7.4
  160. *
  161. * @return resource to open browser window
  162. */
  163. public Resource getResource() {
  164. return getResource(BrowserWindowOpenerState.locationResource);
  165. }
  166. /**
  167. * Returns the URL for this BrowserWindowOpener instance. Returns
  168. * {@code null} if this instance is not URL resource based (a non URL based
  169. * resource has been set for it).
  170. *
  171. * @since 7.4
  172. *
  173. * @return URL to open in the new browser window/tab when the extended
  174. * component is clicked
  175. */
  176. public String getUrl() {
  177. Resource resource = getResource();
  178. if (resource instanceof ExternalResource) {
  179. return ((ExternalResource) resource).getURL();
  180. }
  181. return null;
  182. }
  183. /**
  184. * Sets the target window name that will be used. If a window has already
  185. * been opened with the same name, the contents of that window will be
  186. * replaced instead of opening a new window. If the name is
  187. * <code>null</code> or <code>"_blank"</code>, a new window will always be
  188. * opened.
  189. *
  190. * @param windowName
  191. * the target name for the window
  192. */
  193. public void setWindowName(String windowName) {
  194. getState().target = windowName;
  195. }
  196. /**
  197. * Gets the target window name.
  198. *
  199. * @see #setWindowName(String)
  200. *
  201. * @return the window target string
  202. */
  203. public String getWindowName() {
  204. return getState(false).target;
  205. }
  206. // Avoid breaking url to multiple lines
  207. // @formatter:off
  208. /**
  209. * Sets the features for opening the window. See e.g.
  210. * {@link https://developer.mozilla.org/en-US/docs/DOM/window.open#Position_and_size_features}
  211. * for a description of the commonly supported features.
  212. *
  213. * @param features a string with window features, or <code>null</code> to use the default features.
  214. */
  215. // @formatter:on
  216. public void setFeatures(String features) {
  217. getState().features = features;
  218. }
  219. /**
  220. * Gets the window features.
  221. *
  222. * @see #setFeatures(String)
  223. * @return
  224. */
  225. public String getFeatures() {
  226. return getState(false).features;
  227. }
  228. @Override
  229. protected BrowserWindowOpenerState getState() {
  230. return (BrowserWindowOpenerState) super.getState();
  231. }
  232. @Override
  233. protected BrowserWindowOpenerState getState(boolean markAsDirty) {
  234. return (BrowserWindowOpenerState) super.getState(markAsDirty);
  235. }
  236. @Override
  237. public void attach() {
  238. super.attach();
  239. if (uiProvider != null
  240. && !getSession().getUIProviders().contains(uiProvider)) {
  241. getSession().addUIProvider(uiProvider);
  242. }
  243. }
  244. @Override
  245. public void detach() {
  246. if (uiProvider != null) {
  247. getSession().removeUIProvider(uiProvider);
  248. }
  249. super.detach();
  250. }
  251. private static String generateUIClassUrl(Class<? extends UI> uiClass) {
  252. return "popup/" + uiClass.getSimpleName();
  253. }
  254. /**
  255. * Sets a URI fragment that will be added to the URI opened in the window.
  256. * If the window is opened to contain a Vaadin UI, the fragment will be
  257. * available using {@link Page#getUriFragment()} on the Page instance of the
  258. * new UI.
  259. * <p>
  260. * The default value is <code>null</code>.
  261. *
  262. * @param uriFragment
  263. * the URI fragment string that should be included in the opened
  264. * URI, or <code>null</code> to preserve the original fragment of
  265. * the URI.
  266. */
  267. public void setUriFragment(String uriFragment) {
  268. getState().uriFragment = uriFragment;
  269. }
  270. /**
  271. * Gets that URI fragment configured for opened windows.
  272. *
  273. * @return the URI fragment string, or <code>null</code> if no fragment is
  274. * configured.
  275. *
  276. * @see #setUriFragment(String)
  277. */
  278. public String getUriFragment() {
  279. return getState(false).uriFragment;
  280. }
  281. /**
  282. * Sets a parameter that will be added to the query string of the opened
  283. * URI. If the window is opened to contain a Vaadin UI, the parameter will
  284. * be available using {@link VaadinRequest#getParameter(String)} e.g. using
  285. * the request instance passed to {@link UI#init(VaadinRequest)}.
  286. * <p>
  287. * Setting a parameter with the same name as a previously set parameter will
  288. * replace the previous value.
  289. *
  290. * @param name
  291. * the name of the parameter to add, not <code>null</code>
  292. * @param value
  293. * the value of the parameter to add, not <code>null</code>
  294. *
  295. * @see #removeParameter(String)
  296. * @see #getParameterNames()
  297. * @see #getParameter(String)
  298. */
  299. public void setParameter(String name, String value) {
  300. if (name == null || value == null) {
  301. throw new IllegalArgumentException("Null not allowed");
  302. }
  303. getState().parameters.put(name, value);
  304. }
  305. /**
  306. * Removes a parameter that has been set using
  307. * {@link #setParameter(String, String)}. Removing a parameter that has not
  308. * been set has no effect.
  309. *
  310. * @param name
  311. * the name of the parameter to remove, not <code>null</code>
  312. *
  313. * @see #setParameter(String, String)
  314. */
  315. public void removeParameter(String name) {
  316. if (name == null) {
  317. throw new IllegalArgumentException("Null not allowed");
  318. }
  319. getState().parameters.remove(name);
  320. }
  321. /**
  322. * Gets the names of all parameters set using
  323. * {@link #setParameter(String, String)}.
  324. *
  325. * @return an unmodifiable set of parameter names
  326. *
  327. * @see #setParameter(String, String)
  328. * @see #getParameter(String)
  329. */
  330. public Set<String> getParameterNames() {
  331. return Collections.unmodifiableSet(getState().parameters.keySet());
  332. }
  333. /**
  334. * Gets the value of a parameter set using
  335. * {@link #setParameter(String, String)}. If there is no parameter with the
  336. * given name, <code>null</code> is returned.
  337. *
  338. * @param name
  339. * the name of the parameter to get, not <code>null</code>
  340. * @return the value of the parameter, or <code>null</code> there is no
  341. * parameter
  342. *
  343. * @see #setParameter(String, String)
  344. * @see #getParameter(String)
  345. */
  346. public String getParameter(String name) {
  347. if (name == null) {
  348. throw new IllegalArgumentException("Null not allowed");
  349. }
  350. return getState(false).parameters.get(name);
  351. }
  352. }