1 /* ResourceUrlCreator.java
2    Copyright (C) 2011 Red Hat, Inc
3 
4 This file is part of IcedTea.
5 
6 IcedTea is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10 
11 IcedTea is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 General Public License for more details.
15 
16 You should have received a copy of the GNU General Public License
17 along with IcedTea; see the file COPYING.  If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 USA.
20 
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library.  Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
25 
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module.  An independent module is a module which is not derived from
33 or based on this library.  If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so.  If you do not wish to do so, delete this
36 exception statement from your version. */
37 
38 package net.sourceforge.jnlp.cache;
39 
40 import java.net.MalformedURLException;
41 import java.net.URL;
42 import java.util.LinkedList;
43 import java.util.List;
44 
45 import net.sourceforge.jnlp.DownloadOptions;
46 
47 public class ResourceUrlCreator {
48 
49     protected final Resource resource;
50     protected final DownloadOptions downloadOptions;
51 
ResourceUrlCreator(Resource resource, DownloadOptions downloadOptions)52     public ResourceUrlCreator(Resource resource, DownloadOptions downloadOptions) {
53         this.resource = resource;
54         this.downloadOptions = downloadOptions;
55     }
56 
57     /**
58      * Returns a list of URLs that the resources might be downloadable from.
59      * The Resources may not be downloadable from any of them. The returned order is the order
60      * the urls should be attempted in.
61      * @return a list of URLs that the resources might be downloadable from
62      */
getUrls()63     public List<URL> getUrls() {
64         List<URL> urls = new LinkedList<>();
65         URL url;
66 
67         if (downloadOptions.useExplicitPack() && downloadOptions.useExplicitVersion()) {
68             url = getUrl(resource, true, true);
69             if (url != null) {
70                 urls.add(url);
71             }
72             url = getUrl(resource, false, true);
73             if (url != null) {
74                 urls.add(url);
75             }
76             url = getUrl(resource, true, false);
77             if (url != null) {
78                 urls.add(url);
79             }
80         } else if (downloadOptions.useExplicitPack()) {
81             url = getUrl(resource, true, false);
82             if (url != null) {
83                 urls.add(url);
84             }
85         } else if (downloadOptions.useExplicitVersion()) {
86             url = getUrl(resource, false, true);
87             if (url != null) {
88                 urls.add(url);
89             }
90         }
91 
92         url = getVersionedUrl();
93         urls.add(url);
94 
95         urls.add(resource.getLocation());
96 
97         return urls;
98     }
99 
100     /**
101      * Returns a url for the resource.
102      * @param resource the resource
103      * @param usePack whether the URL should point to the pack200 file
104      * @param useVersion whether the URL should be modified to include the version
105      * @return a URL for the resource or null if an appropriate URL can not be found
106      */
getUrl(Resource resource, boolean usePack, boolean useVersion)107     static URL getUrl(Resource resource, boolean usePack, boolean useVersion) {
108         if (!(usePack || useVersion)) {
109             throw new IllegalArgumentException("either pack200 or version required");
110         }
111 
112         String location = resource.getLocation().toString();
113         int lastSlash = resource.getLocation().toString().lastIndexOf('/');
114         if (lastSlash == -1) {
115             return resource.getLocation();
116         }
117         String filename = location.substring(lastSlash + 1);
118         if (useVersion && resource.getRequestVersion() != null) {
119             // With 'useVersion', j2-commons-cli.jar becomes, for example, j2-commons-cli__V1.0.jar
120             String parts[] = filename.split("\\.", -1 /* Keep blank strings*/);
121 
122             StringBuilder sb = new StringBuilder();
123             for (int i = 0; i < parts.length; i++) {
124                 sb.append(parts[i]);
125                 // Append __V<number> before last '.'
126                 if (i == parts.length -2) {
127                     sb.append("__V").append(resource.getRequestVersion());
128                 }
129                 sb.append('.');
130             }
131             sb.setLength(sb.length() - 1); // remove last '.'
132 
133             filename = sb.toString();
134         }
135         if (usePack) {
136             filename = filename + ".pack.gz";
137         }
138 
139         location = location.substring(0, lastSlash + 1) + filename;
140         try {
141             URL newUrl = new URL(location);
142             return newUrl;
143         } catch (MalformedURLException e) {
144             return null;
145         }
146     }
147 
148     /**
149      * Returns the URL for this resource, including the resource's version number in the query string
150      * @return  url with version cared about
151      */
getVersionedUrl()152     protected URL getVersionedUrl() {
153         URL resourceUrl = resource.getLocation();
154         String protocol = uriPartToString(resourceUrl.getProtocol()) + "://";
155         String userInfo = uriPartToString(resourceUrl.getUserInfo());
156         if (!userInfo.isEmpty()) {
157             userInfo += "@";
158         }
159         String host = uriPartToString(resourceUrl.getHost());
160         String port;
161         if (resourceUrl.getPort() == -1) {
162             port = "";
163         } else {
164             port = ":" + String.valueOf(resourceUrl.getPort());
165         }
166         String path = uriPartToString(resourceUrl.getPath());
167         String query = uriPartToString(resourceUrl.getQuery());
168         if (!query.isEmpty()) {
169             query = "?" + query;
170         }
171         if (resource.getRequestVersion() != null && resource.getRequestVersion().isVersionId()) {
172             if (!query.isEmpty()) {
173                 query += "&";
174             } else {
175                 query = "?" + query;
176             }
177             query += "version-id=" + resource.getRequestVersion();
178         }
179         try {
180             URL url = new URL(protocol + userInfo + host + port + path + query);
181             return url;
182         } catch (MalformedURLException e) {
183             return resourceUrl;
184         }
185     }
186 
uriPartToString(String part)187     private static String uriPartToString(String part) {
188         if (part == null)
189             return "";
190         return part;
191     }
192 
193 }
194