Archive for February 28th, 2010

28
Feb
10

Hosting a WebDAV folder using Tomcat 6

This page describes the process setting up Apache Tomcat 6 to act as a WebDAV server. After you are done you will be able to mount this WebDAV resource from windows or any other WebDAV client and modify file directly on the server. The location will look like a WebFolder to a Windows machine.

Reasons for having your webapp host WebDAV mount point

  • Allows the your users to easly upload/download documents to/from your web application.
  • Allows users to view your web application as a “Share Drive”
  • Allows you to have a “back door” into your application to view Log files.
  • Tools like “Web Drive” or “Net Drive” allow you to assign a drive letter for your application.

Requirements

  • Maven installed and configured
  • Some web security knowledge- The implementation described below will allow anyone to modify files.

Procedure

Start by creating a project from a maven archetype.

mvn archetype:generate -DarchetypeArtifactId=maven-archetype-webapp

Answer the rest of the questions like this…

Define value for groupId: : com.test
Define value for artifactId: : webdavTest
Define value for version:  1.0-SNAPSHOT: :
Define value for package:  com.test: :

Hit enter for the rest of the defaults.

cd to the project’s folder

Next we generate the eclipse project (optional). The project is still not ready however this step makes editing the pom.xml file easier.

mvn eclipse:clean eclipse:eclipse

Import the Existing project (generated project) into eclipse.

Next steps are to typically modify the pom.xml file and insert the rest of the dependencies and regenerate the eclipse project by re-typing the above command and clicking refresh on the eclipse project.

Your pom.xml file should look like this…

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.test</groupId>
  <artifactId>webdavTest</artifactId>
  <packaging>war</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>webdavTest Maven Webapp</name>
  <url>http://maven.apache.org</url>
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>

    <dependency>
		<groupId>org.apache.tomcat</groupId>
		<artifactId>catalina</artifactId>
		<version>6.0.24</version>
		<scope>provided</scope>
    </dependency>

  </dependencies>
  <build>
    <finalName>webdavTest</finalName>

	<plugins>
      <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>tomcat-maven-plugin</artifactId>
        <configuration>
          <server>tomcat</server>
          <update>true</update>
          <url>http://localhost:8080/manager</url>
        </configuration>
      </plugin>
	</plugins>
  </build>
</project>

Your web.xml file should look like this..

src/main/webapp/WEB-INF/web.xml

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
	<display-name>Archetype Created Web Application</display-name>

	<servlet>
		<servlet-name>webdav</servlet-name>
		<servlet-class>org.apache.catalina.servlets.WebdavServlet</servlet-class>
		<init-param>
			<param-name>debug</param-name>
			<param-value>1</param-value>
		</init-param>
		<init-param>
			<param-name>listings</param-name>
			<param-value>true</param-value>
		</init-param>
		<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>
</web-app>

Test the WebDAV location

Start the tomcat server by typing

mvn tomcat:run

Navigate to the following location using your web browser to test:

http://localhost:8080/webdavTest/

if that worked then navigate using your WEBDAV client to the same location. I used windows XP and mapped a network drive. It worked fine.

if you are using linux ubuntu you can type dav://localhost:8080/webdavTest/

TODO Items

Still trying to figure out how to get Jetty server to host this site. I have tried however got an error

javax.naming.NameNotFoundException; remaining name 'Resources'
	at org.eclipse.jetty.jndi.NamingContext.lookup(NamingContext.java:576)
	at org.eclipse.jetty.jndi.NamingContext.lookup(NamingContext.java:663)
	at org.eclipse.jetty.jndi.NamingContext.lookup(NamingContext.java:678)
	at org.eclipse.jetty.jndi.java.javaRootURLContext.lookup(javaRootURLContext.java:110)

The problem was related to the following section of code: Line 262 of DefaultServlet.java

  262           // Load the proxy dir context.
  263           resources = (ProxyDirContext) getServletContext()
  264               .getAttribute(Globals.RESOURCES_ATTR);
  265           if (resources == null) {
  266               try {
  267                   resources =
  268                       (ProxyDirContext) new InitialContext()
  269                       .lookup(RESOURCES_JNDI_NAME);
  270               } catch (NamingException e) {
  271                   // Failed
  272                   throw new ServletException("No resources", e);
  273               }
  274           }
  275
  276           if (resources == null) {
  277               throw new UnavailableException("No resources");
  278           }

I think it has something to do with the difference between the Jndi Implementation available in Jetty vs the one in Tomcat 6. Sorry for the folks that are in love with jetty but for now this only works in Tomcat 6. Not sure about Websphere or other Application servers… Soon as I try I will come back to update this page.

References

28
Feb
10

How to Grep Multiple Lines

This page describes how to find and replace patterns that span across multiple lines.

Once I was coding up some SQL DDL’s and came across a problem. The program I used to generate the DDL did not generate the foreign key relationships such that they could be read by mySQL. The create table looked like this…

CREATE TABLE pwd_category (
       category_i           SMALLINT NOT NULL,
       passwd_i             INTEGER NOT NULL,
       PRIMARY KEY (category_i, passwd_i), 
       FOREIGN KEY (passwd_i)
                             REFERENCES pwd_master, 
       FOREIGN KEY (category_i)
                             REFERENCES pwd_category_master
);

The problem seen above is that mySQL does not like the above format. Instead it wants the DDL to look like this…

CREATE TABLE pwd_category (
       category_i           SMALLINT NOT NULL,
       passwd_i             INTEGER NOT NULL,
       PRIMARY KEY (category_i, passwd_i), 
       FOREIGN KEY (passwd_i) REFERENCES pwd_master  (passwd_i),
       FOREIGN KEY (category_i) REFERENCES pwd_category_master (category_i)
);


Based on sed(1)’s man page you can execute a series of commands within the { } block.

One of the commands is N;
n N Read/append the next line of input into the pattern space.

Step 1

Detect the pattern “FOREIGN KEY” and read the next line.

/FOREIGN KEY/ – search for lines starting with FOREIGN KEY

sed -e '/FOREIGN KEY/{N;p}'

Step 2

{} – apply the enclosed when the preceeding match is made
N – append the next line to the pattern buffer
p – prints the buffer that was just read

The resulting conversion looks like this…

CREATE TABLE pwd_category (
       category_i           SMALLINT NOT NULL,
       passwd_i             INTEGER NOT NULL,
       PRIMARY KEY (category_i, passwd_i), 
       FOREIGN KEY (passwd_i)
                             REFERENCES pwd_master, 
       FOREIGN KEY (passwd_i)
                             REFERENCES pwd_master, 
       FOREIGN KEY (category_i)
                             REFERENCES pwd_category_master
       FOREIGN KEY (category_i)
                             REFERENCES pwd_category_master
);

As you can see that the lines that matched are duplicated…

Step 4

Next we apply a substution using the following pattern

s/FOREIGN KEY \((.*)\).*REFERENCES \(.*\)/FOREIGN KEY \1 REFERENCES \2 \1,/

sed -e '/FOREIGN KEY/{N;s/FOREIGN KEY \((.*)\).*REFERENCES \(.*\)/FOREIGN KEY \1 REFERENCES \2 \1,/p}'

This results in output like this…

CREATE TABLE pwd_category (
       category_i           SMALLINT NOT NULL,
       passwd_i             INTEGER NOT NULL,
       PRIMARY KEY (category_i, passwd_i), 
       FOREIGN KEY (passwd_i) REFERENCES pwd_master,  (passwd_i),
       FOREIGN KEY (passwd_i) REFERENCES pwd_master,  (passwd_i),
       FOREIGN KEY (category_i) REFERENCES pwd_category_master (category_i),
       FOREIGN KEY (category_i) REFERENCES pwd_category_master (category_i),
);

Step 5

Next we get rid of the dups by appending a:
s/\n.*// – delete everything following the first \n.

sed -e '/FOREIGN KEY/{N;s/FOREIGN KEY \((.*)\).*REFERENCES \(.*\)/FOREIGN KEY \1 REFERENCES \2 \1,/;s/\n.*//p}'

This results in output like this…

CREATE TABLE pwd_category (
       category_i           SMALLINT NOT NULL,
       passwd_i             INTEGER NOT NULL,
       PRIMARY KEY (category_i, passwd_i), 
       FOREIGN KEY (passwd_i) REFERENCES pwd_master,  (passwd_i),
       FOREIGN KEY (category_i) REFERENCES pwd_category_master (category_i),
);

Step 6

Next we need to apply some additional clean-up patterns.

sed -e 's/,.*(/ (/' |
sed -e 's/^);/) ENGINE=InnoDB;/'

This results in…

CREATE TABLE pwd_category (
       category_i           SMALLINT NOT NULL,
       passwd_i             INTEGER NOT NULL,
       PRIMARY KEY (category_i, passwd_i), 
       FOREIGN KEY (passwd_i) REFERENCES pwd_master (passwd_i),
       FOREIGN KEY (category_i) REFERENCES pwd_category_master (category_i),
) ENGINE=InnoDB;

The only thing remaining is to cleanup the extra comma. Ohh well. I will fix this some other time…




Follow

Get every new post delivered to your Inbox.

Join 34 other followers