View Javadoc

1   package org.springframework.richclient.jnlp;
2   
3   import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
4   
5   import javax.jnlp.BasicService;
6   import javax.jnlp.ServiceManager;
7   import javax.jnlp.UnavailableServiceException;
8   import java.util.Properties;
9   
10  /**
11   * Subclass of PropertyPlaceholderConfigurer that resolves the following properties as placeholders:
12   * <ul>
13   * <li><code>jnlp.webAppContextUrl</code> the webAppContextUrl, for example
14   * http://domain.com/petclinic/</li>
15   * </ul>
16   * <p/>
17   * <p>Can be combined with "locations" and/or "properties" values.
18   * <p/>
19   * <p>If a placeholder could not be resolved against the provided local
20   * properties within the application, this configurer will fall back to
21   * the JNLP properties. Can also be configured to let jnlp properties
22   * override local properties (contextOverride=true).
23   * <p/>
24   * <p>If not running within a JNLP context (or any other context that
25   * is able to satisfy the BasicService.lookup call), this class will
26   * use the fallBackWebAppContextUrl. This allows for keeping
27   * JnlpPropertyPlaceholderConfigurer definitions in test suites.
28   * <p/>
29   * <p> A typical usage would be:
30   * <pre>
31   * &lt;bean id="jnlpPropertyPlaceholderConfigurer"
32   *      class="be.kahosl.thot.swingui.util.JnlpPropertyPlaceholderConfigurer"&gt;
33   *      &lt;property name="fallBackWebAppContextUrl" value="http://localhost:8080/mywebapp/"/&gt;
34   *      &lt;property name="jnlpRelativeDirectoryPathFromWebAppContext" value="/jnlp/"/&gt;
35   *  &lt;/bean&gt;
36   *  </pre>
37   * <p/>
38   * Use this in combination with Sun's JnlpDownloadServlet to not have to hardcode your server URL:
39   * http://java.sun.com/j2se/1.5.0/docs/guide/javaws/developersguide/downloadservletguide.html
40   *
41   * @author Geoffrey De Smet
42   * @see #setLocations
43   * @see #setProperties
44   * @see #setSystemPropertiesModeName
45   * @see #setContextOverride
46   * @see javax.jnlp.BasicService#getCodeBase()
47   */
48  public class JnlpPropertyPlaceholderConfigurer extends PropertyPlaceholderConfigurer {
49  
50      /**
51       * The placeholder for getWebAppContextUrl()
52       */
53      public static final String WEB_APP_CONTEXT_URL_PLACEHOLDER = "jnlp.webAppContextUrl";
54  
55      private boolean contextOverride = false;
56      private String fallBackWebAppContextUrl = "http://localhost:8080/";
57      private String jnlpRelativeDirectoryPathFromWebAppContext = "/";
58  
59      /**
60       * Set whether the JNLP properties should override local properties within the application.
61       * Default is "false": JNLP properties settings serve as fallback.
62       * <p>Note that system properties will still override JNLP properties,
63       * if the system properties mode is set to "SYSTEM_PROPERTIES_MODE_OVERRIDE".
64       *
65       * @see #setSystemPropertiesModeName
66       * @see #SYSTEM_PROPERTIES_MODE_OVERRIDE
67       */
68      public void setContextOverride(boolean contextOverride) {
69          this.contextOverride = contextOverride;
70      }
71  
72      /**
73       * Set the webAppContextUrl to use when no javax.jnlp.BasicService is available.
74       * This is usefull for testing outside JNLP (Java webstart).
75       * This defaults to <code>http://localhost:8080/</code>.
76       * Ussually you 'll want to set this to <code>http://localhost:8080/mywebapp/</code>.
77       *
78       * @param fallBackWebAppContextUrl the webAppContextUrl to fall back on ending with a slash
79       */
80      public void setFallBackWebAppContextUrl(String fallBackWebAppContextUrl) {
81          this.fallBackWebAppContextUrl = fallBackWebAppContextUrl;
82      }
83  
84      /**
85       * Sets the relative directory path of the JNLP file relative to the WebAppContext.
86       * Default this is <code>/</code>, which means that the JNLP file is in the root of your webapp.
87       * If your JNLP file isn't in the root of you webapp, change it.
88       * For example for <code>http://localhost:8080/mywebapp/dist/jnlp/myswingapp.jnlp</code>
89       * you would set this to <code>/dist/jnlp/</code>.
90       *
91       * @param jnlpRelativeDirectoryPathFromWebAppContext
92       *         the relative directory path starting and ending with a slash
93       */
94      public void setJnlpRelativeDirectoryPathFromWebAppContext(String jnlpRelativeDirectoryPathFromWebAppContext) {
95          this.jnlpRelativeDirectoryPathFromWebAppContext = jnlpRelativeDirectoryPathFromWebAppContext;
96      }
97  
98      protected String resolvePlaceholder(String placeholder, Properties props) {
99          String value = null;
100         if (this.contextOverride) {
101             value = resolvePlaceholder(placeholder);
102         }
103         if (value == null) {
104             value = super.resolvePlaceholder(placeholder, props);
105         }
106         if (value == null) {
107             value = resolvePlaceholder(placeholder);
108         }
109         return value;
110     }
111 
112     /**
113      * Resolves the given placeholder using the jnlp properties.
114      *
115      * @param placeholder the placeholder to resolve
116      * @return the resolved value, of null if none
117      */
118     protected String resolvePlaceholder(String placeholder) {
119         String value = null;
120         if (placeholder.equals(WEB_APP_CONTEXT_URL_PLACEHOLDER)) {
121             value = getWebAppContextUrl();
122         }
123         return value;
124     }
125 
126     /**
127      * Uses the jnlp API to determine the webapp context.
128      * If used outside of webstart, <code>fallBackWebAppContextUrl</code> is returned.
129      * For example this could return <code>http://localhost:8080/mywebapp/</code>.
130      *
131      * @return the url to the webapp ending with a slash
132      */
133     public String getWebAppContextUrl() {
134         String webAppContextUrl;
135         try {
136             BasicService basicService = (BasicService) ServiceManager.lookup("javax.jnlp.BasicService");
137             String codeBase = basicService.getCodeBase().toExternalForm();
138             if (!codeBase.endsWith("/")) {
139                 codeBase += "/";
140             }
141             int webAppContextUrlLength = codeBase.lastIndexOf(jnlpRelativeDirectoryPathFromWebAppContext);
142             webAppContextUrl = codeBase.substring(0, webAppContextUrlLength + 1);
143         } catch (UnavailableServiceException e) {
144             // TODO logging
145             webAppContextUrl = fallBackWebAppContextUrl;
146         }
147         return webAppContextUrl;
148     }
149 
150 }