jackrabbit-oak-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From dpfis...@apache.org
Subject svn commit: r1351618 [2/3] - in /jackrabbit/oak/trunk: ./ oak-core/ oak-it/mk/ oak-it/mk/src/main/java/org/apache/jackrabbit/mk/test/ oak-it/osgi/ oak-it/osgi/src/test/java/org/apache/jackrabbit/oak/osgi/ oak-mk-api/ oak-mk-api/src/ oak-mk-api/src/main...
Date Tue, 19 Jun 2012 09:39:45 GMT
Added: jackrabbit/oak/trunk/oak-mk-remote/src/main/java/org/apache/jackrabbit/mk/remote/util/ChunkedInputStream.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mk-remote/src/main/java/org/apache/jackrabbit/mk/remote/util/ChunkedInputStream.java?rev=1351618&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-mk-remote/src/main/java/org/apache/jackrabbit/mk/remote/util/ChunkedInputStream.java (added)
+++ jackrabbit/oak/trunk/oak-mk-remote/src/main/java/org/apache/jackrabbit/mk/remote/util/ChunkedInputStream.java Tue Jun 19 09:39:41 2012
@@ -0,0 +1,223 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.jackrabbit.mk.remote.util;
+
+import java.io.EOFException;
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Arrays;
+
+import org.apache.jackrabbit.mk.util.IOUtils;
+
+/**
+ * Input stream that reads and decodes HTTP chunks, assuming that no chunk
+ * exceeds 32768 bytes and that a chunk's length is represented by exactly 4
+ * hexadecimal characters.
+ */
+public class ChunkedInputStream extends FilterInputStream {
+
+    /**
+     * Maximum chunk size.
+     */
+    public static final int MAX_CHUNK_SIZE = 0x100000;
+
+    /**
+     * CR + LF combination.
+     */
+    private static final byte[] CRLF = "\r\n".getBytes();
+
+    /**
+     * Chunk data.
+     */
+    private final byte[] data = new byte[MAX_CHUNK_SIZE];
+
+    /**
+     * Chunk suffix (CR + LF).
+     */
+    private final byte[] suffix = new byte[2];
+
+    /**
+     * Current offset.
+     */
+    private int offset;
+
+    /**
+     * Chunk length.
+     */
+    private int length;
+
+    /**
+     * Flag indicating whether the last chunk was read.
+     */
+    private boolean lastChunk;
+    
+    /**
+     * Flag indicating whether there was an error decomposing a chunk.
+     */
+    private boolean chunkError;
+
+    /**
+     * Create a new instance of this class.
+     *
+     * @param in input stream
+     */
+    public ChunkedInputStream(InputStream in) {
+        super(in);
+    }
+
+    /* (non-Javadoc)
+     * @see java.io.FilterInputStream#read()
+     */
+    public int read() throws IOException {
+        if (!lastChunk) {
+            if (offset == length) {
+                readChunk();
+            }
+            if (offset < length) {
+                return data[offset++] & 0xff;
+            }
+        }
+        return -1;
+    }
+
+    /* (non-Javadoc)
+     * @see java.io.FilterInputStream#read(byte[], int, int)
+     */
+    public int read(byte[] b, int off, int len) throws IOException {
+        int read = 0;
+        while (read < len && !lastChunk) {
+            if (offset == length) {
+                readChunk();
+            }
+            int available = Math.min(len - read, length - offset);
+            System.arraycopy(data, offset, b, off + read, available);
+            read += available;
+            offset += available;
+        }
+        return read == 0 && lastChunk ? -1 : read;
+    }
+
+    /**
+     * Read a chunk from the underlying input stream.
+     *
+     * @throws IOException if an error occurs
+     */
+    private void readChunk() throws IOException {
+        offset = length = 0;
+
+        length = readLength(in);
+        if (length < 0 || length > MAX_CHUNK_SIZE) {
+        	chunkError = true;
+            String msg = "Chunk size smaller than 0 or bigger than " + MAX_CHUNK_SIZE;
+            throw new IOException(msg);
+        }
+        readFully(in, data, 0, length);
+        readFully(in, suffix);
+        if (!Arrays.equals(suffix, CRLF)) {
+        	chunkError = true;
+            String msg = "Missing carriage return/line feed combination.";
+            throw new IOException(msg);
+        }
+
+        if (length == 0) {
+            lastChunk = true;
+        }
+    }
+    
+    private int readLength(InputStream in) throws IOException {
+    	int len = 0;
+    	
+    	for (int i = 0; i < 5; i++) {
+    		int n, ch = in.read();
+    		if (ch == -1) {
+    			break;
+    		}
+    		if (ch >= '0' && ch <= '9') {
+    			n = (ch - '0');
+    		} else if (ch >= 'A' && ch <= 'F') {
+    			n = (ch - 'A' + 10);
+    		} else if (ch >= 'a' && ch <= 'f') {
+    			n = (ch - 'a' + 10);
+    		} else if (ch == '\r') {
+    	        ch = in.read();
+    	        if (ch != '\n') {
+    	        	chunkError = true;
+    	            String msg = "Missing carriage return/line feed combination.";
+    	            throw new IOException(msg);
+    	        }
+    			return len;
+    		} else {
+            	chunkError = true;
+                String msg = String.format("Expected hexadecimal character, actual: %c", ch);
+    			throw new IOException(msg);
+    		}
+    		len = len * 16 + n;
+    	}
+        readFully(in, suffix);
+        if (!Arrays.equals(suffix, CRLF)) {
+        	chunkError = true;
+            String msg = "Missing carriage return/line feed combination.";
+            throw new IOException(msg);
+        }
+    	return len;
+    }
+    
+    private static void readFully(InputStream in, byte[] b) throws IOException {
+        readFully(in, b, 0, b.length);
+    }
+    
+    private static void readFully(InputStream in, byte[] b, int off, int len) throws IOException {
+        int count = IOUtils.readFully(in, b, off, len);
+        if (count < len) {
+            String msg = String.format("Expected %d bytes, actually received: %d",
+                    len, count);
+            throw new EOFException(msg);
+        }
+    }
+
+    /**
+     * Recycle this input stream.
+     * 
+     * @param in new underlying input stream
+     */
+    public void recycle(InputStream in) {
+        this.in = in;
+        
+        offset = length = 0;
+        lastChunk = false;
+    }
+    
+    /**
+     * Close this input stream. Finishes reading any pending chunks until
+     * the last chunk is received. Does <b>not</b> close the underlying input
+     * stream.
+     *
+     * @see java.io.FilterInputStream#close()
+     */
+    public void close() throws IOException {
+        if (in != null) {
+            try {
+                while (!chunkError && !lastChunk) {
+                    readChunk();
+                }
+            } finally {
+                in = null;
+            }
+        }
+    }
+}

Propchange: jackrabbit/oak/trunk/oak-mk-remote/src/main/java/org/apache/jackrabbit/mk/remote/util/ChunkedInputStream.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/oak/trunk/oak-mk-remote/src/main/java/org/apache/jackrabbit/mk/remote/util/ChunkedInputStream.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev Url

Added: jackrabbit/oak/trunk/oak-mk-remote/src/main/java/org/apache/jackrabbit/mk/remote/util/ChunkedOutputStream.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mk-remote/src/main/java/org/apache/jackrabbit/mk/remote/util/ChunkedOutputStream.java?rev=1351618&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-mk-remote/src/main/java/org/apache/jackrabbit/mk/remote/util/ChunkedOutputStream.java (added)
+++ jackrabbit/oak/trunk/oak-mk-remote/src/main/java/org/apache/jackrabbit/mk/remote/util/ChunkedOutputStream.java Tue Jun 19 09:39:41 2012
@@ -0,0 +1,189 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.jackrabbit.mk.remote.util;
+
+import java.io.FilterOutputStream;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import static org.apache.jackrabbit.mk.remote.util.ChunkedInputStream.MAX_CHUNK_SIZE;
+
+/**
+ * Output stream that encodes and writes HTTP chunks.
+ */
+public class ChunkedOutputStream extends FilterOutputStream {
+
+    /**
+     * CR + LF combination.
+     */
+    private static final byte[] CRLF = "\r\n".getBytes();
+
+    /**
+     * Last chunk.
+     */
+    private static final byte[] LAST_CHUNK = "0000\r\n\r\n".getBytes();
+
+    /**
+     * Chunk prefix (length encoded as hexadecimal string).
+     */
+    private final byte[] prefix = new byte[4];
+
+    /**
+     * Chunk data.
+     */
+    private final byte[] data;
+
+    /**
+     * Current offset.
+     */
+    private int offset;
+
+    /**
+     * Create a new instance of this class.
+     *
+     * @param out underlying output stream.
+     * @param size internal buffer size
+     * @throws IllegalArgumentException if {@code size} is smaller than 1
+     *         or bigger than {@code 65535}
+     */
+    public ChunkedOutputStream(OutputStream out, int size) {
+        super(out);
+
+        if (size < 1 || size > MAX_CHUNK_SIZE) {
+            String msg = "Chunk size smaller than 1 or bigger than " + MAX_CHUNK_SIZE;
+            throw new IllegalArgumentException(msg);
+        }
+        this.data = new byte[size];
+    }
+
+    /**
+     * Create a new instance of this class.
+     *
+     * @param out underlying output stream.
+     */
+    public ChunkedOutputStream(OutputStream out) {
+        this(out, MAX_CHUNK_SIZE);
+    }
+
+    /* (non-Javadoc)
+     * @see java.io.FilterOutputStream#write(int)
+     */
+    public void write(int b) throws IOException {
+        if (offset == data.length) {
+            writeChunk();
+        }
+        data[offset++] = (byte) (b & 0xff);
+    }
+
+    /* (non-Javadoc)
+     * @see java.io.FilterOutputStream#write(byte[], int, int)
+     */
+    public void write(byte[] b, int off, int len) throws IOException {
+        int written = 0;
+        while (written < len) {
+            if (offset == data.length) {
+                writeChunk();
+            }
+            int available = Math.min(len - written, data.length - offset);
+            System.arraycopy(b, off + written, data, offset, available);
+            written += available;
+            offset += available;
+        }
+    }
+
+    /**
+     * Writes the contents of the internal buffer as chunk to the underlying
+     * output stream.
+     *
+     * @throws IOException if an error occurs
+     */
+    private void writeChunk() throws IOException {
+        toHexString(offset, prefix);
+        out.write(prefix);
+        out.write(CRLF);
+        out.write(data, 0, offset);
+        out.write(CRLF);
+        offset = 0;
+    }
+
+    /**
+     * Convert an integer into a byte array, consisting of its hexadecimal
+     * representation.
+     *
+     * @param n integer
+     * @param b byte array
+     */
+    private static void toHexString(int n, byte[] b) {
+        for (int i = b.length - 1; i >= 0; i--) {
+            int c = n & 0x0f;
+            if (c >= 0 && c <= 9) {
+                c += '0';
+            } else {
+                c += 'A' - 10;
+            }
+            b[i] = (byte) c;
+            n >>= 4;
+        }
+    }
+
+    /**
+     * Flush the contents of the internal buffer to the underlying output
+     * stream as a chunk if it is non-zero. Never do that for a zero-size
+     * chunk as this would indicate EOF.
+     *
+     * @see java.io.FilterOutputStream#flush()
+     */
+    public void flush() throws IOException {
+        if (offset > 0) {
+            writeChunk();
+        }
+        super.flush();
+    }
+    
+    /**
+     * Recycle this output stream.
+     * 
+     * @param out new underlying output stream
+     */
+    public void recycle(OutputStream out) {
+        this.out = out;
+        offset = 0;
+    }
+
+    /**
+     * Close this output stream. Flush the contents of the internal buffer
+     * and writes the last chunk to the underlying output stream. Sets
+     * the internal reference to the underlying output stream to 
+     * {@code null}. Does <b>not</b> close the underlying output stream.
+     *
+     * @see java.io.FilterOutputStream#close()
+     */
+    public void close() throws IOException {
+        if (out == null) {
+            return;
+        }
+        try {
+            if (offset > 0) {
+                writeChunk();
+            }
+            out.write(LAST_CHUNK);
+        } finally {
+            out = null;
+        }
+    }
+}

Propchange: jackrabbit/oak/trunk/oak-mk-remote/src/main/java/org/apache/jackrabbit/mk/remote/util/ChunkedOutputStream.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/oak/trunk/oak-mk-remote/src/main/java/org/apache/jackrabbit/mk/remote/util/ChunkedOutputStream.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev Url

Added: jackrabbit/oak/trunk/oak-mk-remote/src/main/java/org/apache/jackrabbit/mk/remote/util/package-info.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mk-remote/src/main/java/org/apache/jackrabbit/mk/remote/util/package-info.java?rev=1351618&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-mk-remote/src/main/java/org/apache/jackrabbit/mk/remote/util/package-info.java (added)
+++ jackrabbit/oak/trunk/oak-mk-remote/src/main/java/org/apache/jackrabbit/mk/remote/util/package-info.java Tue Jun 19 09:39:41 2012
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+@Version("0.1")
+@Export(optional = "provide:=true")
+package org.apache.jackrabbit.mk.remote.util;
+
+import aQute.bnd.annotation.Export;
+import aQute.bnd.annotation.Version;
+

Propchange: jackrabbit/oak/trunk/oak-mk-remote/src/main/java/org/apache/jackrabbit/mk/remote/util/package-info.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/oak/trunk/oak-mk-remote/src/main/java/org/apache/jackrabbit/mk/remote/util/package-info.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev Url

Added: jackrabbit/oak/trunk/oak-mk-remote/src/main/java/org/apache/jackrabbit/mk/server/BoundaryInputStream.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mk-remote/src/main/java/org/apache/jackrabbit/mk/server/BoundaryInputStream.java?rev=1351618&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-mk-remote/src/main/java/org/apache/jackrabbit/mk/server/BoundaryInputStream.java (added)
+++ jackrabbit/oak/trunk/oak-mk-remote/src/main/java/org/apache/jackrabbit/mk/server/BoundaryInputStream.java Tue Jun 19 09:39:41 2012
@@ -0,0 +1,145 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.jackrabbit.mk.server;
+
+import java.io.InputStream;
+import java.io.IOException;
+
+/**
+ * Stream that reads bytes until it sees a given string boundary, preceded
+ * by CR+LF, as used in multipart/form-data uploads.
+ */
+class BoundaryInputStream extends InputStream {
+
+    private InputStream in;
+
+    private final byte[] boundary;
+
+    private final byte[] buf;
+
+    private int offset;
+
+    private int count;
+
+    private int boundaryIndex;
+
+    private boolean eos;
+
+    /**
+     * Create a new instance of this class.
+     *
+     * @param in base input
+     * @param boundary boundary
+     */
+    public BoundaryInputStream(InputStream in, String boundary) {
+        this(in, boundary, 8192);
+    }
+
+    /**
+     * Create a new instance of this class.
+     *
+     * @param in base input
+     * @param boundary boundary
+     * @param size size of internal read-ahead buffer
+     */
+    public BoundaryInputStream(InputStream in, String boundary, int size) {
+        this.in = in;
+        this.boundary = ("\r\n" + boundary).getBytes();
+
+        // Must be able to unread this many bytes
+        if (size < this.boundary.length + 2) {
+            size = this.boundary.length + 2;
+        }
+        buf = new byte[size];
+    }
+
+    @Override
+    public int read() throws IOException {
+        if (eos) {
+            return -1;
+        }
+        byte[] b = new byte[1];
+        int count = read(b, 0, 1);
+        if (count == -1) {
+            return -1;
+        }
+        return b[0] & 0xff;
+    }
+
+    @Override
+    public int read(byte[] b, int off, int len) throws IOException {
+        if (eos) {
+            return -1;
+        }
+        if (offset == count) {
+            fillBuffer();
+            if (eos) {
+                return -1;
+            }
+        }
+        return copy(b, off, len);
+    }
+
+    private void fillBuffer() throws IOException {
+        if (boundaryIndex > 0) {
+            System.arraycopy(boundary, 0, buf, 0, boundaryIndex);
+        }
+        offset = boundaryIndex;
+        count = in.read(buf, offset, buf.length - offset);
+
+        if (count < 0) {
+            eos = true;
+        }
+        count += offset;
+    }
+
+    private int copy(byte[] b, int off, int len) throws IOException {
+        int i = 0, j = 0;
+
+        while (offset + i < count && j < len) {
+            if (boundary[boundaryIndex] == buf[offset + i]) {
+                boundaryIndex++;
+                i++;
+
+                if (boundaryIndex == boundary.length) {
+                    eos = true;
+                    break;
+                }
+            } else {
+                if (boundaryIndex > 0) {
+                    i -= boundaryIndex;
+                    if (i < 0) {
+                        offset += i;
+                        i = 0;
+                    }
+                    boundaryIndex = 0;
+                }
+                b[off + j] = buf[offset + i];
+                i++;
+                j++;
+            }
+        }
+        offset += i;
+        return j == 0 && eos ? -1 : j;
+    }
+
+    @Override
+    public void close() throws IOException {
+        in = null;
+        eos = true;
+    }
+}

Propchange: jackrabbit/oak/trunk/oak-mk-remote/src/main/java/org/apache/jackrabbit/mk/server/BoundaryInputStream.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/oak/trunk/oak-mk-remote/src/main/java/org/apache/jackrabbit/mk/server/BoundaryInputStream.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev Url

Added: jackrabbit/oak/trunk/oak-mk-remote/src/main/java/org/apache/jackrabbit/mk/server/FileServlet.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mk-remote/src/main/java/org/apache/jackrabbit/mk/server/FileServlet.java?rev=1351618&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-mk-remote/src/main/java/org/apache/jackrabbit/mk/server/FileServlet.java (added)
+++ jackrabbit/oak/trunk/oak-mk-remote/src/main/java/org/apache/jackrabbit/mk/server/FileServlet.java Tue Jun 19 09:39:41 2012
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.jackrabbit.mk.server;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashMap;
+
+import org.apache.jackrabbit.mk.util.IOUtils;
+
+/**
+ * File servlet that will deliver static resources.
+ */
+class FileServlet implements Servlet {
+    
+    /** The one and only instance of this servlet. */
+    public static FileServlet INSTANCE = new FileServlet();
+    
+    /** Just one instance, no need to make constructor public */
+    private FileServlet() {}
+
+    @Override
+    public void service(Request request, Response response) throws IOException {
+        String file = request.getFile();
+        if (file.endsWith("/")) {
+            file += "index.html";
+        }
+        InputStream in = FileServlet.class.getResourceAsStream(file.substring(1));
+        if (in != null) {
+            try {
+                int dotIndex = file.lastIndexOf('.');
+                if (dotIndex != -1) {
+                    String contentType = MIME_TYPES.get(file.substring(dotIndex + 1));
+                    if (contentType == null) {
+                        contentType = "application/octet-stream";
+                    }
+                    response.setContentType(contentType);
+                }
+                IOUtils.copy(in, response.getOutputStream());
+            } finally {
+                IOUtils.closeQuietly(in);
+            }
+        } else {
+            response.setStatusCode(404);
+        }
+    }
+
+    /* Mime types table */
+    private static final HashMap<String, String> MIME_TYPES = new HashMap<String, String>();
+    
+    static {
+        MIME_TYPES.put("html", "text/html");
+        MIME_TYPES.put("css",  "text/css");
+        MIME_TYPES.put("js",   "application/javascript");
+        MIME_TYPES.put("json", "application/json");
+        MIME_TYPES.put("png",  "image/png");
+    }
+}

Propchange: jackrabbit/oak/trunk/oak-mk-remote/src/main/java/org/apache/jackrabbit/mk/server/FileServlet.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/oak/trunk/oak-mk-remote/src/main/java/org/apache/jackrabbit/mk/server/FileServlet.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev Url

Added: jackrabbit/oak/trunk/oak-mk-remote/src/main/java/org/apache/jackrabbit/mk/server/HttpProcessor.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mk-remote/src/main/java/org/apache/jackrabbit/mk/server/HttpProcessor.java?rev=1351618&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-mk-remote/src/main/java/org/apache/jackrabbit/mk/server/HttpProcessor.java (added)
+++ jackrabbit/oak/trunk/oak-mk-remote/src/main/java/org/apache/jackrabbit/mk/server/HttpProcessor.java Tue Jun 19 09:39:41 2012
@@ -0,0 +1,119 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.jackrabbit.mk.server;
+
+import org.apache.jackrabbit.mk.util.IOUtils;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.Socket;
+
+/**
+ * Process all HTTP requests on a single socket.
+ */
+public class HttpProcessor {
+
+    private static final int INITIAL_SO_TIMEOUT = 10000;
+
+    private static final int DEFAULT_SO_TIMEOUT = 30000;
+
+    private static final int MAX_KEEP_ALIVE_REQUESTS = 100;
+
+    private final Socket socket;
+
+    private final Servlet servlet;
+
+    private InputStream socketIn;
+
+    private OutputStream socketOut;
+
+    private final Request request = new Request();
+
+    private final Response response = new Response();
+
+    /**
+     * Create a new instance of this class.
+     *
+     * @param socket socket
+     * @param servlet servlet to invoke for incoming requests
+     */
+    public HttpProcessor(Socket socket, Servlet servlet) {
+        this.socket = socket;
+        this.servlet = servlet;
+    }
+
+    /**
+     * Process all requests on a single socket.
+     *
+     * @throws IOException if an I/O error occurs
+     */
+    public void process() throws IOException {
+        try {
+            socketIn = new BufferedInputStream(socket.getInputStream());
+            socketOut = new BufferedOutputStream(socket.getOutputStream());
+
+            socket.setSoTimeout(INITIAL_SO_TIMEOUT);
+
+            for (int requestNum = 0;; requestNum++) {
+                if (!process(requestNum)) {
+                    break;
+                }
+                if (requestNum == 0) {
+                    socket.setSoTimeout(DEFAULT_SO_TIMEOUT);
+                }
+            }
+        }  finally {
+            IOUtils.closeQuietly(socketOut);
+            IOUtils.closeQuietly(socketIn);
+            IOUtils.closeQuietly(socket);
+        }
+    }
+
+    /**
+     * Process a single request.
+     *
+     * @param requestNum number of this request on the same persistent connection
+     * @return {@code true} if the connection should be kept alive;
+     *         {@code false} otherwise
+     *
+     * @throws IOException if an I/O error occurs
+     */
+    private boolean process(int requestNum) throws IOException {
+        try {
+            request.parse(socketIn);
+        } catch (IOException e) {
+            if (requestNum == 0) {
+                // ignore errors on the very first request (might be wrong protocol)
+                return false;
+            }
+            throw e;
+        }
+        try {
+            boolean keepAlive = request.isKeepAlive() &&
+                    (requestNum + 1 < MAX_KEEP_ALIVE_REQUESTS);
+            response.recycle(socketOut, keepAlive);
+            servlet.service(request, response);
+            return keepAlive;
+        } finally {
+            IOUtils.closeQuietly(request);
+            IOUtils.closeQuietly(response);
+        }
+    }
+}

Propchange: jackrabbit/oak/trunk/oak-mk-remote/src/main/java/org/apache/jackrabbit/mk/server/HttpProcessor.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/oak/trunk/oak-mk-remote/src/main/java/org/apache/jackrabbit/mk/server/HttpProcessor.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev Url

Added: jackrabbit/oak/trunk/oak-mk-remote/src/main/java/org/apache/jackrabbit/mk/server/MicroKernelServlet.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mk-remote/src/main/java/org/apache/jackrabbit/mk/server/MicroKernelServlet.java?rev=1351618&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-mk-remote/src/main/java/org/apache/jackrabbit/mk/server/MicroKernelServlet.java (added)
+++ jackrabbit/oak/trunk/oak-mk-remote/src/main/java/org/apache/jackrabbit/mk/server/MicroKernelServlet.java Tue Jun 19 09:39:41 2012
@@ -0,0 +1,355 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.jackrabbit.mk.server;
+
+import java.io.IOException;
+import java.io.PrintStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.jackrabbit.mk.api.MicroKernel;
+import org.apache.jackrabbit.mk.api.MicroKernelException;
+import org.apache.jackrabbit.mk.json.JsopBuilder;
+import org.apache.jackrabbit.mk.util.MicroKernelInputStream;
+import org.apache.jackrabbit.mk.util.IOUtils;
+
+/**
+ * Servlet handling requests directed at a {@code MicroKernel} instance.
+ */
+class MicroKernelServlet {
+
+    /** The one and only instance of this servlet. */
+    public static MicroKernelServlet INSTANCE = new MicroKernelServlet();
+
+    /** Just one instance, no need to make constructor public */
+    private MicroKernelServlet() {}
+
+    public void service(MicroKernel mk, Request request, Response response) throws IOException {
+        String file = request.getFile();
+        int dotIndex = file.indexOf('.');
+        if (dotIndex == -1) {
+            dotIndex = file.length();
+        }
+        Command command = COMMANDS.get(file.substring(1, dotIndex));
+        if (command != null && mk != null) {
+            try {
+                command.execute(mk, request, response);
+            } catch (MicroKernelException e) {
+                response.setStatusCode(500);
+                response.setContentType("text/plain");
+                e.printStackTrace(new PrintStream(response.getOutputStream()));
+            } catch (Throwable e) {
+                response.setStatusCode(500);
+                response.setContentType("text/plain");
+                e.printStackTrace(new PrintStream(response.getOutputStream()));
+            }
+            return;
+        }
+        response.setStatusCode(404);
+    }
+
+    private static interface Command {
+
+        void execute(MicroKernel mk, Request request, Response response)
+                throws IOException, MicroKernelException;
+    }
+
+    private static final Map<String, Command> COMMANDS = new HashMap<String, Command>();
+
+    static {
+        COMMANDS.put("getHeadRevision", new GetHeadRevision());
+        COMMANDS.put("getRevisionHistory", new GetRevisionHistory());
+        COMMANDS.put("waitForCommit", new WaitForCommit());
+        COMMANDS.put("getJournal", new GetJournal());
+        COMMANDS.put("diff", new Diff());
+        COMMANDS.put("nodeExists", new NodeExists());
+        COMMANDS.put("getChildNodeCount", new GetChildNodeCount());
+        COMMANDS.put("getNodes", new GetNodes());
+        COMMANDS.put("commit", new Commit());
+        COMMANDS.put("branch", new Branch());
+        COMMANDS.put("merge", new Merge());
+        COMMANDS.put("getLength", new GetLength());
+        COMMANDS.put("read", new Read());
+        COMMANDS.put("write", new Write());
+    }
+
+    static class GetHeadRevision implements Command {
+
+        @Override
+        public void execute(MicroKernel mk, Request request, Response response)
+                throws IOException, MicroKernelException {
+
+            response.setContentType("text/plain");
+            response.write(mk.getHeadRevision());
+        }
+    }
+
+    static class GetRevisionHistory implements Command {
+
+        @Override
+        public void execute(MicroKernel mk, Request request, Response response)
+                throws IOException, MicroKernelException {
+
+            long since = request.getParameter("since", 0L);
+            int maxEntries = request.getParameter("max_entries", 10);
+            String path = request.getParameter("path", "");
+
+            response.setContentType("application/json");
+            String json = mk.getRevisionHistory(since, maxEntries, path);
+            if (request.getHeaders().containsKey("User-Agent")) {
+                json = JsopBuilder.prettyPrint(json);
+            }
+            response.write(json);
+        }
+    }
+
+    static class WaitForCommit implements Command {
+
+        @Override
+        public void execute(MicroKernel mk, Request request, Response response)
+                throws IOException, MicroKernelException {
+
+            String headRevision = mk.getHeadRevision();
+
+            String oldHead = request.getParameter("revision_id", headRevision);
+            long maxWaitMillis = request.getParameter("max_wait_millis", 0L);
+
+            String currentHead;
+
+            try {
+                currentHead = mk.waitForCommit(oldHead, maxWaitMillis);
+            } catch (InterruptedException e) {
+                throw new MicroKernelException(e);
+            }
+
+            response.setContentType("text/plain");
+            response.write(currentHead == null ? "null" : currentHead);
+        }
+    }
+
+    static class GetJournal implements Command {
+
+        @Override
+        public void execute(MicroKernel mk, Request request, Response response)
+                throws IOException, MicroKernelException {
+
+            String headRevision = mk.getHeadRevision();
+
+            String fromRevisionId = request.getParameter("from_revision_id", headRevision);
+            String toRevisionId = request.getParameter("to_revision_id", headRevision);
+            String path = request.getParameter("path", "");
+
+            response.setContentType("application/json");
+            String json = mk.getJournal(fromRevisionId, toRevisionId, path);
+            if (request.getHeaders().containsKey("User-Agent")) {
+                json = JsopBuilder.prettyPrint(json);
+            }
+            response.write(json);
+        }
+    }
+
+    static class Diff implements Command {
+
+        @Override
+        public void execute(MicroKernel mk, Request request, Response response)
+                throws IOException, MicroKernelException {
+
+            String headRevision = mk.getHeadRevision();
+
+            String fromRevisionId = request.getParameter("from_revision_id", headRevision);
+            String toRevisionId = request.getParameter("to_revision_id", headRevision);
+            String path = request.getParameter("path", "");
+
+            response.setContentType("application/json");
+            String json = mk.diff(fromRevisionId, toRevisionId, path);
+            if (request.getHeaders().containsKey("User-Agent")) {
+                json = JsopBuilder.prettyPrint(json);
+            }
+            response.write(json);
+        }
+    }
+
+    static class NodeExists implements Command {
+
+        @Override
+        public void execute(MicroKernel mk, Request request, Response response)
+                throws IOException, MicroKernelException {
+
+            String headRevision = mk.getHeadRevision();
+
+            String path = request.getParameter("path", "/");
+            String revisionId = request.getParameter("revision_id", headRevision);
+
+            response.setContentType("text/plain");
+            response.write(Boolean.toString(mk.nodeExists(path, revisionId)));
+        }
+    }
+
+    static class GetChildNodeCount implements Command {
+
+        @Override
+        public void execute(MicroKernel mk, Request request, Response response)
+                throws IOException, MicroKernelException {
+
+            String headRevision = mk.getHeadRevision();
+
+            String path = request.getParameter("path", "/");
+            String revisionId = request.getParameter("revision_id", headRevision);
+
+            response.setContentType("text/plain");
+            response.write(Long.toString(mk.getChildNodeCount(path, revisionId)));
+        }
+    }
+
+    static class GetNodes implements Command {
+
+        @Override
+        public void execute(MicroKernel mk, Request request, Response response)
+                throws IOException, MicroKernelException {
+
+            String headRevision = mk.getHeadRevision();
+
+            String path = request.getParameter("path", "/");
+            String revisionId = request.getParameter("revision_id", headRevision);
+            int depth = request.getParameter("depth", 1);
+            long offset = request.getParameter("offset", 0L);
+            int maxChildNodes = request.getParameter("max_child_nodes", -1);
+            String filter = request.getParameter("filter", "");
+
+            response.setContentType("application/json");
+            String json = mk.getNodes(path, revisionId, depth, offset, maxChildNodes, filter);
+            // OAK-48: MicroKernel.getNodes() should return null for not existing nodes instead of throwing an exception
+            if (json == null) {
+                json = "null";
+            }
+            if (request.getHeaders().containsKey("User-Agent")) {
+                json = JsopBuilder.prettyPrint(json);
+            }
+            response.write(json);
+        }
+    }
+
+    static class Commit implements Command {
+
+        @Override
+        public void execute(MicroKernel mk, Request request, Response response)
+                throws IOException, MicroKernelException {
+
+            String headRevision = mk.getHeadRevision();
+
+            String path = request.getParameter("path", "/");
+            String jsonDiff = request.getParameter("json_diff");
+            String revisionId = request.getParameter("revision_id", headRevision);
+            String message = request.getParameter("message");
+
+            String newRevision = mk.commit(path, jsonDiff, revisionId, message);
+
+            response.setContentType("text/plain");
+            response.write(newRevision);
+        }
+    }
+
+    static class Branch implements Command {
+
+        @Override
+        public void execute(MicroKernel mk, Request request, Response response)
+                throws IOException, MicroKernelException {
+
+            String headRevision = mk.getHeadRevision();
+
+            String trunkRevisionId = request.getParameter("trunk_revision_id", headRevision);
+
+            String newRevision = mk.branch(trunkRevisionId);
+
+            response.setContentType("text/plain");
+            response.write(newRevision);
+        }
+    }
+
+    static class Merge implements Command {
+
+        @Override
+        public void execute(MicroKernel mk, Request request, Response response)
+                throws IOException, MicroKernelException {
+
+            String branchRevisionId = request.getParameter("branch_revision_id");
+            String message = request.getParameter("message");
+
+            String newRevision = mk.merge(branchRevisionId, message);
+
+            response.setContentType("text/plain");
+            response.write(newRevision);
+        }
+    }
+
+    static class GetLength implements Command {
+
+        @Override
+        public void execute(MicroKernel mk, Request request, Response response)
+                throws IOException, MicroKernelException {
+
+            String blobId = request.getParameter("blob_id", "");
+            long length = mk.getLength(blobId);
+
+            response.setContentType("text/plain");
+            response.write(Long.toString(length));
+        }
+    }
+
+    static class Read implements Command {
+
+        @Override
+        public void execute(MicroKernel mk, Request request, Response response)
+                throws IOException, MicroKernelException {
+
+            String blobId = request.getParameter("blob_id", "");
+            long pos = request.getParameter("pos", 0L);
+            int length = request.getParameter("length", -1);
+
+            OutputStream out = response.getOutputStream();
+            if (pos == 0L && length == -1) {
+                /* return the complete binary */
+                InputStream in = new MicroKernelInputStream(mk, blobId);
+                IOUtils.copy(in, out);
+            } else {
+                /* return some range */
+                byte[] buff = new byte[length];
+                int count = mk.read(blobId, pos, buff, 0, length);
+                if (count > 0) {
+                    out.write(buff, 0, count);
+                }
+            }
+        }
+    }
+
+    static class Write implements Command {
+
+        @Override
+        public void execute(MicroKernel mk, Request request, Response response)
+                throws IOException, MicroKernelException {
+
+            InputStream in = request.getFileParameter("file");
+
+            String blobId = mk.write(in);
+
+            response.setContentType("text/plain");
+            response.write(blobId);
+        }
+    }
+}

Propchange: jackrabbit/oak/trunk/oak-mk-remote/src/main/java/org/apache/jackrabbit/mk/server/MicroKernelServlet.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/oak/trunk/oak-mk-remote/src/main/java/org/apache/jackrabbit/mk/server/MicroKernelServlet.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev Url

Added: jackrabbit/oak/trunk/oak-mk-remote/src/main/java/org/apache/jackrabbit/mk/server/Request.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mk-remote/src/main/java/org/apache/jackrabbit/mk/server/Request.java?rev=1351618&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-mk-remote/src/main/java/org/apache/jackrabbit/mk/server/Request.java (added)
+++ jackrabbit/oak/trunk/oak-mk-remote/src/main/java/org/apache/jackrabbit/mk/server/Request.java Tue Jun 19 09:39:41 2012
@@ -0,0 +1,286 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.jackrabbit.mk.server;
+
+import java.io.ByteArrayOutputStream;
+import java.io.Closeable;
+import java.io.EOFException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URLDecoder;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import org.apache.jackrabbit.mk.remote.util.BoundedInputStream;
+import org.apache.jackrabbit.mk.remote.util.ChunkedInputStream;
+import org.apache.jackrabbit.mk.util.IOUtils;
+
+/**
+ * HTTP Request implementation.
+ */
+class Request implements Closeable {
+
+    private static final String HTTP_11_PROTOCOL = "HTTP/1.1";
+
+    private InputStream in;
+
+    private String method;
+
+    private String file;
+
+    private String queryString;
+
+    private String protocol;
+
+    private final Map<String, String> headers = new LinkedHashMap<String, String>();
+
+    private boolean paramsChecked;
+
+    private final Map<String, String> params = new LinkedHashMap<String, String>();
+
+    private final ChunkedInputStream chunkedIn = new ChunkedInputStream(null);
+
+    private InputStream reqIn;
+
+    /**
+     * Parse a request. This automatically resets any internal state, so it can be
+     * used multiple times
+     *
+     * @param in input stream
+     * @throws IOException if an I/O error occurs
+     */
+    void parse(InputStream in) throws IOException {
+        String requestLine = readLine(in);
+
+        String[] parts = requestLine.split(" ");
+        if (parts.length != 3) {
+            String msg = String.format("Bad HTTP request line: %s", requestLine);
+            throw new IOException(msg);
+        }
+        method = parts[0];
+
+        String uri = parts[1];
+        int index = uri.lastIndexOf('?');
+        if (index == -1) {
+            file = uri;
+            queryString = null;
+        } else {
+            file = uri.substring(0, index);
+            queryString = uri.substring(index + 1);
+        }
+
+        protocol = parts[2];
+
+        headers.clear();
+
+        for (;;) {
+            String headerLine = readLine(in);
+            if (headerLine.length() == 0) {
+                break;
+            }
+            parts = headerLine.split(":");
+            if (parts.length == 2) {
+                headers.put(parts[0].trim(), parts[1].trim());
+            }
+        }
+
+        params.clear();
+        paramsChecked = false;
+        reqIn = null;
+
+        this.in = in;
+    }
+
+    /**
+     * Read a single line, terminated by a CR LF combination from an {@code InputStream}.
+     *
+     * @return line
+     * @throws IOException if an I/O error occurs
+     */
+    private static String readLine(InputStream in) throws IOException {
+        StringBuilder line = new StringBuilder(128);
+
+        for (;;) {
+            int c = in.read();
+            switch (c) {
+            case '\r':
+                // swallow
+                break;
+            case '\n':
+                return line.toString();
+            case -1:
+                throw new EOFException();
+            default:
+                line.append((char) c);
+            }
+        }
+    }
+
+    public String getMethod() {
+        return method;
+    }
+
+    public String getFile() {
+        return file;
+    }
+
+    private String getContentType() {
+        String ct = headers.get("Content-Type");
+        if (ct != null) {
+            int sep = ct.indexOf(';');
+            if (sep != -1) {
+                ct = ct.substring(0, sep).trim();
+            }
+        }
+        return ct;
+    }
+
+    private int getContentLength() {
+        String s = headers.get("Content-Length");
+        if (s != null) {
+            try {
+                return Integer.parseInt(s);
+            } catch (RuntimeException e) {
+                /* ignore */
+            }
+        }
+        return -1;
+    }
+
+    public Map<String, String> getHeaders() {
+        return headers;
+    }
+
+    public String getQueryString() {
+        return queryString;
+    }
+
+    public String getParameter(String name) throws IOException {
+        if (!paramsChecked) {
+            try {
+                String contentType = getContentType();
+                if ("application/x-www-form-urlencoded".equals(contentType)) {
+                    ByteArrayOutputStream out = new ByteArrayOutputStream();
+                    IOUtils.copy(getInputStream(), out);
+                    collectParameters(out.toString(), params);
+                }
+            } finally {
+                paramsChecked = true;
+            }
+        }
+        return params.get(name);
+    }
+
+    public String getParameter(String name, String defaultValue) throws IOException {
+        String s = getParameter(name);
+        if (s != null) {
+            return s;
+        }
+        return defaultValue;
+    }
+
+    public int getParameter(String name, int defaultValue) throws IOException {
+        String s = getParameter(name);
+        if (s != null) {
+            try {
+                return Integer.parseInt(s);
+            } catch (RuntimeException e) {
+                /* ignore */
+            }
+        }
+        return defaultValue;
+    }
+
+    public long getParameter(String name, long defaultValue) throws IOException {
+        String s = getParameter(name);
+        if (s != null) {
+            try {
+                return Long.parseLong(s);
+            } catch (RuntimeException e) {
+                /* ignore */
+            }
+        }
+        return defaultValue;
+    }
+
+    public InputStream getFileParameter(String name) throws IOException {
+        String ct = getContentType();
+        if (ct == null || !ct.startsWith("multipart/form-data")) {
+            return null;
+        }
+        if (reqIn != null) {
+            /* might already be consumed */
+            return null;
+        }
+
+        InputStream body = getInputStream();
+        String boundary = readLine(body);
+
+        for (;;) {
+            String line = readLine(body);
+            if (line.length() == 0) {
+                break;
+            }
+            // TODO evaluate other information (such as mime type)
+        }
+        return new BoundaryInputStream(body, boundary);
+    }
+
+    private static void collectParameters(String s, Map<String, String> map) throws IOException {
+        for (String param : s.split("&")) {
+            String[] nv = param.split("=", 2);
+            if (nv.length == 2) {
+                map.put(URLDecoder.decode(nv[0], "UTF-8"), URLDecoder.decode(nv[1], "UTF-8"));
+            }
+        }
+    }
+
+    public InputStream getInputStream() {
+        if (reqIn == null) {
+            String encoding = headers.get("Transfer-Encoding");
+            if ("chunked".equalsIgnoreCase(encoding)) {
+                chunkedIn.recycle(in);
+                reqIn = chunkedIn;
+            } else {
+                int contentLength = getContentLength();
+                if (contentLength == -1) {
+                    contentLength = 0;
+                }
+                reqIn = new BoundedInputStream(in, contentLength);
+            }
+        }
+        return reqIn;
+    }
+
+    boolean isKeepAlive() {
+        return HTTP_11_PROTOCOL.equals(protocol);
+    }
+
+    @Override
+    public void close() {
+        if (in != null) {
+            try {
+                // Consume a possibly non-empty body by triggering the
+                // creation of our request input stream
+                getInputStream();
+                IOUtils.closeQuietly(reqIn);
+            } finally {
+                in = null;
+            }
+        }
+    }
+}

Propchange: jackrabbit/oak/trunk/oak-mk-remote/src/main/java/org/apache/jackrabbit/mk/server/Request.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/oak/trunk/oak-mk-remote/src/main/java/org/apache/jackrabbit/mk/server/Request.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev Url

Added: jackrabbit/oak/trunk/oak-mk-remote/src/main/java/org/apache/jackrabbit/mk/server/Response.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mk-remote/src/main/java/org/apache/jackrabbit/mk/server/Response.java?rev=1351618&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-mk-remote/src/main/java/org/apache/jackrabbit/mk/server/Response.java (added)
+++ jackrabbit/oak/trunk/oak-mk-remote/src/main/java/org/apache/jackrabbit/mk/server/Response.java Tue Jun 19 09:39:41 2012
@@ -0,0 +1,280 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.jackrabbit.mk.server;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import org.apache.jackrabbit.mk.util.IOUtils;
+
+import static org.apache.jackrabbit.mk.remote.util.ChunkedInputStream.MAX_CHUNK_SIZE;
+
+/**
+ * HTTP Response implementation.
+ */
+class Response implements Closeable {
+
+    private OutputStream out;
+
+    private boolean keepAlive;
+
+    private boolean headersSent;
+
+    private boolean committed;
+
+    private boolean chunked;
+
+    private int statusCode;
+
+    private String contentType;
+
+    private final BodyOutputStream bodyOut = new BodyOutputStream();
+
+    private OutputStream respOut;
+
+    private final Map<String, String> headers = new LinkedHashMap<String, String>();
+
+    /**
+     * Recycle this instance, using another output stream and a keep-alive flag.
+     *
+     * @param out output stream
+     * @param keepAlive whether to keep alive the connection
+     */
+    void recycle(OutputStream out, boolean keepAlive) {
+        this.out = out;
+        this.keepAlive = keepAlive;
+
+        headersSent = committed = chunked = false;
+        statusCode = 0;
+        contentType = null;
+        bodyOut.reset();
+        respOut = null;
+        headers.clear();
+    }
+
+    /**
+     * Return the status message associated with a status code.
+     *
+     * @param sc status code
+     * @return associated status message
+     */
+    private static String getStatusMsg(int sc) {
+        switch (sc) {
+        case 200:
+            return "OK";
+        case 400:
+            return "Bad request";
+        case 401:
+            return "Unauthorized";
+        case 404:
+            return "Not found";
+        default:
+            return "Internal server error";
+        }
+    }
+
+    private void sendHeaders() throws IOException {
+        if (headersSent) {
+            return;
+        }
+
+        headersSent = true;
+
+        int statusCode = this.statusCode;
+        if (statusCode == 0) {
+            statusCode = 200;
+        }
+        String msg = getStatusMsg(statusCode);
+        if (respOut == null) {
+            /* Generate minimal body  */
+            String body = String.format(
+                    "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">" +
+                    "<html><head>" +
+                    "<title>%d %s</title>" +
+                    "</head><body>" +
+                    "<h1>%s</h1>" +
+                    "</body></html>", statusCode, msg, msg);
+            setContentType("text/html");
+            write(body);
+        }
+
+        writeLine(String.format("HTTP/1.1 %d %s", statusCode, msg));
+
+        if (committed) {
+            writeLine(String.format("Content-Length: %d", bodyOut.getCount()));
+        } else {
+            chunked = true;
+            writeLine("Transfer-Encoding: chunked");
+        }
+        if (contentType != null) {
+            writeLine(String.format("Content-Type: %s", contentType));
+        }
+        if (!keepAlive) {
+            writeLine("Connection: Close");
+        }
+        if (headers != null) {
+            for (Map.Entry<String, String> header : headers.entrySet()) {
+                writeLine(String.format("%s: %s", header.getKey(), header.getValue()));
+            }
+        }
+
+        writeLine("");
+
+        if (out != null) {
+            out.flush();
+        }
+    }
+
+    @Override
+    public void close() throws IOException {
+        committed = true;
+
+        try {
+            sendHeaders();
+            IOUtils.closeQuietly(respOut);
+
+            if (out != null) {
+                out.flush();
+            }
+        } finally {
+            out = null;
+        }
+    }
+
+    private void writeLine(String s) throws IOException {
+        if (out == null) {
+            return;
+        }
+        out.write(s.getBytes());
+        out.write("\r\n".getBytes());
+    }
+
+    /**
+     * Write some bytes to the body of the response.
+     * @param b buffer
+     * @param off offset
+     * @param len length
+     * @throws IOException if an I/O error occurs
+     */
+    void writeBody(byte[] b, int off, int len) throws IOException {
+        if (out == null) {
+            return;
+        }
+
+        sendHeaders();
+
+        if (chunked) {
+            out.write(String.format("%04X\r\n", len).getBytes());
+        }
+        out.write(b, off, len);
+        if (chunked) {
+            out.write(("\r\n").getBytes());
+        }
+    }
+
+    public void setContentType(String contentType) {
+        this.contentType = contentType;
+    }
+
+    public OutputStream getOutputStream() {
+        if (respOut == null) {
+            respOut = bodyOut;
+        }
+        return respOut;
+    }
+
+    public void setStatusCode(int statusCode) {
+        this.statusCode = statusCode;
+    }
+
+    public void addHeader(String name, String value) {
+        headers.put(name, value);
+    }
+
+    public void write(String s) throws IOException {
+        getOutputStream().write(s.getBytes("8859_1"));
+    }
+
+    /**
+     * Internal {@code OutputStream} passed to servlet handlers.
+     */
+    class BodyOutputStream extends OutputStream {
+
+        /**
+         * Buffer size chosen intentionally to not exceed maximum chunk
+         * size we'd like to transmit.
+         */
+        private final byte[] buf = new byte[MAX_CHUNK_SIZE];
+
+        private int offset;
+
+        /**
+         * Return the number of valid bytes in the buffer.
+         *
+         * @return number of bytes
+         */
+        public int getCount() {
+            return offset;
+        }
+
+        @Override
+        public void write(int b) throws IOException {
+            if (offset == buf.length) {
+                writeBody(buf, 0, offset);
+                offset = 0;
+            }
+            buf[offset++] = (byte) b;
+        }
+
+        @Override
+        public void write(byte[] b, int off, int len) throws IOException {
+            int count = 0;
+            while (count < len) {
+                if (offset == buf.length) {
+                    writeBody(buf, 0, offset);
+                    offset = 0;
+                }
+                int n = Math.min(len - count, buf.length - offset);
+                System.arraycopy(b, off + count, buf, offset, n);
+                count += n;
+                offset += n;
+            }
+        }
+
+        @Override
+        public void flush() throws IOException {
+            if (offset > 0) {
+                writeBody(buf, 0, offset);
+                offset = 0;
+            }
+        }
+
+        public void reset() {
+            offset = 0;
+        }
+
+        @Override
+        public void close() throws IOException {
+            flush();
+
+            writeBody(buf, 0, 0);
+        }
+    }
+}

Propchange: jackrabbit/oak/trunk/oak-mk-remote/src/main/java/org/apache/jackrabbit/mk/server/Response.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/oak/trunk/oak-mk-remote/src/main/java/org/apache/jackrabbit/mk/server/Response.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev Url

Added: jackrabbit/oak/trunk/oak-mk-remote/src/main/java/org/apache/jackrabbit/mk/server/Server.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mk-remote/src/main/java/org/apache/jackrabbit/mk/server/Server.java?rev=1351618&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-mk-remote/src/main/java/org/apache/jackrabbit/mk/server/Server.java (added)
+++ jackrabbit/oak/trunk/oak-mk-remote/src/main/java/org/apache/jackrabbit/mk/server/Server.java Tue Jun 19 09:39:41 2012
@@ -0,0 +1,240 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.jackrabbit.mk.server;
+
+import java.io.EOFException;
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.SocketAddress;
+import java.net.SocketTimeoutException;
+import java.net.UnknownHostException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicReference;
+
+import javax.net.ServerSocketFactory;
+
+import org.apache.jackrabbit.mk.api.MicroKernel;
+
+/**
+ * Server exposing a {@code MicroKernel}.
+ */
+public class Server {
+
+    /** java.net.ServerSocket's default backlog size. */
+    private static final int BACKLOG = 50;
+
+    private final ServerSocketFactory ssFactory;
+
+    private AtomicReference<MicroKernel> mkref;
+
+    private AtomicBoolean started = new AtomicBoolean();
+
+    private AtomicBoolean stopped = new AtomicBoolean();
+
+    private ServerSocket ss;
+
+    private ExecutorService es;
+
+    private int port;
+
+    private InetAddress addr;
+
+    /**
+     * Create a new instance of this class.
+     *
+     * @param mk micro kernel
+     */
+    public Server(MicroKernel mk) {
+        this(mk, ServerSocketFactory.getDefault());
+        this.mkref = new AtomicReference<MicroKernel>(mk);
+    }
+
+    /**
+     * Create a new instance of this class.
+     *
+     * @param mk micro kernel
+     */
+    public Server(MicroKernel mk, ServerSocketFactory ssFactory) {
+        this.mkref = new AtomicReference<MicroKernel>(mk);
+        this.ssFactory = ssFactory;
+    }
+
+    /**
+     * Set port number to listen to.
+     *
+     * @param port port numbern
+     * @throws IllegalStateException if the server is already started
+     */
+    public void setPort(int port) throws IllegalStateException {
+        if (started.get()) {
+            throw new IllegalStateException("Server already started.");
+        }
+        this.port = port;
+    }
+
+    /**
+     * Set bind address.
+     */
+    public void setBindAddress(InetAddress addr) throws IllegalStateException {
+        if (started.get()) {
+            throw new IllegalStateException("Server already started.");
+        }
+        this.addr = addr;
+    }
+
+    /**
+     * Start this server.
+     *
+     * @throws IOException if an I/O error occurs
+     */
+    public void start() throws IOException {
+        if (!started.compareAndSet(false, true)) {
+            return;
+        }
+        ss = createServerSocket();
+        es = createExecutorService();
+
+        new Thread(new Runnable() {
+            @Override
+            public void run() {
+                accept();
+            }
+        }, "Acceptor").start();
+    }
+
+    void accept() {
+        try {
+            while (!stopped.get()) {
+                final Socket socket = ss.accept();
+                es.execute(new Runnable() {
+                    @Override
+                    public void run() {
+                        process(socket);
+                    }
+                });
+            }
+        } catch (IOException e) {
+            /* ignore */
+        }
+    }
+
+    private ServerSocket createServerSocket() throws IOException {
+        return ssFactory.createServerSocket(port, BACKLOG, addr);
+    }
+
+    private ExecutorService createExecutorService() {
+        return Executors.newCachedThreadPool();
+    }
+
+    /**
+     * Process a connection attempt by a client.
+     *
+     * @param socket client socket
+     */
+    void process(Socket socket) {
+        try {
+            socket.setTcpNoDelay(true);
+        } catch (IOException e) {
+            /* ignore */
+        }
+
+        HttpProcessor processor = new HttpProcessor(socket, new Servlet() {
+            @Override
+            public void service(Request request, Response response)
+                    throws IOException {
+                Server.this.service(request, response);
+            }
+        });
+
+        try {
+            processor.process();
+        } catch (SocketTimeoutException e) {
+            /* ignore */
+        } catch (EOFException e) {
+            /* ignore */
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * Service a request.
+     *
+     * @param request request
+     * @param response response
+     * @throws IOException if an I/O error occurs
+     */
+    void service(Request request, Response response) throws IOException {
+        if (request.getMethod().equals("POST")) {
+            MicroKernelServlet.INSTANCE.service(mkref.get(), request, response);
+        } else {
+            FileServlet.INSTANCE.service(request, response);
+        }
+    }
+
+    /**
+     * Return the server's local socket address.
+     *
+     * @return socket address or {@code null} if the server is not started
+     */
+    public InetSocketAddress getAddress() {
+        if (!started.get() || stopped.get()) {
+            return null;
+        }
+        SocketAddress address = ss.getLocalSocketAddress();
+        if (address instanceof InetSocketAddress) {
+            InetSocketAddress isa = (InetSocketAddress) address;
+            if (isa.getAddress().isAnyLocalAddress()) {
+                try {
+                    return new InetSocketAddress(
+                            InetAddress.getByName("localhost"),
+                            ss.getLocalPort());
+                } catch (UnknownHostException e) {
+                    throw new RuntimeException(e);
+                }
+            } else {
+                return isa;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Stop this server.
+     */
+    public void stop() {
+        if (!stopped.compareAndSet(false, true)) {
+            return;
+        }
+        if (es != null) {
+            es.shutdown();
+        }
+        if (ss != null) {
+            try {
+                ss.close();
+            } catch (IOException e) {
+                /* ignore */
+            }
+        }
+    }
+
+}

Propchange: jackrabbit/oak/trunk/oak-mk-remote/src/main/java/org/apache/jackrabbit/mk/server/Server.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/oak/trunk/oak-mk-remote/src/main/java/org/apache/jackrabbit/mk/server/Server.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev Url

Added: jackrabbit/oak/trunk/oak-mk-remote/src/main/java/org/apache/jackrabbit/mk/server/Servlet.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mk-remote/src/main/java/org/apache/jackrabbit/mk/server/Servlet.java?rev=1351618&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-mk-remote/src/main/java/org/apache/jackrabbit/mk/server/Servlet.java (added)
+++ jackrabbit/oak/trunk/oak-mk-remote/src/main/java/org/apache/jackrabbit/mk/server/Servlet.java Tue Jun 19 09:39:41 2012
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.jackrabbit.mk.server;
+
+import java.io.IOException;
+
+/**
+ * Servlet interface handling HTTP requests.
+ */
+interface Servlet {
+
+    public void service(Request request, Response response) throws IOException;
+}

Propchange: jackrabbit/oak/trunk/oak-mk-remote/src/main/java/org/apache/jackrabbit/mk/server/Servlet.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/oak/trunk/oak-mk-remote/src/main/java/org/apache/jackrabbit/mk/server/Servlet.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev Url

Added: jackrabbit/oak/trunk/oak-mk-remote/src/main/resources/org/apache/jackrabbit/mk/server/bg-body.png
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mk-remote/src/main/resources/org/apache/jackrabbit/mk/server/bg-body.png?rev=1351618&view=auto
==============================================================================
Binary file - no diff available.

Propchange: jackrabbit/oak/trunk/oak-mk-remote/src/main/resources/org/apache/jackrabbit/mk/server/bg-body.png
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: jackrabbit/oak/trunk/oak-mk-remote/src/main/resources/org/apache/jackrabbit/mk/server/branch.html
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mk-remote/src/main/resources/org/apache/jackrabbit/mk/server/branch.html?rev=1351618&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-mk-remote/src/main/resources/org/apache/jackrabbit/mk/server/branch.html (added)
+++ jackrabbit/oak/trunk/oak-mk-remote/src/main/resources/org/apache/jackrabbit/mk/server/branch.html Tue Jun 19 09:39:41 2012
@@ -0,0 +1,43 @@
+<html>
+<!--
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You 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.
+  -->
+<head>
+<title>&micro;Kernel prototype: branch</title>
+<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
+<link rel="stylesheet" type="text/css" href="main.css"/>
+</head>
+
+<body>
+    <script src="header.js"></script>
+    <div class="content">
+        <h1>Write Operations: branch</h1>
+        <form method="POST" target="result">
+        <table class="formtable">
+            <tr>
+                <td>Trunk Revision ID</td>
+                <td><input class="text" type="text" name="trunk_revision_id" id="trunk_revision_id" value=""></td>
+            </tr>
+            <tr><td>&nbsp;</td><td>
+            <input type="submit"><br></td></tr></table>
+        </form>
+        <p>
+            <iframe name="result" height="400" width="950" src="about:blank"></iframe>
+        </p>
+        <script src="footer.js"></script>
+    </div>
+</body>
+</html>

Propchange: jackrabbit/oak/trunk/oak-mk-remote/src/main/resources/org/apache/jackrabbit/mk/server/branch.html
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/oak/trunk/oak-mk-remote/src/main/resources/org/apache/jackrabbit/mk/server/commit.html
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mk-remote/src/main/resources/org/apache/jackrabbit/mk/server/commit.html?rev=1351618&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-mk-remote/src/main/resources/org/apache/jackrabbit/mk/server/commit.html (added)
+++ jackrabbit/oak/trunk/oak-mk-remote/src/main/resources/org/apache/jackrabbit/mk/server/commit.html Tue Jun 19 09:39:41 2012
@@ -0,0 +1,57 @@
+<html>
+<!--
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You 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.
+  -->
+<head>
+<title>&micro;Kernel prototype: commit</title>
+<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
+<link rel="stylesheet" type="text/css" href="main.css"/>
+</head>
+
+<body>
+    <script src="header.js"></script>
+    <div class="content">
+        <h1>Write Operations: commit</h1>
+        <form method="POST" target="result">
+        <table class="formtable">
+            <tr>
+                <td>Path</td>
+                <td><input class="text" type="text" name="path" id="path" value="/"></td>
+            </tr>
+            <tr>
+                <td>JSON Diff</td>
+                <td><input class="text" type="text" name="json_diff" id="json_diff"
+                   value='+"test" : {"jcr:primaryType":"nt:unstructured"}'>
+                </td>
+            </tr>
+            <tr>
+                <td>Revision ID</td>
+                <td><input class="text" type="text" name="revision_id" id="revision_id" value=""></td>
+            </tr>
+            <tr>
+                <td>Message</td>
+                <td><input class="text" type="text" name="message" id="message" value=""></td>
+            </tr>
+            <tr><td>&nbsp;</td><td>
+            <input type="submit"><br></td></tr></table>
+        </form>
+        <p>
+            <iframe name="result" height="400" width="950" src="about:blank"></iframe>
+        </p>
+        <script src="footer.js"></script>
+    </div>
+</body>
+</html>

Propchange: jackrabbit/oak/trunk/oak-mk-remote/src/main/resources/org/apache/jackrabbit/mk/server/commit.html
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/oak/trunk/oak-mk-remote/src/main/resources/org/apache/jackrabbit/mk/server/diff.html
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mk-remote/src/main/resources/org/apache/jackrabbit/mk/server/diff.html?rev=1351618&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-mk-remote/src/main/resources/org/apache/jackrabbit/mk/server/diff.html (added)
+++ jackrabbit/oak/trunk/oak-mk-remote/src/main/resources/org/apache/jackrabbit/mk/server/diff.html Tue Jun 19 09:39:41 2012
@@ -0,0 +1,51 @@
+<html>
+<!--
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You 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.
+  -->
+<head>
+<title>&micro;Kernel prototype: diff</title>
+<meta http-equiv="content-type" content="text/html; charset=utf-8"></meta>
+<link rel="stylesheet" type="text/css" href="main.css"></link>
+</head>
+
+<body>
+    <script src="header.js"></script>
+    <div class="content">
+        <h1>Revision Operations: diff</h1>
+        <form method="POST" target="result">
+        <table class="formtable">
+            <tr>
+                <td>From Revision ID</td>
+                <td><input class="text" type="text" name="from_revision_id" id="from_revision_id" value=""></td>
+            </tr>
+            <tr>
+                <td>To Revision ID</td>
+                <td><input class="text" type="text" name="to_revision_id" id="to_revision_id" value=""></td>
+            </tr>
+            <tr>
+                <td>Filter</td>
+                <td><input class="text" type="text" name="filter" id="filter" value=""></td>
+            </tr>
+            <tr><td>&nbsp;</td><td>
+            <input type="submit"><br></td></tr></table>
+        </form>
+        <p>
+            <iframe name="result" height="400" width="950" src="about:blank"></iframe>
+        </p>
+        <script src="footer.js"></script>
+    </div>
+</body>
+</html>

Propchange: jackrabbit/oak/trunk/oak-mk-remote/src/main/resources/org/apache/jackrabbit/mk/server/diff.html
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/oak/trunk/oak-mk-remote/src/main/resources/org/apache/jackrabbit/mk/server/footer.js
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mk-remote/src/main/resources/org/apache/jackrabbit/mk/server/footer.js?rev=1351618&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-mk-remote/src/main/resources/org/apache/jackrabbit/mk/server/footer.js (added)
+++ jackrabbit/oak/trunk/oak-mk-remote/src/main/resources/org/apache/jackrabbit/mk/server/footer.js Tue Jun 19 09:39:41 2012
@@ -0,0 +1,17 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+document.write('<div class="footer"><a href="http://www.apache.org/licenses/">License</a> | Powered by <a href="http://jackrabbit.apache.org/">Apache Jackrabbit</a></div>');

Propchange: jackrabbit/oak/trunk/oak-mk-remote/src/main/resources/org/apache/jackrabbit/mk/server/footer.js
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/oak/trunk/oak-mk-remote/src/main/resources/org/apache/jackrabbit/mk/server/footer.js
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev Url

Added: jackrabbit/oak/trunk/oak-mk-remote/src/main/resources/org/apache/jackrabbit/mk/server/getChildNodeCount.html
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mk-remote/src/main/resources/org/apache/jackrabbit/mk/server/getChildNodeCount.html?rev=1351618&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-mk-remote/src/main/resources/org/apache/jackrabbit/mk/server/getChildNodeCount.html (added)
+++ jackrabbit/oak/trunk/oak-mk-remote/src/main/resources/org/apache/jackrabbit/mk/server/getChildNodeCount.html Tue Jun 19 09:39:41 2012
@@ -0,0 +1,47 @@
+<html>
+<!--
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You 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.
+  -->
+<head>
+<title>&micro;Kernel prototype: getLength</title>
+<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
+<link rel="stylesheet" type="text/css" href="main.css"/>
+</head>
+
+<body>
+    <script src="header.js"></script>
+    <div class="content">
+        <h1>Read Operations: getChildNodeCount</h1>
+        <form method="POST" target="result">
+        <table class="formtable">
+            <tr>
+                <td>Path</td>
+                <td><input class="text" type="text" name="path" id="path" value="/"></td>
+            </tr>
+            <tr>
+                <td>Revision ID</td>
+                <td><input class="text" type="text" name="revision_id" id="revision_id" value=""></td>
+            </tr>
+            <tr><td>&nbsp;</td><td>
+            <input type="submit"><br></td></tr></table>
+        </form>
+        <p>
+            <iframe name="result" height="400" width="950" src="about:blank"></iframe>
+        </p>
+        <script src="footer.js"></script>
+    </div>
+</body>
+</html>

Propchange: jackrabbit/oak/trunk/oak-mk-remote/src/main/resources/org/apache/jackrabbit/mk/server/getChildNodeCount.html
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/oak/trunk/oak-mk-remote/src/main/resources/org/apache/jackrabbit/mk/server/getHeadRevision.html
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mk-remote/src/main/resources/org/apache/jackrabbit/mk/server/getHeadRevision.html?rev=1351618&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-mk-remote/src/main/resources/org/apache/jackrabbit/mk/server/getHeadRevision.html (added)
+++ jackrabbit/oak/trunk/oak-mk-remote/src/main/resources/org/apache/jackrabbit/mk/server/getHeadRevision.html Tue Jun 19 09:39:41 2012
@@ -0,0 +1,39 @@
+<html>
+<!--
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You 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.
+  -->
+<head>
+<title>&micro;Kernel prototype: getHeadRevision</title>
+<meta http-equiv="content-type" content="text/html; charset=utf-8"></meta>
+<link rel="stylesheet" type="text/css" href="main.css"></link>
+</head>
+
+<body>
+    <script src="header.js"></script>
+    <div class="content">
+        <h1>Revision Operations: getHeadRevision</h1>
+        <form method="POST" target="result">
+            <table class="formtable">
+            <tr><td>&nbsp;</td><td>
+            <input type="submit"><br></td></tr></table>
+        </form>
+        <p>
+            <iframe name="result" height="400" width="950" src="about:blank"></iframe>
+        </p>
+        <script src="footer.js"></script>
+    </div>
+</body>
+</html>

Propchange: jackrabbit/oak/trunk/oak-mk-remote/src/main/resources/org/apache/jackrabbit/mk/server/getHeadRevision.html
------------------------------------------------------------------------------
    svn:eol-style = native



Mime
View raw message