1 19 20 package org.netbeans.modules.project.ui; 21 22 import java.awt.Component ; 23 import java.awt.Cursor ; 24 import java.awt.event.ActionEvent ; 25 import java.io.File ; 26 import java.net.MalformedURLException ; 27 import java.net.URL ; 28 import java.util.Arrays ; 29 import java.util.HashMap ; 30 import java.util.HashSet ; 31 import java.util.List ; 32 import java.util.Map ; 33 import java.util.Set ; 34 import java.util.SortedSet ; 35 import java.util.TreeSet ; 36 import javax.swing.Action ; 37 import javax.swing.JFrame ; 38 import javax.swing.SwingUtilities ; 39 import org.netbeans.api.project.FileOwnerQuery; 40 import org.netbeans.api.project.Project; 41 import org.netbeans.api.project.ProjectUtils; 42 import org.netbeans.spi.project.AuxiliaryConfiguration; 43 import org.openide.ErrorManager; 44 import org.openide.cookies.EditCookie; 45 import org.openide.cookies.OpenCookie; 46 import org.openide.explorer.ExplorerManager; 47 import org.openide.filesystems.FileObject; 48 import org.openide.filesystems.FileStateInvalidException; 49 import org.openide.filesystems.URLMapper; 50 import org.openide.loaders.DataObject; 51 import org.openide.loaders.DataObjectNotFoundException; 52 import org.openide.nodes.Node; 53 import org.openide.util.ContextAwareAction; 54 import org.openide.util.Mutex; 55 import org.openide.util.NbBundle; 56 import org.openide.windows.CloneableTopComponent; 57 import org.openide.windows.TopComponent; 58 import org.openide.windows.WindowManager; 59 import org.openide.xml.XMLUtil; 60 import org.w3c.dom.Document ; 61 import org.w3c.dom.Element ; 62 import org.w3c.dom.NodeList ; 63 64 68 public class ProjectUtilities { 69 70 static final String OPEN_FILES_NS = "http://www.netbeans.org/ns/projectui-open-files/1"; static final String OPEN_FILES_ELEMENT = "open-files"; static final String FILE_ELEMENT = "file"; 74 static OpenCloseProjectDocument OPEN_CLOSE_PROJECT_DOCUMENT_IMPL = new OpenCloseProjectDocument () { 76 public boolean open (FileObject fo) { 77 DataObject dobj; 78 try { 79 dobj = DataObject.find (fo); 80 } catch (DataObjectNotFoundException donfo) { 81 assert false : "DataObject must exist for " + fo; 82 return false; 83 } 84 EditCookie ec = dobj.getCookie(EditCookie.class); 85 OpenCookie oc = dobj.getCookie(OpenCookie.class); 86 if (ec != null) { 87 ec.edit(); 88 } else if (oc != null) { 89 oc.open(); 90 } else { 91 if (ERR.isLoggable (ErrorManager.INFORMATIONAL)) ERR.log ("No EditCookie nor OpenCookie for " + dobj); 92 return false; 93 } 94 return true; 95 } 96 97 public Map <Project,SortedSet <String >> close(final Project[] projects, 98 final boolean notifyUI) { 99 final Wrapper wr = new Wrapper(); 100 101 wr.urls4project = new HashMap <Project,SortedSet <String >>(); 102 if (SwingUtilities.isEventDispatchThread()) { 103 doClose(projects, notifyUI, wr); 104 } else { 105 try { 106 SwingUtilities.invokeAndWait(new Runnable () { 107 public void run() { 108 doClose(projects, notifyUI, wr); 109 } 110 }); 111 } 112 catch (Exception ex) { 113 ERR.notify(ErrorManager.INFORMATIONAL, ex); 114 } 115 } 116 return wr.urls4project; 117 } 118 119 private void doClose(Project[] projects, boolean notifyUI, Wrapper wr) { 120 List <Project> listOfProjects = Arrays.asList(projects); 121 Set <DataObject> openFiles = new HashSet <DataObject>(); 122 final Set <TopComponent> tc2close = new HashSet <TopComponent>(); 123 for (TopComponent tc : WindowManager.getDefault().getRegistry().getOpened()) { 124 if (! (tc instanceof CloneableTopComponent)) { 126 continue; 127 } 128 if (tc instanceof ExplorerManager.Provider) { 130 continue; 131 } 132 DataObject dobj = tc.getLookup().lookup(DataObject.class); 133 134 if (dobj != null) { 135 FileObject fobj = dobj.getPrimaryFile(); 136 Project owner = FileOwnerQuery.getOwner(fobj); 137 138 if (listOfProjects.contains(owner)) { 139 if (notifyUI) { 140 openFiles.add(dobj); 141 tc2close.add(tc); 142 } else if (!dobj.isModified()) { 143 tc2close.add(tc); 145 } 146 if (!wr.urls4project.containsKey(owner)) { 147 wr.urls4project.put(owner, new TreeSet <String >()); 149 } 150 URL url = null; 151 152 try { 153 url = dobj.getPrimaryFile().getURL(); 154 wr.urls4project.get(owner).add(url.toExternalForm()); 155 } 156 catch (FileStateInvalidException fsie) { 157 assert false : "FileStateInvalidException in " + 158 dobj.getPrimaryFile(); 159 } 160 } 161 } 162 } 163 if (notifyUI) { 164 for (DataObject dobj : DataObject.getRegistry().getModifiedSet()) { 165 FileObject fobj = dobj.getPrimaryFile(); 166 Project owner = FileOwnerQuery.getOwner(fobj); 167 168 if (listOfProjects.contains(owner) && 169 !openFiles.contains(dobj)) { 170 openFiles.add(dobj); 171 } 172 } 173 } 174 if (!notifyUI || 175 (!openFiles.isEmpty() && ExitDialog.showDialog(openFiles))) { 176 for (TopComponent tc : tc2close) { 178 tc.close(); 179 } 180 } else { 181 if (!openFiles.isEmpty()) { 183 wr.urls4project = null; 184 } 185 } 186 } 187 }; 188 189 private static class Wrapper { 190 Map <Project,SortedSet <String >> urls4project; 191 } 192 193 private static final ErrorManager ERR = ErrorManager.getDefault().getInstance(ProjectUtilities.class.getName()); 194 195 private ProjectUtilities() {} 196 197 public static void selectAndExpandProject( final Project p ) { 198 199 SwingUtilities.invokeLater (new Runnable () { 201 202 final ProjectTab ptLogial = ProjectTab.findDefault(ProjectTab.ID_LOGICAL); 203 204 public void run () { 205 Node root = ptLogial.getExplorerManager ().getRootContext (); 206 Node projNode = null; 208 for (Node n : root.getChildren().getNodes()) { 209 Project prj = n.getLookup().lookup(Project.class); 210 if (prj != null && prj.getProjectDirectory().equals(p.getProjectDirectory())) { 211 projNode = n; 212 break; 213 } 214 } 215 if (projNode == null) { 216 projNode = root.getChildren ().findChild( ProjectUtils.getInformation( p ).getName() ); 218 } 219 220 if ( projNode != null ) { 221 try { 222 ptLogial.getExplorerManager ().setSelectedNodes( new Node[] { projNode } ); 223 ptLogial.expandNode( projNode ); 224 } catch (Exception ignore) { 227 } 229 } 230 } 231 }); 232 233 } 234 235 243 public static void openAndSelectNewObject (final DataObject newDo) { 244 Mutex.EVENT.writeAccess (new Runnable () { 246 public void run () { 247 final Node node = newDo.getNodeDelegate (); 248 Action a = node.getPreferredAction(); 249 if (a instanceof ContextAwareAction) { 250 a = ((ContextAwareAction) a).createContextAwareInstance(node.getLookup ()); 251 } 252 if (a != null) { 253 a.actionPerformed(new ActionEvent (node, ActionEvent.ACTION_PERFORMED, "")); } 255 256 final ProjectTab ptLogical = ProjectTab.findDefault(ProjectTab.ID_LOGICAL); 258 final ProjectTab ptPhysical = ProjectTab.findDefault(ProjectTab.ID_PHYSICAL); 259 SwingUtilities.invokeLater (new Runnable () { 262 public void run () { 263 boolean success = ptLogical.selectNode (newDo.getPrimaryFile ()); 264 if (!success) { 265 ptPhysical.selectNode (newDo.getPrimaryFile ()); 266 } 267 } 268 }); 269 } 270 }); 271 } 272 273 277 public static void makeProjectTabVisible( final boolean requestFocus ) { 278 final ProjectTab ptLogical = ProjectTab.findDefault (ProjectTab.ID_LOGICAL); 279 280 ptLogical.open(); 283 if ( requestFocus ) { 284 ptLogical.requestActive(); 285 } 286 else { 287 ptLogical.requestVisible(); 288 } 289 292 } 293 294 295 305 public static String canUseFileName (FileObject targetFolder, String folderName, String newObjectName, String extension, boolean allowFileSeparator) { 306 assert newObjectName != null; 308 boolean allowSlash = false; 309 boolean allowBackslash = false; 310 int errorVariant = 0; 311 312 if (allowFileSeparator) { 313 if (File.separatorChar == '\\') { 314 errorVariant = 3; 315 allowSlash = allowBackslash = true; 316 } else { 317 errorVariant = 1; 318 allowSlash = true; 319 } 320 } 321 322 if ((!allowSlash && newObjectName.indexOf('/') != -1) || (!allowBackslash && newObjectName.indexOf('\\') != -1)) { 323 assert errorVariant == 0 || errorVariant == 1 : "Invalid error variant: " + errorVariant; 325 326 return NbBundle.getMessage(ProjectUtilities.class, "MSG_not_valid_filename", newObjectName, new Integer (errorVariant)); 327 } 328 329 if (targetFolder == null) { 331 return NbBundle.getMessage (ProjectUtilities.class, "MSG_fs_or_folder_does_not_exist"); } 333 334 if (!targetFolder.canWrite ()) { 336 return NbBundle.getMessage (ProjectUtilities.class, "MSG_fs_is_readonly"); } 338 339 StringBuffer relFileName = new StringBuffer (); 341 if (folderName != null) { 342 if (!allowBackslash && folderName.indexOf('\\') != -1) { 343 return NbBundle.getMessage(ProjectUtilities.class, "MSG_not_valid_folder", folderName, new Integer (1)); 344 } 345 relFileName.append(folderName); 346 relFileName.append('/'); 347 } 348 relFileName.append(newObjectName); 349 if (extension != null && extension.length() != 0) { 350 relFileName.append('.'); 351 relFileName.append(extension); 352 } 353 if (targetFolder.getFileObject(relFileName.toString()) != null) { 354 return NbBundle.getMessage (ProjectUtilities.class, "MSG_file_already_exist", newObjectName); } 356 357 return null; 359 } 360 361 362 public static class WaitCursor implements Runnable { 363 364 private boolean show; 365 366 private WaitCursor( boolean show ) { 367 this.show = show; 368 } 369 370 public static void show() { 371 invoke( new WaitCursor( true ) ); 372 } 373 374 public static void hide() { 375 invoke( new WaitCursor( false ) ); 376 } 377 378 private static void invoke( WaitCursor wc ) { 379 if ( SwingUtilities.isEventDispatchThread() ) { 380 wc.run(); 381 } 382 else { 383 SwingUtilities.invokeLater( wc ); 384 } 385 } 386 387 public void run() { 388 try { 389 JFrame f = (JFrame )WindowManager.getDefault ().getMainWindow (); 390 Component c = f.getGlassPane (); 391 c.setVisible ( show ); 392 c.setCursor (show ? Cursor.getPredefinedCursor (Cursor.WAIT_CURSOR) : null); 393 } 394 catch (NullPointerException npe) { 395 ErrorManager.getDefault ().notify (ErrorManager.INFORMATIONAL, npe); 396 } 397 } 398 } 399 400 408 public static boolean closeAllDocuments(Project[] projects, boolean notifyUI) { 409 if (projects == null) { 410 throw new IllegalArgumentException ("No projects are specified."); } 412 413 if (projects.length == 0) { 414 return true; 416 } 417 418 Map <Project,SortedSet <String >> urls4project = OPEN_CLOSE_PROJECT_DOCUMENT_IMPL.close(projects, notifyUI); 419 420 if (urls4project != null) { 421 for (Map.Entry <Project,SortedSet <String >> entry : urls4project.entrySet()) { 424 storeProjectOpenFiles(entry.getKey(), entry.getValue()); 425 } 426 } 427 428 return urls4project != null; 429 } 430 431 static private void storeProjectOpenFiles (Project p, SortedSet <String > urls) { 432 AuxiliaryConfiguration aux = p.getLookup().lookup(AuxiliaryConfiguration.class); 433 if (aux != null) { 434 435 aux.removeConfigurationFragment (OPEN_FILES_ELEMENT, OPEN_FILES_NS, false); 436 437 Document xml = XMLUtil.createDocument (OPEN_FILES_ELEMENT, OPEN_FILES_NS, null, null); 438 Element fileEl; 439 440 Element openFiles = xml.createElementNS (OPEN_FILES_NS, OPEN_FILES_ELEMENT); 441 442 for (String url : urls) { 444 fileEl = openFiles.getOwnerDocument ().createElement (FILE_ELEMENT); 445 fileEl.appendChild(fileEl.getOwnerDocument().createTextNode(url)); 446 openFiles.appendChild (fileEl); 447 } 448 449 aux.putConfigurationFragment (openFiles, false); 450 } 451 } 452 453 457 public static void openProjectFiles (Project p) { 458 boolean dolog = ERR.isLoggable(ErrorManager.INFORMATIONAL); 459 if (dolog) ERR.log("Trying to open files from " + p + "..."); 460 461 AuxiliaryConfiguration aux = p.getLookup().lookup(AuxiliaryConfiguration.class); 462 463 if (aux == null) { 464 if (dolog) ERR.log("No AuxiliaryConfiguration in " + p); 465 return ; 466 } 467 468 Element openFiles = aux.getConfigurationFragment (OPEN_FILES_ELEMENT, OPEN_FILES_NS, false); 469 if (openFiles == null) { 470 if (dolog) ERR.log("No " + OPEN_FILES_ELEMENT + " in private.xml"); 471 return; 472 } 473 474 NodeList list = openFiles.getElementsByTagName (FILE_ELEMENT); 475 if (list == null) { 476 if (dolog) ERR.log("No " + FILE_ELEMENT + " in " + OPEN_FILES_ELEMENT); 477 return ; 478 } 479 480 for (int i = 0; i < list.getLength (); i++) { 481 String url = list.item (i).getChildNodes ().item (0).getNodeValue (); 482 if (dolog) ERR.log("Will try to open " + url); 483 FileObject fo; 484 try { 485 fo = URLMapper.findFileObject (new URL (url)); 486 } catch (MalformedURLException mue) { 487 assert false : "MalformedURLException in " + url; 488 continue; 489 } 490 if (fo == null) { 491 if (dolog) ERR.log("Could not find " + url); 492 continue; 493 } 494 495 OPEN_CLOSE_PROJECT_DOCUMENT_IMPL.open (fo); 496 } 497 498 aux.removeConfigurationFragment (OPEN_FILES_ELEMENT, OPEN_FILES_NS, false); 500 } 501 502 interface OpenCloseProjectDocument { 505 506 boolean open(FileObject fo); 508 509 Map <Project,SortedSet <String >> close(Project[] projects, boolean notifyUI); 512 } 513 514 } 515 | Popular Tags |