1 19 20 package org.netbeans.modules.ruby.rubyproject; 21 22 import java.awt.Dialog ; 23 import java.awt.event.MouseEvent ; 24 import java.io.File ; 25 import java.io.IOException ; 26 import java.net.MalformedURLException ; 27 import java.net.URL ; 28 import java.text.MessageFormat ; 29 import java.util.Arrays ; 30 import java.util.Collection ; 31 import java.util.HashSet ; 32 import java.util.LinkedHashSet ; 33 import java.util.Set ; 34 import java.util.regex.Pattern ; 35 import javax.swing.JButton ; 36 import javax.swing.event.ChangeEvent ; 37 import javax.swing.event.ChangeListener ; 38 import org.netbeans.api.project.ProjectInformation; 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.api.project.ProjectManager; 43 import org.netbeans.api.project.ProjectUtils; 44 import org.netbeans.modules.ruby.rubyproject.api.RubyExecution; 45 import org.netbeans.modules.ruby.rubyproject.execution.FileLocator; 46 import org.netbeans.modules.ruby.rubyproject.ui.customizer.RubyProjectProperties; 47 import org.netbeans.modules.ruby.rubyproject.ui.customizer.MainClassChooser; 48 import org.netbeans.modules.ruby.rubyproject.ui.customizer.MainClassWarning; 49 import org.netbeans.spi.project.ActionProvider; 50 import org.netbeans.modules.ruby.spi.project.support.rake.RakeProjectHelper; 51 import org.netbeans.modules.ruby.spi.project.support.rake.EditableProperties; 52 import org.netbeans.spi.project.ui.support.DefaultProjectOperations; 53 import org.openide.DialogDescriptor; 54 import org.openide.DialogDisplayer; 55 import org.openide.ErrorManager; 56 import org.openide.LifecycleManager; 57 import org.openide.awt.HtmlBrowser; 58 import org.openide.awt.MouseUtils; 59 import org.openide.cookies.SaveCookie; 60 import org.openide.filesystems.FileObject; 61 import org.openide.filesystems.FileUtil; 62 import org.openide.loaders.DataObject; 63 import org.openide.loaders.DataObjectNotFoundException; 64 import org.openide.util.Exceptions; 65 import org.openide.util.Lookup; 66 import org.openide.util.NbBundle; 67 68 71 public class RubyActionProvider implements ActionProvider { 72 76 public static final String COMMAND_RDOC = "rdoc"; 78 private static final String [] supportedActions = { 80 COMMAND_BUILD, 81 COMMAND_CLEAN, 82 COMMAND_REBUILD, 83 COMMAND_RDOC, 84 COMMAND_RUN, 86 COMMAND_RUN_SINGLE, 87 COMMAND_TEST_SINGLE, 91 COMMAND_DELETE, 94 COMMAND_COPY, 95 COMMAND_MOVE, 96 COMMAND_RENAME, 97 }; 98 99 100 RubyProject project; 102 103 private UpdateHelper updateHelper; 105 106 107 108 final Set <String > bkgScanSensitiveActions; 109 110 public RubyActionProvider( RubyProject project, UpdateHelper updateHelper ) { 111 this.bkgScanSensitiveActions = new HashSet <String >(Arrays.asList(new String [] { 112 COMMAND_RUN, 113 COMMAND_RUN_SINGLE, 114 })); 118 119 this.updateHelper = updateHelper; 120 this.project = project; 121 } 122 123 public String [] getSupportedActions() { 124 return supportedActions; 125 } 126 127 private void runRubyScript(FileObject fileObject, String target, String displayName, final Lookup context) { 128 String applicationArgs = project.evaluator().getProperty(RubyProjectProperties.APPLICATION_ARGS); 129 String options = project.evaluator().getProperty(RubyProjectProperties.RUN_JVM_ARGS); 130 131 if (options != null && options.trim().length() == 0) { 132 options = null; 133 } 134 if (applicationArgs != null && applicationArgs.trim().length() == 0) { 135 applicationArgs = null; 136 } 137 138 FileObject[] srcPath = project.getSourceRoots().getRoots(); 142 FileObject[] testPath = project.getTestSourceRoots().getRoots(); 143 StringBuilder sb = new StringBuilder (); 144 if (srcPath != null && srcPath.length > 0) { 145 for (FileObject root : srcPath) { 146 if (sb.length() > 0) { 147 sb.append(' '); 148 } 149 sb.append("-I\""); 150 sb.append(FileUtil.toFile(root).getAbsoluteFile()); 151 sb.append("\""); 152 } 153 } 154 if (testPath != null && testPath.length > 0) { 155 for (FileObject root : testPath) { 156 if (sb.length() > 0) { 157 sb.append(' '); 158 } 159 sb.append("-I\""); 160 sb.append(FileUtil.toFile(root).getAbsoluteFile()); 161 sb.append("\""); 162 } 163 } 164 String includePath = sb.toString(); 165 if (options != null) { 166 options = includePath + " " + options; 167 } else { 168 options = includePath; 169 } 170 171 if (!new File (target).exists()) { 175 if (srcPath != null && srcPath.length > 0) { 176 boolean found = false; for (FileObject root : srcPath) { 178 FileObject fo = root.getFileObject(target); 179 if (fo != null) { 180 target = FileUtil.toFile(fo).getAbsolutePath(); 181 found = true; 182 break; 183 } 184 } 185 if (!found && testPath != null) { 186 for (FileObject root : testPath) { 187 FileObject fo = root.getFileObject(target); 188 if (fo != null) { 189 target = FileUtil.toFile(fo).getAbsolutePath(); 190 break; 191 } 192 } 193 } 194 } 195 } 196 197 String runDir = project.evaluator().getProperty(RubyProjectProperties.RUN_WORK_DIR); 198 File pwd = getSourceFolder(); 199 if (runDir != null && runDir.length() > 0) { 200 File dir = new File (runDir); 201 if (!dir.exists()) { 202 dir = new File (FileUtil.toFile(project.getProjectDirectory()), runDir); 204 if (!dir.exists()) { 205 if (srcPath != null && srcPath.length > 0) { 207 for (FileObject root : srcPath) { 208 dir = new File (FileUtil.toFile(root), runDir); 209 if (dir.exists()) { 210 break; 211 } 212 } 213 } 214 } 215 } 216 if (dir.exists()) { 217 pwd = dir; 218 } 219 } 220 221 new ExecutionService(new ExecutionDescriptor(displayName, pwd, target). 222 showSuspended(true). 223 allowInput(). 224 fileObject(fileObject). 225 initialArgs(options). 226 additionalArgs(applicationArgs). 227 fileLocator(new RubyFileLocator(context)). 228 addOutputRecognizer(RubyExecution.RUBY_COMPILER)). 229 run(); 230 } 231 232 public void invokeAction(final String command, final Lookup context) throws IllegalArgumentException { 233 248 249 if (COMMAND_RUN.equals(command)) { 251 if (!RubyInstallation.getInstance().isValidRuby(true)) { 252 return; 253 } 254 if (!RubyInstallation.getInstance().isValidRake(true)) { 255 return; 256 } 257 258 String config = project.evaluator().getProperty(RubyConfigurationProvider.PROP_CONFIG); 259 String path; 260 if (config == null || config.length() == 0) { 261 path = RakeProjectHelper.PROJECT_PROPERTIES_PATH; 262 } else { 263 path = "nbproject/configs/" + config + ".properties"; } 266 EditableProperties ep = updateHelper.getProperties(path); 267 268 String mainClass = project.evaluator().getProperty(RubyProjectProperties.MAIN_CLASS); 273 MainClassStatus result = isSetMainClass (project.getSourceRoots().getRoots(), mainClass); 274 if (context.lookup(RubyConfigurationProvider.Config.class) != null) { 275 result = MainClassStatus.SET_AND_VALID; 280 } 281 if (result != MainClassStatus.SET_AND_VALID) { 282 do { 283 if (showMainClassWarning (mainClass, ProjectUtils.getInformation(project).getDisplayName(), ep,result)) { 285 return; 286 } 287 mainClass = ep.get(RubyProjectProperties.MAIN_CLASS); 289 result=isSetMainClass (project.getSourceRoots().getRoots(), mainClass); 290 } while (result != MainClassStatus.SET_AND_VALID); 291 try { 292 if (updateHelper.requestSave()) { 293 updateHelper.putProperties(path, ep); 294 ProjectManager.getDefault().saveProject(project); 295 } 296 else { 297 return; 298 } 299 } catch (IOException ioe) { 300 ErrorManager.getDefault().log(ErrorManager.INFORMATIONAL, "Error while saving project: " + ioe); 301 } 302 } 303 304 LifecycleManager.getDefault().saveAll(); 306 307 String displayName = (mainClass != null) ? "Ruby" : "Rake"; 309 ProjectInformation info = ProjectUtils.getInformation(project); 310 if (info != null) { 311 displayName = info.getDisplayName(); 312 } 313 314 if (mainClass != null) { 315 FileObject fileObject = null; 317 runRubyScript(fileObject, mainClass, displayName, context); 318 return; 319 } 320 321 323 RubyFileLocator fileLocator = new RubyFileLocator(context); 324 File pwd = getSourceFolder(); new ExecutionService(new ExecutionDescriptor(displayName, pwd, RubyInstallation.getInstance().getRake()). 326 fileLocator(new RubyFileLocator(context)). 327 addOutputRecognizer(RubyExecution.RUBY_COMPILER)). 328 run(); 329 330 return; 331 } else if (COMMAND_RUN_SINGLE.equals(command)) { 332 if (!RubyInstallation.getInstance().isValidRuby(true)) { 333 return; 334 } 335 336 FileObject[] fos = findSources(context); 337 if (fos == null) { 338 fos = findTestSources(context, false); 339 } 340 if (fos == null || fos.length == 0) { 341 return; 342 } 343 FileObject file = fos[0]; 344 345 try { 347 DataObject dobj = DataObject.find(file); 348 if (dobj != null) { 349 SaveCookie saveCookie = dobj.getCookie(SaveCookie.class); 350 if (saveCookie != null) { 351 saveCookie.save(); 352 } 353 } 354 } catch (DataObjectNotFoundException donfe) { 355 ErrorManager.getDefault().notify(donfe); 356 } catch (IOException ioe) { 357 ErrorManager.getDefault().notify(ioe); 358 } 359 360 runRubyScript(file, FileUtil.toFile(file).getAbsolutePath(), file.getNameExt(), context); 362 return; 363 } else if (COMMAND_BUILD.equals(command)) { 364 if (!RubyInstallation.getInstance().isValidRake(true)) { 365 return; 366 } 367 368 LifecycleManager.getDefault().saveAll(); 370 371 String displayName = "Rake"; File pwd = getSourceFolder(); new ExecutionService(new ExecutionDescriptor(displayName, pwd, RubyInstallation.getInstance().getRake()). 374 fileLocator(new RubyFileLocator(context)). 375 addOutputRecognizer(RubyExecution.RUBY_COMPILER)). 376 run(); 377 return; 378 } else if (COMMAND_CLEAN.equals(command)) { 379 if (!RubyInstallation.getInstance().isValidRake(true)) { 380 return; 381 } 382 383 String displayName = "Rake"; File pwd = getSourceFolder(); new ExecutionService(new ExecutionDescriptor(displayName, pwd, RubyInstallation.getInstance().getRake(), "clean"). 387 fileLocator(new RubyFileLocator(context)). 388 addOutputRecognizer(RubyExecution.RUBY_COMPILER)). 389 run(); 390 return; 391 } 392 393 if (COMMAND_RDOC.equals(command)) { 394 if (!RubyInstallation.getInstance().isValidRDoc(true)) { 395 return; 396 } 397 398 LifecycleManager.getDefault().saveAll(); 399 File pwd = FileUtil.toFile(project.getProjectDirectory()); 400 401 Runnable showBrowser = new Runnable () { 402 public void run() { 403 FileObject doc = project.getProjectDirectory().getFileObject("doc"); 406 if (doc != null) { 407 FileObject index = doc.getFileObject("index.html"); 408 if (index != null) { 409 try { 410 URL url = FileUtil.toFile(index).toURI().toURL(); 411 412 HtmlBrowser.URLDisplayer.getDefault().showURL(url); 413 } 414 catch (MalformedURLException ex) { 415 ErrorManager.getDefault().notify(ex); 416 }; 417 } 418 } 419 } 420 }; 421 422 RubyFileLocator fileLocator = new RubyFileLocator(context); 423 String displayName = "Ruby Documentation"; new ExecutionService(new ExecutionDescriptor(displayName, pwd, RubyInstallation.getInstance().getRDoc()). 425 fileLocator(fileLocator). 426 postBuild(showBrowser). 427 addOutputRecognizer(RubyExecution.RUBY_COMPILER)). 428 run(); 429 430 return; 431 } 432 433 if (COMMAND_TEST_SINGLE.equals(command)) { 434 if (!RubyInstallation.getInstance().isValidRuby(true)) { 435 return; 436 } 437 FileObject[] files = findTestSourcesForSources(context); 438 439 FileObject file = findSources(context)[0]; 440 441 try { 443 DataObject dobj = DataObject.find(file); 444 if (dobj != null) { 445 SaveCookie saveCookie = dobj.getCookie(SaveCookie.class); 446 if (saveCookie != null) { 447 saveCookie.save(); 448 } 449 } 450 } catch (DataObjectNotFoundException donfe) { 451 ErrorManager.getDefault().notify(donfe); 452 } catch (IOException ioe) { 453 ErrorManager.getDefault().notify(ioe); 454 } 455 456 String target = FileUtil.getRelativePath(getRoot(project.getSourceRoots().getRoots(),file), file); 457 String displayName = file.getNameExt(); 458 File pwd = getSourceFolder(); 459 new ExecutionService(new ExecutionDescriptor(displayName, pwd, target). 460 showSuspended(true). 461 allowInput(). 462 fileLocator(new RubyFileLocator(context)). 463 addOutputRecognizer(RubyExecution.RUBY_COMPILER)). 464 run(); 465 466 return; 467 } 468 469 if (COMMAND_TEST.equals(command)) { 471 if (!RubyInstallation.getInstance().isValidRuby(true)) { 472 return; 473 } 474 475 FileObject[] files = findTestSourcesForSources(context); 476 477 throw new RuntimeException ("Not yet implemented"); 479 } 480 481 482 if (COMMAND_DELETE.equals(command)) { 483 DefaultProjectOperations.performDefaultDeleteOperation(project); 484 return; 485 } 486 487 if (COMMAND_COPY.equals(command)) { 488 DefaultProjectOperations.performDefaultCopyOperation(project); 489 return; 490 } 491 492 if (COMMAND_MOVE.equals(command)) { 493 DefaultProjectOperations.performDefaultMoveOperation(project); 494 return; 495 } 496 497 if (COMMAND_RENAME.equals(command)) { 498 DefaultProjectOperations.performDefaultRenameOperation(project, null); 499 return; 500 } 501 } 502 503 568 public boolean isActionEnabled( String command, Lookup context ) { 569 if ( command.equals( COMMAND_COMPILE_SINGLE ) ) { 574 return findSourcesAndPackages( context, project.getSourceRoots().getRoots()) != null 575 || findSourcesAndPackages( context, project.getTestSourceRoots().getRoots()) != null; 576 } 577 else if ( command.equals( COMMAND_TEST_SINGLE ) ) { 578 return findTestSourcesForSources(context) != null; 579 } 580 else if ( command.equals( COMMAND_DEBUG_TEST_SINGLE ) ) { 581 FileObject[] files = findTestSourcesForSources(context); 582 return files != null && files.length == 1; 583 } else if (command.equals(COMMAND_RUN_SINGLE) || 584 command.equals(COMMAND_DEBUG_SINGLE)) { 585 FileObject fos[] = findSources(context); 586 if (fos != null && fos.length == 1) { 587 return true; 588 } 589 fos = findTestSources(context, false); 590 return fos != null && fos.length == 1; 591 } else { 592 return true; 594 } 595 } 596 597 598 599 601 602 private static final Pattern SRCDIRJAVA = Pattern.compile("\\.java$"); private static final String SUBST = "Test.java"; 605 608 private FileObject[] findSources(Lookup context) { 609 FileObject[] srcPath = project.getSourceRoots().getRoots(); 610 for (int i=0; i< srcPath.length; i++) { 611 FileObject[] files = findSelectedFiles(context, srcPath[i], RubyInstallation.RUBY_MIME_TYPE, true); if (files != null) { 613 return files; 614 } 615 } 616 return null; 617 } 618 619 private FileObject[] findSourcesAndPackages (Lookup context, FileObject srcDir) { 620 if (srcDir != null) { 621 FileObject[] files = findSelectedFiles(context, srcDir, null, true); if (files != null) { 624 for (int i = 0; i < files.length; i++) { 625 if (!files[i].isFolder() && files[i].getMIMEType().equals(RubyInstallation.RUBY_MIME_TYPE)) { 626 return null; 627 } 628 } 629 } 630 return files; 631 } else { 632 return null; 633 } 634 } 635 636 private FileObject[] findSourcesAndPackages (Lookup context, FileObject[] srcRoots) { 637 for (int i=0; i<srcRoots.length; i++) { 638 FileObject[] result = findSourcesAndPackages(context, srcRoots[i]); 639 if (result != null) { 640 return result; 641 } 642 } 643 return null; 644 } 645 646 648 private FileObject[] findTestSources(Lookup context, boolean checkInSrcDir) { 649 FileObject[] testSrcPath = project.getTestSourceRoots().getRoots(); 651 for (int i=0; i< testSrcPath.length; i++) { 652 FileObject[] files = findSelectedFiles(context, testSrcPath[i], RubyInstallation.RUBY_MIME_TYPE, true); if (files != null) { 654 return files; 655 } 656 } 657 return null; 671 } 672 673 674 676 private FileObject[] findTestSourcesForSources(Lookup context) { 677 FileObject[] sourceFiles = findSources(context); 678 if (sourceFiles == null) { 679 return null; 680 } 681 FileObject[] testSrcPath = project.getTestSourceRoots().getRoots(); 682 if (testSrcPath.length == 0) { 683 return null; 684 } 685 FileObject[] srcPath = project.getSourceRoots().getRoots(); 686 FileObject srcDir = getRoot(srcPath, sourceFiles[0]); 687 return new FileObject[] { srcDir }; } 696 697 private FileObject getRoot (FileObject[] roots, FileObject file) { 698 assert file != null : "File can't be null"; FileObject srcDir = null; 700 for (int i=0; i< roots.length; i++) { 701 assert roots[i] != null : "Source Path Root can't be null"; if (FileUtil.isParentOf(roots[i],file) || roots[i].equals(file)) { 703 srcDir = roots[i]; 704 break; 705 } 706 } 707 return srcDir; 708 } 709 710 private static enum MainClassStatus { 711 SET_AND_VALID, 712 SET_BUT_INVALID, 713 UNSET 714 } 715 716 722 private MainClassStatus isSetMainClass(FileObject[] sourcesRoots, String mainClass) { 723 724 if (MainClassChooser.unitTestingSupport_hasMainMethodResult != null) { 726 return MainClassChooser.unitTestingSupport_hasMainMethodResult ? MainClassStatus.SET_AND_VALID : MainClassStatus.SET_BUT_INVALID; 727 } 728 729 if (mainClass == null || mainClass.length () == 0) { 730 return MainClassStatus.UNSET; 731 } 732 733 if (RubyProjectUtil.isMainClass (mainClass, sourcesRoots)) { 735 return MainClassStatus.SET_AND_VALID; 736 } 737 return MainClassStatus.SET_BUT_INVALID; 738 } 739 740 748 private boolean showMainClassWarning(String mainClass, String projectName, EditableProperties ep, MainClassStatus messageType) { 749 boolean canceled; 750 final JButton okButton = new JButton (NbBundle.getMessage (RubyActionProvider.class, "LBL_MainClassWarning_ChooseMainClass_OK")); okButton.getAccessibleContext().setAccessibleDescription (NbBundle.getMessage (RubyActionProvider.class, "AD_MainClassWarning_ChooseMainClass_OK")); 752 753 String message; 755 switch (messageType) { 756 case UNSET: 757 message = MessageFormat.format (NbBundle.getMessage(RubyActionProvider.class,"LBL_MainClassNotFound"), new Object [] { 758 projectName 759 }); 760 break; 761 case SET_BUT_INVALID: 762 message = MessageFormat.format (NbBundle.getMessage(RubyActionProvider.class,"LBL_MainClassWrong"), new Object [] { 763 mainClass, 764 projectName 765 }); 766 break; 767 default: 768 throw new IllegalArgumentException (); 769 } 770 final MainClassWarning panel = new MainClassWarning (message,project.getSourceRoots().getRoots()); 771 Object [] options = new Object [] { 772 okButton, 773 DialogDescriptor.CANCEL_OPTION 774 }; 775 776 panel.addChangeListener (new ChangeListener () { 777 public void stateChanged (ChangeEvent e) { 778 if (e.getSource () instanceof MouseEvent && MouseUtils.isDoubleClick (((MouseEvent )e.getSource ()))) { 779 okButton.doClick (); 781 } else { 782 okButton.setEnabled (panel.getSelectedMainClass () != null); 783 } 784 } 785 }); 786 787 okButton.setEnabled (false); 788 DialogDescriptor desc = new DialogDescriptor (panel, 789 NbBundle.getMessage (RubyActionProvider.class, "CTL_MainClassWarning_Title", ProjectUtils.getInformation(project).getDisplayName()), true, options, options[0], DialogDescriptor.BOTTOM_ALIGN, null, null); 791 desc.setMessageType (DialogDescriptor.INFORMATION_MESSAGE); 792 Dialog dlg = DialogDisplayer.getDefault ().createDialog (desc); 793 dlg.setVisible (true); 794 if (desc.getValue() != options[0]) { 795 canceled = true; 796 } else { 797 mainClass = panel.getSelectedMainClass (); 798 canceled = false; 799 ep.put(RubyProjectProperties.MAIN_CLASS, mainClass == null ? "" : mainClass); 800 } 801 dlg.dispose(); 802 803 return canceled; 804 } 805 806 810 public static FileObject[] findSelectedFiles(Lookup context, FileObject dir, String mimeType, boolean strict) { 811 if (dir != null && !dir.isFolder()) { 812 throw new IllegalArgumentException ("Not a folder: " + dir); } 814 Collection <FileObject> files = new LinkedHashSet <FileObject>(); for (DataObject d : context.lookupAll(DataObject.class)) { 817 FileObject f = d.getPrimaryFile(); 818 boolean matches = FileUtil.toFile(f) != null; 819 if (dir != null) { 820 matches &= (FileUtil.isParentOf(dir, f) || dir == f); 821 } 822 if (mimeType != null) { 823 matches &= f.getMIMEType().equals(mimeType); 824 } 825 if (matches) { 829 files.add(f); 830 } else if (strict) { 831 return null; 832 } 833 } 834 if (files.isEmpty()) { 835 return null; 836 } 837 return files.toArray(new FileObject[files.size()]); 838 } 839 840 841 private class RubyFileLocator implements FileLocator { 842 private Lookup context; 843 844 RubyFileLocator(Lookup context) { 845 this.context = context; 846 } 847 848 public FileObject find(String file) { 849 FileObject[] fos = null; 850 if (context != Lookup.EMPTY) { 851 852 FileObject[] srcPath = project.getSourceRoots().getRoots(); 854 if (srcPath != null) { 855 for (FileObject root : srcPath) { 856 FileObject f = root.getFileObject(file); 857 if (f != null) { 858 return f; 859 } 860 } 861 } 862 863 fos = findSources(context); 865 if (fos != null) { 866 for (FileObject fo : fos) { 867 if (fo.getNameExt().equals(file)) { 868 return fo; 869 } 870 } 871 } 872 } 873 874 FileObject[] srcPath = project.getSourceRoots().getRoots(); 876 for (FileObject root : srcPath) { 877 try { 879 File f = new File (FileUtil.toFile(root), file); 880 if (f.exists()) { 881 f = f.getCanonicalFile(); 882 return FileUtil.toFileObject(f); 883 } 884 } catch (IOException ioe) { 885 Exceptions.printStackTrace(ioe); 886 } 887 888 FileObject fo = findFile(root, file); 890 if (fo != null) { 891 return fo; 892 } 893 } 894 895 return null; 896 } 897 898 private FileObject findFile(FileObject fo, String name) { 899 if (name.equals(fo.getNameExt())) { 900 return fo; 901 } 902 903 for (FileObject child : fo.getChildren()) { 904 FileObject found = findFile(child, name); 905 if (found != null) { 906 return found; 907 } 908 } 909 910 return null; 911 } 912 } 913 914 private File getSourceFolder() { 915 FileObject[] srcPath = project.getSourceRoots().getRoots(); 917 if (srcPath != null && srcPath.length > 0) { 918 return FileUtil.toFile(srcPath[0]); 919 } else { 920 return FileUtil.toFile(project.getProjectDirectory()); 921 } 922 } 923 } 924 | Popular Tags |