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) 2009, 2012, Oracle and/or its affiliates. All rights reserved. |
|
24 */ |
|
25 |
|
26 package com.oracle.solaris.vp.panel.common.action; |
|
27 |
|
28 import java.awt.EventQueue; |
|
29 import java.util.logging.Logger; |
|
30 import javax.swing.JOptionPane; |
|
31 import com.oracle.solaris.vp.panel.common.*; |
|
32 import com.oracle.solaris.vp.panel.common.api.auth.*; |
|
33 import com.oracle.solaris.vp.util.misc.*; |
|
34 import com.oracle.solaris.vp.util.misc.finder.Finder; |
|
35 |
|
36 /** |
|
37 * The {@code DefaultStructuredAction} is a {@link StructuredAction} that uses a |
|
38 * {@link ClientContext} to handle errors and show a busy indicator while work |
|
39 * is being done. |
|
40 * <p/> |
|
41 * Subclasses should implement {@link #workBusy}, and optionally {@link |
|
42 * #getRuntimeInput} if they need to interact with the user prior to running. |
|
43 */ |
|
44 public class DefaultStructuredAction<P, I, O> |
|
45 extends StructuredAction<P, I, O> { |
|
46 |
|
47 // |
|
48 // Instance data |
|
49 // |
|
50 |
|
51 private ClientContext context; |
|
52 |
|
53 // |
|
54 // Constructors |
|
55 // |
|
56 |
|
57 public DefaultStructuredAction(String text, P pInput, |
|
58 ClientContext context) { |
|
59 |
|
60 super(text, pInput); |
|
61 this.context = context; |
|
62 } |
|
63 |
|
64 public DefaultStructuredAction(String text, ClientContext context) { |
|
65 this(text, null, context); |
|
66 } |
|
67 |
|
68 // |
|
69 // StructuredAction methods |
|
70 // |
|
71 |
|
72 /** |
|
73 * Calls {@link #setBusyAndWork}, then catches, displays, and re-throws any |
|
74 * resulting {@link ActionFailedException}s, and catches any resulting |
|
75 * {@link ActionUnauthorizedException}s and prompts the user to change his |
|
76 * login before retrying. |
|
77 * <p> |
|
78 * Note: See {@link #setBusyAndWork} for the note about calling this method |
|
79 * on the Swing event thread. |
|
80 * |
|
81 * @param pInput |
|
82 * see {@link StructuredAction#work} |
|
83 * |
|
84 * @param rtInput |
|
85 * see {@link StructuredAction#work} |
|
86 * |
|
87 * @return see {@link StructuredAction#work} |
|
88 * |
|
89 * @exception ActionAbortedException |
|
90 * thrown by {@link #setBusyAndWork} or {@link |
|
91 * ClientContext#login} |
|
92 * |
|
93 * @exception ActionFailedException |
|
94 * see {@link StructuredAction#work} |
|
95 */ |
|
96 @Override |
|
97 public O work(P pInput, I rtInput) throws ActionAbortedException, |
|
98 ActionFailedException { |
|
99 |
|
100 LoginRequest request = null; |
|
101 |
|
102 while (true) { |
|
103 try { |
|
104 if (request != null) { |
|
105 try { |
|
106 context.login(request, false); |
|
107 } finally { |
|
108 request = null; |
|
109 } |
|
110 } |
|
111 |
|
112 return setBusyAndWork(pInput, rtInput); |
|
113 |
|
114 } catch (ActionFailedException e) { |
|
115 showError(e); |
|
116 throw e; |
|
117 |
|
118 } catch (ActionUnauthorizedException e) { |
|
119 String eMessage = e.getMessage(); |
|
120 if (eMessage == null) { |
|
121 eMessage = Finder.getString("error.server.permission"); |
|
122 } |
|
123 |
|
124 String userVal = null; |
|
125 String roleVal = null; |
|
126 |
|
127 // Prioritize users over roles (more user-friendly) |
|
128 PrincipalHintList hints = e.getHints(); |
|
129 UserHint uhint = hints.getFirstHint(UserHint.class); |
|
130 if (uhint != null) { |
|
131 userVal = uhint.getUsername(); |
|
132 } else { |
|
133 RoleHint rhint = hints.getFirstHint(RoleHint.class); |
|
134 if (rhint != null) { |
|
135 roleVal = rhint.getRolename(); |
|
136 } |
|
137 } |
|
138 |
|
139 // Log in with a different user/role and try again |
|
140 ConnectionInfo info = context.getConnectionInfo(); |
|
141 LoginProperty<String> host = |
|
142 new LoginProperty<String>(info.getHost(), false); |
|
143 LoginProperty<String> user = |
|
144 new LoginProperty<String>(userVal != null ? |
|
145 userVal : info.getUser(), true); |
|
146 LoginProperty<String> role = |
|
147 new LoginProperty<String>(roleVal != null ? |
|
148 roleVal : info.getRole(), true); |
|
149 |
|
150 DialogMessage message = new DialogMessage( |
|
151 eMessage, JOptionPane.WARNING_MESSAGE); |
|
152 |
|
153 request = new LoginRequest(host, user, role, message); |
|
154 } |
|
155 } |
|
156 } |
|
157 |
|
158 // |
|
159 // DefaultStructuredAction methods |
|
160 // |
|
161 |
|
162 public ClientContext getClientContext() { |
|
163 return context; |
|
164 } |
|
165 |
|
166 /** |
|
167 * Sets the busy state of this {@code DefaultStructuredAction}'s {@link |
|
168 * ClientContext}, then calls {@link #workBusy}, preventing the user from |
|
169 * interacting with the application until {@link #workBusy} is complete. |
|
170 * <p> |
|
171 * Note: in a Swing context, this method should not be called on the event |
|
172 * thread, since a) it calls {@link #workBusy} which may perform intensive |
|
173 * non-UI work, and b) it displays the {@link ClientContext#getBusyIndicator |
|
174 * ClientContext's busy indicator}, which may invoke UI effects that would |
|
175 * not be displayed until after this method is done (when the event thread |
|
176 * is free). |
|
177 * |
|
178 * @param pInput |
|
179 * see {@link StructuredAction#work} |
|
180 * |
|
181 * @param rtInput |
|
182 * see {@link StructuredAction#work} |
|
183 * |
|
184 * @return see {@link StructuredAction#work} |
|
185 * |
|
186 * @exception ActionAbortedException |
|
187 * see {@link StructuredAction#work} |
|
188 * |
|
189 * @exception ActionFailedException |
|
190 * see {@link StructuredAction#work} |
|
191 * |
|
192 * @exception ActionUnauthorizedException |
|
193 * see {@link #workBusy} |
|
194 */ |
|
195 public O setBusyAndWork(P pInput, I rtInput) throws ActionAbortedException, |
|
196 ActionFailedException, ActionUnauthorizedException { |
|
197 |
|
198 assert (!EventQueue.isDispatchThread()); |
|
199 |
|
200 context.getBusyIndicator().setBusyIndicatorDisplayed(true); |
|
201 |
|
202 try { |
|
203 return workBusy(pInput, rtInput); |
|
204 } finally { |
|
205 context.getBusyIndicator().setBusyIndicatorDisplayed(false); |
|
206 } |
|
207 } |
|
208 |
|
209 protected void setClientContext(ClientContext context) { |
|
210 this.context = context; |
|
211 } |
|
212 |
|
213 /** |
|
214 * Handles {@link ActionFailedException}s thrown by {@link #work}. |
|
215 * <p/> |
|
216 * This default implementation logs ({@code Level.FINE}) the error to the |
|
217 * {@link ClientContext} log. |
|
218 */ |
|
219 protected void showError(ActionFailedException e) { |
|
220 Logger.getLogger(getClass().getPackage().getName()).fine( |
|
221 ThrowableUtil.getTrueMessage(e)); |
|
222 } |
|
223 |
|
224 /** |
|
225 * Does the core work of this action. |
|
226 * <p> |
|
227 * This default implementation does nothing and returns {@code null}. |
|
228 * |
|
229 * @param pInput |
|
230 * see {@link StructuredAction#work} |
|
231 * |
|
232 * @param rtInput |
|
233 * see {@link StructuredAction#work} |
|
234 * |
|
235 * @return see {@link StructuredAction#work} |
|
236 * |
|
237 * @exception ActionAbortedException |
|
238 * see {@link StructuredAction#work} |
|
239 * |
|
240 * @exception ActionFailedException |
|
241 * see {@link StructuredAction#work} |
|
242 * |
|
243 * @exception ActionUnauthorizedException |
|
244 * if the current user has insufficient privileges for this |
|
245 * operation |
|
246 */ |
|
247 public O workBusy(P pInput, I rtInput) |
|
248 throws ActionAbortedException, ActionFailedException, |
|
249 ActionUnauthorizedException { |
|
250 |
|
251 return null; |
|
252 } |
|
253 } |
|