1 /* |
|
2 * CDDL HEADER START |
|
3 * |
|
4 * The contents of this file are subject to the terms of the |
|
5 * Common Development and Distribution License (the "License"). |
|
6 * You may not use this file except in compliance with the License. |
|
7 * |
|
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE |
|
9 * or http://www.opensolaris.org/os/licensing. |
|
10 * See the License for the specific language governing permissions |
|
11 * and limitations under the License. |
|
12 * |
|
13 * When distributing Covered Code, include this CDDL HEADER in each |
|
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. |
|
15 * If applicable, add the following below this CDDL HEADER, with the |
|
16 * fields enclosed by brackets "[]" replaced with your own identifying |
|
17 * information: Portions Copyright [yyyy] [name of copyright owner] |
|
18 * |
|
19 * CDDL HEADER END |
|
20 */ |
|
21 |
|
22 /* |
|
23 * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. |
|
24 */ |
|
25 |
|
26 package com.oracle.solaris.vp.client.common; |
|
27 |
|
28 import java.io.*; |
|
29 import java.net.*; |
|
30 import java.security.*; |
|
31 import java.util.*; |
|
32 import com.oracle.solaris.vp.panel.common.*; |
|
33 import com.oracle.solaris.vp.panel.common.action.ActionAbortedException; |
|
34 import com.oracle.solaris.vp.panel.common.api.panel.*; |
|
35 import com.oracle.solaris.vp.panel.common.api.panels.CustomPanel; |
|
36 import com.oracle.solaris.vp.panel.common.api.panels.Panel; |
|
37 import com.oracle.solaris.vp.panel.common.api.panels.ResourceDescriptor; |
|
38 import com.oracle.solaris.vp.util.misc.*; |
|
39 import com.oracle.solaris.vp.util.misc.finder.Finder; |
|
40 |
|
41 public abstract class PanelResourceManager { |
|
42 // |
|
43 // PanelResourceManager methods |
|
44 // |
|
45 |
|
46 /** |
|
47 * Returns the PanelResourceManager subclass -determined user |
|
48 * directory. |
|
49 */ |
|
50 abstract protected String getUserDir(); |
|
51 |
|
52 /** |
|
53 * Checks to see if the download process has been cancelled. Subclasses |
|
54 * should override this method if they provide a method for the user to |
|
55 * cancel the login process. This default implementation does nothing. |
|
56 * |
|
57 * @exception ActionAbortedException |
|
58 * if the action has been cancelled |
|
59 */ |
|
60 protected void checkForCancel() throws ActionAbortedException { |
|
61 } |
|
62 |
|
63 /** |
|
64 * Downloads all resources needed by a particular {@link CustomPanel}. |
|
65 * |
|
66 * @param info |
|
67 * the connection information |
|
68 * |
|
69 * @param panel |
|
70 * the {@link CustomPanel} that requires resources downloaded |
|
71 * |
|
72 * @return the {@code URL}s pointing to local copies of the downloaded |
|
73 * resources for the given panel, or {@code null} if an error |
|
74 * occurred |
|
75 * |
|
76 * @exception ActionAbortedException |
|
77 * if the download is aborted before it is complete |
|
78 * |
|
79 * @exception PanelResourceException |
|
80 * if a resource could not be downloaded |
|
81 */ |
|
82 protected URL[] downloadAll(ConnectionInfo info, CustomPanel panel) |
|
83 throws ActionAbortedException, PanelResourceException |
|
84 { |
|
85 List<URL> urls = new ArrayList<URL>(); |
|
86 boolean isLocal = NetUtil.isLocalAddress(info.getHost()); |
|
87 |
|
88 PanelBeanTracker tracker = null; |
|
89 Panel bean = null; |
|
90 |
|
91 // Download each resource |
|
92 for (ResourceDescriptor descriptor : panel.getResourceDescriptors()) { |
|
93 checkForCancel(); |
|
94 |
|
95 InputStream in = null; |
|
96 String fileName = null; |
|
97 String remoteFile = descriptor.getFile(); |
|
98 |
|
99 try { |
|
100 fileName = isLocal ? remoteFile : |
|
101 getLocalCacheName(info, remoteFile); |
|
102 |
|
103 final File file = new File(fileName); |
|
104 URI uri = AccessController.doPrivileged( |
|
105 new PrivilegedAction<URI>() { |
|
106 @Override |
|
107 public URI run() { |
|
108 return file.toURI(); |
|
109 } |
|
110 }); |
|
111 urls.add(uri.toURL()); |
|
112 |
|
113 if (!isLocal) { |
|
114 boolean download = true; |
|
115 |
|
116 if (file.exists()) { |
|
117 byte[] sHash = descriptor.getHash(); |
|
118 if (sHash != null) { |
|
119 byte[] cHash = FileUtil.getHash( |
|
120 fileName, descriptor.getHashAlgorithm()); |
|
121 |
|
122 if (Arrays.equals(sHash, cHash)) { |
|
123 download = false; |
|
124 } |
|
125 } |
|
126 } |
|
127 |
|
128 if (download) { |
|
129 final File parent = file.getParentFile(); |
|
130 if (parent != null && !parent.exists()) { |
|
131 String path = parent.getCanonicalPath(); |
|
132 showStatus(Finder.getString("download.status.mkdir", |
|
133 path)); |
|
134 |
|
135 if (!AccessController.doPrivileged( |
|
136 new PrivilegedAction<Boolean>() { |
|
137 @Override |
|
138 public Boolean run() { |
|
139 return parent.mkdirs(); |
|
140 } |
|
141 })) { |
|
142 throw new IOException( |
|
143 Finder.getString("download.error.mkdir", |
|
144 path)); |
|
145 } |
|
146 |
|
147 checkForCancel(); |
|
148 } |
|
149 |
|
150 showStatus(Finder.getString( |
|
151 "download.status.download", fileName)); |
|
152 |
|
153 if (bean == null) { |
|
154 if (tracker == null) { |
|
155 tracker = createTracker(info); |
|
156 } |
|
157 bean = tracker.getBean(); |
|
158 } |
|
159 |
|
160 final byte[] resource = bean.getResource( |
|
161 descriptor.getToken()); |
|
162 |
|
163 AccessController.doPrivileged( |
|
164 new PrivilegedExceptionAction<Object>() { |
|
165 @Override |
|
166 public Object run() throws IOException { |
|
167 OutputStream out = |
|
168 new FileOutputStream(file); |
|
169 out.write(resource); |
|
170 out.close(); |
|
171 return null; |
|
172 } |
|
173 }); |
|
174 } |
|
175 } |
|
176 } |
|
177 |
|
178 catch (Exception e) { |
|
179 throw new PanelResourceException(Finder.getString( |
|
180 "download.error.download", panel.getName(), info.getHost(), |
|
181 remoteFile), e); |
|
182 } |
|
183 |
|
184 finally { |
|
185 IOUtil.closeIgnore(in); |
|
186 if (tracker != null) { |
|
187 tracker.dispose(); |
|
188 } |
|
189 } |
|
190 } |
|
191 |
|
192 return urls.toArray(new URL[urls.size()]); |
|
193 } |
|
194 |
|
195 /** |
|
196 * Returns the file name of the locally cached version of the given remote |
|
197 * file, mapped to {@link PanelResourceManager#getUserDir |
|
198 * userdir}/cache/<i>host</i>/<i>path</i>. |
|
199 */ |
|
200 public String getLocalCacheName(ConnectionInfo info, String remoteFile) { |
|
201 return TextUtil.join(File.separator, |
|
202 getUserDir(), "cache", info.getHost(), remoteFile); |
|
203 } |
|
204 |
|
205 /** |
|
206 * Displays the user-friendly status of this {@code PanelResourceManager}. |
|
207 * Subclasses may wish to override this method -- this default |
|
208 * implementation does nothing. |
|
209 */ |
|
210 protected void showStatus(String status) { |
|
211 } |
|
212 |
|
213 // |
|
214 // Private methods |
|
215 // |
|
216 |
|
217 private PanelBeanTracker createTracker(ConnectionInfo info) |
|
218 throws PanelResourceException { |
|
219 |
|
220 PanelBeanTracker tracker; |
|
221 |
|
222 try { |
|
223 tracker = new PanelBeanTracker(); |
|
224 tracker.setConnectionInfo(info); |
|
225 |
|
226 } catch (TrackerException e) { |
|
227 Throwable cause = e.getCause(); |
|
228 String message = Finder.getString("download.error.general", |
|
229 info.getHost()); |
|
230 throw new PanelResourceException(message, cause); |
|
231 } |
|
232 |
|
233 return tracker; |
|
234 } |
|
235 } |
|