All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.netbeans.modules.subversion.VersionsCache Maven / Gradle / Ivy

The newest version!
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package org.netbeans.modules.subversion;

import java.io.*;
import java.text.ParseException;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.netbeans.modules.subversion.client.*;
import org.netbeans.modules.subversion.ui.diff.Setup;
import org.netbeans.modules.subversion.util.*;
import org.netbeans.modules.versioning.historystore.Storage;
import org.netbeans.modules.versioning.historystore.StorageManager;
import org.netbeans.modules.versioning.util.FileUtils;
import org.netbeans.modules.versioning.util.Utils;
import org.openide.filesystems.FileUtil;
import org.tigris.subversion.svnclientadapter.*;

/**
 * File revisions cache. It can access pristine files.
 *
 * @author Petr Kuzel
 */
public class VersionsCache {

    private static VersionsCache instance;

    /** Creates a new instance of VersionsCache */
    private VersionsCache() {
    }

    public static synchronized VersionsCache getInstance() {
        if (instance == null) {
            instance = new VersionsCache();
        }
        return instance;
    }

    /**
     * Loads a content of the given file in the given revision. May communicate over network.
     * @param repoUrl target repository URL
     * @param url target file full url
     * @param revision target revision, will be used also as the peg revision
     * @param fileName basename of the file which will be used as a temporary file's name
     * @return a temporary file with given file's content
     * @throws java.io.IOException
     */
    public File getFileRevision(SVNUrl repoUrl, SVNUrl url, String revision, String fileName) throws IOException {
        return getFileRevision(repoUrl, url, revision, revision, fileName);
    }
    /**
     * Loads a content of the given file in the given revision. May communicate over network.
     * @param repoUrl target repository URL
     * @param url target file full url
     * @param revision target revision
     * @param pegRevision peg revision
     * @param fileName basename of the file which will be used as a temporary file's name
     * @return a temporary file with given file's content
     * @throws java.io.IOException
     */
    public File getFileRevision(SVNUrl repoUrl, SVNUrl url, String revision, String pegRevision, String fileName) throws IOException {
        boolean canUseRevisionsCache = true;
        try {
            canUseRevisionsCache = SVNRevision.getRevision(revision).getKind() == SVNRevision.Kind.number
                    && SVNRevision.getRevision(pegRevision).getKind() == SVNRevision.Kind.number;
        } catch (ParseException ex) { }
        try {
            if (!canUseRevisionsCache || "false".equals(System.getProperty("versioning.subversion.historycache.enable", "true"))) { //NOI18N
                SvnClient client = Subversion.getInstance().getClient(repoUrl);
                InputStream in = getInputStream(client, url, revision, pegRevision);
                return createContent(fileName, in);
            } else {
                String rootUrl = repoUrl.toString();
                String resourceUrl = url.toString() + "@" + pegRevision; //NOI18N
                Storage cachedVersions = StorageManager.getInstance().getStorage(rootUrl);
                File cachedFile = cachedVersions.getContent(resourceUrl, fileName, revision);
                if (cachedFile.length() == 0) { // not yet cached
                    SvnClient client = Subversion.getInstance().getClient(repoUrl);
                    InputStream in = getInputStream(client, url, revision, pegRevision);
                    cachedFile = createContent(fileName, in);
                    if (cachedFile.length() != 0) {
                        cachedVersions.setContent(resourceUrl, revision, cachedFile);
                    }
                }
                return cachedFile;
            }
        } catch (SVNClientException ex) {
            throw new IOException("Can not load: " + url + " in revision: " + revision, ex);
        }
    }

    /**
     * Loads the file in specified revision.
     * For peg revision revision will be used for existing files, for repository files it will be the HEAD revision.
     * 

It's may connect over network I/O do not * call from the GUI thread.

* * @return null if the file does not exit in given revision */ public File getFileRevision(File base, String revision) throws IOException { return getFileRevision(base, revision, Setup.REVISION_BASE); } /** * Loads the file in specified revision. * *

It's may connect over network I/O do not * call from the GUI thread. * * @return null if the file does not exit in given revision */ public File getFileRevision(File base, String revision, String pegRevision) throws IOException { try { SvnClientFactory.checkClientAvailable(); } catch (SVNClientException e) { return null; } if (Setup.REVISION_BASE.equals(revision)) { return getBaseRevisionFile(base); } else if (Setup.REVISION_PRISTINE.equals(revision)) { // should not be used, will not work with 1.7 String name = base.getName(); File svnDir = getMetadataDir(base.getParentFile()); if (svnDir != null) { File text_base = new File(svnDir, "text-base"); // NOI18N File pristine = new File(text_base, name + ".svn-base"); // NOI18N if (pristine.isFile()) { return pristine; } else { return null; } } else { return null; } } else if (Setup.REVISION_CURRENT.equals(revision)) { return base; } else { SVNRevision svnrevision = SvnUtils.toSvnRevision(revision); try { SvnClient client = Subversion.getInstance().getClient(base); FileStatusCache cache = Subversion.getInstance().getStatusCache(); InputStream in = null; try { boolean gotContent = false; if ((cache.getStatus(base).getStatus() & FileInformation.STATUS_VERSIONED) != 0) { try { in = client.getContent(base, svnrevision); gotContent = true; } catch (SVNClientException e) { if(svnrevision.getKind() != SVNRevision.Kind.number || !(SvnClientExceptionHandler.isFileNotFoundInRevision(e.getMessage()) || SvnClientExceptionHandler.isPathNotFound(e.getMessage()))) { throw e; } } } if (!gotContent) { if (Setup.REVISION_BASE.equals(pegRevision)) { try { // we can't contact server with BASE being peg revision ISVNStatus st = SvnUtils.getSingleStatus(client, base); if (st != null && st.getRevision() != null) { pegRevision = st.getRevision().toString(); } else { pegRevision = SVNRevision.HEAD.toString(); } } catch (SVNClientException e) {} } SVNUrl url = SvnUtils.getRepositoryUrl(base); if (url != null) { in = getInputStream(client, url, revision, pegRevision); } else { in = new ByteArrayInputStream(org.openide.util.NbBundle.getMessage(VersionsCache.class, "MSG_UnknownURL").getBytes()); // NOI18N } } } catch (SVNClientException e) { if(SvnClientExceptionHandler.isFileNotFoundInRevision(e.getMessage()) || SvnClientExceptionHandler.isPathNotFound(e.getMessage())) { in = new ByteArrayInputStream(new byte[] {}); } else { throw e; } } return createContent(base.getName(), in); } catch (SVNClientException ex) { throw new IOException("Can not load: " + base.getAbsolutePath() + " in revision: " + revision, ex); } } } /** * Returns content of the given file at its base revision. * In other words, returns content of the given file without local * modifications. * The returned {@code File} may be deleted after use. * The returned {@code File} is not scheduled for automatic * deletion upon JVM shutdown. * * @param referenceFile reference file * @return file holding content of the unmodified version of the given file * @exception java.io.IOException if some file handling operation failed */ File getBaseRevisionFile(File referenceFile) throws IOException { try { boolean newMetadataFormat = false; File svnDir = getMetadataDir(referenceFile.getParentFile()); if (svnDir == null) { // try to check 1.7 metadata File topmost = Subversion.getInstance().getTopmostManagedAncestor(referenceFile); File newMetadataFolder; if (topmost != null && (newMetadataFolder = new File(topmost, SvnUtils.SVN_ADMIN_DIR)).exists()) { svnDir = newMetadataFolder; newMetadataFormat = new File(svnDir, "pristine").exists(); //NOI18N if (!newMetadataFormat) { Logger.getLogger(VersionsCache.class.getName()).log(Level.FINE, "No 1.7 metadata in {0}", svnDir); //NOI18N } } } if (svnDir == null) { return null; } if (newMetadataFormat) { return getContentBase(referenceFile, new File(Utils.getTempFolder(), referenceFile.getName() + ".netbeans-base")); //NOI18N } else { File svnBase = new File(svnDir, "text-base/" + referenceFile.getName() + ".svn-base"); //NOI18N if (!svnBase.exists()) { if (new File(svnDir, "pristine").exists()) { //NOI18N - svn1.7, file is directly in the root of a checkout return getContentBase(referenceFile, new File(Utils.getTempFolder(), referenceFile.getName() + ".netbeans-base")); //NOI18N } return null; } File expanded = new File(svnDir, "text-base/" + referenceFile.getName() + ".netbeans-base"); //NOI18N if (expanded.canRead() && svnBase.isFile() && expanded.length() == svnBase.length() && (expanded.lastModified() >= svnBase.lastModified())) { return expanded; } expanded = getContentBase(referenceFile, expanded); expanded.setLastModified(svnBase.lastModified()); return expanded; } } catch (SVNClientException e) { throw new IOException(e); } } private File getContentBase (File referenceFile, File output) throws SVNClientException, IOException { SvnClient client = Subversion.getInstance().getClient(false); // local call, does not need to be instantiated with the file instance InputStream in; try { in = client.getContent(referenceFile, SVNRevision.BASE); } catch (SVNClientException ex) { if(SvnClientExceptionHandler.isUnversionedResource(ex.getMessage()) || SvnClientExceptionHandler.hasNoBaseRevision(ex.getMessage())) { // Subversion 1.7 error messages in = new ByteArrayInputStream(new byte[] {}); } else { throw ex; } } output = FileUtil.normalizeFile(output); FileUtils.copyStreamToFile(new BufferedInputStream(in), output); return output; } /** * Tries to acquire a content of the given file url in the given revision * @param client * @param url * @param revision * @param pegRevision * @return content of the file in the given revision * @throws org.tigris.subversion.svnclientadapter.SVNClientException */ private InputStream getInputStream (SvnClient client, SVNUrl url, String revision, String pegRevision) throws SVNClientException { InputStream in = null; try { in = client.getContent(url, SvnUtils.toSvnRevision(revision), SvnUtils.toSvnRevision(pegRevision)); } catch (SVNClientException e) { if (SvnClientExceptionHandler.isFileNotFoundInRevision(e.getMessage()) || SvnClientExceptionHandler.isPathNotFound(e.getMessage())) { in = new ByteArrayInputStream(new byte[]{}); } else { throw e; } } return in; } /** * Creates a temporary file and prints the content of in to it. * @param fileName temporary file name, will be prefixed by "nb-svn" * @param in content to be printed * @return created temporary file * @throws java.io.IOException */ private File createContent (String fileName, InputStream in) throws IOException { // keep original extension so MIME can be guessed by the extension File tmp = new File(Utils.getTempFolder(), fileName); // NOI18N tmp = FileUtil.normalizeFile(tmp); tmp.deleteOnExit(); // hard to track actual lifetime FileUtils.copyStreamToFile(new BufferedInputStream(in), tmp); return tmp; } private File getMetadataDir(File dir) { File svnDir = new File(dir, SvnUtils.SVN_ADMIN_DIR); // NOI18N if (!svnDir.isDirectory()) { return null; } return svnDir; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy