WebDAV Client

Lebensraum:

Vorbereitungen

Testumgebung


Zum Testen von WebDAV kann ein Apache Tomcat verwendet werden.
Installation, Starten und Test sind dennkbar einfach:
  • Entpacken
  • Ausführen von /bin/startup.bat
  • Aufrufen von http://localhost:8080/ im Browser

Um den Tomcat WebDAV-fähig zu machen genügt das Hinzufügen einer Servlet-Konfiguration (Details) zur web.xml im conf-Verzeichnis des Tomcat:

<servlet>
  <servlet-name>webdav</servlet-name>
  <servlet-class>org.apache.catalina.servlets.WebdavServlet</servlet-class>
  <init-param>
    <param-name>debug</param-name>
    <param-value>0</param-value>
  </init-param>
  <init-param>
    <param-name>listings</param-name>
    <param-value>true</param-value>
  </init-param>

  <!-- The following for read-write access -->

  <init-param>
    <param-name>readonly</param-name>
    <param-value>false</param-value>
  </init-param>
</servlet>

<servlet-mapping>
  <servlet-name>webdav</servlet-name>
  <url-pattern>/*</url-pattern>
</servlet-mapping>

Nach dem Neustart des Tomcat zeigt ein Aufruf von http://localhost:8080 im Browser wird nun ein Verzeichnis-Listing angezeigt.

Bibliotheken


Als WebDAV-Bibliothek für die Implementierung eines einfachen WebDAV-Clients kommt das Apacheprojekt Jackrabbit zum Einsatz,
genauer gesagt die WebDAV-Komponente. Es bieten sich zwei Möglichkeiten an: Entweder man verwendet die jackrabbit-standalone*.jar oder man nutzt
die Komponente einzeln mit den benötigten Abhängigkeiten:
  • jackrabbit-webdav*.jar
  • jackrabbit-jcr-commons*.jar
  • commons-codec*.jar
  • commons-httpclient*.jar
  • slf4j-api*.jar
  • slf4j-log4j*.jar
  • commons-logging*.jar
  • log4j*.jar

WebDAV Client

Initialisierung


Die Basis des WebDAV-Client ist der org.apache.commons.httpclient.HttpClient. Dieser muss wie folgt initialisiert werden,
um Methoden ausführen zu können:

// ConnectionManager erstellen
HttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();
// Setzen von Connection Parametern (maximale Connections zum Host)
HttpConnectionManagerParams params = new HttpConnectionManagerParams();
int maxHostConnections = 20;
HostConfiguration hostConfig = new HostConfiguration();
params.setMaxConnectionsPerHost(hostConfig, maxHostConnections);
connectionManager.setParams(params);
// Einen neuen HttpClient anlegen
HttpClient client = new HttpClient(connectionManager);
// Setzen der Konfiguration
client.setHostConfiguration(hostConfig);

Wird für den Zugriff auf das WebDAV-Verzeichnis eine Authentifizierung benötigt, müssen die entsprechenden Credentials berücksichtigt werden:

// Setzen des Users und entsprechenden Passworts für die Verbindung zum WebDAV-Server
Credentials creds = new UsernamePasswordCredentials("user", "geheim");
// Der Hostname muss hier immer vollständig angegeben werden, 
// da sonst bei der Verbindung zum Server die Credentials nicht gefunden werden
client.getState().setCredentials(new AuthScope("localhost",8080,AuthScope.ANY_REALM,AuthScope.ANY_SCHEME), creds);

Auch die Verbindung über einen Proxy kann konfiguriert werden:

// Proxy konfigurieren
hostConfig.setProxy("myproxy", 80);
// Falls nötig, kann auch User und Passwort für den Proxy gesetzt werden
Credentials proxyCreds = new UsernamePasswordCredentials("user","passwort");
client.getState().setProxyCredentials(new AuthScope("myproxy",80,AuthScope.ANY_REALM,AuthScope.ANY_SCHEME),proxyCreds);

Verzeichnisstruktur auslesen


Für das Auslesen der Verzeichnisstruktur wir die Methode "Property Find" verwendet,
die durch die Klasse org.apache.jackrabbit.webdav.client.methods.PropFindMethod abgebildet wird:

PropFindMethod propFind = new PropFindMethod(uri.toString(), DavConstants.PROPFIND_ALL_PROP, DavConstants.DEPTH_1);
client.executeMethod(propFind);


Für die Suchtiefe kann
  • DEPTH_0 - nur durch URI angegebenes Element
  • DEPTH_1 - URI und Kindelemente 1. Grades
  • DEPTH_INFINITY - alle Kindelemente unterhalb der URI
definiert werden. Es ist zu beachten, dass nicht alle Web-Server (bzw. deren Konfiguration) die Einstellung DEPTH_INFINITY unterstützen.
Der Statuscode des Methodenaufrufs informiert über den Erfolg des Aufrufs und kann wie folgt abgerufen werden:

if (propFind.getStatusCode() != 207) { // 207 == MultiStatus
	throw new IOException("Fehler: " + propFind.getStatusText() + " ("+propFind.getStatusCode()+")";
}

Das Ergebnis der Abfrage ist ein Array von org.apache.jackrabbit.webdav.MultiStatusResponse und kann, wie im Folgenden gezeigt, ausgewertet werden:

MultiStatusResponse[] responses = propFind.getResponseBodyAsMultiStatus().getResponses();
for (MultiStatusResponse response : responses) {
	// das Property "getcontentlength" indiziert, dass es sich um eine Datei und nicht um ein Verzeichnis handelt
	if (response.getProperties(200).get("getcontentlength") != null) {
		System.out.println("FILE: " + response.getHref() + " SIZE: " 
		+ response.getProperties(200).get("getcontentlength").getValue());
	} else {
		System.out.println("DIR: " + response.getHref());
	}
}

Datei Up- und Download sowie Löschen


Der Download einer Datei kann mit der Methode org.apache.commons.httpclient.methods.GetMethod wie folgt realisiert:

GetMethod getMethod = new GetMethod(uri.toString());
client.executeMethod(getMethod);
BufferedInputStream bis = new BufferedInputStream(getMethod.getResponseBodyAsStream());

Der Upload einer Datei kann mit der Methode org.apache.jackrabbit.webdav.client.methods.PutMethod wie folt realisiert:

PutMethod putMethod = new PutMethod(fileUri.toString());   
RequestEntity requestEntity = new InputStreamRequestEntity(inputStream);   
putMethod.setRequestEntity(requestEntity);   
client.executeMethod(putMethod);
if(putMethod.getStatusCode() != 201 // 201 == Datei angelegt
   && putMethod.getStatusCode() != 204) { // 204 == Datei überschrieben
	String errorText = "Fehler beim Upload:" + putMethod.getStatusText() 
	+ " (" + putMethod.getStatusCode() + ")"; 
	throw new IOException(errorText);
} 

Das Löschen einer Datei via WebDAV kann analog mit der Methode org.apache.jackrabbit.webdav.client.methods.DeleteMethod realisiert werden:

DeleteMethod deleteMethod = new DeleteMethod(uri.toString());
client.executeMethod(deleteMethod);
if (deleteMethod.getStatusCode() != 204) {
	throw new IOException("Fehler beim Löschen: " + deleteMethod.getStatusText() 
	+ " (" + deleteMethod.getStatusCode() + ")");
}