<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
 
 <title>unicron.github.com</title>
 <link href="http://feeds.feedburner.com/unicron" rel="self"/>
 <link href="http://unicron.github.com/"/>
 <updated>2011-11-01T19:58:17-07:00</updated>
 <id>http://unicron.github.com/</id>
 <author>
   <name>unicron</name>
   <email>unicron@gmail.com</email>
 </author>

 
 <entry>
   <title>Weekend of Eating</title>
   <link href="http://unicron.github.com/food and drink/2011/10/17/weekend-of-eating.html"/>
   <updated>2011-10-17T00:00:00-07:00</updated>
   <id>http://unicron.github.com/food and drink/2011/10/17/weekend-of-eating</id>
   <content type="html">&lt;p&gt;What a weekend! My inlaws were in town this past weekend and we ended up eating what felt like &lt;em&gt;constantly&lt;/em&gt;. Here is a summary of what I ate (yes this is just me).&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Chipotle grilled cheese from &lt;a href='http://bigcheesetruck.com/'&gt;Big Cheese&lt;/a&gt;, chicken pot pie and apple crumb pie from &lt;a href='http://dangerouspiesdc.com/'&gt;Dangerous Pies&lt;/a&gt; (Foggy Bottom)&lt;/li&gt;

&lt;li&gt;Roasted Miso-glazed chilean sea bass and coconut cake at &lt;a href='http://www.seapearlrestaurant.com/'&gt;Sea Pearl&lt;/a&gt; (Merrifield, VA)&lt;/li&gt;

&lt;li&gt;Reuben sandwich and chili cheese fries from &lt;a href='http://www.chickandruths.com/'&gt;Chick n Ruths&lt;/a&gt; (Annapolis, MD)&lt;/li&gt;

&lt;li&gt;Crab cake, crab dip, steamed shrimp, and hushpuppies from &lt;a href='http://www.cantlers.com/'&gt;Jimmy Cantlers&lt;/a&gt; (Annapolis, MD)&lt;/li&gt;

&lt;li&gt;Bacon flight, eggs benedict, and a doughnut at &lt;a href='http://eoladc.com/'&gt;Eola&lt;/a&gt; (Dupont)&lt;/li&gt;

&lt;li&gt;Burrata, polenta with crispy goat, pheasant ragu, spaghetti, pumpkin risotto, truffle, fontina, and duck egg pizza from &lt;a href='http://graffiatodc.com/'&gt;Graffiato&lt;/a&gt; (Penn Quarter)&lt;/li&gt;

&lt;li&gt;Scallion, sour cream, and bacon omelette at &lt;a href='http://www.lepainquotidien.us/'&gt;Le Pain Quotidien&lt;/a&gt; (Dupont)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I know, I know&amp;#8230; this is pretty worthless without pictures! Well, honestly, I was too busy eating. Maybe next time. Seriously.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Computer Chronicles</title>
   <link href="http://unicron.github.com/apple/2011/10/10/computer-chronicles.html"/>
   <updated>2011-10-10T00:00:00-07:00</updated>
   <id>http://unicron.github.com/apple/2011/10/10/computer-chronicles</id>
   <content type="html">&lt;p&gt;Growing up, we had an original Mac at home. I remember fondly playing Airborne! and using a very rudimentary word processing program (may have been Word) along with a crazy paint program. The brick-shaped mouse, clickity-click cushion-keyed keyboard, and giant dot-matrix printer were all beige, just like the computer itself. I think the Mac even had a handle on top, though it wasn&amp;#8217;t exactly light. 128kb of RAM was a lot.&lt;/p&gt;

&lt;p&gt;Later, my father&amp;#8217;s place of work purchased him a home office setup, including a Mac IIvx (68030 chipset). I don&amp;#8217;t recall exactly how fast it was, but 60mhz seems about right. It was fast! It ran System 7 and had a 14.4bps modem for getting on the internets, or AOL at that time probably. We had an enormous 17&amp;#8221; monitor, a Kensington Turbomouse, and a laser printer that took up its own desk. It was very high technology, and whenever there was a school project everyone crowded into our basement to use it. I enjoyed playing SimCity, F/A-18 Hornet, and eventually figured out Myst on this machine.&lt;/p&gt;

&lt;p&gt;Sometime during high school my father&amp;#8217;s job decided to &amp;#8220;upgrade&amp;#8221; the computer to a Dell. It was a Pentium 120mhz, with 8mb S3 video and a &lt;a href='http://en.wikipedia.org/wiki/Iomega_Jaz_drive'&gt;Jaz&lt;/a&gt; drive. Of course, no one else in the world had a Jaz drive, so if you wanted to use it you had to find another computer with a SCSI card and take the whole thing with you. This computer also had Windows NT 3.51 on it, rather than Windows 95 which some of my friends had. This meant I spent my days playing Nintendo, or visiting my neighbor to play TIE Fighter and Dark Forces (two of the best games ever made). Eventually we upgraded to Windows 98 and I was lost to Diablo and Doom II, plus an odd MMO called Meridian 59. During this time, I used the PC for most of my school work, unless I needed to print something on the laser printer (much nicer than any printer I have used since). Basically I stopped using the Mac, but mostly because it was slow and wouldn&amp;#8217;t play the newer games.&lt;/p&gt;

&lt;p&gt;When I went off to college, I took with me a Dell Pentium III 500mhz powerhouse. It lasted about 2 years before I upgraded to some other Dell that was at least double the speed. I&amp;#8217;m sure I upgraded the video card a couple of times but it made a reasonable gaming machine until the end of school. CS by the day and Diablo II at night.&lt;/p&gt;

&lt;p&gt;During my sophomore year, I purchased a black Powerbook G3 off eBay as a project laptop to cart around and take notes. I realized after I bought it that this was not practical, and that the age of laptop notetaking had not arrived. Believe me when I say that the week I tried this out I got so many looks and it was so awkward to take to class and have to recharge it that I was more than slightly embarrased by it. Not to mention that it was decidedly slow for the era in which I purchased it (could be why I was able to afford it). I sold it again just months after buying it, though I did make a slight profit.&lt;/p&gt;

&lt;p&gt;After graduation, I received a gift from my parents. A brand new aluminum Powerbook G4. This thing was beautiful. It wasn&amp;#8217;t staggeringly fast, but Warcraft III ran decent enough and it was small and easy to take with me. I loved using it. The only problem with it was that I didn&amp;#8217;t really need a laptop. I worked in front of a computer all day writing code, and I didn&amp;#8217;t need to take a laptop with me anywhere except the occassional family vacation. In hindsight, an iMac would have been the better choice, and it&amp;#8217;s what my brother did (smart kid). In the end, I used this computer off and on for about 5 years before selling it for $400 or so.&lt;/p&gt;

&lt;p&gt;This is where my usage of Macintosh computers ends up until now. I sit typing this on a 2006 Dell Dimension 9150 Pentium D which has been keep relevant with the help of friends&amp;#8217; discarded video cards and extra PSUs. It is nearing the end, and puts out tons of noise and heat due to the hacked-on upgrades which the case design does not elegantly accomodate. It has served me well, getting me through countless hours of CS, NWN, Civilization 3-5, and the occassional game of Starcraft II. But to be honest, my interest in gaming has waned over the years, and even my Wii sits unplayed-with (har). It is time, I said to my wife, to look at owning another Mac.&lt;/p&gt;

&lt;p&gt;Would it make sense? Probably not. But we both use iPod regularly, and she has an iPhone. We lust after the device that absolutely no-one needs: the iPad. And we both approve of the Apple design sense. But would it really make more sense than buying a new Dell or HP, or (gasp) buying and building? That&amp;#8217;s difficult to say. But what isn&amp;#8217;t difficult to see is that web development is becoming easier and easier on a Mac. In fact some newer or newly-popular languages are easier/more convenient to develop in using a Mac than a PC (so if I get that odd pang of developer-mania during my off hours I can satisfy it). And, if I need a bit of a fix, both Steam and Diablo III (will) work just fine on a Mac ;)&lt;/p&gt;

&lt;p&gt;I wanted to chronical this in tribute to what Apple and Steve Jobs have done. Steve took the idea of a personal computer, and made it just personal. iPhones, iPods, iPads, iMacs - sure, they are all computers, but they are also just devices that serve as extensions to daily personal life. I don&amp;#8217;t just want an Apple product, I covet one. Mostly because it looks good and works well, but also because it was what I grew up with. I feel personally attached to it. I realize now that the reason I sought the Dell was to play games, more as a gaming machine than a personal computer. And if I had been able to play the same games on a Mac, I never would have left.&lt;/p&gt;

&lt;p&gt;Many say Apple is a ridiculous company and that Steve Jobs was an absurd man. I say that he was a genius, both in business and in design, and that Apple will always design for the consumer who is after truly personal computing.&lt;/p&gt;

&lt;p&gt;Thanks, Steve.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Maintaining Office 2003 Programmability with Side-by-Side Office Install</title>
   <link href="http://unicron.github.com/.net/2010/02/05/maintaining-office-2003-side-by-side.html"/>
   <updated>2010-02-05T00:00:00-08:00</updated>
   <id>http://unicron.github.com/.net/2010/02/05/maintaining-office-2003-side-by-side</id>
   <content type="html">&lt;p&gt;In order to build for Office 2003 interop/automation while having Office 2007 installed in a side-by-side installation, you need to remove the .NET programmability support from each 2007 product. This ensures that the latest version available in the GAC is version 11 (2003), since most of the time .NET builds will pull from there instead of a local reference.&lt;/p&gt;

&lt;p&gt;To do this, go to add/remove programs and call up the “Change Features” window for Office 2007, find the item called “.NET Programmability Support” under each individual product you have installed, and remove it. There are also items under Office Tools for Graph and Smart Tags.&lt;/p&gt;

&lt;p&gt;Then, your GAC will include only version 11 assemblies for each product rather than 11 and 12. You should be able to build as you did before under 2003 alone.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>One-way Hashing for C# and Java</title>
   <link href="http://unicron.github.com/.net/java/2009/10/29/one-way-hashing-for-c-sharp-and-java.html"/>
   <updated>2009-10-29T00:00:00-07:00</updated>
   <id>http://unicron.github.com/.net/java/2009/10/29/one-way-hashing-for-c-sharp-and-java</id>
   <content type="html">&lt;p&gt;I was recently faced with the need to create some sort of verification measure for URLs. Basically, public users would be able to access an internal system using a generated URL, and I needed to make sure that these links were very difficult to &lt;em&gt;guess&lt;/em&gt; or even &lt;em&gt;reverse-engineer&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;I decided to use an SHA1 hash, which creates a reproducible series of bytes that can then be authenticated by comparison at a later time. This is a pretty common way of checking to make sure your message has not been tampered with and, while it can be hacked, it is very, very difficult (and time-consuming) to do so. For my use, it is a reasonable solution.&lt;/p&gt;

&lt;p&gt;The trick here is that I needed to generate the hash in Java and then check it in C#. This sounds easy (and it is), but I did spend some time tracking down how to get &lt;strong&gt;the same output&lt;/strong&gt; from these two algorithms when converting back to a string. Unfortunately, you can’t just pass the bytes around in a URL.&lt;/p&gt;

&lt;p&gt;Let’s take a look at the Java version:&lt;/p&gt;
&lt;pre class='prettyprint'&gt;
public static String generateSHA1Hash(String input) throws Exception {

	MessageDigest messagedigest = MessageDigest.getInstance(&quot;SHA&quot;);
	messagedigest.update(input.getBytes(&quot;UTF-8&quot;));
	byte digest[] = messagedigest.digest();

	StringBuffer s = new StringBuffer(digest.length * 2);
	int length = digest.length;
	for (int n = 0; n &amp;lt; length; n++) {
		int number = digest[n];
		number = (number &amp;lt; 0) ? (number + 256) : number;
		s.append(Integer.toString(number, 16));
	}

	return s.toString();
}
&lt;/pre&gt;
&lt;p&gt;The input is an ID string plus a &lt;em&gt;salt&lt;/em&gt;(another, static string). You need the salt in order to prevent someone from guessing how the hash is generated. The key is that second part which is taking each byte and converting it into a character (so it can be easily displayed and passed around). This is where the difficulty presented itself. I could get the same output in byte form, but the character conversion was funky. I feel like I am probably doing something wrong, because I had to actually just drop any space ” ” characters in the C# version:&lt;/p&gt;
&lt;pre class='prettyprint'&gt;
private bool checkHash(message) {

	SHA1 sha = new SHA1Managed();
	UTF8Encoding ue = new UTF8Encoding();
	byte[] data = ue.GetBytes(message);
	byte[] digest = sha.ComputeHash(data);

	StringBuilder newHash = new StringBuilder();
	int length = digest.Length;
	for (int n = 0; n &amp;lt; length; n++) {
		//remove spaces to match java
		newHash.Append(String.Format(&quot;{0,2:x}&quot;, digest[n]).Replace(&quot; &quot;, String.Empty));
	}

	return (docReq.Hash.Equals(newHash.ToString()))
}
&lt;/pre&gt;
&lt;p&gt;In this example, message is the incoming text to hash (in this case, the ID string along with the &lt;em&gt;same salt&lt;/em&gt; used in generating the original), and docReq.Hash is the existing hash to compare against. As you can see, the code is not quite the same (but very similar). Can anyone point out the mistake I made and tell me why the C# version produces ” ” characters, but the Java version does not?&lt;/p&gt;

&lt;p&gt;Either way, these &lt;strong&gt;do&lt;/strong&gt; produce the same comparable result. Just remember to &lt;em&gt;salt&lt;/em&gt;your inputs!&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Simple WebDAV Part 2</title>
   <link href="http://unicron.github.com/.net/webdav/2009/10/15/simple-webdav-part-2.html"/>
   <updated>2009-10-15T00:00:00-07:00</updated>
   <id>http://unicron.github.com/.net/webdav/2009/10/15/simple-webdav-part-2</id>
   <content type="html">&lt;p&gt;&lt;strong&gt;Part 2&lt;/strong&gt; of this &lt;strong&gt;&lt;a href='http://unicron.github.com/documentum/java/webdav/2009/09/21/simple-webdav-part-1.html' title='Simple WebDAV Part 1'&gt;series&lt;/a&gt;&lt;/strong&gt; is about the client-side extension used to open the remote file locally. Normally, clicking a link to a file causes the browser to prompt the user or OS for what to do with it, and then pull it down as a stream. This behavior can sometimes be modified depending on the HTTP headers sent along with the server response (attachment specification, MIME type, etc.), and browser plugins, but in nearly all cases it is still the browser interacting with the file as a stream and opening it directly. Since the browser is not a WebDAV client, it doesn’t implement the protocols we need.&lt;/p&gt;

&lt;p&gt;What we need to do is open the file directly using a WebDAV client, such as Microsoft Word. We can accomplish this one of several ways:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Write our own COM component which we can instantiate from browser javascript.&lt;/li&gt;

&lt;li&gt;Use the the SharePoint library which is built-in to Office 2000-2007.&lt;/li&gt;

&lt;li&gt;Provide only the link and have the user open Word and the file location interactively.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Write our own COM Component&lt;/strong&gt;:&lt;br /&gt;This is the initial approach I took, and it can be a good one for several reasons. First, it allows you to control how the file is opened in the client application. You can have full access to the application using Office Automation, which can be powerful if you need to set things up a certain way for the user. I wrote my implementation using a combination of C# and VB.NET, but I am confident it could be accomplished using other 4GLs.&lt;/p&gt;

&lt;p&gt;For my component, I created the interface and implementation in C# and wrote the client interaction in VB.NET. This was more personal preference than anything else because I prefer C#, but have had better luck doing Office Automation using VB. The key here is to also implement the IObjectSafety interface in order to avoid an annoying security popup every time a user clicks on your links.&lt;/p&gt;

&lt;p&gt;You can see how simple this is (remember to create new GUIDs for yourself!):&lt;/p&gt;

&lt;p&gt;&lt;em&gt;WebEditCS.cs&lt;/em&gt;:&lt;/p&gt;
&lt;pre class='prettyprint'&gt;
namespace WebEdit.ActiveX.CS {

	[
		Guid(&quot;B6E9F230-F7C6-4686-9DB1-6C0E8C33FBA2&quot;),
		InterfaceType(ComInterfaceType.InterfaceIsDual),
		ComVisible(true)
	]
	public interface IWebEditCS {
		[DispId(1)]
		bool DoWebEdit(int app, string url);
	};

	[
		Guid(&quot;01453349-18FB-434f-AB73-BFA3F73D9967&quot;),

		// This is basically the programmer friendly name
		// for the guid above. We define this because it will
		// be used to instantiate this class. I think this can be
		// whatever you want. Generally it is
		// [assemblyname].[classname]
		ProgId(&quot;WebEdit.ActiveX&quot;),

		// No class interface is generated for this class and
		// no interface is marked as the default.
		// Users are expected to expose functionality through
		// interfaces that will be explicitly exposed by the object
		// This means the object can only expose interfaces we define
		ClassInterface(ClassInterfaceType.None),

		// Set the default COM interface that will be used for
		// Automation. Languages like: C#, C++ and VB
		// allow to query for interface's we're interested in
		// but Automation only aware languages like javascript do
		// not allow to query interface(s) and create only the
		// default one
		ComDefaultInterface(typeof(IWebEditCS)),
		ComVisible(true)
	]
	public class WebEditCS : IObjectSafetyImpl, IWebEditCS {

		public bool DoWebEdit(int app, string url) {
			return WebEditVB.DoWebEditVB(app, url);
		}
	};
}
&lt;/pre&gt;
&lt;p&gt;This is just an example, and could be modified a lot to open different applications with different settings. This particular version also uses a single copy of each application by getting a reference to the running object (if it exists). While this is probably the safest way to do Office Automation, it isn’t the only one (you can certainly open a new copy every time a link is opened…). Experiment and find what works best for your situation.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;WebEditVB.vb&lt;/em&gt;:&lt;/p&gt;
&lt;pre class='prettyprint'&gt;
Namespace WebEdit.ActiveX.VB
	Public Class WebEditVB

		Private Shared Function GetInstance(ByVal appName As String) As Object
			Dim application As Object = Nothing

			Try
				application = Marshal.GetActiveObject(appName)
				If application Is Nothing Then
					application = CreateObject(appName)
				End If
			Catch ex As Exception
				application = CreateObject(appName)
			End Try

			Return application
		End Function

		Public Shared Function DoWebEditVB(ByVal app As Integer, ByVal url As String) As Boolean

			Dim application As Object = Nothing
			Dim document As Object = Nothing

			Try
				If app = 0 Then
					application = GetInstance(&quot;Word.Application&quot;)
					application.Visible = True
					document = application.Documents.Open(url)
					document.Activate()

				ElseIf app = 1 Then
					application = GetInstance(&quot;PowerPoint.Application&quot;)
					application.Visible = True
					document = application.Presentations.Open(url)

				ElseIf app = 2 Then
					'user cannot have an open spreadsheet with a cell currently being edited!
					application = GetInstance(&quot;Excel.Application&quot;)
					application.Visible = True
					document = application.Workbooks.Open(url)
					document.Activate()
				End If

			Catch ex As Exception
				Try
					Dim logName As String = &quot;C:Program FilesNLRBQuickEdit-ErrorLog.txt&quot;
					Dim fs As FileStream = New FileStream(logName, FileMode.Append, FileAccess.Write)
					Dim sw As StreamWriter = New StreamWriter(fs)
					sw.WriteLine(DateTime.Now.ToString())
					sw.WriteLine(ex.ToString())
					sw.Close()
					fs.Close()
				Catch
				End Try

				Return False
			End Try

			Return True
		End Function

	End Class
End Namespace
&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Use the SharePoint Library&lt;/strong&gt;:&lt;br /&gt;After developing my own control, I discovered that there was an even easier way to accomplish the same thing. I found out that Microsoft ships a (probably similar) control as part of each Office installation starting with Office 2000. This control seems to work pretty much the same as my version, except it doesn’t implement IObjectSafety. The advantage is that you do not have to deploy any kind of client-side control because it is already on every machine with Office! In many cases, even though it is not as nice for your users (who will have to click ‘Yes’ on a dialog every time), it is often the only viable option in an enterprise (which often won’t allow you to push ActiveX/COM controls out to users).&lt;/p&gt;

&lt;p&gt;As you can see above, I don’t have any specialized logic for opening these applications or files, so using the library that ships with Office is great for me. I implemented this so that it tries to use each version of the library (there is a different version for each Office version…) in turn.&lt;/p&gt;
&lt;pre class='prettyprint'&gt;
function webedit(id) {
	if (window.ActiveXObject) {
		var ed;
		try {
			//Office 2003
			ed = new ActiveXObject('SharePoint.OpenDocuments.2');
		} catch (err1) {
			try {
				//Office 2000/XP
				ed = new ActiveXObject('SharePoint.OpenDocuments.1');
			} catch (err2) {
				try {
					//Office 2007
					ed = new ActiveXObject('SharePoint.OpenDocuments.3');
				} catch (err3) {
					window.alert('Unable to create an ActiveX object to open the document. This is most likely because of the security settings for your browser.');
					return false;
				}
			}
		}
		if (ed) {
			ed.EditDocument('/webdav/--'+id);
			return false;
		} else {
			window.alert('Cannot instantiate the required ActiveX control to open the document. This is most likely because you do not have Office installed or you have an older version of Office.');
			return false;
		}
	} else {
		window.alert('Internet Explorer is required to use this feature.');
	}
	return false;
}
&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Provide only the Link&lt;/strong&gt;:&lt;br /&gt;As a last resort, you can always provide/display a link for the user to open manually. While this sounds silly, users still gain the benefit of WebDAV actions from within their local apps, meaning they still save directly against the repository. This can be helpful for people who work on a few files a day for a longer period of time rather than those who open lots and lots of documents daily.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Simple WebDAV Part 1</title>
   <link href="http://unicron.github.com/documentum/java/webdav/2009/09/21/simple-webdav-part-1.html"/>
   <updated>2009-09-21T00:00:00-07:00</updated>
   <id>http://unicron.github.com/documentum/java/webdav/2009/09/21/simple-webdav-part-1</id>
   <content type="html">&lt;p&gt;This is &lt;strong&gt;part 1 of a &lt;a href='http://unicron.github.com/.net/webdav/2009/10/15/simple-webdav-part-2.html' title='Simple WebDAV Part 2'&gt;2-part&lt;/a&gt; series&lt;/strong&gt; detailing how I implemented &lt;a href='http://www.webdav.org/'&gt;WebDAV&lt;/a&gt; support for a &lt;a href='http://www.emc.com/products/family/documentum-family.htm'&gt;Documentum&lt;/a&gt; repository. It is very basic and does not implement all of the methods that WebDAV supports, but it gets the job done. The end result is a type of &amp;#8220;Web Edit&amp;#8221; functionality that allows single-click checkout, edit, and checkin for Microsoft Office files (but the idea isn&amp;#8217;t restricted in any way to MS Office types).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The first goal is the actual WebDAV server&lt;/strong&gt;, which was actually much easier to put together than I expected. Some of you may already know, but I was surprised to learn that Apache Tomcat 5.5+ has WebDAV support &lt;strong&gt;built in&lt;/strong&gt; as a standalone servlet. I simply copied this &amp;#8220;WebdavServlet&amp;#8221; and stuck my code in where it made sense. WebdavServlet uses the filesystem as its repository, which is a common and flexible way to handle opening and editing files. This works fine for us, since we are working with physical files as well (they just don&amp;#8217;t happen to be in this particular location, yet). &lt;strong&gt;Our second goal is to get those files to behave as if they are local&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Let&amp;#8217;s take a look at WebdavServlet.java (obtained via &lt;a href='http://subversion.tigris.org/'&gt;Subversion&lt;/a&gt; @ http://svn.apache.org/repos/asf/tomcat/trunk/java/org/apache/catalina/servlets/WebdavServlet.java). In addition to the DefaultServlet&amp;#8217;s &lt;strong&gt;GET&lt;/strong&gt; and &lt;strong&gt;PUT&lt;/strong&gt; methods, it implements two methods specific to the WebDAV protocol that we are interested in: &lt;strong&gt;LOCK&lt;/strong&gt; and &lt;strong&gt;UNLOCK&lt;/strong&gt;. We can drop our custom code into these methods to push and pull files from Documentum (or any other system, really):&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;LOCK:&lt;/strong&gt; Interestingly, there are two steps to perform here. First, you must get the file from Documentum and move it to a local path (I am just moving it to the root of the application context). You should do this right after the path is retrieved from the request object (look for this line in doLock():&lt;/p&gt;
&lt;pre class='prettyprint'&gt;
String path = getRelativePath(req);

...

Content contentObj = d.getContents().get(0);
// Get the Content of this file
if (contentObj.canGetAsFile()) {
	File f = contentObj.getAsFile();
	File to = new File(getServletContext().getRealPath(&quot;/&quot;)+ path);
	if (f.renameTo(to))
		log(&quot;get successful.&quot;);
	else {
		if (f.exists() &amp;amp;&amp;amp; f.canWrite())
			f.delete();
		log(&quot;file move failed.&quot;);
	}
} else {
	log(&quot;get unsuccessful.&quot;);
}
&lt;/pre&gt;
&lt;p&gt;The second step is to checkout the document in Documentum. You can do this pretty much wherever you want in the method, but I prefer to wait until the very end of doLock() to make sure that the file was downloaded successfully. Now you have the local file for Tomcat to serve with GET (which is called after LOCK), and it is locked for editing in your repository.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GET:&lt;/strong&gt; This one is the easiest! We actually don&amp;#8217;t have to modify this at all. This will serve our files from the filesystem like it normally would.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;PUT:&lt;/strong&gt; As you can probably guess, we will use this method to save the file back to Documentum. Just place your logic at the end of the method, and do as you normally would when saving files to the repository from disk. A slight catch is that you should also checkout the file again, because you can&amp;#8217;t be sure that the user is finished editing. Keep in mind that any save operation will fire a PUT, so the user should maintain the lock. Once the WebDAV client is ready to release the lock, it will call UNLOCK.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;UNLOCK:&lt;/strong&gt; All you do here is cancel the checkout in the repository. That&amp;#8217;s it. Well, I also delete it from the filesystem just to be sure it doesn&amp;#8217;t get stepped on later:&lt;/p&gt;
&lt;pre class='prettyprint'&gt;
//remove the file from the filesystem
File f = new File(getServletContext().getRealPath(&quot;/&quot;)+ path);
if (f.exists() &amp;amp;&amp;amp; f.canWrite()) {
	f.delete();
	log(&quot;file deleted.&quot;);
}
&lt;/pre&gt;
&lt;p&gt;Now, you may be wondering &amp;#8220;hey, what about security?&amp;#8221; This is a very good question and is something that, fortunate for me, I did not have to worry about since this is not a public system. Tomcat&amp;#8217;s WebDAV default web.xml does allow for the normal Tomcat authentication methods (using conf/tomcat-users.xml and the like) so this is still a possibility. I pass the username in the URL to the file, so I know who to perform repository operations as, in the form&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;http://&amp;lt;domain&amp;gt;/&amp;lt;application context&amp;gt;/&amp;lt;username&amp;gt;–i_chronicle_id.&amp;lt;file extension&amp;gt;.&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Your WebDAV server implementation should now be complete! But how will you provide the single-click &amp;#8220;Web Edit&amp;#8221; capability that many organizations ask for, and many other products integrate? &lt;a href='http://unicron.github.com/.net/webdav/2009/10/15/simple-webdav-part-2.html' title='Simple WebDAV Part 2'&gt;&lt;strong&gt;In part 2&lt;/strong&gt;&lt;/a&gt;, I&amp;#8217;ll show you how to create a COM component using .Net which can start an application and load WebDAV URLs.&lt;/p&gt;

&lt;p&gt;Cheers!&lt;/p&gt;</content>
 </entry>
 
 
</feed>