1 19 20 package org.netbeans.modules.versioning.system.cvss; 21 22 import org.netbeans.lib.cvsclient.command.CommandException; 23 import org.netbeans.lib.cvsclient.command.GlobalOptions; 24 import org.netbeans.lib.cvsclient.command.checkout.CheckoutCommand; 25 import org.netbeans.lib.cvsclient.connection.AuthenticationException; 26 import org.netbeans.lib.cvsclient.admin.Entry; 27 import org.netbeans.lib.cvsclient.CVSRoot; 28 import org.netbeans.modules.versioning.system.cvss.util.Utils; 29 import org.openide.filesystems.FileUtil; 30 import org.openide.util.NbBundle; 31 32 import java.io.*; 33 34 42 public class VersionsCache { 43 44 47 public static final String REVISION_CURRENT = ""; 49 52 public static final String REVISION_BASE = "*"; 54 57 public static final String REVISION_HEAD = "HEAD"; 59 private static final String CACHE_DIR = "CVS/RevisionCache/"; 61 private static VersionsCache instance = new VersionsCache(); 62 63 private long purgeTimestamp = Long.MAX_VALUE; 64 65 public static VersionsCache getInstance() { 66 return instance; 67 } 68 69 private VersionsCache() { 70 } 71 72 87 public synchronized File getRemoteFile(File baseFile, String revision, ExecutorGroup group) throws IOException, 88 IllegalCommandException, CommandException, AuthenticationException, NotVersionedException { 89 return getRemoteFile(baseFile, revision, group, false); 90 } 91 92 public synchronized File getRemoteFile(File baseFile, String revision, ExecutorGroup group, boolean quiet) throws IOException, 93 IllegalCommandException, CommandException, AuthenticationException, NotVersionedException { 94 String resolvedRevision = resolveRevision(baseFile, revision); 95 if (revision == REVISION_CURRENT) { 96 return baseFile.canRead() ? baseFile : null; 97 } 98 File file = getCachedRevision(baseFile, resolvedRevision); 99 if (file != null) return file; 100 file = checkoutRemoteFile(baseFile, revision, group, quiet); 101 if (file == null) return null; 102 return saveRevision(baseFile, file, resolvedRevision); 103 } 104 105 private String resolveRevision(File baseFile, String revision) throws IOException { 106 if (revision == REVISION_BASE) { 107 return getBaseRevision(baseFile); 108 } 109 if (revision.equals(REVISION_HEAD)) { 110 Entry entry = CvsVersioningSystem.getInstance().getAdminHandler().getEntry(baseFile); 111 if (entry != null && entry.getTag() != null) { 112 return entry.getTag(); 113 } 114 } 115 return revision; 116 } 117 118 122 public void purgeVolatileRevisions() { 123 purgeTimestamp = System.currentTimeMillis(); 124 } 125 126 private File saveRevision(File baseFile, File file, String revision) { 127 File cacheDir; 129 if (baseFile.getParentFile().isDirectory()) { 130 cacheDir = new File(baseFile.getParentFile(), CACHE_DIR); 131 } else { 132 cacheDir = file.getParentFile(); 133 } 134 if (!cacheDir.exists() && !cacheDir.mkdirs()) return file; 135 File destFile = new File(cacheDir, cachedName(baseFile, revision)); 136 try { 137 FileInputStream fin = new FileInputStream(file); 138 FileOutputStream fos = new FileOutputStream(destFile); 139 FileUtil.copy(fin, fos); 140 fin.close(); 141 fos.close(); 142 if (file.equals(baseFile)) { 144 FileInformation info = CvsVersioningSystem.getInstance().getStatusCache().createFileInformation(baseFile); 146 if (info.getStatus() != FileInformation.STATUS_VERSIONED_UPTODATE) { 147 destFile.delete(); 148 return null; 149 } 150 } else { 151 file.delete(); 152 } 153 return destFile; 154 } catch (IOException e) { 155 } 157 return file; 158 } 159 160 private File getCachedRevision(File baseFile, String revision) { 161 File cachedCopy = new File(baseFile.getParentFile(), CACHE_DIR + cachedName(baseFile, revision)); 162 if (isVolatile(revision)) { 163 if (cachedCopy.lastModified() < purgeTimestamp) { 164 cachedCopy.delete(); 165 } 166 } 167 if (cachedCopy.canRead()) return cachedCopy; 168 return null; 169 } 170 171 private boolean isVolatile(String revision) { 172 return revision.indexOf('.') == -1; 173 } 174 175 private String getBaseRevision(File file) throws IOException { 176 Entry entry = CvsVersioningSystem.getInstance().getAdminHandler().getEntry(file); 177 if (entry == null) { 178 throw new IllegalArgumentException ("Cannot get BASE revision, there is no Entry for the file: " + file.getAbsolutePath()); 179 } 180 String rawRev = entry.getRevision(); 181 if (rawRev != null && rawRev.startsWith("-")) { return rawRev.substring(1); 184 } 185 return rawRev; 186 } 187 188 private String cachedName(File baseFile, String revision) { 189 return baseFile.getName() + "#" + revision; } 191 192 private String getRepositoryForDirectory(File directory, String repository) { 193 if (directory == null) return null; 194 if (!directory.exists()) { 195 return getRepositoryForDirectory(directory.getParentFile(), repository) + "/" + directory.getName(); } 197 try { 198 return CvsVersioningSystem.getInstance().getAdminHandler().getRepositoryForDirectory(directory.getAbsolutePath(), repository); } catch (IOException e) { 200 return null; 201 } 202 } 203 204 215 private File checkoutRemoteFile(File baseFile, String revision, ExecutorGroup group, boolean quiet) throws IOException { 216 217 if (revision == REVISION_BASE) { 218 FileInformation info = CvsVersioningSystem.getInstance().getStatusCache().createFileInformation(baseFile); 220 if (info.getStatus() == FileInformation.STATUS_VERSIONED_UPTODATE) { 221 return baseFile; 222 } 223 } 224 revision = resolveRevision(baseFile, revision); 225 226 GlobalOptions options = CvsVersioningSystem.createGlobalOptions(); 227 String root = Utils.getCVSRootFor(baseFile.getParentFile()); 228 CVSRoot cvsRoot = CVSRoot.parse(root); 229 String repository = cvsRoot.getRepository(); 230 options.setCVSRoot(root); 231 232 String repositoryPath = getRepositoryForDirectory(baseFile.getParentFile(), repository) + "/" + baseFile.getName(); 234 CheckoutCommand cmd = new CheckoutCommand(); 235 cmd.setRecursive(false); 236 assert repositoryPath.startsWith(repository) : repositoryPath + " does not start with: " + repository; 238 repositoryPath = repositoryPath.substring(repository.length()); 239 if (repositoryPath.startsWith("/")) { repositoryPath = repositoryPath.substring(1); 241 } 242 cmd.setModule(repositoryPath); 243 cmd.setPipeToOutput(true); 244 cmd.setCheckoutByRevision(revision); 245 String msg = NbBundle.getMessage(VersionsCache.class, "MSG_VersionsCache_FetchingProgress", revision, baseFile.getName()); 246 cmd.setDisplayName(msg); 247 248 VersionsCacheExecutor executor = new VersionsCacheExecutor(cmd, options, quiet); 249 if (group != null) { 250 group.progress(msg); 251 group.addExecutor(executor); 252 } 253 executor.execute(); 254 ExecutorSupport.wait(new ExecutorSupport [] { executor }); 255 if (group == null) { 256 executor.getGroup().executed(); 257 } 258 259 if (executor.isSuccessful()) { 260 return executor.getCheckedOutVersion(); 261 } else { 262 if (executor.isCancelled()) { 263 return null; 264 } 265 IOException ioe = new IOException(NbBundle.getMessage(VersionsCache.class, "Bk4001", revision, baseFile.getName())); 267 ioe.initCause(executor.getFailure()); 268 throw ioe; 269 } 270 271 } 272 } 273 | Popular Tags |