Java tutorial
/** * Copyright 2011-2014 The Kuali Foundation * * Licensed under the Educational Community 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.opensource.org/licenses/ecl2.php * * 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.kuali.maven.plugins.externals; import java.io.File; import java.util.ArrayList; import java.util.Collections; import java.util.List; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.tmatesoft.svn.core.SVNCommitInfo; import org.tmatesoft.svn.core.SVNDepth; import org.tmatesoft.svn.core.SVNDirEntry; import org.tmatesoft.svn.core.SVNException; import org.tmatesoft.svn.core.SVNPropertyValue; import org.tmatesoft.svn.core.SVNURL; import org.tmatesoft.svn.core.auth.ISVNAuthenticationManager; import org.tmatesoft.svn.core.internal.io.dav.DAVRepositoryFactory; import org.tmatesoft.svn.core.internal.io.fs.FSRepositoryFactory; import org.tmatesoft.svn.core.internal.io.svn.SVNRepositoryFactoryImpl; import org.tmatesoft.svn.core.io.SVNRepository; import org.tmatesoft.svn.core.io.SVNRepositoryFactory; import org.tmatesoft.svn.core.wc.SVNClientManager; import org.tmatesoft.svn.core.wc.SVNCommitClient; import org.tmatesoft.svn.core.wc.SVNCopyClient; import org.tmatesoft.svn.core.wc.SVNCopySource; import org.tmatesoft.svn.core.wc.SVNInfo; import org.tmatesoft.svn.core.wc.SVNPropertyData; import org.tmatesoft.svn.core.wc.SVNRevision; import org.tmatesoft.svn.core.wc.SVNUpdateClient; import org.tmatesoft.svn.core.wc.SVNWCClient; import org.tmatesoft.svn.core.wc.SVNWCUtil; public class SVNUtils { private static final Logger LOGGER = LoggerFactory.getLogger(SVNUtils.class); private static final String EMPTY_STRING = ""; private static final String EXTERNALS_PROPERTY_NAME = "svn:externals"; private static final String EXTERNALS_COMMENT = "#"; private static final String DELETE_EXTERNALS_COMMIT_MESSAGE = "Delete externals"; private static final String CREATE_EXTERNALS_COMMIT_MESSAGE = "Create externals"; private static final String LINEFEED = "\n"; private static final String SPACE = " "; private static final String SEMICOLON = ":"; protected static SVNUtils instance; protected SVNUtils() { super(); initialize(); } protected void initialize() { SVNRepositoryFactoryImpl.setup(); DAVRepositoryFactory.setup(); FSRepositoryFactory.setup(); } public synchronized static SVNUtils getInstance() { if (instance == null) { instance = new SVNUtils(); } return instance; } public void showExternals(List<SVNExternal> externals) { for (SVNExternal e : externals) { StringBuilder sb = new StringBuilder(); sb.append("[" + e.getPath()); sb.append(", " + e.getWorkingCopyPath()); sb.append(", " + e.getUrl()); sb.append("]"); LOGGER.info(sb.toString()); } } /** * Copy <code>src</code> to <code>dst</code> creating parent directories as needed. An exception is thrown if <code>dst</code> already * exists. */ public SVNCommitInfo copy(String src, String dst) { return copy(src, null, dst, null); } /** * Copy <code>src</code> to <code>dst</code> creating parent directories as needed. An exception is thrown if <code>dst</code> already * exists. */ public SVNCommitInfo copy(String src, String dst, String msg) { return copy(src, null, dst, msg); } /** * Copy <code>src</code> at the indicated revision to <code>dst</code> creating parent directories as needed. An exception is thrown if * <code>dst</code> already exists. */ public SVNCommitInfo copy(String src, Long revision, String dst) { return copy(src, revision, dst, null); } /** * Copy <code>src</code> at the indicated revision to <code>dst</code> creating parent directories as needed. An exception is thrown if * <code>dst</code> already exists. */ public SVNCommitInfo copy(String src, Long revision, String dst, String msg) { Copy copy = new Copy(); copy.setSource(src); copy.setRevision(revision); copy.setDestination(dst); copy.setMessage(msg); return copy(copy); } public SVNCommitInfo setExternals(String url, List<SVNExternal> externals) { return setExternals(url, externals, null); } public SVNCommitInfo setExternals(String url, List<SVNExternal> externals, String message) { return setExternals(url, externals, message, null, null); } public SVNCommitInfo setExternals(String url, List<SVNExternal> externals, String message, String username, String password) { SVNClientManager manager = SVNClientManager.newInstance(null, username, password); SVNWCClient client = manager.getWCClient(); String commitMessage = StringUtils.isBlank(message) ? CREATE_EXTERNALS_COMMIT_MESSAGE : message; SVNURL svnUrl = getSvnUrl(url); StringBuilder sb = new StringBuilder(); for (SVNExternal external : externals) { sb.append(external.getPath() + " " + external.getUrl() + "\n"); } SVNPropertyValue value = SVNPropertyValue.create(sb.toString()); try { return client.doSetProperty(svnUrl, EXTERNALS_PROPERTY_NAME, value, SVNRevision.HEAD, commitMessage, null, true, null); } catch (SVNException e) { throw new IllegalStateException(e); } } public SVNCommitInfo setExternals(File repositoryPath, List<SVNExternal> externals, String message, String username, String password) { SVNClientManager manager = SVNClientManager.newInstance(null, username, password); SVNWCClient client = manager.getWCClient(); String commitMessage = StringUtils.isBlank(message) ? CREATE_EXTERNALS_COMMIT_MESSAGE : message; SVNURL svnUrl = getSvnUrl(repositoryPath.getAbsolutePath()); StringBuilder sb = new StringBuilder(); for (SVNExternal external : externals) { sb.append(external.getPath() + " " + external.getUrl() + "\n"); } SVNPropertyValue value = SVNPropertyValue.create(sb.toString()); try { return client.doSetProperty(svnUrl, EXTERNALS_PROPERTY_NAME, value, SVNRevision.HEAD, commitMessage, null, true, null); } catch (SVNException e) { throw new IllegalStateException(e); } } public SVNCommitInfo deleteExternals(String url) { return deleteExternals(url, null); } public SVNCommitInfo deleteExternals(String url, String message) { return deleteExternals(url, message, null, null); } public SVNCommitInfo deleteExternals(String url, String message, String username, String password) { SVNClientManager manager = SVNClientManager.newInstance(null, username, password); SVNWCClient client = manager.getWCClient(); String commitMessage = StringUtils.isBlank(message) ? DELETE_EXTERNALS_COMMIT_MESSAGE : message; SVNURL svnUrl = getSvnUrl(url); try { return client.doSetProperty(svnUrl, EXTERNALS_PROPERTY_NAME, null, SVNRevision.HEAD, commitMessage, null, true, null); } catch (SVNException e) { throw new IllegalStateException(e); } } public void markForDeletion(List<File> files) { SVNWCClient client = getSVNWCClient(); try { for (File file : files) { client.doDelete(file, true, false); } } catch (SVNException e) { throw new IllegalStateException(e); } } protected SVNURL[] getSvnUrlArray(List<File> files) { String singleSlashPrefix = "file:/"; String doubleSlashPrefix = "file://"; SVNURL[] array = new SVNURL[files.size()]; for (int i = 0; i < files.size(); i++) { File file = files.get(i); String fileUrlString = file.toURI().toString(); boolean singleSlash = StringUtils.startsWith(fileUrlString, singleSlashPrefix); boolean doubleSlash = StringUtils.startsWith(fileUrlString, doubleSlashPrefix); if (singleSlash && !doubleSlash) { fileUrlString = StringUtils.replace(fileUrlString, singleSlashPrefix, doubleSlashPrefix); } SVNURL fileUrl = getSvnUrl(fileUrlString); array[i] = fileUrl; } return array; } public void markForDeletion(File file) { markForDeletion(Collections.singletonList(file)); } public SVNCommitInfo copy(Copy copy) { SVNClientManager manager = SVNClientManager.newInstance(null, copy.getUsername(), copy.getPassword()); SVNCopyClient client = manager.getCopyClient(); SVNURL dstUrl = getSvnUrl(copy.getDestination()); SVNURL srcUrl = getSvnUrl(copy.getSource()); SVNRevision revision = SVNRevision.HEAD; if (copy.getRevision() != null) { revision = SVNRevision.create(copy.getRevision()); } String msg = copy.getMessage(); if (StringUtils.isBlank(msg)) { String r = (copy.getRevision() != null) ? "@" + revision : ""; msg = "Copy " + copy.getSource() + r + " to " + copy.getDestination(); } SVNCopySource svnCopySource = new SVNCopySource(SVNRevision.HEAD, revision, srcUrl); SVNCopySource[] sources = new SVNCopySource[] { svnCopySource }; try { return client.doCopy(sources, dstUrl, false, true, true, msg, null); } catch (SVNException e) { throw new IllegalStateException(e); } } /** * Return the Subversion url that corresponds with the local working copy */ public String getUrl(File workingCopyPath) { SVNInfo info = getInfo(workingCopyPath); return info.getURL().toDecodedString(); } /** * Return any svn:externals associated with the given url. Returns an empty list if there are none. Never returns null. */ public List<SVNExternal> getExternals(String url) { try { SVNWCClient client = getSVNWCClient(); SVNURL svnUrl = getSvnUrl(url); SVNPropertyData data = client.doGetProperty(svnUrl, EXTERNALS_PROPERTY_NAME, SVNRevision.HEAD, SVNRevision.HEAD); return getExternals(data, null); } catch (SVNException e) { throw new IllegalStateException(e); } } public long checkout(String url, File dstPath, String username, String password) { try { SVNClientManager manager = SVNClientManager.newInstance(null, username, password); SVNUpdateClient client = manager.getUpdateClient(); client.setIgnoreExternals(false); SVNURL svnUrl = getSvnUrl(url); return client.doCheckout(svnUrl, dstPath, SVNRevision.HEAD, SVNRevision.HEAD, SVNDepth.INFINITY, false); } catch (SVNException e) { throw new IllegalStateException(e); } } public SVNCommitInfo commit(List<File> workingCopyPaths, String message, String username, String password) { File[] fileArray = workingCopyPaths.toArray(new File[workingCopyPaths.size()]); return commit(fileArray, message, username, password); } public SVNCommitInfo commit(File[] workingCopyPaths, String message, String username, String password) { try { SVNClientManager manager = SVNClientManager.newInstance(null, username, password); SVNCommitClient client = manager.getCommitClient(); client.setIgnoreExternals(false); return client.doCommit(workingCopyPaths, true, message, null, null, true, false, SVNDepth.INFINITY); } catch (SVNException e) { throw new IllegalStateException(e); } } public SVNCommitInfo commit(File workingCopyPath, String message, String username, String password) { return commit(new File[] { workingCopyPath }, message, username, password); } public void addFiles(File workingCopyPath, String username, String password) { try { SVNClientManager manager = SVNClientManager.newInstance(null, username, password); SVNWCClient client = manager.getWCClient(); client.setIgnoreExternals(false); client.doAdd(workingCopyPath, true, false, true, SVNDepth.INFINITY, true, true); } catch (SVNException e) { throw new IllegalStateException(e); } } /** * Return any svn:externals associated with the working copy. Returns an empty list if there are none. Never returns null. */ public List<SVNExternal> getExternals(File workingCopyPath) { try { SVNWCClient client = getSVNWCClient(); SVNPropertyData data = client.doGetProperty(workingCopyPath, EXTERNALS_PROPERTY_NAME, SVNRevision.WORKING, SVNRevision.WORKING); return getExternals(data, workingCopyPath); } catch (SVNException e) { throw new IllegalStateException(e); } } /** * Return the revision of the last commit for the working copy. */ public long getLastRevision(File workingCopyPath) { SVNInfo info = getInfo(workingCopyPath); return info.getCommittedRevision().getNumber(); } /** * Return the revision of the last commit for the given url */ public long getLastRevision(String url) { SVNRepository repository = getRepository(url); return getLastRevision(repository); } /** * Convert the svn:externals definitions into a <code>List</code> of <code>SVNExternal</code> objects. This method never returns * <code>null</code>. If there are no svn:externals definitions an empty <code>List</code> is returned. */ protected List<SVNExternal> getExternals(SVNPropertyData data, File workingCopyPath) { // The property svn:externals is not set on this directory if (data == null) { return new ArrayList<SVNExternal>(); } // Extract the property value SVNPropertyValue value = data.getValue(); // Convert the value to a String String s = SVNPropertyValue.getPropertyAsString(value); // Split the string up into lines String[] tokens = StringUtils.split(s, LINEFEED); // Iterate through the lines looking for externals List<SVNExternal> externals = new ArrayList<SVNExternal>(); for (String token : tokens) { // Trim whitespace token = token.trim(); // Ignore comments and blank lines if (token.startsWith(EXTERNALS_COMMENT) || StringUtils.isBlank(token)) { continue; } // We've located a non-blank, non-comment line // We've already trimmed off leading and trailing whitespace // Split up the remaining portion of the string using space as a delimiter // The split method skips all spaces in the line (even adjacent spaces) // The String[] returned by split() will only contain tokens with non-space characters String[] values = StringUtils.split(token, SPACE); // If we don't have exactly 2 non-blank tokens there is trouble if (values.length != 2) { throw new IllegalStateException( "Unparseable svn:externals definition - [" + token + ", " + workingCopyPath + "]"); } // Extract the 2 values we are interested in String value1 = values[0]; String value2 = values[1]; // Some SVN clients store svn:externals as <module> <location>, others store it as <location> <module> String url = getUrl(value1, value2); String path = getPath(value1, value2); // Get the file representing the local working copy of the svn:external File externalsPath = getExternalWorkingCopyPath(workingCopyPath, path); // Store the info we've accumulated into an object SVNExternal external = new SVNExternal(); external.setUrl(url); external.setPath(path); external.setWorkingCopyPath(externalsPath); // Add our object to the list externals.add(external); } // Return the list we've found return externals; } protected boolean isUrl(String s) { return s.contains(SEMICOLON); } protected String getUrl(String value1, String value2) { if (isUrl(value1)) { return value1; } else { return value2; } } protected String getPath(String value1, String value2) { if (isUrl(value1)) { return value2; } else { return value1; } } protected File getExternalWorkingCopyPath(File workingCopyPath, String path) { if (workingCopyPath == null) { return null; } else { return new File(workingCopyPath.getAbsolutePath() + File.separator + path); } } protected SVNWCClient getSVNWCClient() { ISVNAuthenticationManager authMgr = SVNWCUtil.createDefaultAuthenticationManager(); return new SVNWCClient(authMgr, null); } protected SVNInfo getInfo(File workingCopyPath) { try { SVNWCClient client = getSVNWCClient(); SVNRevision revision = SVNRevision.create(-1); return client.doInfo(workingCopyPath, revision); } catch (SVNException e) { throw new IllegalStateException(e); } } protected long getLastRevision(SVNRepository repository) { try { SVNDirEntry entry = repository.info(EMPTY_STRING, -1); return entry.getRevision(); } catch (SVNException e) { throw new IllegalStateException(e); } } protected SVNRepository getRepository(String url) { return getRepository(url, null, null); } protected SVNRepository getRepository(String url, String username, String password) { try { SVNURL svnUrl = getSvnUrl(url); SVNRepository repository = SVNRepositoryFactory.create(svnUrl, null); if (!StringUtils.isBlank(username) && !StringUtils.isBlank(password)) { ISVNAuthenticationManager authManager = SVNWCUtil.createDefaultAuthenticationManager(username, password); repository.setAuthenticationManager(authManager); } return repository; } catch (SVNException e) { throw new IllegalStateException(e); } } @SuppressWarnings("deprecation") protected SVNURL getSvnUrl(String url) { try { return SVNURL.parseURIDecoded(url); } catch (SVNException e) { try { return SVNURL.fromFile(new File(url)); } catch (SVNException e1) { throw new IllegalStateException(e1); } } } }