/* * Copyright 2013 Brian Rosenberger (Brutex Network) * * Licensed 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 net.brutex.svn; import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.StringTokenizer; import net.brutex.svn.SVNCommitInfo.ChangeType; import org.apache.log4j.Logger; /* Executes the svnlook utility * * @author Brian Rosenberger bru(at)brutex.de * @since 0.1 */ public class SVNLookExecutor { private Logger logger = Logger.getLogger(SVNLookExecutor.class); private final File svnlook; private final String repos; private String TXN = null; private String rev = null; /** * Instantiates a new sVN look executor. * * @param svnlook the svnlook * @param repos the repos */ public SVNLookExecutor(File svnlook, String repos) { if(! svnlook.exists() ) throw new IllegalArgumentException( String.format("The svnlook executable at '%s' does not exist.", svnlook.toString())); if(! svnlook.isFile() ) throw new IllegalArgumentException( String.format("The svnlook utility at'%s' is not a file.", svnlook.toString())); logger.debug(String.format("Instantiating '%s' with svnlook at '%s'.", this.getClass().getCanonicalName(), svnlook.toString())); this.svnlook = svnlook; logger.debug(String.format("Working against svn repository at '%s'.", repos)); this.repos = repos; } /** * Execute svn look. * * @param command the command * @return the string */ private String executeSVNLook(SVNLookCommand command) { StringBuilder sb = new StringBuilder(); StringBuilder sberr = new StringBuilder(); //This throws an IllegalArgumentException when neither TXN nor REV is valid String[] params; try { params = getTargetParam(); } catch (IllegalArgumentException e) { logger.error(e.getMessage()); throw e; } try { List cmdline = new ArrayList(5); cmdline.add(svnlook.toString()); cmdline.add(command.getValue()); cmdline.add(params[0]); cmdline.add(params[1]); cmdline.add(repos); ProcessBuilder pf = new ProcessBuilder(cmdline); logger.debug(String.format("Executing svnlook with commandline '%s'.", pf.command())); Process svnprocess = pf.start(); BufferedReader stdin = new BufferedReader(new InputStreamReader(svnprocess.getInputStream())); BufferedReader stderr = new BufferedReader(new InputStreamReader(svnprocess.getErrorStream())); String s; while( (s = stdin.readLine()) != null ) { sb.append(s + '\n'); } while( (s = stderr.readLine()) != null ) { sberr.append(s + '\n'); } stdin.close(); stderr.close(); } catch (IOException e) { logger.error( String.format( "Error calling the svnlook utility: '%s'", e.getMessage())); e.printStackTrace(); } String error = sberr.toString(); if( error.length()>0 ) { error = "Failed to call svnlook. The STDERR was '"+error+"'"; logger.error(error); throw new IllegalArgumentException(error); } String output = sb.toString().trim(); logger.debug(String.format("Svnlook output was '%s'", output)); return output; } /* * Returns either -t TXN oder -rev REVISION * * @returns */ private String[] getTargetParam() { String[] result = new String[2]; if( (TXN==null || TXN.length()<=0) && (rev==null || rev.length()<=0) ) throw new IllegalArgumentException("Either TXN or revision must be provided."); if( TXN!=null && TXN.length()>0 && rev!=null && rev.length()>0 ) throw new IllegalArgumentException("Both, TXN and revision are given. Don't know what to use."); if( TXN!=null && TXN.length()>0) { result[0] = "-t"; result[1] = TXN; return result; } if( rev!=null && rev.length()>0) { result[0] = "-r"; result[1] = rev; return result; } throw new IllegalArgumentException("Either TXN or revision must be provided."); } public void setTXN(String TXN) { if(TXN==null || TXN.length()<=0) throw new IllegalArgumentException("TXN cannot be null or empty."); this.TXN = TXN; } public void setRev(String rev) { if(rev==null || rev.length()<=0) throw new IllegalArgumentException("Revision cannot be null or empty."); this.rev = rev; } public SVNCommitInfo getCommitInfo() { String author = executeSVNLook(SVNLookCommand.AUTHOR); String logmessage = executeSVNLook(SVNLookCommand.LOG); String files = executeSVNLook(SVNLookCommand.CHANGED); SVNCommitInfo result = new SVNCommitInfo(author, new Date(), logmessage); files += "\n"; StringTokenizer tokenizer = new StringTokenizer(files, "\n"); String s; while( tokenizer.hasMoreTokens()) { s=tokenizer.nextToken(); logger.debug(String.format("Tokenizing file list. Token '%s'.", s)); if(s.startsWith("A")) { result.addFileInfo(ChangeType.ADDED, s.substring(1).trim()); continue; } if(s.startsWith("D")) { result.addFileInfo(ChangeType.DELETED, s.substring(1).trim()); continue; } if(s.startsWith("UU")) { result.addFileInfo(ChangeType.BOTHUPDATE, s.substring(2).trim()); continue; } if(s.startsWith("_U")) { result.addFileInfo(ChangeType.METAUPDATE, s.substring(2).trim()); continue; } if(s.startsWith("U")) { result.addFileInfo(ChangeType.UPDATED, s.substring(1).trim()); continue; } } result.setTxn(TXN); result.setRev(rev); return result; } }