001 /*
002 * file CcBrowser.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.CcBrowser
010 *
011 * © Copyright IBM Corporation 2006, 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 package com.ibm.rational.stp.client.samples;
016
017 import java.awt.BorderLayout;
018 import java.awt.FlowLayout;
019 import java.awt.Font;
020 import java.awt.Label;
021 import java.awt.event.ActionEvent;
022 import java.awt.event.ActionListener;
023 import java.io.File;
024 import java.util.Arrays;
025 import java.util.Vector;
026
027 import javax.swing.BoxLayout;
028 import javax.swing.JButton;
029 import javax.swing.JDialog;
030 import javax.swing.JFrame;
031 import javax.swing.JPanel;
032 import javax.swing.JScrollPane;
033 import javax.swing.JTextArea;
034 import javax.swing.JTextField;
035 import javax.swing.plaf.basic.BasicBorders;
036 import javax.wvcm.ControllableFolder;
037 import javax.wvcm.WvcmException;
038
039 import com.ibm.rational.stp.client.samples.BrowserDataModel.Operations;
040 import com.ibm.rational.wvcm.stp.StpLocation;
041 import com.ibm.rational.wvcm.stp.StpProvider;
042 import com.ibm.rational.wvcm.stp.cc.CcActivity;
043 import com.ibm.rational.wvcm.stp.cc.CcConfigSpec;
044 import com.ibm.rational.wvcm.stp.cc.CcFile;
045 import com.ibm.rational.wvcm.stp.cc.CcProvider;
046 import com.ibm.rational.wvcm.stp.cc.CcResource;
047 import com.ibm.rational.wvcm.stp.cc.CcStream;
048 import com.ibm.rational.wvcm.stp.cc.CcView;
049
050 /**
051 * An extension of the Browser example demonstrating application of ClearCase
052 * operations to the displayed resource
053 *
054 */
055 public class CcBrowser implements Operations {
056
057 public CcBrowser(com.ibm.rational.wvcm.stp.StpResource res) {
058 m_resource = res;
059 }
060
061 /**
062 * Returns the operations supported by the type of ClearCase resource being
063 * displayed in this window.
064 *
065 * @see com.ibm.rational.stp.client.samples.BrowserDataModel.Operations#getList()
066 */
067 public Vector<String> getList() {
068 if (m_resource instanceof CcView)
069 return new Vector<String>(Arrays.asList(viewOps));
070 else if (m_resource instanceof ControllableFolder)
071 return new Vector<String>(Arrays.asList(folderOps));
072 else if (m_resource instanceof CcFile)
073 return new Vector<String>(Arrays.asList(fileOps));
074 else
075 return new Vector<String>(Arrays.asList(otherOps));
076 }
077
078 /**
079 * Supports the operations implemented in the 7.1 CM API
080 * <ul>
081 * <li>VOB properties
082 * <li>Get CQ CqUserDb from Project (Translate CLEARQUEST_USER_DB property
083 * from CqUserDbRef to CqUserDb (ref.getUserDb))
084 * <li>Create Stream(parent stream, is-read-only, is-integration-stream)
085 * <li>Create Activity(headline, comment)
086 * <li>Get CQ record for an activity (Translate MY_ACTIVITY_LIST to Record
087 * list via CqRecordRef.getRecord().)
088 * <li>Create a Web view(new directory name, new tag name) Delete a view
089 * </ul>
090 */
091 public void execute(Object op, BrowserDataModel model) {
092 try {
093 if (op.equals(EDITCS_OP)) {
094 showConfigSpec((CcView) m_resource, true);
095 } else if (op.equals(VIEWCS_OP)) {
096 showConfigSpec((CcView) m_resource, false);
097 return; // No need to refresh
098 } else if (op.equals(DELETE_OP)) {
099 m_resource.doUnbindAll(null);
100 } else if (op.equals(MKVIEW_OP)) {
101 showResource("New View", mkView(m_resource));
102 return;
103 } else if (op.equals(MKACT_OP)) {
104 showResource("New Activity", mkActivity(m_resource));
105 return;
106 } else if (op.equals(MKSTREAM_OP)) {
107 showResource("New Stream", mkStream(m_resource));
108 return;
109 } else {
110 CcFile res = (CcFile) m_resource;
111
112 if (op.equals(CHECKOUT_OP)) {
113 res.doCheckout(null, null);
114 } else if (op.equals(CHECKIN_OP)) {
115 res.doCheckin(null, null);
116 } else if (op.equals(UNCHECKOUT_OP)) {
117 res.doUncheckout(null);
118 } else if (op.equals(CONTROL_OP)) {
119 res.doVersionControl(null);
120 } else if (op.equals(LOAD_OP)) {
121 res.doLoad(null);
122 } else if (op.equals(REFRESH_OP)) {
123 res.doRefresh(null, null);
124 } else if (op.equals(EDIT_OP)) {
125 File file = ((StpLocation) res.location()).getFile();
126 Runtime.getRuntime().exec("Notepad.exe \""
127 + file.getCanonicalFile() + "\"");
128 return; // no need to redisplay
129 } else if (op.equals(MKFILE_OP)) {
130 showResource("New File", mkFile(m_resource));
131 return; // no need to redisplay
132 } else if (op.equals(MKDIR_OP)) {
133 showResource("New Directory", mkDir(m_resource));
134 return; // no need to redisplay
135 } else
136 return;
137 }
138
139 model.redisplay();
140 } catch (Throwable t) {
141 Utilities.exception(null, "Invalid resource", t);
142 }
143 }
144
145 /**
146 * Displays the Config Spec for a specified ClearCase View and, optionally,
147 * allows the user to edit it.
148 *
149 * @param view
150 * The Workspace proxy for the ClearCase view whose ConfigSpec is
151 * to be displayed. Must not be null and must define the
152 * CONFIG_SPEC property.
153 * @param allowEdit
154 * If true, the displayed Config Spec is made editable and a
155 * button is added to the window for the user to click to commit
156 * the modified Config Spec.
157 * @throws WvcmException
158 * thrown if the required properties are not defined by the
159 * given proxy.
160 */
161 private void showConfigSpec(final CcView view, boolean allowEdit)
162 throws WvcmException {
163 final CcConfigSpec cs = view.getConfigSpec();
164 final JTextArea text = new JTextArea(680, 400);
165
166 text.append(cs.getElementRules());
167 text.append(BAR);
168 text.append(cs.getLoadRules());
169 text.setBorder(BasicBorders.getTextFieldBorder());
170 text.setCaretPosition(0);
171 text.setFont(new Font("Monospaced", Font.PLAIN, 12));
172
173 JFrame frame = new JFrame("Config Spec for " + view.getDisplayName());
174 final JDialog dialog = new JDialog(frame);
175 final JPanel panel = new JPanel(new BorderLayout());
176
177 if (allowEdit) {
178 final JPanel subpanel = new JPanel(new FlowLayout());
179 JButton update = new JButton("Update");
180
181 subpanel.add(update);
182 update.addActionListener(new ActionListener() {
183 public void actionPerformed(ActionEvent arg0) {
184 // set the return value here
185 try {
186 String newSpec = text.getText();
187 int sep = newSpec.indexOf(BAR);
188
189 cs.setElementRules(newSpec.substring(0, sep));
190 cs.setLoadRules(newSpec.substring(sep + BAR.length()));
191
192 view.setConfigSpec(cs);
193 view.doWriteProperties(null);
194 dialog.setVisible(false);
195 } catch (Throwable t) {
196 Utilities.exception(dialog, "Update Config Spec", t);
197 }
198 }
199 });
200
201 panel.add(subpanel, BorderLayout.SOUTH);
202
203 dialog.setModal(true);
204 }
205
206 panel.add(new JScrollPane(text), BorderLayout.CENTER);
207
208 dialog.setContentPane(panel);
209 dialog.setBounds(200, 300, 600, 300);
210 dialog.setVisible(true);
211 dialog.setVisible(false);
212 }
213
214 /**
215 * A convenience method for invoking {@link Browser#showResource
216 * Browser.showResource} on a given resource only if it is not null.
217 *
218 * @param name A brief description of the resource type for inclusion in
219 * the title of window that will be used to display the resource
220 * @param res The resource to be displayed. May be null.
221 * @throws WvcmException If there are problems viewing a non-null resource.
222 */
223 void showResource(String name, CcResource res) throws WvcmException {
224 if (res != null) {
225 Browser.showResource(name + " " + res.location(),
226 res,
227 Browser.META_PROPS.toArray(),
228 true);
229 }
230 }
231
232 /**
233 * Creates a new file after getting its name from the user.
234 * @param dir The directory in which to create the new file.
235 * @return A ControllableResource proxy representing the newly created
236 * file.
237 */
238 CcFile mkFile(javax.wvcm.Resource dir) {
239 try {
240 String[] names = { "New File Location" };
241 // Todo Need to decode the selector name
242 String[] args = { ((StpLocation) dir.location()).getCanonicalPath() };
243
244 getArgs(names, args);
245
246 File file = new File(args[0]);
247 CcProvider provider = (CcProvider) dir.provider();
248 StpLocation fileLoc = provider
249 .filePathLocation(StpProvider.Domain.CLEAR_CASE, file);
250
251 file.createNewFile();
252 // TODO Need to modify this for running on UNIX systems
253 Runtime.getRuntime().exec("Notepad.exe \""
254 + file.getCanonicalFile() + "\"");
255
256 return provider.ccFile(fileLoc);
257 } catch (Throwable t) {
258 Utilities.exception(null, "Make File", t);
259 }
260
261 return null;
262 }
263
264 /**
265 * Creates a new directory after obtaining its name from the user
266 * @param parent The default context in which the directory will be
267 * constructed. May be changed by user.
268 * @return A ControllableFolder for the newly constructed directory.
269 */
270 CcFile mkDir(javax.wvcm.Resource parent) {
271 try {
272 String[] names = { "New Directory Location" };
273 String[] args =
274 { ((StpLocation) parent.location()).getCanonicalPath() };
275
276 getArgs(names, args);
277
278 File dir = new File(args[0]);
279 CcProvider provider = (CcProvider) parent.provider();
280 StpLocation fileLoc = provider
281 .filePathLocation(StpProvider.Domain.CLEAR_CASE, dir);
282
283 dir.mkdir();
284
285 return provider.ccDirectory(fileLoc);
286 } catch (Throwable t) {
287 Utilities.exception(null, "Make Directory", t);
288 }
289
290 return null;
291 }
292
293 /**
294 * Creates a ClearCase view after getting creation parameters from the user.
295 * @param context The Default context in which the view is to be created.
296 * May be modified by the user.
297 * @return A Workspace proxy for the created view. Will be null if the
298 * view was not created.
299 */
300 CcView mkView(javax.wvcm.Resource context) {
301 try {
302 String[] names = { "View Tag", "File Area", "Comment" };
303 String[] args = { null, context.location().string(), "Create view" };
304
305 getArgs(names, args);
306
307 CcProvider provider = (CcProvider) context.provider();
308 StpLocation clientLoc = (StpLocation) provider.location(args[1]);
309 CcView clientWs = provider.ccView(clientLoc);
310
311 clientWs.setComment(args[2]);
312 // TODO When implemented...
313 // clientWs.setIsUcmView(args[3]);
314 //
315 // if (clientWs.getIsUcmView()) {
316 // clientWs.setProject(args[4]);
317 // clientWs.setStream(args[5]);
318 // }
319 clientWs.doCreateResource(null);
320 } catch (Throwable t) {
321 Utilities.exception(null, "Make View", t);
322 }
323
324 return null;
325 }
326
327 /**
328 * Creates a new UCM Stream after obtaining parameters from user.
329 * @param context The default context in which to create the new UCM Stream.
330 * May be modified by the user.
331 * @return A UcmStream proxy for the new stream; null if the stream was not
332 * created.
333 */
334 CcStream mkStream(javax.wvcm.Resource context) {
335 try {
336 String[] args = getArgs(new String[] { "Name (required)",
337 "Parent Stream/Project (required)",
338 "Is Read Only (true/false)",
339 "Default Deliver Target (optional)" });
340 CcProvider provider = (CcProvider) context.provider();
341 StpLocation streamLoc = (StpLocation) provider.location(args[0]);
342 CcStream stream = provider.ccStream(streamLoc);
343 StpLocation parentSelector = provider.stpLocation(args[1]);
344
345 if (parentSelector.getNamespace().equals(StpLocation.Namespace.STREAM)) {
346 stream.setIsIntegrationStream(false);
347 stream.setParentStream(provider.ccStream((StpLocation) provider
348 .location(args[1])));
349 } else {
350 stream.setIsIntegrationStream(true);
351 stream.setParentProject(provider.ccProject((StpLocation) provider
352 .location(args[1])));
353 }
354
355 stream.setIsReadOnly(args[2].startsWith("t"));
356
357 if (args[3].length() > 0) {
358 stream.setDefaultDeliverTarget(provider
359 .ccStream((StpLocation) provider.location(args[3])));
360 }
361
362 stream.doCreateResource(null);
363
364 return stream;
365 } catch (Throwable t) {
366 Utilities.exception(null, "Make Stream", t);
367 }
368 return null;
369 }
370
371 /**
372 * Creates an activity based on input from the user.
373 * @param context The context in which the activity will be created, which
374 * may be ignored by the user.
375 * @return A UcmActivity proxy for the newly created activity; null if the
376 * activity was not created.
377 */
378 CcActivity mkActivity(javax.wvcm.Resource context) {
379 try {
380 String[] args = getArgs(new String[] { "Stream (required)",
381 "Headline (optional)", "Comment (optional)" });
382 CcProvider provider = (CcProvider) context.provider();
383 StpLocation streamLoc = (StpLocation) provider.location(args[0]);
384 CcStream stream = provider.ccStream(streamLoc);
385 StpLocation actloc = (StpLocation) provider.location("cc.activity:foo@"
386 + streamLoc.getRepo());
387 CcActivity act = provider.ccActivity(actloc);
388
389 act.setStream(stream);
390 act.setHeadline(args[1]);
391 act.setComment(args[2]);
392 act.doCreateResource(null);
393
394 return act;
395 } catch (Throwable t) {
396 Utilities.exception(null, "Make Activity", t);
397 }
398
399 return null;
400 }
401
402 /**
403 * Displays a list of parameters to the user with default values and then
404 * allows the user to add or modify values.
405 * @param names The names of the parameters to be obtained from the user.
406 * @param result On input, the default values to display in the dialog;
407 * on output, contains the values entered by the user.
408 */
409 void getArgs(final String[] names, final String[] result) {
410 JFrame frame = new JFrame("Enter Parameters");
411 final JDialog dialog = new JDialog(frame);
412 final JPanel panel = new JPanel();
413 panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
414 final JTextField[] fields = new JTextField[names.length];
415
416 for (int i = 0; i < names.length; ++i) {
417 JTextField field = new JTextField();
418
419 if (result[i] != null)
420 field.setText(result[i]);
421
422 fields[i] = field;
423 panel.add(new Label(names[i]));
424 panel.add(field);
425 }
426
427 JButton update = new JButton("Ok");
428
429 panel.add(update);
430 update.addActionListener(new ActionListener() {
431 public void actionPerformed(ActionEvent arg0) {
432 // set the return value here
433 try {
434 for (int j = 0; j < names.length; ++j)
435 result[j] = fields[j].getText();
436
437 dialog.dispose();
438 } catch (Throwable t) {
439 Utilities.exception(dialog, "Specify Parameters", t);
440 }
441 }
442 });
443
444 dialog.setModal(true);
445 dialog.setContentPane(panel);
446 dialog.setBounds(200, 300, 600, 20 + 60 * names.length);
447 dialog.setVisible(false);
448 }
449
450 /**
451 * Obtains a list of parameter values from the user.
452 * @param names The names of the parameters that user is supposed to provide.
453 * @return A String array contain the user's input for each parameter.
454 */
455 String[] getArgs(String[] names) {
456 final String[] result = new String[names.length];
457 getArgs(names, result);
458
459 return result;
460 }
461
462 /**
463 * The line of text used to separate the Element Rules from the Load Rules
464 * in a Config Spec.
465 */
466 private static final String BAR = "=== Element Rules/Load Rules Boundary DO NOT REMOVE ===\n";
467
468 final private static String CHECKOUT_OP = "Check Out";
469
470 final private static String CHECKIN_OP = "Check In";
471
472 final private static String UNCHECKOUT_OP = "Uncheck Out";
473
474 final private static String CONTROL_OP = "Control";
475
476 final private static String REFRESH_OP = "Refresh";
477
478 final private static String LOAD_OP = "Load";
479
480 // final private static String UNLOAD_OP = "Unload";
481 final private static String EDIT_OP = "Edit";
482
483 final private static String DELETE_OP = "Delete";
484
485 final private static String VIEWCS_OP = "View Config Spec";
486
487 final private static String EDITCS_OP = "Edit Config Spec";
488
489 final private static String MKDIR_OP = "Make Directory";
490
491 final private static String MKFILE_OP = "Make File";
492
493 final private static String MKVIEW_OP = "Make View";
494
495 final private static String MKACT_OP = "Make Activity";
496
497 final private static String MKSTREAM_OP = "Make Stream";
498
499 /** The operations supported on Folders */
500 private static final String[] folderOps = { CHECKOUT_OP, CHECKIN_OP,
501 UNCHECKOUT_OP, CONTROL_OP, REFRESH_OP, LOAD_OP,
502 // UNLOAD_OP,
503 DELETE_OP, MKDIR_OP, MKFILE_OP, MKACT_OP, MKSTREAM_OP, MKVIEW_OP };
504
505 /** The operations supported on Files */
506 private static final String[] fileOps = { CHECKOUT_OP, CHECKIN_OP,
507 UNCHECKOUT_OP, CONTROL_OP, REFRESH_OP, LOAD_OP,
508 // UNLOAD_OP,
509 EDIT_OP, DELETE_OP, MKACT_OP, MKSTREAM_OP, MKVIEW_OP };
510
511 /** The operations supported on views */
512 private static final String[] viewOps = { VIEWCS_OP, EDITCS_OP, REFRESH_OP,
513 DELETE_OP, MKDIR_OP, MKACT_OP, MKSTREAM_OP, MKVIEW_OP, };
514
515 /** The operations supported on all resources */
516 private static final String[] otherOps = { DELETE_OP, MKACT_OP,
517 MKSTREAM_OP, MKVIEW_OP, };
518
519 /** A proxy for the resource being displayed by this Browser window */
520 com.ibm.rational.wvcm.stp.StpResource m_resource;
521
522 /**
523 * Starts the ClearCase version of the Browser using the CcBrower class as
524 * the source for resource operations.
525 *
526 * @param args
527 * Not used in this application
528 */
529 public static void main(String[] args) throws Exception {
530 Browser.g_operationsClass = CcBrowser.class;
531
532 Browser.main(args);
533 }
534
535 }