1 31 32 33 package org.antlr.works.scm.p4; 34 35 import org.antlr.works.prefs.AWPrefs; 36 import org.antlr.works.scm.SCM; 37 import org.antlr.works.scm.SCMDelegate; 38 import org.antlr.works.utils.Console; 39 40 import javax.swing.*; 41 import java.io.*; 42 import java.util.ArrayList ; 43 import java.util.Iterator ; 44 import java.util.List ; 45 46 public class P4 implements SCM { 47 48 protected static final int CMD_EDIT = 1; 49 protected static final int CMD_ADD = 2; 50 protected static final int CMD_REVERT = 3; 51 protected static final int CMD_DELETE = 4; 52 protected static final int CMD_SUBMIT = 5; 53 protected static final int CMD_SYNC = 6; 54 protected static final int CMD_FSTAT = 7; 55 56 protected SCMDelegate delegate = null; 57 protected String fileStatus = null; 58 59 protected P4Scheduler scheduler = new P4Scheduler(); 60 protected P4CommandCompletion lastCompletion = null; 61 62 protected Console console; 63 64 private final Object lock = new Object (); 65 66 public P4(SCMDelegate delegate, Console console) { 67 this.delegate = delegate; 68 this.console = console; 69 } 70 71 public synchronized void queryFileStatus(String file) { 72 runCommand(new P4Command(CMD_FSTAT, new String [] { "fstat", file }, null)); 73 } 74 75 public synchronized void editFile(String file) { 76 scheduleCommand(new P4Command(CMD_EDIT, new String [] { "edit", file }, null)); 77 queryFileStatus(file); 78 } 79 80 public synchronized void addFile(String file) { 81 scheduleCommand(new P4Command(CMD_ADD, new String [] { "add", file }, null)); 82 queryFileStatus(file); 83 } 84 85 public synchronized void deleteFile(String file) { 86 scheduleCommand(new P4Command(CMD_DELETE, new String [] { "delete", file }, null)); 87 queryFileStatus(file); 88 } 89 90 public synchronized void revertFile(String file) { 91 scheduleCommand(new P4Command(CMD_REVERT, new String [] { "revert", file }, null)); 92 queryFileStatus(file); 93 } 94 95 public synchronized void submitFile(String file, String description, boolean remainOpen) { 96 scheduleCommand(new P4Command(CMD_FSTAT, new String [] { "fstat", file }, null)); 97 scheduleCommand(new P4CommandSubmit(file, description, remainOpen)); 98 queryFileStatus(file); 99 } 100 101 public synchronized void sync() { 102 runCommand(new P4Command(CMD_SYNC, new String [] { "sync" }, null)); 103 } 104 105 public synchronized boolean isFileWritable() { 106 if(fileStatus == null) 107 return true; 108 else 109 return fileStatus.equals("edit"); 110 } 111 112 public synchronized String getFileStatus() { 113 return fileStatus; 114 } 115 116 public synchronized boolean hasErrors() { 117 if(lastCompletion == null) 118 return false; 119 else 120 return lastCompletion.hasErrors(); 121 } 122 123 public synchronized String getErrorsDescription() { 124 if(lastCompletion == null) 125 return ""; 126 else 127 return lastCompletion.errorsDescription(); 128 } 129 130 public void resetErrors() { 131 lastCompletion = null; 132 } 133 134 protected void runCommand(P4Command command) { 135 scheduleCommand(command); 136 scheduleLaunch(); 137 } 138 139 protected void scheduleCommand(P4Command command) { 140 scheduler.scheduleCommand(command); 141 } 142 143 protected synchronized void scheduleLaunch() { 144 if(!scheduler.isRunning()) 145 scheduler.start(); 146 } 147 148 protected class P4Scheduler implements Runnable , P4CommandCompletionDelegate { 149 150 protected List <P4Command> scheduledCommands = new ArrayList <P4Command>(); 151 protected P4Command runningCommand = null; 152 153 public void start() { 154 new Thread (this).start(); 155 } 156 157 public void run() { 158 scheduleRun(null); 159 } 160 161 protected void scheduleCommand(P4Command command) { 162 synchronized(lock) { 163 scheduledCommands.add(command); 164 } 165 } 166 167 protected synchronized boolean isRunning() { 168 return runningCommand != null; 169 } 170 171 protected synchronized void scheduleRun(P4Command previousCommand) { 172 if(runningCommand != null) { 173 if(runningCommand != previousCommand) { 174 return; 177 } 178 } 179 180 synchronized(lock) { 181 if(scheduledCommands.isEmpty()) { 182 runningCommand = null; 183 } else { 184 runningCommand = scheduledCommands.get(0); 185 scheduledCommands.remove(0); 186 } 187 } 188 189 if(runningCommand == null) { 190 schedulerDidComplete(); 191 } else 192 runningCommand.run(previousCommand, this); 193 } 194 195 public void commandDidComplete(P4CommandCompletion completion) { 196 if(completion.commandID == CMD_FSTAT) { 197 fileStatus = completion.getObjectForKey(P4Results.OTHER, "action"); 199 if(fileStatus == null) { 200 if(completion.hasErrors()) 201 fileStatus = "?"; 202 else 203 fileStatus = "closed"; 204 } 205 206 if(delegate != null) 207 delegate.scmFileStatusDidChange(fileStatus); 208 } 209 210 lastCompletion = completion; 211 212 if(completion.hasErrors()) { 213 synchronized(lock) { 215 scheduledCommands.clear(); 216 runningCommand = null; 217 delegate.scmCommandsDidComplete(); 218 } 219 } else 220 scheduleRun(runningCommand); 221 } 222 223 public void schedulerDidComplete() { 224 if(delegate != null) { 225 SwingUtilities.invokeLater(new Runnable () { 226 public void run() { 227 delegate.scmCommandsDidComplete(); 228 } 229 }); 230 } 231 } 232 } 233 234 protected class P4Command { 235 236 public int commandID; 237 public String [] commands; 238 public String [] inputArguments; 239 public P4CommandCompletion completion = null; 240 241 public P4Command(int commandID, String [] commands, String [] inputArguments) { 242 this.commandID = commandID; 243 this.commands = commands; 244 this.inputArguments = inputArguments; 245 } 246 247 public void run(P4Command previousCommand, P4CommandCompletionDelegate delegate) { 248 runCommand(commandID, commands, inputArguments, delegate); 249 } 250 251 protected boolean runCommand(int commandID, String [] params, String [] inputArguments, P4CommandCompletionDelegate delegate) { 252 String [] command = buildCommand(params); 253 boolean success = false; 254 255 try { 256 Process p = Runtime.getRuntime().exec(command); 257 258 completion = new P4CommandCompletion(p, commandID, delegate); 259 260 if(inputArguments != null) { 261 OutputStream os = p.getOutputStream(); 262 OutputStreamWriter osw = new OutputStreamWriter(os); 263 BufferedWriter out = new BufferedWriter(osw); 264 for(int i=0; i<inputArguments.length; i++) { 265 out.write(inputArguments[i]); 266 out.newLine(); 267 } 268 out.flush(); 269 out.close(); 270 } 271 272 success = (completion.processExitCode = p.waitFor()) == 0; 273 completion.processTerminated(); 274 275 } catch (Exception e) { 276 console.print(e); 277 } 278 return success; 279 } 280 281 protected String [] buildCommand(String [] params) { 282 String [] command = new String [10+params.length]; 283 284 int i = 0; 285 command[i++] = AWPrefs.getP4ExecPath(); 286 command[i++] = "-s"; 287 command[i++] = "-p"; 288 command[i++] = AWPrefs.getP4Port(); 289 command[i++] = "-u"; 290 command[i++] = AWPrefs.getP4User(); 291 command[i++] = "-P"; 292 command[i++] = AWPrefs.getP4Password(); 293 command[i++] = "-c"; 294 command[i++] = AWPrefs.getP4Client(); 295 296 for(int j=0; j<params.length; j++) 297 command[i++] = params[j]; 298 299 return command; 300 } 301 } 302 303 protected class P4CommandSubmit extends P4Command { 304 305 public String file; 306 public String description; 307 public boolean remainOpen; 308 309 public P4CommandSubmit(String file, String description, boolean remainOpen) { 310 super(CMD_SUBMIT, null, null); 311 312 this.file = file; 313 this.description = description; 314 this.remainOpen = remainOpen; 315 } 316 317 public void run(P4Command previousCommand, P4CommandCompletionDelegate delegate) { 318 String depotFile = previousCommand.completion.getObjectForKey(P4Results.OTHER, "depotFile"); 320 if(depotFile != null) { 321 String [] commands; 322 if(remainOpen) 323 commands = new String [] { "submit", "-r", "-i" }; 324 else 325 commands = new String [] { "submit", "-i" }; 326 327 runCommand(CMD_SUBMIT, 329 commands, 330 new String [] { "Change: new", 331 "Client: "+AWPrefs.getP4Client(), 332 "User: "+ AWPrefs.getP4User(), 333 "Description:\n\t"+description, 334 "Files:\n\t"+depotFile}, 335 delegate); 336 } 337 } 338 } 339 340 protected class P4Results { 341 342 public static final int ERROR = 0; 343 public static final int WARNING = 1; 344 public static final int TEXT = 2; 345 public static final int INFO = 3; 346 public static final int EXIT = 4; 347 public static final int OTHER = 5; 348 349 protected List [] texts = new List [6]; 350 351 public P4Results() { 352 for(int i=0; i<texts.length; i++) 353 texts[i] = new ArrayList (); 354 } 355 356 public void reset() { 357 for(int i=0; i<texts.length; i++) 358 texts[i].clear(); 359 } 360 361 public void add(int index, String error) { 362 texts[index].add(error.trim()); 363 } 364 365 public List get(int index) { 366 return texts[index]; 367 } 368 } 369 370 protected interface P4CommandCompletionDelegate { 371 public void commandDidComplete(P4CommandCompletion completion); 372 } 373 374 protected class P4CommandCompletion implements StreamWatcherDelegate { 375 376 public P4Results results = new P4Results(); 377 public int commandID = 0; 378 public P4CommandCompletionDelegate delegate = null; 379 380 public StreamWatcher errorStreamWatcher = null; 381 public StreamWatcher inputStreamWatcher = null; 382 383 public int processExitCode = 0; 384 public boolean processTerminated = false; 385 386 public P4CommandCompletion(Process p, int commandID, P4CommandCompletionDelegate delegate) { 387 results.reset(); 388 389 this.commandID = commandID; 390 this.delegate = delegate; 391 392 errorStreamWatcher = new StreamWatcher(p.getErrorStream(), "error", this); 393 errorStreamWatcher.start(); 394 395 inputStreamWatcher = new StreamWatcher(p.getInputStream(), "input", this); 396 inputStreamWatcher.start(); 397 } 398 399 public boolean hasErrors() { 400 return results.get(P4Results.ERROR).size() > 0; 401 } 402 403 public String errorsDescription() { 404 StringBuffer sb = new StringBuffer (); 405 for(Iterator iter = results.get(P4Results.ERROR).iterator(); iter.hasNext(); ) { 406 sb.append((String )iter.next()); 407 } 408 return sb.toString(); 409 } 410 411 public String getObjectForKey(int index, String key) { 412 Iterator iter = results.get(index).iterator(); 413 while(iter.hasNext()) { 414 String text = (String )iter.next(); 415 if(text.startsWith(key)) { 416 return text.substring(key.length()+1).trim(); 417 } 418 } 419 return null; 420 } 421 422 public synchronized void processTerminated() { 423 processTerminated = true; 424 notifyIfCommandCompleted(); 425 } 426 427 public synchronized void notifyIfCommandCompleted() { 428 if(errorStreamWatcher == null && inputStreamWatcher == null && processTerminated) { 429 if(delegate != null) 432 delegate.commandDidComplete(this); 433 } 434 } 435 436 public synchronized void streamWatcherDidReceiveText(StreamWatcher sw, String line) { 437 if(P4.this.delegate != null) 438 P4.this.delegate.scmLog(line); 439 440 int index = line.indexOf(':'); 441 String text = line; 442 if(index != -1) 443 text = line.substring(index+1); 444 445 if(line.startsWith("error:")) 446 results.add(P4Results.ERROR, text); 447 else if(line.startsWith("warning:")) 448 results.add(P4Results.WARNING, text); 449 else if(line.startsWith("text:")) 450 results.add(P4Results.TEXT, text); 451 else if(line.startsWith("info:")) 452 results.add(P4Results.INFO, text); 453 else if(line.startsWith("exit:")) 454 results.add(P4Results.EXIT, text); 455 else 456 results.add(P4Results.OTHER, text); 457 } 458 459 public synchronized void streamWatcherDidEnd(StreamWatcher sw) { 460 if(sw == errorStreamWatcher) 461 errorStreamWatcher = null; 462 if(sw == inputStreamWatcher) 463 inputStreamWatcher = null; 464 465 notifyIfCommandCompleted(); 466 } 467 } 468 469 protected interface StreamWatcherDelegate { 470 public void streamWatcherDidReceiveText(StreamWatcher sw, String text); 471 public void streamWatcherDidEnd(StreamWatcher sw); 472 } 473 474 protected class StreamWatcher extends Thread { 475 476 public InputStream is; 477 public String type; 478 public StreamWatcherDelegate delegate; 479 480 public StreamWatcher(InputStream is, String type, StreamWatcherDelegate delegate) { 481 this.is = is; 482 this.type = type; 483 this.delegate = delegate; 484 } 485 486 public void run() { 487 try { 488 BufferedReader br = new BufferedReader(new InputStreamReader(is)); 489 String line; 490 while ( (line = br.readLine()) != null) { 491 if(delegate != null) 492 delegate.streamWatcherDidReceiveText(this, line); 493 } 494 } catch (IOException e) { 495 console.print(e); 496 } 497 if(delegate != null) 498 delegate.streamWatcherDidEnd(this); 499 } 500 } 501 502 } 503 | Popular Tags |