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 }