001 /*
002 * file Utilities.java
003 *
004 * Licensed Materials - Property of IBM
005 * Restricted Materials of IBM - you are allowed to copy, modify and
006 * redistribute this file as part of any program that interfaces with
007 * IBM Rational CM API.
008 *
009 * com.ibm.rational.stp.client.samples.Utilities
010 *
011 * (C) Copyright IBM Corporation 2004, 2008. All Rights Reserved.
012 * Note to U.S. Government Users Restricted Rights: Use, duplication or
013 * disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
014 */
015
016 package com.ibm.rational.stp.client.samples;
017
018 import java.awt.Component;
019 import java.io.File;
020 import java.io.FileReader;
021 import java.lang.reflect.InvocationTargetException;
022 import java.util.List;
023
024 import javax.swing.JOptionPane;
025 import javax.wvcm.Feedback;
026 import javax.wvcm.ProviderFactory;
027 import javax.wvcm.Resource;
028 import javax.wvcm.ResourceList;
029 import javax.wvcm.WvcmException;
030 import javax.wvcm.PropertyRequestItem.PropertyRequest;
031 import javax.wvcm.ProviderFactory.Callback;
032 import javax.wvcm.ProviderFactory.Callback.Authentication;
033
034 import com.ibm.rational.wvcm.stp.StpException;
035 import com.ibm.rational.wvcm.stp.StpProvider;
036 import com.ibm.rational.wvcm.stp.StpResource;
037 import com.ibm.rational.wvcm.stp.StpProvider.Domain;
038 import com.ibm.rational.wvcm.stp.StpProvider.StpCallback;
039 import com.ibm.rational.wvcm.stp.cq.CqDbSet;
040 import com.ibm.rational.wvcm.stp.cq.CqProvider;
041 import com.ibm.rational.wvcm.stp.cq.CqUser;
042 import com.ibm.rational.wvcm.stp.cq.CqUserDb;
043
044 /**
045 * A collection of static utility methods supporting the CM API examples
046 */
047 public class Utilities {
048
049 /**
050 * A simple Authentication object in which the username and password
051 * obtained from the user is cached for use by the CM API.
052 */
053 static class UnPw implements Authentication {
054 /**
055 * Constructs an Authentication object
056 *
057 * @param unpw A String[] containing the username and password.
058 */
059 UnPw(String[] unpw) { m_data = unpw; }
060
061 public String loginName() { return m_data[0]; }
062 public String password() { return m_data.length > 1 ? m_data[1] : ""; };
063
064 /** The cached credentials */
065 private String[] m_data;
066 }
067
068 /** Password used by static callback */
069 public static String g_pass = "";
070 /** User name used by static callback */
071 public static String g_user = "admin";
072
073 private static Callback g_callback = new Callback()
074 {
075 public Authentication getAuthentication(String realm, int retryCount)
076 {
077 if (retryCount > 0)
078 throw new IllegalAccessError("Wrong username/password for " + realm);
079 return new Authentication()
080 {
081 public String loginName()
082 {
083 return g_user;
084 }
085
086 public String password()
087 {
088 return g_pass;
089 }
090 };
091 }
092 };
093
094 public static CqProvider getStaticProvider()
095 throws Exception
096 {
097 return (CqProvider) ProviderFactory
098 .createProvider(CqProvider.CQ_ONLY_PROVIDER_CLASS, g_callback);
099 }
100
101 /**
102 * Constructs an instance of the CM API provider with or without an
103 * authenticator.
104 *
105 * @return The instantiated Provider object
106 * @throws Exception
107 * If the Provider could not be instantiated
108 */
109 static StpProvider getProvider() throws Exception {
110 try {
111 Callback callback = new StpCallback() {
112 private UnPw m_unpw;
113
114 public Authentication getAuthentication(String r, int c)
115 { return null; /* Will not be called */ }
116
117 public Authentication getAuthenticationEx(Domain domain,
118 String realm,
119 int retryCount,
120 StpProvider provider,
121 WvcmException failure)
122 throws WvcmException
123 {
124 // Try to reuse last credentials on each new repository
125 if (m_unpw != null && retryCount == 0)
126 return m_unpw;
127
128 String title = "Enter " + domain
129 + " Username '+' Password for "
130 + realm + " [" + retryCount + "]";
131
132 if (failure != null)
133 title = "Login failed: " + failure + "\n" + title;
134
135 String unpw = JOptionPane.showInputDialog(title, "admin+");
136
137 if (unpw == null || unpw.length() == 0)
138 throw new IllegalAccessError("User canceled request");
139
140 if (unpw.equals("anonymous"))
141 return null;
142
143 if (unpw.startsWith("@")) {
144 File file = new File(unpw.substring(1));
145
146 try {
147 FileReader reader = new FileReader(file);
148 char[] buf = new char[100];
149 int count = reader.read(buf);
150
151 unpw = new String(buf, 0, count);
152 reader.close();
153 } catch (Throwable t) {
154 Utilities.exception(null,
155 "Reading password file " + unpw,
156 t);
157 }
158 }
159
160 return m_unpw = new UnPw(unpw.split("\\+", -2));
161 }
162 };
163
164 // Instantiate a Provider
165 return (StpProvider) ProviderFactory
166 .createProvider(StpProvider.PROVIDER_CLASS, callback);
167 } catch (InvocationTargetException ite) {
168 WvcmException e = (WvcmException) ite.getTargetException();
169
170 System.out.println("*** " + e);
171
172 for (Throwable nested: e.getNestedExceptions())
173 System.out.println("*** " + nested);
174
175 throw e;
176 }
177 }
178
179 static ResourceList<CqUserDb> getUserDbList(CqProvider provider,
180 PropertyRequest feedback)
181 throws WvcmException
182 {
183 PropertyRequest wantedProps =
184 new PropertyRequest(CqDbSet.CURRENT_USER
185 .nest(CqUser.SUBSCRIBED_DATABASES.nest(feedback)));
186 ResourceList<CqUserDb> result = provider.resourceList();
187
188 for (CqDbSet set : provider.doGetDbSetList(wantedProps)) {
189 if (set.getResourceError() == null)
190 result.addAll(set.getCurrentUser().getSubscribedDatabases());
191 }
192
193 return result;
194 }
195
196 /**
197 * Extracts the message content from a Throwable and returns it as a
198 * hierarchical array of Strings capturing the nesting of the Throwable's
199 * message components. This structure formats reasonably in a SWING
200 * showMessageDialog invocation.
201 *
202 * @param ex The Throwable object whose message content is to be extracted.
203 * @return If the given Throwable has nested components, an array consisting
204 * of the Throwable's message and an array of the nested messages.
205 */
206 private static Object messages(Throwable ex) {
207 String msg = ex.getLocalizedMessage();
208
209 if (msg == null || msg.length() == 0)
210 msg = ex.toString();
211
212 if (ex instanceof StpException) {
213 Throwable[] nested = ((StpException) ex).getNestedExceptions();
214
215 if (nested != null && nested.length > 0) {
216 Object[] msgs = new Object[nested.length];
217
218 for (int i = 0; i < msgs.length; ++i)
219 msgs[i] = messages(nested[i]);
220
221 return new Object[] { msg, msgs };
222 }
223 } else if (ex.getCause() != null) {
224 return new Object[] {msg, new Object[]{messages(ex.getCause())}};
225 }
226
227 return msg;
228 }
229
230 /**
231 * Displays a Swing dialog containing the messages associated with a given
232 * Throwable.
233 *
234 * @param frame The parent frame for the message dialog.
235 * @param title The title to appear in the dialog window.
236 * @param ex The throwable whose messages are to be displayed.
237 */
238 static void exception(Component frame, String title, Throwable ex) {
239 JOptionPane.showMessageDialog(frame,
240 messages(ex),
241 title,
242 JOptionPane.ERROR_MESSAGE);
243 }
244
245 /**
246 * Returns a String suitable for displaying the type of resource as
247 * determined by its proxy class.
248 *
249 * @param resource
250 * A Resource proxy from which the type of resource will be
251 * determined.
252 * @return A String containing the simple name of the most derived CM API
253 * interface implemented by the given proxy.
254 */
255 static String resourceType(Resource resource) {
256 Class interfaces[] = resource.getClass().getInterfaces();
257 Class<?> choice = Resource.class;
258
259 for (int i = 0; i < interfaces.length; ++i) {
260 String name = interfaces[i].getName();
261 if (name.startsWith("com.ibm.rational.wvcm.")
262 || name.startsWith("javax.wvcm")) {
263
264 // Within the CM API, select the most derived interface
265 // this resource implements
266 if (choice.isAssignableFrom(interfaces[i]))
267 choice = interfaces[i];
268 }
269 }
270
271 String name = choice.getName();
272
273 return name.substring(1+name.lastIndexOf('.'));
274 }
275
276 static boolean isListOfResources(Object val)
277 {
278 return val instanceof ResourceList;
279 }
280
281 static ResourceList<? extends StpResource> toResourceList(StpProvider provider,
282 List list)
283 {
284 if (list instanceof ResourceList)
285 return (ResourceList<? extends StpResource>)list;
286
287 return provider.resourceList();
288 }
289 }