1 19 20 package org.netbeans.modules.subversion; 21 22 import org.netbeans.modules.subversion.config.SvnConfigFiles; 23 import org.netbeans.modules.subversion.util.Context; 24 import org.netbeans.modules.subversion.client.*; 25 import org.netbeans.modules.subversion.util.SvnUtils; 26 import org.openide.ErrorManager; 27 import org.openide.filesystems.FileObject; 28 import org.openide.filesystems.FileUtil; 29 import org.tigris.subversion.svnclientadapter.*; 30 import org.openide.util.RequestProcessor; 31 import java.io.*; 32 import java.util.*; 33 import java.beans.PropertyChangeListener ; 34 import java.beans.PropertyChangeSupport ; 35 import java.util.logging.Level ; 36 import java.util.logging.Logger ; 37 import org.netbeans.modules.subversion.ui.diff.Setup; 38 import org.netbeans.modules.subversion.ui.ignore.IgnoreAction; 39 import org.netbeans.modules.versioning.spi.VCSInterceptor; 40 import org.netbeans.modules.versioning.spi.OriginalContent; 41 import org.netbeans.modules.versioning.util.VersioningListener; 42 import org.netbeans.modules.versioning.util.VersioningEvent; 43 import org.netbeans.modules.versioning.VersioningManager; 44 import org.netbeans.api.queries.SharabilityQuery; 45 import org.netbeans.modules.subversion.ui.repository.RepositoryConnection; 46 47 53 public class Subversion { 54 55 59 static final String PROP_ANNOTATIONS_CHANGED = "annotationsChanged"; 60 61 static final String PROP_VERSIONED_FILES_CHANGED = "versionedFilesChanged"; 62 63 static final String INVALID_METADATA_MARKER = "invalid-metadata"; 65 private static final int STATUS_DIFFABLE = 66 FileInformation.STATUS_NOTVERSIONED_NEWLOCALLY | 67 FileInformation.STATUS_VERSIONED_ADDEDLOCALLY | 68 FileInformation.STATUS_VERSIONED_UPTODATE | 69 FileInformation.STATUS_VERSIONED_MODIFIEDLOCALLY | 70 FileInformation.STATUS_VERSIONED_MODIFIEDINREPOSITORY | 71 FileInformation.STATUS_VERSIONED_CONFLICT | 72 FileInformation.STATUS_VERSIONED_MERGE | 73 FileInformation.STATUS_VERSIONED_REMOVEDINREPOSITORY | 74 FileInformation.STATUS_VERSIONED_MODIFIEDINREPOSITORY | 75 FileInformation.STATUS_VERSIONED_MODIFIEDINREPOSITORY; 76 77 private static Subversion instance; 78 79 private FileStatusCache fileStatusCache; 80 private FilesystemHandler filesystemHandler; 81 private FileStatusProvider fileStatusProvider; 82 private Annotator annotator; 83 private HashMap<String , RequestProcessor> processorsToUrl; 84 85 private SvnClient noUrlClientWithoutListeners; 86 private SvnClient noUrlClientWithListeners; 87 88 private final PropertyChangeSupport support = new PropertyChangeSupport (this); 89 90 public static synchronized Subversion getInstance() { 91 if (instance == null) { 92 instance = new Subversion(); 93 instance.init(); 94 } 95 return instance; 96 } 97 98 private Subversion() { 99 } 100 101 private void init() { 102 Diagnostics.init(); 103 loadIniParserClassesWorkaround(); 104 setupSvnClientFactory(); 105 106 fileStatusCache = new FileStatusCache(); 107 annotator = new Annotator(this); 108 fileStatusProvider = new FileStatusProvider(); 109 filesystemHandler = new FilesystemHandler(this); 110 cleanup(); 111 } 112 113 public static void setupSvnClientFactory() { 114 try { 115 SvnClientFactory.getInstance().setup(); 116 } catch (SVNClientException ex) { 117 Logger.getLogger("org.netbeans.modules.subversion").log(Level.INFO, UnsupportedSvnClientAdapter.getMessage()); 118 119 } 124 } 125 126 129 private void loadIniParserClassesWorkaround() { 130 ClassLoader cl = Thread.currentThread().getContextClassLoader(); 131 Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader()); 132 try { 133 SvnConfigFiles.getInstance(); } finally { 135 Thread.currentThread().setContextClassLoader(cl); 136 } 137 } 138 139 private void cleanup() { 140 getRequestProcessor().post(new Runnable () { 141 public void run() { 142 try { 143 Diagnostics.println("Cleaning up"); fileStatusCache.cleanUp(); 145 } finally { 147 Diagnostics.println("END Cleaning up"); } 149 } 150 }, 3000); 151 } 152 153 public void shutdown() { 154 fileStatusProvider.shutdown(); 155 } 157 158 public SvnFileNode [] getNodes(Context context, int includeStatus) { 159 File [] files = fileStatusCache.listFiles(context, includeStatus); 160 SvnFileNode [] nodes = new SvnFileNode[files.length]; 161 for (int i = 0; i < files.length; i++) { 162 nodes[i] = new SvnFileNode(files[i]); 163 } 164 return nodes; 165 } 166 167 173 public String getMimeType(File file) { 174 FileObject fo = FileUtil.toFileObject(file); 175 String foMime; 176 if (fo == null) { 177 foMime = "content/unknown"; 178 } else { 179 foMime = fo.getMIMEType(); 180 if ("content/unknown".equals(foMime)) { 181 foMime = "text/plain"; 182 } 183 } 184 if ((fileStatusCache.getStatus(file).getStatus() & FileInformation.STATUS_VERSIONED) == 0) { 185 return SvnUtils.isFileContentBinary(file) ? "application/octet-stream" : foMime; 186 } else { 187 PropertiesClient client = new PropertiesClient(file); 188 try { 189 byte [] mimeProperty = client.getProperties().get("svn:mime-type"); 190 if (mimeProperty == null) return foMime; 191 return new String (mimeProperty); 192 } catch (IOException e) { 193 return foMime; 194 } 195 } 196 } 197 198 201 public boolean isAdministrative(File file) { 202 String name = file.getName(); 203 return isAdministrative(name) && file.isDirectory(); 204 } 205 206 public boolean isAdministrative(String fileName) { 207 return fileName.equals(".svn") || fileName.equals("_svn"); } 209 210 public FileStatusCache getStatusCache() { 211 return fileStatusCache; 212 } 213 214 public Annotator getAnnotator() { 215 return annotator; 216 } 217 218 public SvnClient getClient(SVNUrl repositoryUrl, 219 String username, 220 String password) 221 throws SVNClientException 222 { 223 return getClient(repositoryUrl, username, password, SvnClientExceptionHandler.EX_DEFAULT_HANDLED_EXCEPTIONS); 224 } 225 226 public SvnClient getClient(SVNUrl repositoryUrl, 227 String username, 228 String password, 229 int handledExceptions) throws SVNClientException { 230 SvnClient client = SvnClientFactory.getInstance().createSvnClient(repositoryUrl, null, username, password, handledExceptions); 231 attachListeners(client); 232 return client; 233 } 234 235 public SvnClient getClient(SVNUrl repositoryUrl, SvnProgressSupport support) throws SVNClientException { 236 String username = ""; String password = ""; RepositoryConnection rc = SvnModuleConfig.getDefault().getRepositoryConnection(repositoryUrl.toString()); 239 if(rc != null) { 240 username = rc.getUsername(); 241 password = rc.getPassword(); 242 } 243 SvnClient client = SvnClientFactory.getInstance().createSvnClient(repositoryUrl, support, username, password, SvnClientExceptionHandler.EX_DEFAULT_HANDLED_EXCEPTIONS); 244 attachListeners(client); 245 return client; 246 } 247 248 public SvnClient getClient(File file) throws SVNClientException { 249 return getClient(file, null); 250 } 251 252 public SvnClient getClient(File file, SvnProgressSupport support) throws SVNClientException { 253 SVNUrl repositoryUrl = SvnUtils.getRepositoryRootUrl(file); 254 assert repositoryUrl != null : "Unable to get repository: " + file.getAbsolutePath() + " is probably unmanaged."; 256 return getClient(repositoryUrl, support); 257 } 258 259 public SvnClient getClient(Context ctx, SvnProgressSupport support) throws SVNClientException { 260 File[] roots = ctx.getRootFiles(); 261 SVNUrl repositoryUrl = null; 262 for (int i = 0; i<roots.length; i++) { 263 repositoryUrl = SvnUtils.getRepositoryRootUrl(roots[0]); 264 if (repositoryUrl != null) { 265 break; 266 } 267 } 268 269 assert repositoryUrl != null : "Unable to get repository, context contains only unmanaged files!"; 271 return getClient(repositoryUrl, support); 272 } 273 274 public SvnClient getClient(SVNUrl repositoryUrl) throws SVNClientException { 275 return getClient(repositoryUrl, null); 276 } 277 278 290 public SvnClient getClient(boolean attachListeners) { 291 cleanupFilesystem(); 292 if(attachListeners) { 293 if(noUrlClientWithListeners == null) { 294 noUrlClientWithListeners = SvnClientFactory.getInstance().createSvnClient(); 295 attachListeners(noUrlClientWithListeners); 296 } 297 return noUrlClientWithListeners; 298 } else { 299 if(noUrlClientWithoutListeners == null) { 300 noUrlClientWithoutListeners = SvnClientFactory.getInstance().createSvnClient(); 301 } 302 return noUrlClientWithoutListeners; 303 } 304 } 305 306 public FilesystemHandler getFileSystemHandler() { 307 return filesystemHandler; 308 } 309 310 317 public boolean isManaged(File file) { 318 return VersioningManager.getInstance().getOwner(file) instanceof SubversionVCS && !SvnUtils.isPartOfSubversionMetadata(file); 319 } 320 321 public void versionedFilesChanged() { 322 support.firePropertyChange(PROP_VERSIONED_FILES_CHANGED, null, null); 323 } 324 325 332 File getTopmostManagedParent(File file) { 333 if (SvnUtils.isPartOfSubversionMetadata(file)) { 334 for (;file != null; file = file.getParentFile()) { 335 if (isAdministrative(file)) { 336 file = file.getParentFile(); 337 break; 338 } 339 } 340 } 341 File topmost = null; 342 for (; file != null; file = file.getParentFile()) { 343 if (new File(file, ".svn/entries").canRead() || new File(file, "_svn/entries").canRead()) { topmost = file; 345 } 346 } 347 return topmost; 348 } 349 350 353 public void cleanupFilesystem() { 354 filesystemHandler.removeInvalidMetadata(); 355 } 356 357 private void attachListeners(SvnClient client) { 358 client.addNotifyListener(getLogger(client.getSvnUrl())); 359 client.addNotifyListener(fileStatusCache); 360 } 361 362 368 public OutputLogger getLogger(SVNUrl repositoryRoot) { 369 return OutputLogger.getLogger(repositoryRoot); 370 } 371 372 381 boolean isIgnored(final File file) { 382 String name = file.getName(); 383 384 386 final File parent = file.getParentFile(); 387 if (parent != null) { 388 int pstatus = fileStatusCache.getStatus(parent).getStatus(); 389 if ((pstatus & FileInformation.STATUS_VERSIONED) != 0) { 390 try { 391 SvnClient client = getClient(false); 392 393 List<String > patterns = client.getIgnoredPatterns(parent); 394 List<String > gignores = SvnConfigFiles.getInstance().getGlobalIgnores(); 395 for (Iterator<String > it = gignores.iterator(); it.hasNext(); patterns.add(it.next())); 397 398 if(SvnUtils.getMatchinIgnoreParterns(patterns,name, true).size() > 0) { 399 return true; 400 } 401 402 } catch (SVNClientException ex) { 403 ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, ex); 404 } 405 } 406 } 407 408 if (SharabilityQuery.getSharability(file) == SharabilityQuery.NOT_SHARABLE) { 409 try { 410 FileInformation info = fileStatusCache.getCachedStatus(file); if (SubversionVisibilityQuery.isHiddenFolder(info, file)) { 413 return false; 414 } 415 if (SharabilityQuery.getSharability(parent) != SharabilityQuery.NOT_SHARABLE) { 417 if ((fileStatusCache.getStatus(parent).getStatus() & FileInformation.STATUS_VERSIONED) != 0) { 418 IgnoreAction.ignore(file); 419 } 420 } 421 } catch (SVNClientException ex) { 422 ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, ex); 423 } 424 return true; 425 } else { 426 if (".nbintdb".equals(name)) { return true; 429 } 430 431 return false; 432 } 433 } 434 435 438 public RequestProcessor getRequestProcessor() { 439 return getRequestProcessor(null); 440 } 441 442 445 public RequestProcessor getRequestProcessor(SVNUrl url) { 446 if(processorsToUrl == null) { 447 processorsToUrl = new HashMap<String , RequestProcessor>(); 448 } 449 450 String key; 451 if(url != null) { 452 key = url.toString(); 453 } else { 454 key = "ANY_URL"; } 456 457 RequestProcessor rp = processorsToUrl.get(key); 458 if(rp == null) { 459 rp = new RequestProcessor("Subversion - " + key, 1, true); processorsToUrl.put(key, rp); 461 } 462 return rp; 463 } 464 465 FileStatusProvider getVCSAnnotator() { 466 return fileStatusProvider; 467 } 468 469 VCSInterceptor getVCSInterceptor() { 470 return filesystemHandler; 471 } 472 473 476 public void refreshAllAnnotations() { 477 support.firePropertyChange(PROP_ANNOTATIONS_CHANGED, null, null); 478 } 479 480 void addPropertyChangeListener(PropertyChangeListener listener) { 481 support.addPropertyChangeListener(listener); 482 } 483 484 void removePropertyChangeListener(PropertyChangeListener listener) { 485 support.removePropertyChangeListener(listener); 486 } 487 488 public OriginalContent getVCSOriginalContent(File file) { 489 FileInformation info = fileStatusCache.getStatus(file); 490 if ((info.getStatus() & STATUS_DIFFABLE) == 0) return null; 491 return new SubversionOriginalContent(file); 492 } 493 494 495 private class SubversionOriginalContent extends OriginalContent implements VersioningListener { 496 497 public SubversionOriginalContent(File working) { 498 super(working); 499 } 500 501 protected void getOriginalFiles(File destination, Set<File> files) throws Exception { 502 for (File file : files) { 503 File original = VersionsCache.getInstance().getFileRevision(file, Setup.REVISION_BASE); 504 if (original == null) throw new IOException("Unable to get BASE revision of " + file); 505 506 File daoFile = new File(destination, file.getName()); 507 org.netbeans.modules.versioning.util.Utils.copyStreamsCloseAll(new FileOutputStream(daoFile), new FileInputStream(original)); 508 daoFile.deleteOnExit(); 509 } 510 } 511 512 public void versioningEvent(VersioningEvent event) { 513 if (FileStatusCache.EVENT_FILE_STATUS_CHANGED == event.getId()) { 514 File eventFile = (File) event.getParams()[0]; 515 if (eventFile.equals(workingCopy)) { 516 support.firePropertyChange(PROP_CONTENT_CHANGED, null, null); 517 } 518 } 519 } 520 521 public void addPropertyChangeListener(PropertyChangeListener listener) { 522 if (!support.hasListeners(null)) { 523 fileStatusCache.addVersioningListener(this); 524 } 525 super.addPropertyChangeListener(listener); 526 } 527 528 public void removePropertyChangeListener(PropertyChangeListener listener) { 529 super.removePropertyChangeListener(listener); 530 if (!support.hasListeners(null)) { 531 fileStatusCache.removeVersioningListener(this); 532 } 533 } 534 } 535 536 } 537 | Popular Tags |