<rss version="2.0"><channel><title>RSS feed for InstantSpot site orangepips</title><link>http://orangepips.instantspot.com</link><language>en-us</language><copyright>This work is Copyright &#xA9; 2008 by orangepips</copyright><generator>RSSVille ColdFusion FeedMaker, version 1.0</generator><pubDate>Thu, 24 Jul 2008 11:27:27 GMT</pubDate><item><title>Export Subversion Files Changed between Two Revision Numbers</title><link>http://orangepips.instantspot.com/blog/2008/03/06/Export-Subversion-Files-Changed-between-Two-Revision-Numbers</link><description>&lt;p&gt;&lt;strong&gt;Update 6/2/2008&lt;/strong&gt;: in response to Mike&apos;s comment, here is a code snippet for how to use the SVNChangedFiles class, which will export the files between the two revision numbers from a Subversion branch into the directory you specify:&lt;/p&gt;
&lt;p&gt;&lt;div class=&quot;code&quot; &gt;&lt;pre&gt;SVNChangedFiles ecf = new SVNChangedFiles(
  [SVNbranchURL], 
  [SVNusername], 
  [SVNpassword], 
  [SVNstartRevisionNumber], 
  [SVNendRevisionNumber], 
  [PathToLocalDirectory], 
  [useAncestry]
);

ecf.export();
&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;
&lt;p&gt;The way the &lt;a href=&quot;http://www.siteexecutive.com&quot;&gt;product I work on&lt;/a&gt; is delivered sometimes requires being able to issue just a subset of files that have changed since a full release as a package. Subversion as-is doesn&apos;t really want to help you with this problem. You can do something like:&lt;/p&gt;
&lt;p&gt;&lt;tt&gt;svn diff -r[###]:[###] http://[URL to Repository]/[branch] --summarize&lt;/tt&gt;&lt;/p&gt;
&lt;p&gt;But then you are left to do something with those results in order to actually pull those particular files.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.verysimple.com/blog/2007/09/06/using-tortoisesvn-to-export-only-newmodified-files/&quot;&gt;The Tortois SVN client can help you with this problem&lt;/a&gt;, but nothing something I want to script from Ant build files. Fortunately &lt;a href=&quot;http://svnbook.red-bean.com/en/1.1/ch08s02.html&quot;&gt;SVN has an API &lt;/a&gt;that allows you hack things the way you like. And there are some good &lt;a href=&quot;http://svnkit.com&quot;&gt;Java Subversion client libraries for this purpose, such as SVNKit&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;So here is something I hacked together for pulling changed files that can also work as an Ant task.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;SVNChangedFiles&lt;/strong&gt;&lt;br /&gt;
&lt;div class=&quot;code&quot; &gt;&lt;pre&gt;import java.io.File;
import java.util.ArrayList;

import org.tmatesoft.svn.core.SVNException;
import org.tmatesoft.svn.core.SVNNodeKind;
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.wc.ISVNDiffStatusHandler;
import org.tmatesoft.svn.core.wc.SVNDiffClient;
import org.tmatesoft.svn.core.wc.SVNDiffStatus;
import org.tmatesoft.svn.core.wc.SVNRevision;
import org.tmatesoft.svn.core.wc.SVNStatusType;
import org.tmatesoft.svn.core.wc.SVNUpdateClient;
import org.tmatesoft.svn.core.wc.SVNWCUtil;

public class SVNChangedFiles {
	private SVNURL branchURL;
	private String username;
	private String password;
	private SVNRevision startingRevision;
	private SVNRevision endingRevision;
	private String destinationDirectory;

	private ISVNAuthenticationManager authManager;

	/**
	 * &amp;lt;p&amp;gt;
	 * Tested with SVNKit 1.1.4
	 * &amp;lt;/p&amp;gt;
	 * &amp;lt;p&amp;gt;
	 * Use to export added or modified files from a Subversion repository at
	 * branchURL between startingRevision and endingRevision revisions to the specified
	 * destinationDirectory.
	 * &amp;lt;/p&amp;gt;
	 *
	 * @param branchURL	fully qualified URL of the SVN repository (i.e. &amp;quot;http://[domain]/[path-to-svn]/[branch]&amp;quot;)
	 * @param username	SVN username
	 * @param password	SVN password
	 * @param startingRevision	Starting revision number for the branch specified
	 * @param endingRevision	Ending revision number for the branch specified
	 * @param destinationDirectory	Root directory where to export files. &amp;lt;i&amp;gt;Files with same name will be overwritten without warning.&amp;lt;/i&amp;gt;
	 */
	public SVNChangedFiles(String branchURL, String username, String password,
			long startingRevision, long endingRevision,
			String destinationDirectory) {
		super();
		DAVRepositoryFactory.setup();
		try {
			this.branchURL = SVNURL.parseURIEncoded(branchURL);
			this.username = username;
			this.password = password;
			this.startingRevision = SVNRevision.create(startingRevision);
			this.endingRevision = SVNRevision.create(endingRevision);
			this.destinationDirectory = destinationDirectory;

			this.authManager = SVNWCUtil.createDefaultAuthenticationManager(this.username, this.password);
		} catch (SVNException e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * &amp;lt;p&amp;gt;Calls {@link SVNChangedFiles#export(ArrayList)} passing in a null.
	 */
	public void export() { export(null); }

	/**
	 * &amp;lt;p&amp;gt;
	 * Exports files added or modified between the startingRevision and endingRevision revision numbers,
	 * including creating sub-directories, relative to the destinationDirectory.&amp;lt;/p&amp;gt;
	 * &amp;lt;/p&amp;gt;
	 * &amp;lt;p&amp;gt;
	 * &amp;lt;i&amp;gt;Files of the same name will be overwritten without warning.&amp;lt;/i&amp;gt;
	 * &amp;lt;/p&amp;gt;
	 *
	 * @param changes ArrayList of SVNDiffStatus objects for export, passing null will populate with the results of {@link SVNChangedFiles#list()}
	 */
	public void export(ArrayList changes) {
		if (changes == null) changes = list();
		SVNUpdateClient updateClient = new SVNUpdateClient(authManager, SVNWCUtil.createDefaultOptions(true));
		try {

			for (int idx = 0; idx &amp;lt; changes.size(); idx++) {
				SVNDiffStatus change = (SVNDiffStatus) changes.get(idx);
				File destination = new File(destinationDirectory + &amp;quot;\\&amp;quot; + change.getPath());
				updateClient.doExport(change.getURL(), destination, this.endingRevision, this.endingRevision, null, true, false);
			}
		} catch(Exception e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * &amp;lt;p&amp;gt;
	 * Returns an {@link java.util.ArrayList} of {@link org.tmatesoft.svn.core.wc.SVNDiffStatus} objects
	 * representing all files exported or modified on the given branchURL between the startingRevision and endingRevision
	 * revisions.
	 * &amp;lt;/p&amp;gt;
	 * @return {@link java.util.ArrayList} of {@link org.tmatesoft.svn.core.wc.SVNDiffStatus}
	 */
	public ArrayList list() {
		try {
			SVNDiffClient diffClient = new SVNDiffClient(authManager, SVNWCUtil.createDefaultOptions(true));

			ArrayList changes = new ArrayList();

			// adds to changes
			ImplISVNDiffStatusHandler handler = new ImplISVNDiffStatusHandler(changes);

			diffClient.doDiffStatus(this.branchURL, this.startingRevision,
					this.branchURL, this.endingRevision, true, false, handler);

			return changes;
		} catch (SVNException e) {
			throw new RuntimeException(e);
		}
	}

	private static class ImplISVNDiffStatusHandler implements ISVNDiffStatusHandler {

		private ArrayList changes;

		public ImplISVNDiffStatusHandler(ArrayList changes) {
			this.changes = changes;
		}

		public void handleDiffStatus(SVNDiffStatus status) throws SVNException {
			if (status.getKind() == SVNNodeKind.FILE &amp;amp;&amp;amp; (status.getModificationType() == SVNStatusType.STATUS_ADDED || status.getModificationType() == SVNStatusType.STATUS_MODIFIED))
				changes.add(status);
		}

	}

}
&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;
&lt;p&gt;Instantiate and call the export() method to pull the files changed on the branch between the starting and ending revision numbers into the specified destination directory.&lt;/p&gt;
&lt;p&gt;Building this requires the SVNKit library.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Ant Task&lt;/strong&gt;&lt;br /&gt;
&lt;div class=&quot;code&quot; &gt;&lt;pre&gt;import java.util.ArrayList;

import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Task;

import org.tmatesoft.svn.core.wc.SVNDiffStatus;

public class SVNExportChangedFilesAntTask extends Task {
	private String branch;
	private String username;
	private String password;
	private long start;
	private long end;
	private String destination;

	public void execute() throws BuildException {
		// TODO Auto-generated method stub
		super.execute();
		SVNChangedFiles changedFiles = new SVNChangedFiles(getBranch(), getUsername(), getPassword(), getStart(), getEnd(), getDestination());

		System.out.println(&amp;quot;Export Root Directory:\t&amp;quot; + getDestination());

		ArrayList changes = changedFiles.list();
		for (int idx = 0; idx &amp;lt; changes.size(); idx++) {
			SVNDiffStatus change = (SVNDiffStatus) changes.get(idx);
			ArrayList singleChange = new ArrayList();
			singleChange.add(change);
			changedFiles.export(singleChange);
			System.out.println(&amp;quot;\tExported:\t&amp;quot; + change.getFile());
		}
	}

	public String getBranch() {
		return branch;
	}
	public void setBranch(String branch) {
		this.branch = branch;
	}
	public String getUsername() {
		return username;
	}
	public void setUsername(String username) {
		this.username = username;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	public long getStart() {
		return start;
	}
	public void setStart(long start) {
		this.start = start;
	}
	public long getEnd() {
		return end;
	}
	public void setEnd(long end) {
		this.end = end;
	}
	public String getDestination() {
		return destination;
	}
	public void setDestination(String destination) {
		this.destination = destination;
	}


}
&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;
&lt;p&gt;I leave configuring this with Ant as an excercise for the reader. Once configured it is called as such:&lt;/p&gt;
&lt;p&gt;&lt;div class=&quot;code&quot; &gt;&lt;pre&gt;&amp;lt;exportChangedFiles
	branch=&amp;quot;[Branch URL]&amp;quot;
	start=&amp;quot;[Start Revision Number]&amp;quot;
	end=&amp;quot;[End Revision Number]&amp;quot;
	destination=&amp;quot;[Full path of directory to export files to]&amp;quot;
	password=&amp;quot;[Password]&amp;quot;
	username=&amp;quot;[Username]&amp;quot;
/&amp;gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;
Building this requires the &lt;a href=&quot;http://ant.apache.org/&quot;&gt;Apache Ant library&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description><pubDate>Thu, 06 Mar 2008 16:47:00 GMT</pubDate><guid>http://orangepips.instantspot.com/blog/2008/03/06/Export-Subversion-Files-Changed-between-Two-Revision-Numbers</guid><category>Subversion,Java</category></item><item><title>XML StAX Processing with Coldfusion</title><link>http://orangepips.instantspot.com/blog/2007/03/28/XML-StAX-Processing-with-Coldfusion</link><description>&lt;p&gt;Several problems with Coldfusion XML processing and solution set:&lt;/p&gt;
&lt;ol&gt;
    &lt;li&gt;&lt;strong&gt;Slow&lt;/strong&gt;: due to DOM processor (&lt;a href=&quot;http://xerces.apache.org/&quot;&gt;Xerces&lt;/a&gt;)&lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;Inconsistent Round-Tripping&lt;/strong&gt; (i.e. 	serialization / deserialization) :
    &lt;ol&gt;
        &lt;li&gt;(un-) escaping characters&lt;/li&gt;
        &lt;li&gt;non-printable characters&lt;/li&gt;
        &lt;li&gt;missing / multiple XML declaration(s)&lt;/li&gt;
        &lt;li&gt;character set problems&lt;/li&gt;
        &lt;li&gt;et al.&lt;/li&gt;
    &lt;/ol&gt;
    &lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;Kludgy Tree API&lt;/strong&gt; yes you can use structure and 	array functions, just don&apos;t like it.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Note, don&apos;t see this as a flame on Adobe/Macromedia. The Coldfusion XML implementation uses best available technology at the time and APIs that fit in with the language paradigm. Just have better options now.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Slow Solution&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;http://woodstox.codehaus.org/&quot;&gt;Woodstox&lt;/a&gt;&lt;/strong&gt;: &lt;a title=&quot;CFDJ: Advanced XML Processing with StAX in ColdFusion&quot; href=&quot;http://coldfusion.sys-con.com/read/236002.htm&quot;&gt;Jim Collins wrote a CFDJ article about using a StAX XML processor with Coldfusion&lt;/a&gt;. Unfortunately, as near as I can tell, his &lt;a href=&quot;http://sourceforge.net/projects/cfsynergy&quot;&gt;open source project to integrate Coldfusion with Woodstox&lt;/a&gt; was never released. &lt;a title=&quot;SUN: Streaming APIs for XML Parsers&quot; href=&quot;http://java.sun.com/performance/reference/whitepapers/StAX-1_0.pdf&quot;&gt;Testing demonstrates&lt;/a&gt; a StAX processor, such as Woodstox, provides very efficient (read: fast) XML processing, and a more intuitive API, than a SAX processor. But still not intuitive enough for me. So enter...&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Round-Tripping &amp;amp; API Solutions&lt;br /&gt;
&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a title=&quot;XML object model&quot; href=&quot;http://www.xom.nu/&quot;&gt;XOM&lt;/a&gt;&lt;/strong&gt; provides a very easy to use API that roundtrips XML like a champ. Correct I/O is XOM&apos;s middle name. But it doesn&apos;t integrate natively with a StAX processor unless you use...&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;http://dsd.lbl.gov/nux/&quot;&gt;NUX&lt;/a&gt; &lt;/strong&gt;is like a Swiss Army knife for XML. But the purpose of this entry just know it&apos;s the glue between XOM and Woodstox (&lt;em&gt;note that NUX includes the XOM jar so you do not need to download it separately&lt;/em&gt;).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Code&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Download the Woodstox and NUX jars and configure them in your Coldfusion classpath. The examples below build upon each other.&lt;/p&gt;
&lt;p&gt;&lt;u&gt;Setup&lt;/u&gt;&lt;/p&gt;
&lt;p&gt;Creates a &lt;a href=&quot;http://www.xom.nu/apidocs/nu/xom/Builder.html&quot;&gt;XOM Builder object&lt;/a&gt; backed by a StAX processor.&lt;font face=&quot;courier new,courier&quot;&gt; &lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font size=&quot;2&quot; face=&quot;courier new,courier&quot;&gt;inputFactory = createObject(&amp;quot;java&amp;quot;, &amp;quot;com.ctc.wstx.stax.WstxInputFactory&amp;quot;).init()&lt;br /&gt;
builder = createObject(&amp;quot;java&amp;quot;, &amp;quot;nux.xom.io.StaxUtil&amp;quot;).createBuilder(local.joInputFactory, javacast(&amp;quot;null&amp;quot;, &amp;quot;&amp;quot;)&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;u&gt;XMLParse() Alternative&lt;/u&gt;&lt;/p&gt;
&lt;p&gt;Returns a &lt;a href=&quot;http://www.xom.nu/apidocs/nu/xom/Document.html&quot;&gt;XOM Document object&lt;/a&gt;. Note: provide &lt;em&gt;XMLString &lt;/em&gt;variable.&lt;/p&gt;
&lt;p&gt;&lt;font size=&quot;2&quot; face=&quot;courier new,courier&quot;&gt;document = builder.create(XMLString)&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;u&gt;XMLSearch() Alternative&lt;/u&gt;&lt;/p&gt;
&lt;p&gt;Returns a &lt;a href=&quot;http://www.xom.nu/apidocs/nu/xom/Nodes.html&quot;&gt;XOM Nodes object&lt;/a&gt; (i.e. an iterator of Node objects). Note: provide &lt;em&gt;XQueryString&lt;/em&gt; variable.&lt;/p&gt;
&lt;p&gt;&lt;font size=&quot;2&quot; face=&quot;courier new,courier&quot;&gt;nodes = createObject(&amp;quot;java&amp;quot;, &amp;quot;nux.com.xquery.XQueryUtil&amp;quot;).xquery(document, XQueryString)&lt;br /&gt;
&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font size=&quot;2&quot; face=&quot;courier new,courier&quot;&gt;loop from=&amp;quot;0&amp;quot; to=&amp;quot;#nodes.size() - 1#&amp;quot; index=&amp;quot;idx&amp;quot; &lt;br /&gt;
element = nodes.get(javacast(&amp;quot;int&amp;quot;, idx)) &lt;br /&gt;
attributeValue = element.getAttribute(&amp;quot;attributeName&amp;quot;).getValue() &lt;br /&gt;
attributeText = element.getValue &lt;br /&gt;
/loop &lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;u&gt;ToString() Alternative&lt;/u&gt;&lt;/p&gt;
&lt;p&gt;Creates a string representation of the XML.&lt;/p&gt;
&lt;p&gt;&lt;font size=&quot;2&quot; face=&quot;courier new,courier&quot;&gt;XMLString = document.toXML()&lt;/font&gt;&lt;/p&gt;</description><pubDate>Wed, 28 Mar 2007 15:04:00 GMT</pubDate><guid>http://orangepips.instantspot.com/blog/2007/03/28/XML-StAX-Processing-with-Coldfusion</guid><category>XML,Coldfusion</category></item></channel></rss>