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

com.jtstand.FileRevision Maven / Gradle / Ivy

/*
 * Copyright (c) 2009 Albert Kurucz. 
 *
 * This file, FileRevision.java is part of JTStand.
 *
 * JTStand is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * JTStand is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with GTStand.  If not, see .
 */
package com.jtstand;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringWriter;
import java.io.Writer;
import java.net.URI;
import java.util.Enumeration;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.persistence.Entity;
import javax.persistence.EntityManager;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Query;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlTransient;
import javax.xml.bind.annotation.XmlType;
import org.tmatesoft.svn.core.SVNException;
import org.tmatesoft.svn.core.SVNNodeKind;
import org.tmatesoft.svn.core.SVNProperties;
import org.tmatesoft.svn.core.SVNProperty;
import org.tmatesoft.svn.core.SVNURL;
import org.tmatesoft.svn.core.internal.io.dav.DAVRepositoryFactory;
import org.tmatesoft.svn.core.io.SVNRepository;
import org.tmatesoft.svn.core.wc.SVNClientManager;
import org.tmatesoft.svn.core.wc.SVNStatus;
import org.tmatesoft.svn.core.wc.SVNStatusType;

/**
 *
 * @author albert_kurucz
 */
@Entity
@Table(uniqueConstraints =
@UniqueConstraint(columnNames = {"subversionurl", "revision"}))
@XmlType(propOrder = {"revision", "subversionUrl"})
@XmlAccessorType(value = XmlAccessType.PROPERTY)
public class FileRevision {

    private static final ConcurrentHashMap FILE_CACHE = new java.util.concurrent.ConcurrentHashMap();
    private static final Object FILE_CACHE_LOCK = new Object();
    private String subversionUrl;
    private Long revision;
    private transient File file;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    public FileRevision() {
    }

    public FileRevision(String subversionUrl, Long revision) {
        this.subversionUrl = subversionUrl;
        this.revision = revision;
        synchronized (FILE_CACHE_LOCK) {
            Enumeration keys = FILE_CACHE.keys();
            while (keys.hasMoreElements()) {
                FileRevision fr = keys.nextElement();
                if (fr.subversionUrl.equals(subversionUrl)
                        && fr.revision.equals(revision)) {
                    file = fr.file;
                    break;
                }
            }
        }
    }

    public FileRevision(String subversionUrl, Long revision, File file) {
        this.subversionUrl = subversionUrl;
        this.revision = revision;
        this.file = file;
    }

    public static FileRevision query(EntityManager em, FileRevision creator) {
        if (em == null) {
            return null;
        }
        if (creator == null) {
            throw new IllegalArgumentException("creator parameter cannot be null");
        }
        if (creator.getId() != null && em.contains(creator)) {
            return creator;
        }
        try {
            Query q1 = em.createQuery("from FileRevision frev where frev.subversionUrl = :subversionUrl and frev.revision = :revision");
            q1.setParameter("subversionUrl", creator.getSubversionUrl());
            q1.setParameter("revision", creator.getRevision());
            FileRevision fr = (FileRevision) q1.getSingleResult();
            fr.setFile(creator.getFile());
            return fr;
        } catch (Exception ex) {
            return null;
        }
    }

    FileRevision resolve(String subversionUrl, Long revision) {
        synchronized (FILE_CACHE_LOCK) {
            Enumeration keys = FILE_CACHE.keys();
            while (keys.hasMoreElements()) {
                FileRevision fr = keys.nextElement();
                if (fr.subversionUrl.equals(subversionUrl) && fr.revision.equals(revision)) {
                    return new FileRevision(subversionUrl, revision, fr.file);
                }
            }
        }
        if (file != null) {
            try {
                File parentFile = file.getParentFile();
                System.out.println("Path of Filer's parent: '" + parentFile.getAbsolutePath());

                URI filerURI = URI.create(subversionUrl);
                System.out.println("filerURI:" + filerURI);

                URI parentURI = filerURI.resolve(".");
                System.out.println("parentURI:" + parentURI);

                URI uri = new URI(subversionUrl);
                System.out.println("uri:" + uri);

                URI relative = parentURI.relativize(uri);
                System.out.println("Relative path:" + relative);

                File f = new File(parentFile.getPath() + File.separator + relative.toString());
                System.out.println("Resolved file path:" + f.getPath());

                return new FileRevision(subversionUrl, revision, f);
            } catch (Exception ex) {
                System.out.println("Exception while checking current revision of local file: " + ex);
            }
        }
        return new FileRevision(subversionUrl, revision);
    }

//    public static FileRevision query(final FileRevision creator) {
//        return (new FileRevisionQuery(creator)).query();
//    }
    @XmlTransient
    public Long getId() {
        return id;
    }

    @XmlAttribute
    public String getSubversionUrl() {
        return subversionUrl;
    }

    public void setSubversionUrl(String subversionUrl) {
        this.subversionUrl = subversionUrl;
    }

    @XmlAttribute
    public Long getRevision() {
        return revision;
    }

    public void setRevision(Long revision) {
        this.revision = revision;
    }

    public static FileRevision createFromUrlOrFile(String subversionUrlorFilePath, long revision) {
        File checkfile = new File(subversionUrlorFilePath);
        if (checkfile.isFile()) {
            SVNClientManager cm = SVNClientManager.newInstance();
            try {
                SVNStatus svns = cm.getStatusClient().doStatus(checkfile, false);
                long currentRevision = svns.getCommittedRevision().getNumber();
                if (revision == 0) {
                    revision = currentRevision;
                }
                System.out.println("URL of the file: " + svns.getURL());
                System.out.println("Current revision of the file: " + Long.toString(currentRevision));
                return new FileRevision(svns.getURL().toString(), revision, checkfile);
            } catch (SVNException ex) {
                Logger.getLogger(FileRevision.class.getName()).log(Level.SEVERE, null, ex);
                ex.printStackTrace();
                System.exit(1);
            }
        }
        if (revision == 0) {
            revision = -1L;
        }
        synchronized (FILE_CACHE_LOCK) {
            Enumeration keys = FILE_CACHE.keys();
            while (keys.hasMoreElements()) {
                FileRevision fr = keys.nextElement();
                if (fr.subversionUrl.equals(subversionUrlorFilePath) && fr.revision.equals(revision)) {
                    return fr;
                }
            }
        }
        return new FileRevision(subversionUrlorFilePath, revision);
    }

    @XmlTransient
    public File getFile() {
        return file;
    }

    public void setFile(File file) {
        this.file = file;
    }

    public Object unmarshal(Unmarshaller un, boolean useCache)
            throws SVNException, JAXBException {
        if (useCache) {
            synchronized (FILE_CACHE_LOCK) {
                Object object = FILE_CACHE.get(this);
                if (object != null) {
                    return object;
                }
                object = un.unmarshal(getInputStream());
                FILE_CACHE.put(this, object);
                return object;
            }
        } else {
            return un.unmarshal(getInputStream());
        }
    }

    public String getText(String charset) throws SVNException, IOException {
//        System.out.println("Reading file...");
        return convertStreamToString(getInputStreamUnprotected(), charset);
    }

    public static String convertStreamToString(InputStream is, String charset)
            throws IOException {
        if (is == null) {
            return "";
        }
        Writer writer = new StringWriter();
        char[] buffer = new char[1024];
        try {
            Reader reader = new BufferedReader(new InputStreamReader(is, charset));
            int n;
            while ((n = reader.read(buffer)) != -1) {
                writer.write(buffer, 0, n);
            }
        } finally {
            is.close();
        }
        return writer.toString();
    }

    public static InputStream protectInputStream(InputStream is, String charset) throws IOException {
        String text = convertStreamToString(is, charset);
        return (text == null) ? null : new ByteArrayInputStream(text.getBytes(charset));
    }

    private InputStream getInputStream() throws SVNException {
        try {
            return protectInputStream(getInputStreamUnprotected(), "UTF-8");
        } catch (IOException ex) {
            Logger.getLogger(FileRevision.class.getName()).log(Level.SEVERE, null, ex);
        }
        return null;
    }

    private InputStream getInputStreamUnprotected() throws SVNException {
        if (file != null && file.isFile()) {
//            System.out.println("Path: '" + file.getAbsolutePath() + "' revision: '" + revision + "'");
            SVNClientManager cm = SVNClientManager.newInstance();
            try {
                SVNStatus svns = cm.getStatusClient().doStatus(file, false);
                if (SVNStatusType.STATUS_NORMAL.equals(svns.getContentsStatus())) {
                    long committedRevision = svns.getCommittedRevision().getNumber();
                    if (svns.getURL().toDecodedString().equals(subversionUrl)) {
                        if (committedRevision == revision) {
                            return new FileInputStream(file);
                        } else {
                            System.out.println("Committed revision of the file is " + Long.toString(committedRevision) + " instead of " + revision + "!");
                        }
                    } else {
                        System.out.println("Local copy URL: '" + svns.getURL().toDecodedString() + "' does not match!");
                    }
                } else {
                    System.out.println("Status is '" + svns.getContentsStatus() + "' instead of '" + SVNStatusType.STATUS_NORMAL + "'!");
                }
            } catch (FileNotFoundException ex) {
                System.out.println("Exception while reading local file: " + ex);
            } catch (Exception ex) {
                System.out.println("Exception while checking current revision of local file: " + ex);
            }
        }
        System.out.println("URL: '" + subversionUrl + "' revision: '" + revision + "'");
        DAVRepositoryFactory.setup();
        int pos = subversionUrl.lastIndexOf('/');
        String url = subversionUrl.substring(0, pos);
//        System.out.println("URL: " + url);
        String filePath = subversionUrl.substring(pos + 1);
//        System.out.println("Path: " + filePath);
        SVNRepository repository = DAVRepositoryFactory.create(SVNURL.parseURIDecoded(url));
        SVNNodeKind nodeKind = repository.checkPath(filePath, -1);
        if (nodeKind.equals(SVNNodeKind.NONE)) {
            throw new IllegalArgumentException("Specified file with URL: '" + subversionUrl + "' is not versioned");
        } else if (nodeKind.equals(SVNNodeKind.DIR)) {
            throw new IllegalArgumentException("Specified file with URL: '" + subversionUrl + "' is a directory");
        }

        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        SVNProperties props = new SVNProperties();
        repository.getFile(filePath, revision, props, baos);
        Long rev = Long.parseLong(props.getStringValue(SVNProperty.COMMITTED_REVISION));
        if (!rev.equals(revision)) {
            if (-1 == revision) {
                System.out.println("Changing revision from: '" + revision + "' to: '" + rev + "'...");
                revision = rev;
            } else {
                throw new IllegalArgumentException("Expected revision: " + revision + " found revision: " + rev);
            }
        }
        repository.closeSession();
        return new ByteArrayInputStream(baos.toByteArray());
    }

    @Override
    public int hashCode() {
        int hash = 0;
        hash += (subversionUrl != null ? subversionUrl.hashCode() : 0);
        hash += (revision != null ? revision.hashCode() : 0);
        return hash;
    }

    @Override
    public boolean equals(Object object) {
        if (!(object instanceof FileRevision)) {
            return false;
        }
        FileRevision other = (FileRevision) object;
        if ((this.subversionUrl == null && other.getSubversionUrl() != null) || (this.subversionUrl != null && !this.subversionUrl.equals(other.getSubversionUrl()))) {
            return false;
        }
        if ((this.revision == null && other.getRevision() != null) || (this.revision != null && !this.revision.equals(other.getRevision()))) {
            return false;
        }
        return true;
    }

    @Override
    public String toString() {
        String retval = getSubversionUrl() + "@" + getRevision();
        if (file != null) {
            retval += "@" + file.getPath();
        }
        return retval;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy