1 19 20 package org.netbeans.modules.ruby.railsprojects; 21 22 import java.io.File ; 23 import java.io.IOException ; 24 import java.net.MalformedURLException ; 25 import java.net.URL ; 26 import java.util.Arrays ; 27 import java.util.Collection ; 28 import java.util.HashSet ; 29 import java.util.LinkedHashSet ; 30 import java.util.Set ; 31 import org.netbeans.api.project.ProjectInformation; 32 import org.netbeans.modules.ruby.railsprojects.server.WebrickServer; 33 import org.netbeans.modules.ruby.rubyproject.api.RubyExecution; 34 import org.netbeans.modules.ruby.rubyproject.execution.ExecutionService; 35 import org.netbeans.modules.ruby.rubyproject.api.RubyInstallation; 36 import org.netbeans.api.project.ProjectUtils; 37 import org.netbeans.modules.ruby.railsprojects.ui.customizer.RailsProjectProperties; 38 import org.netbeans.modules.ruby.rhtml.RhtmlKit; 39 import org.netbeans.modules.ruby.rubyproject.execution.ExecutionDescriptor; 40 import org.netbeans.modules.ruby.rubyproject.execution.ExecutionService; 41 import org.netbeans.modules.ruby.rubyproject.api.RubyInstallation; 42 import org.netbeans.modules.ruby.rubyproject.execution.FileLocator; 43 import org.netbeans.spi.project.ActionProvider; 44 import org.netbeans.spi.project.ui.support.DefaultProjectOperations; 45 import org.openide.ErrorManager; 46 import org.openide.LifecycleManager; 47 import org.openide.awt.HtmlBrowser; 48 import org.openide.cookies.SaveCookie; 49 import org.openide.filesystems.FileObject; 50 import org.openide.filesystems.FileUtil; 51 import org.openide.loaders.DataObject; 52 import org.openide.loaders.DataObjectNotFoundException; 53 import org.openide.util.Exceptions; 54 import org.openide.util.Lookup; 55 56 59 public class RailsActionProvider implements ActionProvider { 60 64 public static final String COMMAND_RDOC = "rdoc"; 66 private static final String [] supportedActions = { 68 COMMAND_BUILD, 69 COMMAND_CLEAN, 70 COMMAND_REBUILD, 71 COMMAND_RDOC, 72 COMMAND_RUN, 74 COMMAND_RUN_SINGLE, 75 COMMAND_TEST_SINGLE, 79 COMMAND_DELETE, 82 COMMAND_COPY, 83 COMMAND_MOVE, 84 COMMAND_RENAME, 85 }; 86 87 88 RailsProject project; 90 91 private UpdateHelper updateHelper; 93 94 95 96 final Set <String > bkgScanSensitiveActions; 97 98 public RailsActionProvider( RailsProject project, UpdateHelper updateHelper ) { 99 this.bkgScanSensitiveActions = new HashSet <String >(Arrays.asList(new String [] { 100 COMMAND_RUN, 101 COMMAND_RUN_SINGLE, 102 })); 106 107 this.updateHelper = updateHelper; 108 this.project = project; 109 } 110 111 115 public String [] getSupportedActions() { 116 return supportedActions; 117 } 118 119 public void invokeAction( final String command, final Lookup context ) throws IllegalArgumentException { 120 if (COMMAND_RUN.equals(command)) { 122 LifecycleManager.getDefault().saveAll(); 124 125 WebrickServer server = project.getLookup().lookup(WebrickServer.class); 126 if (server != null) { 127 server.showUrl(""); } 129 130 return; 131 } else if (COMMAND_RUN_SINGLE.equals(command)) { 132 FileObject file = findSources(context)[0]; 133 134 try { 136 DataObject dobj = DataObject.find(file); 137 if (dobj != null) { 138 SaveCookie saveCookie = dobj.getCookie(SaveCookie.class); 139 if (saveCookie != null) { 140 saveCookie.save(); 141 } 142 } 143 } catch (DataObjectNotFoundException donfe) { 144 ErrorManager.getDefault().notify(donfe); 145 } catch (IOException ioe) { 146 ErrorManager.getDefault().notify(ioe); 147 } 148 149 String path = ""; 151 String fileName = file.getName(); 152 final String CONTROLLER_SUFFIX = "_controller"; final String HELPER_SUFFIX = "_helper"; 155 if (file.getExt().equals("rhtml")) { String view = fileName; 157 String controller = file.getParent() != null ? file.getParent().getName() : null; 158 if (controller != null) { 159 path = controller + "/" + view; 160 } else { 161 path = view; 162 } 163 } else if (fileName.endsWith(CONTROLLER_SUFFIX)) { 164 path = fileName.substring(0, fileName.length()-CONTROLLER_SUFFIX.length()); 165 } else if (fileName.endsWith(HELPER_SUFFIX)) { 166 path = fileName.substring(0, fileName.length()-HELPER_SUFFIX.length()); 167 } else if (fileName.endsWith("_test")) { 170 runRubyScript(FileUtil.toFile(file).getAbsolutePath(), file.getNameExt(), context); 172 return; 173 } 174 175 WebrickServer server = project.getLookup().lookup(WebrickServer.class); 176 if (server != null) { 177 server.showUrl(path); 178 } 179 180 return; 181 } else if (COMMAND_BUILD.equals(command)) { 182 if (!RubyInstallation.getInstance().isValidRake(true)) { 183 return; 184 } 185 186 LifecycleManager.getDefault().saveAll(); 188 189 RubyFileLocator fileLocator = new RubyFileLocator(context); 190 String displayName = "Rake"; 191 192 ProjectInformation info = ProjectUtils.getInformation(project); 193 if (info != null) { 194 displayName = info.getDisplayName(); 195 } 196 197 File pwd = FileUtil.toFile(project.getProjectDirectory()); 198 new ExecutionService(new ExecutionDescriptor(displayName, pwd, RubyInstallation.getInstance().getRake()). 199 fileLocator(fileLocator). 200 addOutputRecognizer(RubyExecution.RUBY_COMPILER)). 201 run(); 202 return; 203 } 208 209 if (COMMAND_RDOC.equals(command)) { 210 if (!RubyInstallation.getInstance().isValidRake(true)) { 211 return; 212 } 213 214 LifecycleManager.getDefault().saveAll(); 216 File pwd = FileUtil.toFile(project.getProjectDirectory()); 217 218 Runnable showBrowser = new Runnable () { 219 public void run() { 220 FileObject doc = project.getProjectDirectory().getFileObject("doc/app"); 223 if (doc != null) { 224 FileObject index = doc.getFileObject("index.html"); 225 if (index != null) { 226 try { 227 URL url = FileUtil.toFile(index).toURI().toURL(); 228 229 HtmlBrowser.URLDisplayer.getDefault().showURL(url); 230 } 231 catch (MalformedURLException ex) { 232 ErrorManager.getDefault().notify(ex); 233 }; 234 } 235 } 236 } 237 }; 238 239 RubyFileLocator fileLocator = new RubyFileLocator(context); 240 String displayName = "Rake - Documentation"; 241 new ExecutionService(new ExecutionDescriptor(displayName, pwd, RubyInstallation.getInstance().getRake(), "appdoc"). 242 postBuild(showBrowser). 243 fileLocator(fileLocator). 244 addOutputRecognizer(RubyExecution.RUBY_COMPILER)). 245 run(); 246 } 247 248 if (COMMAND_DELETE.equals(command)) { 249 DefaultProjectOperations.performDefaultDeleteOperation(project); 250 return ; 251 } 252 253 if (COMMAND_COPY.equals(command)) { 254 DefaultProjectOperations.performDefaultCopyOperation(project); 255 return ; 256 } 257 258 if (COMMAND_MOVE.equals(command)) { 259 DefaultProjectOperations.performDefaultMoveOperation(project); 260 return ; 261 } 262 263 if (COMMAND_RENAME.equals(command)) { 264 DefaultProjectOperations.performDefaultRenameOperation(project, null); 265 return ; 266 } 267 } 268 269 private void runRubyScript(String target, String displayName, final Lookup context) { 270 String applicationArgs = project.evaluator().getProperty(RailsProjectProperties.APPLICATION_ARGS); 271 String options = project.evaluator().getProperty(RailsProjectProperties.RUN_JVM_ARGS); 272 273 if (options != null && options.trim().length() == 0) { 274 options = null; 275 } 276 if (applicationArgs != null && applicationArgs.trim().length() == 0) { 277 applicationArgs = null; 278 } 279 280 FileObject[] srcPath = project.getSourceRoots().getRoots(); 284 FileObject[] testPath = project.getTestSourceRoots().getRoots(); 285 StringBuilder sb = new StringBuilder (); 286 if (srcPath != null && srcPath.length > 0) { 287 for (FileObject root : srcPath) { 288 if (sb.length() > 0) { 289 sb.append(' '); 290 } 291 sb.append("-I\""); 292 sb.append(FileUtil.toFile(root).getAbsoluteFile()); 293 sb.append("\""); 294 } 295 } 296 if (testPath != null && testPath.length > 0) { 297 for (FileObject root : testPath) { 298 if (sb.length() > 0) { 299 sb.append(' '); 300 } 301 sb.append("-I\""); 302 sb.append(FileUtil.toFile(root).getAbsoluteFile()); 303 sb.append("\""); 304 } 305 } 306 String includePath = sb.toString(); 307 if (options != null) { 308 options = includePath + " " + options; 309 } else { 310 options = includePath; 311 } 312 313 if (!new File (target).exists()) { 317 if (srcPath != null && srcPath.length > 0) { 318 boolean found = false; for (FileObject root : srcPath) { 320 FileObject fo = root.getFileObject(target); 321 if (fo != null) { 322 target = FileUtil.toFile(fo).getAbsolutePath(); 323 found = true; 324 break; 325 } 326 } 327 if (!found && testPath != null) { 328 for (FileObject root : testPath) { 329 FileObject fo = root.getFileObject(target); 330 if (fo != null) { 331 target = FileUtil.toFile(fo).getAbsolutePath(); 332 break; 333 } 334 } 335 } 336 } 337 } 338 339 String runDir = project.evaluator().getProperty(RailsProjectProperties.RUN_WORK_DIR); 340 File pwd = getSourceFolder(); 341 if (runDir != null && runDir.length() > 0) { 342 File dir = new File (runDir); 343 if (!dir.exists()) { 344 dir = new File (FileUtil.toFile(project.getProjectDirectory()), runDir); 346 if (!dir.exists()) { 347 if (srcPath != null && srcPath.length > 0) { 349 for (FileObject root : srcPath) { 350 dir = new File (FileUtil.toFile(root), runDir); 351 if (dir.exists()) { 352 break; 353 } 354 } 355 } 356 } 357 } 358 if (dir.exists()) { 359 pwd = dir; 360 } 361 } 362 363 new ExecutionService(new ExecutionDescriptor(displayName, pwd, target). 364 showSuspended(true). 365 allowInput(). 366 initialArgs(options). 367 additionalArgs(applicationArgs). 368 fileLocator(new RubyFileLocator(context)). 369 addOutputRecognizer(RubyExecution.RUBY_COMPILER)). 370 run(); 371 } 372 373 374 private File getSourceFolder() { 375 FileObject[] srcPath = project.getSourceRoots().getRoots(); 377 if (srcPath != null && srcPath.length > 0) { 378 return FileUtil.toFile(srcPath[0]); 379 } else { 380 return FileUtil.toFile(project.getProjectDirectory()); 381 } 382 } 383 384 449 public boolean isActionEnabled( String command, Lookup context ) { 450 if ( command.equals( COMMAND_COMPILE_SINGLE ) ) { 455 return findSourcesAndPackages( context, project.getSourceRoots().getRoots()) != null 456 || findSourcesAndPackages( context, project.getTestSourceRoots().getRoots()) != null; 457 } 458 else if ( command.equals( COMMAND_TEST_SINGLE ) ) { 459 return findTestSourcesForSources(context) != null; 460 } 461 else if ( command.equals( COMMAND_DEBUG_TEST_SINGLE ) ) { 462 FileObject[] files = findTestSourcesForSources(context); 463 return files != null && files.length == 1; 464 } else if (command.equals(COMMAND_RUN_SINGLE) || 465 command.equals(COMMAND_DEBUG_SINGLE)) { 466 FileObject fos[] = findSources(context); 467 if (fos != null && fos.length == 1) { 468 return true; 469 } 470 fos = findTestSources(context, false); 471 return fos != null && fos.length == 1; 472 } else { 473 return true; 475 } 476 } 477 478 479 480 482 485 private FileObject[] findSources(Lookup context) { 486 FileObject[] srcPath = project.getSourceRoots().getRoots(); 487 for (int i=0; i< srcPath.length; i++) { 488 FileObject[] files = findSelectedFiles(context, srcPath[i], RubyInstallation.RUBY_MIME_TYPE, true); if (files != null) { 490 return files; 491 } 492 files = findSelectedFiles(context, srcPath[i], RhtmlKit.RHTML_MIME_TYPE, true); if (files != null) { 494 return files; 495 } 496 } 497 return null; 498 } 499 500 private FileObject[] findSourcesAndPackages (Lookup context, FileObject srcDir) { 501 if (srcDir != null) { 502 FileObject[] files = findSelectedFiles(context, srcDir, null, true); if (files != null) { 505 for (int i = 0; i < files.length; i++) { 506 if (!files[i].isFolder() && (files[i].getMIMEType().equals(RubyInstallation.RUBY_MIME_TYPE) || 507 files[i].getMIMEType().equals(RhtmlKit.RHTML_MIME_TYPE))) { 508 return null; 509 } 510 } 511 } 512 return files; 513 } else { 514 return null; 515 } 516 } 517 518 private FileObject[] findSourcesAndPackages (Lookup context, FileObject[] srcRoots) { 519 for (int i=0; i<srcRoots.length; i++) { 520 FileObject[] result = findSourcesAndPackages(context, srcRoots[i]); 521 if (result != null) { 522 return result; 523 } 524 } 525 return null; 526 } 527 528 530 private FileObject[] findTestSources(Lookup context, boolean checkInSrcDir) { 531 return null; 553 } 554 555 556 558 private FileObject[] findTestSourcesForSources(Lookup context) { 559 return null; 576 } 577 578 579 583 public static FileObject[] findSelectedFiles(Lookup context, FileObject dir, String mimeType, boolean strict) { 584 if (dir != null && !dir.isFolder()) { 585 throw new IllegalArgumentException ("Not a folder: " + dir); } 587 Collection <FileObject> files = new LinkedHashSet <FileObject>(); for (DataObject d : context.lookupAll(DataObject.class)) { 590 FileObject f = d.getPrimaryFile(); 591 boolean matches = FileUtil.toFile(f) != null; 592 if (dir != null) { 593 matches &= (FileUtil.isParentOf(dir, f) || dir == f); 594 } 595 if (mimeType != null) { 596 matches &= f.getMIMEType().equals(mimeType); 597 } 598 if (matches) { 602 files.add(f); 603 } else if (strict) { 604 return null; 605 } 606 } 607 if (files.isEmpty()) { 608 return null; 609 } 610 return files.toArray(new FileObject[files.size()]); 611 } 612 613 614 private class RubyFileLocator implements FileLocator { 615 private Lookup context; 616 617 RubyFileLocator(Lookup context) { 618 this.context = context; 619 } 620 621 public FileObject find(String file) { 622 FileObject[] fos = null; 623 if (context != Lookup.EMPTY) { 624 625 FileObject[] srcPath = project.getSourceRoots().getRoots(); 627 if (srcPath != null) { 628 for (FileObject root : srcPath) { 629 FileObject f = root.getFileObject(file); 630 if (f != null) { 631 return f; 632 } 633 } 634 } 635 636 fos = findSources(context); 638 if (fos != null) { 639 for (FileObject fo : fos) { 640 if (fo.getNameExt().equals(file)) { 641 return fo; 642 } 643 } 644 } 645 } 646 647 FileObject[] srcPath = project.getSourceRoots().getRoots(); 649 for (FileObject root : srcPath) { 650 try { 652 File f = new File (FileUtil.toFile(root), file); 653 if (f.exists()) { 654 f = f.getCanonicalFile(); 655 return FileUtil.toFileObject(f); 656 } 657 } catch (IOException ioe) { 658 Exceptions.printStackTrace(ioe); 659 } 660 661 FileObject fo = findFile(root, file); 663 if (fo != null) { 664 return fo; 665 } 666 } 667 668 return null; 669 } 670 671 private FileObject findFile(FileObject fo, String name) { 672 if (name.equals(fo.getNameExt())) { 673 return fo; 674 } 675 676 for (FileObject child : fo.getChildren()) { 677 FileObject found = findFile(child, name); 678 if (found != null) { 679 return found; 680 } 681 } 682 683 return null; 684 } 685 } 686 } 687 | Popular Tags |