Package org.fao.geonet.kernel

Source Code of org.fao.geonet.kernel.SvnManager

//=============================================================================
//===  Copyright (C) 2001-2011 Food and Agriculture Organization of the
//===  United Nations (FAO-UN), United Nations World Food Programme (WFP)
//===  and United Nations Environment Programme (UNEP)
//===
//===  This program is free software; you can redistribute it and/or modify
//===  it under the terms of the GNU General Public License as published by
//===  the Free Software Foundation; either version 2 of the License, or (at
//===  your option) any later version.
//===
//===  This program 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
//===  General Public License for more details.
//===
//===  You should have received a copy of the GNU General Public License
//===  along with this program; if not, write to the Free Software
//===  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
//===
//===  Contact: Jeroen Ticheler - FAO - Viale delle Terme di Caracalla 2,
//===  Rome - Italy. email: geonetwork@osgeo.org
//==============================================================================

package org.fao.geonet.kernel;

import jeeves.server.UserSession;
import jeeves.server.context.ServiceContext;
import org.apache.commons.lang.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.fao.geonet.Constants;
import org.fao.geonet.constants.Geonet;
import org.fao.geonet.constants.Params;
import org.fao.geonet.domain.*;
import org.fao.geonet.kernel.setting.SettingManager;
import org.fao.geonet.repository.*;
import org.fao.geonet.repository.specification.OperationAllowedSpecs;
import org.fao.geonet.utils.Log;
import org.fao.geonet.utils.Xml;
import org.jdom.Element;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.tmatesoft.svn.core.*;
import org.tmatesoft.svn.core.auth.ISVNAuthenticationManager;
import org.tmatesoft.svn.core.io.ISVNEditor;
import org.tmatesoft.svn.core.io.SVNRepository;
import org.tmatesoft.svn.core.io.SVNRepositoryFactory;
import org.tmatesoft.svn.core.wc.SVNWCUtil;

import javax.sql.DataSource;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.sql.Connection;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

@Aspect
public class SvnManager {

    @Autowired
    OperationAllowedRepository _operationAllowedRepository;
    @Autowired
    GroupRepository _groupRepository;
    @Autowired
    OperationRepository _operationRepository;
    @Autowired
    private SettingManager _settingManager;
    @Autowired
    private DataSource _dataSource;

    // configure via setter in Geonetwork app
    private ServiceContext context;
    // configure in init method
    private SVNURL repoUrl;
    // configure in spring configuration of bean
    private String subversionPath;

    private static String username = "geonetwork";
    private static String password = "geonetwork";

    private Map<TransactionStatus, SvnTask> tasks = new ConcurrentHashMap<TransactionStatus, SvnTask>();
    private boolean _enabled = false;

    // SvnTask holds information used to commit changes to a metadata record
    private static class SvnTask {
        Set<String> ids; // metadata ids
        String sessionLogMessage; // session log message for svn commit
        // Map<String,String> props; // properties to set on metadata record
    }

    /**
     * Constructor. Creates the subversion repository if it doesn't exist or just open the subversion repository if it does. Stores the
     * URL
     * of the repository in repoUrl. Adds the commit/abort listeners to the DbmsPool resource provider.
     */
    public void init() throws Exception {
        this._enabled = true;
        String uuid = _settingManager.getValue("system/site/svnUuid");

        boolean dbCreated = false;
        if (StringUtils.isEmpty(uuid)) {
            dbCreated = true;
            uuid = UUID.randomUUID().toString();
            _settingManager.setValue("system/site/svnUuid", uuid);
        }

        File subFile = new File(subversionPath);
        boolean repoCreated = false;

        // if subversion repo doesn't exist then create it with siteId
        try {
            boolean enableRevisionProperties = true;
            boolean force = false;
            repoUrl = SVNRepositoryFactory.createLocalRepository(subFile, uuid, enableRevisionProperties, force);
            repoCreated = true;
        } catch (SVNException e) {

            if (subFile.exists()) { // set the repoUrl and try and open it
                subFile = subFile.getCanonicalFile();
                repoUrl = SVNURL.fromFile(subFile);

            } else {
                e.printStackTrace();
                throw new IllegalArgumentException("Problem creating or using repository at path " + subversionPath);
            }
        }

        // open the repository now
        SVNRepository repo = null;
        try {
            repo = getRepository();
        } catch (SVNException se) {
            Log.error(Geonet.SVN_MANAGER, "Failed to open subversion repo at path " + subversionPath);
            se.printStackTrace();
            throw se;
        }

        // do some checks on existing repo and recreate it if empty
        if (!repoCreated) {
            String repoUuid = repo.getRepositoryUUID(true);
            long latestRev = repo.getLatestRevision();
            // check that repository has something in it
            if (latestRev > 1) {
                // check that repository uuid matches the repo uuid in database
                if (!uuid.equals(repoUuid)) {
                    throw new IllegalArgumentException("Subversion repository at " + subversionPath + " has uuid " + repoUuid
                                                       + " which does not match repository uuid held in database " + uuid);
                }
            } else {
                // if nothing in repo and it doesn't have the uuid we expect then
                // recreate it and reopen it
                if (!uuid.equals(repoUuid)) {
                    Log.warning(Geonet.SVN_MANAGER, "Recreating subversion repository at " + subversionPath
                                                    + " as previous repository was empty");
                    boolean enableRevisionProperties = true;
                    boolean force = true;
                    repoUrl = SVNRepositoryFactory.createLocalRepository(subFile, uuid, enableRevisionProperties, force);
                    repoCreated = true;
                    repo = getRepository();
                }
            }
        }


        Connection conn = null;
        String dbUrl;
        try {
            conn = _dataSource.getConnection();
            dbUrl = conn.getMetaData().getURL();
        } finally {
            if (conn != null) {
                conn.close();
            }
        }
        // set database URL as property on root of repository if database was
        // created or if new subversion repo created
        if (dbCreated || repoCreated) {
            Map<String, String> props = new HashMap<String, String>();
            props.put(Params.Svn.DBURLPROP, dbUrl);
            ISVNEditor editor = getEditor("Setting " + Params.Svn.DBURLPROP + " to " + dbUrl);
            editor.openRoot(-1);
            SvnUtils.modifyFileProps(editor, "/", props);
            editor.closeDir();
            SVNCommitInfo info = editor.closeEdit();
            if (Log.isDebugEnabled(Geonet.SVN_MANAGER))
                Log.debug(Geonet.SVN_MANAGER, "Committed " + dbUrl + " as property " + Params.Svn.DBURLPROP + ":" + info);
        } else {
            // get database URL from root of repository and check against dbUrl
            // if it doesn't match then stop
            SVNProperties rootProps = new SVNProperties();
            Collection<SVNDirEntry> nullColl = null;
            repo.getDir("/", -1, rootProps, nullColl);
            String repoDbUrl = rootProps.getStringValue(Params.Svn.DBURLPROP).trim();
            if (repoDbUrl == null || (!dbUrl.trim().equals(repoDbUrl))) {
                throw new IllegalArgumentException("Repository uses database URL of '" + repoDbUrl
                                                   + "' which does not match current database URL '" + dbUrl + "'. Modify the svn " +
                                                   "property " + Params.Svn.DBURLPROP
                                                   + " on the root of the subversion repository at " + subversionPath
                                                   + " or specify a different subversion repository");
            }
        }
    }

    /**
     * Spring Aspect Oriented programming for intercepting transaction commits.
     */
    @After("execution(* commit(org.springframework.transaction.TransactionStatus))")
    public void commitJoinPointHandler(JoinPoint joinPoint) {
        if (!_enabled) {
            return;
        }
        TransactionStatus status = (TransactionStatus) joinPoint.getArgs()[0];
        SvnTask task = tasks.get(status);

        ISVNEditor editor = null;

        if (task != null) {
            try {
                editor = getEditor(task.sessionLogMessage + " (committing transaction " + status + ")");
                editor.openRoot(-1); // open the root directory.
                for (Iterator<String> it = task.ids.iterator(); it.hasNext(); ) {
                    String id = it.next();
                    commitMetadata(id, editor);
                    it.remove();
                }
                editor.closeDir(); // close the root directory.
                if (Log.isDebugEnabled(Geonet.SVN_MANAGER))
                    Log.debug(Geonet.SVN_MANAGER, "Committed changes to subversion repository for metadata ids " + task.ids);
            } catch (Exception e) {
                Log.error(Geonet.SVN_MANAGER, "Failed to commit changes to subversion repository for metadata ids " + task.ids);
                e.printStackTrace();
                if (editor != null) {
                    try {
                        editor.abortEdit();
                    } catch (Exception ex) {
                        Log.error(Geonet.SVN_MANAGER, "Failed to abort subversion editor");
                        ex.printStackTrace();
                    }
                }
            } finally {
                tasks.remove(status);
            }
        }
    }

    /**
     * Spring Aspect Oriented programming for intercepting transaction rollbacks.
     */
    @Before("execution(* rollback(org.springframework.transaction.TransactionStatus))")
    public void rollbackJoinPointHandler(JoinPoint joinPoint) {
        if (!_enabled) {
            return;
        }

        TransactionStatus status = (TransactionStatus) joinPoint.getArgs()[0];
        tasks.remove(status);
    }

    public void setSubversionPath(String subversionPath) {
        this.subversionPath = subversionPath;
    }

    public void setContext(ServiceContext context) {
        this.context = context;
    }

    /**
     * Create a string from the user information in the UserSession session.
     *
     * @param context Context describing the user and service
     * @return The string representing the user information in the session
     */
    private String sessionToLogMessage(ServiceContext context) {
        UserSession session = context.getUserSession();
        if (session == null)
            session = getDefaultSession();
        String result = "GeoNetwork service: " + context.getService() + " GeoNetwork User " + session.getUserIdAsInt() + " (Username: "
                        + session.getUsername() + " Name: " + session.getName() + " " + session.getSurname() + ") Executed from IP " +
                        "address "
                        + context.getIpAddress();
        return result;
    }

    /**
     * Create a map of the user information in the UserSession session.
     *
     * @param context Context describing the user and service
     * @param props   The map of properties to add the session props too
     * @return The map of properties with the session props added
     */
    private Map<String, String> sessionToProps(ServiceContext context, Map<String, String> props) {
        UserSession session = context.getUserSession();
        if (session == null)
            session = getDefaultSession();
        props.put(Params.Svn.OPERATOR, session.getUserId());
        props.put(Params.Svn.USERNAME, session.getUsername());
        props.put(Params.Svn.NAME, session.getName());
        props.put(Params.Svn.SURNAME, session.getSurname());
        props.put(Params.Svn.SERVICE, context.getService());
        props.put(Params.Svn.IPADDR, context.getIpAddress());
        return props;
    }

    /**
     * Create a blank user session object in cases where the context doesn't have one.
     *
     * @return The blank user session object
     */
    private UserSession getDefaultSession() {
        UserSession session = new UserSession();
        return session;
    }

    /**
     * Creates a history request for this metadata id that will cause metadata and metadata properties to be committed/aborted when the
     * database is committed/aborted.
     *
     * @param id      The metadata id that will be tracked
     * @param context Describing the servicer and user carrying out operation
     * @throws Exception when something goes wrong
     */
    public void setHistory(final String id, final ServiceContext context) throws Exception {

        if (!_enabled) {
            return ;
        }
        if (!exists(id))
            return; // not in repo so exit

        if (Log.isDebugEnabled(Geonet.SVN_MANAGER))
            Log.debug(Geonet.SVN_MANAGER, "History will be recorded on metadata " + id);

        final Map<String, String> props = sessionToProps(context, new HashMap<String, String>());

        try {
            final TransactionStatus status = TransactionAspectSupport.currentTransactionStatus();
            checkSvnTask(status, id, sessionToLogMessage(context), props);
            if (Log.isDebugEnabled(Geonet.SVN_MANAGER)) {
                Log.debug(Geonet.SVN_MANAGER, "Changes to metadata " + id + " will be committed/aborted with the database "
                                              + "channel " + status);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * Get the latest file from the directory of the subversion repository corresponding to this metadata id.
     *
     * @param id   Id of the metadata record in the subversion repo
     * @param file File to retrieve from the subversion repo - could be metadata.xml, owner.xml, privileges.xml, status.xml,
     *             categories.xml,
     *             ...
     * @return Element XML metadata
     */
    private Element getFile(String id, String file) throws Exception {

        if (!exists(id))
            return null; // not in repo so exit

        String filePath = id + "/" + file;
        SVNRepository repo = getRepository();
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        repo.getFile(filePath, -1, new SVNProperties(), baos);

        Element rec = Xml.loadString(baos.toString(org.fao.geonet.Constants.ENCODING), false);
        return (Element) rec.detach();
    }

    /**
     * Creates a directory to hold metadata and property histories and add the metadata specified as the first version.
     *
     * @param id      The metadata id that will be tracked
     * @param context Service context describing user and operation
     * @param md      Metadata record - initial version
     * @throws Exception
     */
    public void createMetadataDir(final String id, ServiceContext context, Element md) throws Exception {
        if (!_enabled) {
            return;
        }

        if (exists(id))
            return; // already in repo so exit

        String logMessage = sessionToLogMessage(context) + " adding directory for metadata " + id;
        if (Log.isDebugEnabled(Geonet.SVN_MANAGER))
            Log.debug(Geonet.SVN_MANAGER, logMessage);

        ISVNEditor editor = getEditor(logMessage);

        try {
            // Create an id/ directory item in the repository
            editor.openRoot(-1);
            SvnUtils.addDir(editor, id);
            if (Log.isDebugEnabled(Geonet.SVN_MANAGER))
                Log.debug(Geonet.SVN_MANAGER, "Directory for metadata " + id + " was added");
            editor.closeDir();
            editor.closeEdit();
        } catch (SVNException svne) {
            editor.abortEdit();
            svne.printStackTrace();
            throw svne;
        }

        // Add the id/metadata.xml item plus properties to the repository
        try {
            logMessage = sessionToLogMessage(context) + " adding initial version of metadata " + id;
            editor = getEditor(logMessage);
            editor.openRoot(-1);
            final ISVNEditor finalEditor = editor;

            commitMetadata(id, finalEditor);

            if (Log.isDebugEnabled(Geonet.SVN_MANAGER))
                Log.debug(Geonet.SVN_MANAGER, "Metadata " + id + " was added");
            editor.closeDir();
            SVNCommitInfo commitInfo = editor.closeEdit();
            if (Log.isDebugEnabled(Geonet.SVN_MANAGER))
                Log.debug(Geonet.SVN_MANAGER, "Commit returned " + commitInfo);
        } catch (SVNException svne) {
            editor.abortEdit();
            svne.printStackTrace();
            throw svne;
        }
    }

    /**
     * Deletes a metadata directory from the subversion repository immediately.
     *
     * @param id      The metadata id that will be removed
     * @param context Service context describing the user and operation
     * @throws Exception when something goes wrong
     */
    public void deleteDir(String id, ServiceContext context) throws Exception {
        if (!_enabled) {
            return;
        }

        if (!exists(id))
            return; // not in repo so exit

        String logMessage = sessionToLogMessage(context) + " deleting directory for metadata " + id;
        if (Log.isDebugEnabled(Geonet.SVN_MANAGER))
            Log.debug(Geonet.SVN_MANAGER, logMessage);

        ISVNEditor editor = getEditor(logMessage);

        try {
            SvnUtils.deleteDir(editor, id);
            SVNCommitInfo commitInfo = editor.closeEdit();
            if (Log.isDebugEnabled(Geonet.SVN_MANAGER))
                Log.debug(Geonet.SVN_MANAGER, "Directory for metadata " + id + " deleted: " + commitInfo);
        } catch (SVNException svne) {
            editor.abortEdit(); // abort the update on the XML in the repository
            svne.printStackTrace();
            throw svne;
        }
    }

    /**
     * Check (and create if not present) a subversion commit task for a metadata id. If a commit task exists then the metadata and
     * properties will be read at the end of the database commit and committed to the subversion repo.
     *
     * @param transaction       The resource we will listen to for commits/aborts
     * @param id                The metadata id we want to track
     * @param sessionLogMessage The log message used to record changes
     * @param props             The properties we want to record on the metadata in repo
     * @throws Exception when something goes wrong with the commit
     */
    private void checkSvnTask(TransactionStatus transaction, String id, String sessionLogMessage, Map<String,
            String> props) throws Exception {
        SvnTask task = tasks.get(transaction);
        if (task == null) {
            task = new SvnTask();
            task.ids = new HashSet<String>();
            task.sessionLogMessage = sessionLogMessage;
            // task.props = props;
            tasks.put(transaction, task);
        }

        Set<String> ids = task.ids;
        if (!ids.contains(id)) {
            ids.add(id);
        }
    }

    /**
     * Get an SVNRepository object for use by this class.
     *
     * @return SVNRepository object
     */
    private SVNRepository getNewRepository() throws SVNException {
        SVNRepository repository = SVNRepositoryFactory.create(repoUrl);
        if (username != null) {
            ISVNAuthenticationManager authManager = SVNWCUtil.createDefaultAuthenticationManager(new File(repoUrl.getPath()), username,
                    password);
            repository.setAuthenticationManager(authManager);
        }
        return repository;
    }

    /**
     * Returns an ISVNEditor that allows commits to occur on the repository.
     *
     * @param logMessage The Log message that will be used on commit success
     * @return ISVNEditor object for operations on the repository
     * @throws SVNException if something goes wrong
     */
    private ISVNEditor getEditor(String logMessage) throws SVNException {
        SVNRepository repository = getNewRepository();
        ISVNEditor editor = repository.getCommitEditor(logMessage, null /* locks */, false /* keepLocks */, null /* mediator */);
        return editor;
    }

    /**
     * Returns an SVNRepository.
     *
     * @throws SVNException if something goes wrong
     */
    private SVNRepository getRepository() throws SVNException {
        return getNewRepository();
    }

    /**
     * Commits an ISVNEditor with changes to the repository.
     *
     * @param id     Id number of metadata record being tracked for changes
     * @param editor ISVNEditor for commits to subversion repo
     * @throws SVNException if something goes wrong
     */
    public void commitMetadata(String id, ISVNEditor editor) throws Exception {
        if (!_enabled) {
            return;
        }

        DataManager dataMan = context.getBean(DataManager.class);

        try {
            // get the metadata record and if different commit changes
            commitMetadataChanges(editor, id, dataMan);

            // get the metadata owner and if different commit changes
            commitMetadataOwner(editor, id);

            // get the metadata privileges and if different commit changes
            commitMetadataPrivileges(editor, id);

            // get the metadata categories and if different commit changes
            commitMetadataCategories(editor, id, dataMan);

            // get the metadata status and if different commit changes
            commitMetadataStatus(editor, id, dataMan);
        } catch (Exception e) {
            editor.abortEdit();
            e.printStackTrace();
            throw e;
        }
    }

    /**
     * Commits changes to metadata categories.
     *
     * @param editor  ISVNEditor for commits to subversion repo
     * @param id      Id number of metadata record being tracked for changes
     * @param dataMan DataManager object with extract methods
     * @throws Exception if something goes wrong
     */
    private void commitMetadataCategories(ISVNEditor editor, String id, DataManager dataMan) throws Exception {

        // get categories from the database
        Collection<MetadataCategory> categs = dataMan.getCategories(id);
        Element catXml = new Element("results");
        for (MetadataCategory categ : categs) {
            catXml.addContent(
                    new Element("record")
                            .addContent(new Element("id").setText("" + categ.getId()))
                            .addContent(new Element("name").setText(categ.getName()))
            );
        }
        String now = Xml.getString(catXml);

        if (exists(id + "/categories.xml")) {
            // Update the id/categories.xml item in the repository
            Element categsPrevVersion = getFile(id, "categories.xml");
            String old = Xml.getString(categsPrevVersion);
            if (!old.equals(now)) {
                SvnUtils.modifyFile(editor, id + "/categories.xml", old.getBytes(Constants.ENCODING), now.getBytes(Constants.ENCODING));
                if (Log.isDebugEnabled(Geonet.SVN_MANAGER))
                    Log.debug(Geonet.SVN_MANAGER, "Categories of metadata " + id + " updated");
            }
        } else {
            // Add the id/owner.xml item to the repository
            SvnUtils.addFile(editor, id + "/categories.xml", now.getBytes(Constants.ENCODING));
            if (Log.isDebugEnabled(Geonet.SVN_MANAGER))
                Log.debug(Geonet.SVN_MANAGER, "Categories of metadata " + id + " added");

        }
    }

    /**
     * Commits changes to metadata status.
     *
     * @param editor  ISVNEditor for commits to subversion repo
     * @param id      Id number of metadata record being tracked for changes
     * @param dataMan DataManager object with extract methods
     * @throws Exception if something goes wrong
     */
    private void commitMetadataStatus(ISVNEditor editor, String id, DataManager dataMan) throws Exception {

        // get current status from the database
        MetadataStatus status = dataMan.getStatus(Integer.valueOf(id));
        if (status == null)
            return;

        String now = Xml.getString(status.getAsXml());

        if (exists(id + "/status.xml")) {
            // Update the id/status.xml item in the repository
            Element statusPrevVersion = getFile(id, "status.xml");
            String old = Xml.getString(statusPrevVersion);
            if (!old.equals(now)) {

                SvnUtils.modifyFile(editor, id + "/status.xml", old.getBytes(Constants.ENCODING), now.getBytes(Constants.ENCODING));
                if (Log.isDebugEnabled(Geonet.SVN_MANAGER))
                    Log.debug(Geonet.SVN_MANAGER, "Status of metadata " + id + " was updated");
            }
        } else {
            // Add the id/owner.xml item to the repository
            SvnUtils.addFile(editor, id + "/status.xml", now.getBytes(Constants.ENCODING));
            if (Log.isDebugEnabled(Geonet.SVN_MANAGER))
                Log.debug(Geonet.SVN_MANAGER, "Status of metadata " + id + " was added");

        }
    }

    /**
     * Commits changes to metadata record.
     *
     * @param editor  ISVNEditor for commits to subversion repo
     * @param id      Id number of metadata record being tracked for changes
     * @param dataMan DataManager object with extract methods
     * @throws Exception if something goes wrong
     */
    private void commitMetadataChanges(ISVNEditor editor, String id, DataManager dataMan) throws Exception {
        // get metadata record from database
        Element md = dataMan.getMetadata(id);
        String now = Xml.getString(md);

        if (exists(id + "/metadata.xml")) {
            Element mdPrevVersion = getFile(id, "metadata.xml");
            String old = Xml.getString(mdPrevVersion);
            if (!old.equals(now)) {

                // Update the id/metadata.xml item in the repository
                SvnUtils.modifyFile(editor, id + "/metadata.xml", old.getBytes(Constants.ENCODING), now.getBytes(Constants.ENCODING));

                if (Log.isDebugEnabled(Geonet.SVN_MANAGER))
                    Log.debug(Geonet.SVN_MANAGER, "Metadata " + id + " was updated");
            }
        } else {
            SvnUtils.addFile(editor, id + "/metadata.xml", now.getBytes(Constants.ENCODING));
        }
    }

    /**
     * Commits changes to metadata owners.
     *
     * @param editor ISVNEditor for commits to subversion repo
     * @param id     Id number of metadata record being tracked for changes
     * @throws Exception if something goes wrong
     */
    private void commitMetadataOwner(ISVNEditor editor, String id) throws Exception {

        // get owner from the database
        Set<Integer> ids = new HashSet<Integer>();
        ids.add(Integer.valueOf(id));
        Metadata metadata = this.context.getBean(MetadataRepository.class).findOne(id);
        User user = this.context.getBean(UserRepository.class).findOne(metadata.getSourceInfo().getOwner());
        // Backwards compatibility.  Format the metadata as XML in same format as previous versions.
        Element xml = new Element("results").addContent(
                new Element("record")
                        .addContent(new Element("metadataid").setText(id))
                        .addContent(new Element("userid").setText("" + user.getId()))
                        .addContent(new Element("name").setText(user.getName()))
                        .addContent(new Element("surname").setText(user.getSurname()))
                        .addContent(new Element("email").setText(user.getEmail()))
                        .addContent(new Element("email").setText(user.getEmail()))
        );
        //
        String now = Xml.getString(xml);

        if (exists(id + "/owner.xml")) {
            // Update the id/owner.xml item in the repository
            Element ownerPrevVersion = getFile(id, "owner.xml");
            String old = Xml.getString(ownerPrevVersion);
            if (!old.equals(now)) {

                SvnUtils.modifyFile(editor, id + "/owner.xml", old.getBytes(Constants.ENCODING), now.getBytes(Constants.ENCODING));
                if (Log.isDebugEnabled(Geonet.SVN_MANAGER))
                    Log.debug(Geonet.SVN_MANAGER, "Ownership of metadata " + id + " was updated");
            }
        } else {
            // Add the id/owner.xml item to the repository
            SvnUtils.addFile(editor, id + "/owner.xml", now.getBytes(Constants.ENCODING));
            if (Log.isDebugEnabled(Geonet.SVN_MANAGER))
                Log.debug(Geonet.SVN_MANAGER, "Ownership of metadata " + id + " was added");

        }
    }

    /**
     * Commits changes to metadata privileges.
     *
     * @param editor ISVNEditor for commits to subversion repo
     * @param id     Id number of metadata record being tracked for changes
     * @throws Exception if something goes wrong
     */
    private void commitMetadataPrivileges(ISVNEditor editor, String id) throws Exception {
        Sort sort = SortUtils.createSort(OperationAllowed_.id, OperationAllowedId_.operationId);
        Specification<OperationAllowed> hasMetadataId = OperationAllowedSpecs.hasMetadataId(Integer.valueOf(id));
        List<OperationAllowed> opsAllowed = _operationAllowedRepository.findAll(hasMetadataId, sort);
        Element privs = new Element("response");
        for (OperationAllowed operationAllowed : opsAllowed) {
            Element record = new Element("record");
            final OperationAllowedId operationAllowedId = operationAllowed.getId();
            record.addContent(new Element("group_id").setText(Integer.toString(operationAllowedId.getGroupId())));
            final Group group = _groupRepository.findOne(operationAllowedId.getGroupId());
            record.addContent(new Element("group_name").setText(group.getName()));
            final Operation operation = _operationRepository.findOne(operationAllowedId.getOperationId());
            record.addContent(new Element("operation_id").setText(Integer.toString(operationAllowedId.getOperationId())));
            record.addContent(new Element("operation_name").setText(operation.getName()));
            privs.addContent(record);
        }

        String now = Xml.getString(privs);

        if (exists(id + "/privileges.xml")) {
            // Update the id/privileges.xml item in the repository
            Element privsPrevVersion = getFile(id, "privileges.xml");
            String old = Xml.getString(privsPrevVersion);
            if (!old.equals(now)) {

                SvnUtils.modifyFile(editor, id + "/privileges.xml", old.getBytes(Constants.ENCODING), now.getBytes(Constants.ENCODING));

                if (Log.isDebugEnabled(Geonet.SVN_MANAGER))
                    Log.debug(Geonet.SVN_MANAGER, "Privileges of metadata " + id + " were updated");
            }
        } else {
            // Add the id/owner.xml item to the repository
            SvnUtils.addFile(editor, id + "/privileges.xml", now.getBytes(Constants.ENCODING));
            if (Log.isDebugEnabled(Geonet.SVN_MANAGER))
                Log.debug(Geonet.SVN_MANAGER, "Privileges of metadata " + id + " were added");
        }
    }

    /**
     * Check if the directory/file exists in the subversion repository.
     *
     * @param filePath The file path from root. eg. 10/metadata.xml.
     * @return true if exists, false otherwise
     */
    private boolean exists(String filePath) throws SVNException {
        SVNRepository repo = getRepository();
        SVNNodeKind nodeKind = repo.checkPath(filePath, -1);
        if (nodeKind == SVNNodeKind.FILE || nodeKind == SVNNodeKind.DIR)
            return true;
        else
            return false;
    }
}
TOP

Related Classes of org.fao.geonet.kernel.SvnManager

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.