commit de6ddb74522969f7a13e7a09c05b9406d30b5ad6 from: leo date: Fri Jan 23 14:37:02 2009 UTC fixed cache handling added more vfs tests litmus test (basic, copymove works fully) updated libraries using maven2 commit - 606c7aeff77ed85d0c8374e5ef56a9fc92549687 commit + de6ddb74522969f7a13e7a09c05b9406d30b5ad6 blob - 366af8a561343bd5d1b259929b35c50840a49bae blob + 1582d815464b5a6997af06d36a8f835f6544238a --- pom.xml +++ pom.xml @@ -1,71 +1,83 @@ - 4.0.0 - com.thinkberg.moxo - moxo - jar - 1.0-SNAPSHOT - Moxo S3 DAV Proxy - http://thinkberg.com - - - codehaus-m2-repository - Codehaus Maven 2.x Repository - http://repository.codehaus.org - - - - - junit - junit - 3.8.1 - test - - - jets3t - jets3t - 0.5.0 - - - commons-httpclient - commons-httpclient - 3.0.1 - - - commons-vfs - commons-vfs - 1.0 - - - org.mortbay.jetty - jetty - 6.1.1 - - - dom4j - dom4j - 1.6.1 - - - jaxen - jaxen - 1.1 - - - - - - org.apache.maven.plugins - maven-jar-plugin - - - - com.thinkberg.moxo.MoxoJettyRunner - true - - - - - - + 4.0.0 + com.thinkberg.moxo + moxo + jar + 1.0-SNAPSHOT + Moxo S3 DAV Proxy + http://thinkberg.com + + + codehaus-m2-repository + Codehaus Maven 2.x Repository + http://repository.codehaus.org + + + jets3t + jets3t + http://jets3t.s3.amazonaws.com/maven2 + + + + + junit + junit + 3.8.1 + test + + + net.java.dev.jets3t + jets3t + 0.6.1 + + + commons-httpclient + commons-httpclient + 3.0.1 + + + commons-vfs + commons-vfs + 1.0 + + + org.mortbay.jetty + jetty + 6.1.1 + + + dom4j + dom4j + 1.6.1 + + + jaxen + jaxen + 1.1 + + + + + + maven-compiler-plugin + + 1.5 + 1.5 + + + + org.apache.maven.plugins + maven-jar-plugin + + + + com.thinkberg.moxo.MoxoJettyRunner + true + + + + + + blob - 81f9dc3075c006734e4d4a76f76f86d0023776df blob + 834ca79e40db93587eb89c07798c51befb4cdbe8 --- src/main/java/com/thinkberg/moxo/Main.java +++ src/main/java/com/thinkberg/moxo/Main.java @@ -16,11 +16,7 @@ package com.thinkberg.moxo; -import java.io.BufferedInputStream; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; +import java.io.*; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.net.MalformedURLException; @@ -41,7 +37,6 @@ import java.util.jar.JarInputStream; public class Main { private final static URL location = Main.class.getProtectionDomain().getCodeSource().getLocation(); - @SuppressWarnings({"RedundantArrayCreation"}) public static void main(String args[]) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException { ClassLoader parentClassLoader = Thread.currentThread().getContextClassLoader(); @@ -63,6 +58,7 @@ public class Main { } Class mainClass = classLoader.loadClass("com.thinkberg.moxo.MoxoJettyRunner"); + @SuppressWarnings({"RedundantArrayCreation"}) final Method main = mainClass.getDeclaredMethod("main", new Class[]{String[].class}); main.invoke(null, new Object[]{args}); } @@ -72,6 +68,7 @@ public class Main { * * @return the classpath */ + @SuppressWarnings({"ConstantConditions"}) private static URL[] initClassPath() { List urlArray = new ArrayList(); InputStream manifestIn = null; @@ -112,7 +109,7 @@ public class Main { // ignore errors } } - return urlArray.toArray(new URL[0]); + return urlArray.toArray(new URL[urlArray.size()]); } /** blob - e1d96cf755ad2bafbd99a230101d870629bf7423 blob + fad5566e89f5e3a1e30cdf358aff899558c340ff --- src/main/java/com/thinkberg/moxo/MoxoJettyRunner.java +++ src/main/java/com/thinkberg/moxo/MoxoJettyRunner.java @@ -40,7 +40,7 @@ public class MoxoJettyRunner { try { Server server = new Server(); - XmlConfiguration xmlConfiguration = new XmlConfiguration(getResource(CONF_JETTY_XML)); + XmlConfiguration xmlConfiguration = new XmlConfiguration(getXmlConfigurationUrl()); xmlConfiguration.configure(server); server.start(); server.join(); @@ -50,12 +50,11 @@ public class MoxoJettyRunner { } } - @SuppressWarnings({"SameParameterValue"}) - private static URL getResource(String resource) { - URL url = MoxoJettyRunner.class.getResource("/" + resource); + private static URL getXmlConfigurationUrl() { + URL url = MoxoJettyRunner.class.getResource("/" + MoxoJettyRunner.CONF_JETTY_XML); if (null == url) { try { - url = new File(resource).toURL(); + url = new File(MoxoJettyRunner.CONF_JETTY_XML).toURL(); System.err.println("Loading configuration from file: " + url.toExternalForm()); } catch (MalformedURLException e) { // ignore ... blob - 15364b45c9595d79770be30f05df170501a74e69 (mode 644) blob + /dev/null --- src/main/java/com/thinkberg/moxo/ResourceManager.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2007 Matthias L. Jugel. - * - * Licensed 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 com.thinkberg.moxo; - -import org.apache.commons.vfs.FileObject; -import org.apache.commons.vfs.FileSystemException; -import org.apache.commons.vfs.FileSystemManager; -import org.apache.commons.vfs.VFS; -import org.jets3t.service.Jets3tProperties; - -/** - * The resource manager is responsible for providing a virtual file system root. - * - * @author Matthias L. Jugel - */ -public class ResourceManager { - private static FileObject root; - - static { - try { - String propertiesFileName = System.getProperty("moxo.properties", "moxo.properties"); - Jets3tProperties properties = Jets3tProperties.getInstance(propertiesFileName); - FileSystemManager fsm = VFS.getManager(); - FileObject rootObject = fsm.resolveFile("s3://" + properties.getStringProperty("bucket", null)); - root = fsm.createVirtualFileSystem(rootObject); - System.err.println("Created virtual file system: " + rootObject); - } catch (FileSystemException e) { - System.err.println("Can't create virtual file system: " + e.getMessage()); - e.printStackTrace(); - } - } - - public static FileObject getFileObject(String path) throws FileSystemException { - return root.resolveFile(path); - } -} blob - b6e185d27e3e58d31107a6a92117d79beee64682 blob + 12c455d7b8e0da5274b892269a2919198c3cace9 --- src/main/java/com/thinkberg/moxo/dav/CopyMoveBase.java +++ src/main/java/com/thinkberg/moxo/dav/CopyMoveBase.java @@ -16,7 +16,6 @@ package com.thinkberg.moxo.dav; -import com.thinkberg.moxo.ResourceManager; import com.thinkberg.moxo.dav.lock.LockException; import com.thinkberg.moxo.dav.lock.LockManager; import org.apache.commons.vfs.FileObject; @@ -35,7 +34,7 @@ public abstract class CopyMoveBase extends WebdavHandl public void service(HttpServletRequest request, HttpServletResponse response) throws IOException { boolean overwrite = getOverwrite(request); - FileObject object = ResourceManager.getFileObject(request.getPathInfo()); + FileObject object = getVFSObject(request.getPathInfo()); FileObject targetObject = getDestination(request); try { blob - 3533537d1b03790bb012ae0befe0c5539f1330a5 blob + bd7f9830c75e3fb90449db9a7f2685aeeff2e237 --- src/main/java/com/thinkberg/moxo/dav/DeleteHandler.java +++ src/main/java/com/thinkberg/moxo/dav/DeleteHandler.java @@ -16,9 +16,10 @@ package com.thinkberg.moxo.dav; -import com.thinkberg.moxo.ResourceManager; import com.thinkberg.moxo.dav.lock.LockException; import com.thinkberg.moxo.dav.lock.LockManager; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.apache.commons.vfs.FileObject; import org.apache.commons.vfs.FileSelectInfo; import org.apache.commons.vfs.FileSelector; @@ -33,6 +34,7 @@ import java.io.IOException; * @version $Id$ */ public class DeleteHandler extends WebdavHandler { + private static final Log LOG = LogFactory.getLog(DeleteHandler.class); private final static FileSelector ALL_FILES_SELECTOR = new FileSelector() { public boolean includeFile(FileSelectInfo fileSelectInfo) throws Exception { @@ -45,7 +47,7 @@ public class DeleteHandler extends WebdavHandler { }; public void service(HttpServletRequest request, HttpServletResponse response) throws IOException { - FileObject object = ResourceManager.getFileObject(request.getPathInfo()); + FileObject object = getVFSObject(request.getPathInfo()); if (request instanceof Request) { String fragment = ((Request) request).getUri().getFragment(); if (fragment != null) { @@ -66,7 +68,9 @@ public class DeleteHandler extends WebdavHandler { } if (object.exists()) { - if (object.delete(ALL_FILES_SELECTOR) > 0) { + int deletedObjects = object.delete(ALL_FILES_SELECTOR); + LOG.debug("deleted " + deletedObjects + " objects"); + if (deletedObjects > 0) { response.setStatus(HttpServletResponse.SC_OK); } else { response.sendError(HttpServletResponse.SC_FORBIDDEN); blob - bcfd04dc1bfcf5fd118934e8a0108b8e9f592b13 blob + 2d54a47a9b4dc425e1300cefea568d7718c7f90f --- src/main/java/com/thinkberg/moxo/dav/GetHandler.java +++ src/main/java/com/thinkberg/moxo/dav/GetHandler.java @@ -16,7 +16,6 @@ package com.thinkberg.moxo.dav; -import com.thinkberg.moxo.ResourceManager; import org.apache.commons.vfs.FileContent; import org.apache.commons.vfs.FileObject; import org.apache.commons.vfs.FileSystemException; @@ -35,7 +34,7 @@ import java.io.OutputStream; public class GetHandler extends WebdavHandler { public void service(HttpServletRequest request, HttpServletResponse response) throws IOException { - FileObject object = ResourceManager.getFileObject(request.getPathInfo()); + FileObject object = getVFSObject(request.getPathInfo()); if (object.exists()) { if (FileType.FOLDER.equals(object.getType())) { blob - 51fd09bff59cddb5c4212b9d20ddb56a28d8c5d3 blob + 214793924ede616c96a919382f76715c89613a58 --- src/main/java/com/thinkberg/moxo/dav/HeadHandler.java +++ src/main/java/com/thinkberg/moxo/dav/HeadHandler.java @@ -16,7 +16,6 @@ package com.thinkberg.moxo.dav; -import com.thinkberg.moxo.ResourceManager; import org.apache.commons.vfs.FileObject; import org.apache.commons.vfs.FileType; @@ -31,7 +30,7 @@ import java.io.IOException; public class HeadHandler extends GetHandler { public void service(HttpServletRequest request, HttpServletResponse response) throws IOException { - FileObject object = ResourceManager.getFileObject(request.getPathInfo()); + FileObject object = getVFSObject(request.getPathInfo()); if (object.exists()) { if (FileType.FOLDER.equals(object.getType())) { blob - 8e7e95dc2594e7ce20d4a8e2afd6b1d6729fb992 blob + d4223a80e73f36560895ea20948921ce11bb8739 --- src/main/java/com/thinkberg/moxo/dav/LockHandler.java +++ src/main/java/com/thinkberg/moxo/dav/LockHandler.java @@ -16,22 +16,21 @@ package com.thinkberg.moxo.dav; -import com.thinkberg.moxo.ResourceManager; import com.thinkberg.moxo.dav.lock.Lock; import com.thinkberg.moxo.dav.lock.LockConflictException; import com.thinkberg.moxo.dav.lock.LockException; import com.thinkberg.moxo.dav.lock.LockManager; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.apache.commons.vfs.FileObject; -import org.dom4j.Document; -import org.dom4j.DocumentException; -import org.dom4j.DocumentHelper; -import org.dom4j.Element; -import org.dom4j.Node; +import org.dom4j.*; +import org.dom4j.io.OutputFormat; import org.dom4j.io.SAXReader; import org.dom4j.io.XMLWriter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import java.io.ByteArrayOutputStream; import java.io.IOException; import java.net.URL; import java.util.Iterator; @@ -43,6 +42,8 @@ import java.util.Iterator; * @version $Id$ */ public class LockHandler extends WebdavHandler { + private static final Log LOG = LogFactory.getLog(LockHandler.class); + private static final String TAG_LOCKSCOPE = "lockscope"; private static final String TAG_LOCKTYPE = "locktype"; private static final String TAG_OWNER = "owner"; @@ -53,7 +54,7 @@ public class LockHandler extends WebdavHandler { private static final String HEADER_LOCK_TOKEN = "Lock-Token"; public void service(HttpServletRequest request, HttpServletResponse response) throws IOException { - FileObject object = ResourceManager.getFileObject(request.getPathInfo()); + FileObject object = getVFSObject(request.getPathInfo()); try { Lock lock = LockManager.getInstance().checkCondition(object, getIf(request)); @@ -91,7 +92,7 @@ public class LockHandler extends WebdavHandler { } } - log("LOCK(" + lockType + ", " + lockScope + ", " + owner + ")"); + LOG.debug("LOCK(" + lockType + ", " + lockScope + ", " + owner + ")"); Lock requestedLock = new Lock(object, lockType, lockScope, owner, getDepth(request), getTimeout(request)); try { @@ -109,6 +110,9 @@ public class LockHandler extends WebdavHandler { } private void sendLockAcquiredResponse(HttpServletResponse response, Lock lock) throws IOException { + if (!lock.getObject().exists()) { + response.setStatus(SC_CREATED); + } response.setContentType("text/xml"); response.setCharacterEncoding("UTF-8"); response.setHeader(HEADER_LOCK_TOKEN, "<" + lock.getToken() + ">"); @@ -121,6 +125,18 @@ public class LockHandler extends WebdavHandler { XMLWriter xmlWriter = new XMLWriter(response.getWriter()); xmlWriter.write(propDoc); - log(propDoc); + + logXml(propDoc); } + + private void logXml(Node element) { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + try { + XMLWriter xmlWriter = new XMLWriter(bos, OutputFormat.createPrettyPrint()); + xmlWriter.write(element); + LOG.debug(bos.toString()); + } catch (IOException e) { + LOG.debug("ERROR writing XML log: " + e.getMessage()); + } + } } blob - c7bd42b7da7d33d12157b1d0f6dac1a96b20dfbb blob + 26c2f2d817fea565d73ce19efee0bf802f26c328 --- src/main/java/com/thinkberg/moxo/dav/MkColHandler.java +++ src/main/java/com/thinkberg/moxo/dav/MkColHandler.java @@ -16,7 +16,6 @@ package com.thinkberg.moxo.dav; -import com.thinkberg.moxo.ResourceManager; import com.thinkberg.moxo.dav.lock.LockException; import com.thinkberg.moxo.dav.lock.LockManager; import org.apache.commons.vfs.FileObject; @@ -25,6 +24,7 @@ import org.apache.commons.vfs.FileType; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import java.io.BufferedReader; import java.io.IOException; /** @@ -34,12 +34,14 @@ import java.io.IOException; public class MkColHandler extends WebdavHandler { public void service(HttpServletRequest request, HttpServletResponse response) throws IOException { - if (request.getReader().readLine() != null) { + BufferedReader bufferedReader = request.getReader(); + String line = bufferedReader.readLine(); + if (line != null) { response.sendError(HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE); return; } - FileObject object = ResourceManager.getFileObject(request.getPathInfo()); + FileObject object = getVFSObject(request.getPathInfo()); try { LockManager.getInstance().checkCondition(object, getIf(request)); blob - fb5876098ccd381b67aa1aa2065a55e2ee93d7af blob + 105b947a18e598dc34be32c8564a80e80f7fa409 --- src/main/java/com/thinkberg/moxo/dav/OptionsHandler.java +++ src/main/java/com/thinkberg/moxo/dav/OptionsHandler.java @@ -16,7 +16,6 @@ package com.thinkberg.moxo.dav; -import com.thinkberg.moxo.ResourceManager; import org.apache.commons.vfs.FileObject; import org.apache.commons.vfs.FileType; @@ -35,7 +34,7 @@ public class OptionsHandler extends WebdavHandler { String path = request.getPathInfo(); StringBuffer options = new StringBuffer(); - FileObject object = ResourceManager.getFileObject(path); + FileObject object = getVFSObject(path); if (object.exists()) { options.append("OPTIONS, GET, HEAD, POST, DELETE, TRACE, COPY, MOVE, LOCK, UNLOCK, PROPFIND"); if (FileType.FOLDER.equals(object.getType())) { blob - 169c09204e05f26f192ab23f7ad567443352bb55 blob + 9f8b33f2d2f8c952a1dba98b56c888dad88670b3 --- src/main/java/com/thinkberg/moxo/dav/PropFindHandler.java +++ src/main/java/com/thinkberg/moxo/dav/PropFindHandler.java @@ -16,22 +16,21 @@ package com.thinkberg.moxo.dav; -import com.thinkberg.moxo.ResourceManager; import com.thinkberg.moxo.dav.data.DavResource; import com.thinkberg.moxo.dav.data.DavResourceFactory; import com.thinkberg.moxo.vfs.DepthFileSelector; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.apache.commons.vfs.FileObject; import org.apache.commons.vfs.FileSystemException; -import org.dom4j.Document; -import org.dom4j.DocumentException; -import org.dom4j.DocumentHelper; -import org.dom4j.Element; +import org.dom4j.*; import org.dom4j.io.OutputFormat; import org.dom4j.io.SAXReader; import org.dom4j.io.XMLWriter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import java.io.ByteArrayOutputStream; import java.io.IOException; import java.net.URL; import java.util.ArrayList; @@ -48,12 +47,26 @@ public class PropFindHandler extends WebdavHandler { private static final String TAG_MULTISTATUS = "multistatus"; private static final String TAG_HREF = "href"; private static final String TAG_RESPONSE = "response"; + private static final Log LOG = LogFactory.getLog(PropFindHandler.class); + void logXml(Node element) { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + try { + XMLWriter xmlWriter = new XMLWriter(bos, OutputFormat.createPrettyPrint()); + xmlWriter.write(element); + LOG.debug(bos.toString()); + } catch (IOException e) { + LOG.error(e.getMessage()); + } + } + + public void service(HttpServletRequest request, HttpServletResponse response) throws IOException { SAXReader saxReader = new SAXReader(); try { Document propDoc = saxReader.read(request.getInputStream()); - // log(propDoc); + logXml(propDoc); + Element propFindEl = propDoc.getRootElement(); Element propEl = (Element) propFindEl.elementIterator().next(); String propElName = propEl.getName(); @@ -71,7 +84,7 @@ public class PropFindHandler extends WebdavHandler { ignoreValues = true; } - FileObject object = ResourceManager.getFileObject(request.getPathInfo()); + FileObject object = getVFSObject(request.getPathInfo()); if (object.exists()) { // respond as XML encoded multi status response.setContentType("text/xml"); @@ -84,7 +97,7 @@ public class PropFindHandler extends WebdavHandler { getBaseUrl(request), getDepth(request), ignoreValues); - //log(multiStatusResponse); + logXml(multiStatusResponse); // write the actual response XMLWriter writer = new XMLWriter(response.getWriter(), OutputFormat.createCompactFormat()); @@ -93,15 +106,16 @@ public class PropFindHandler extends WebdavHandler { writer.close(); } else { - log("!! " + object.getName().getPath() + " NOT FOUND"); + LOG.error(object.getName().getPath() + " NOT FOUND"); response.sendError(HttpServletResponse.SC_NOT_FOUND); } } catch (DocumentException e) { - log("!! inavlid request: " + e.getMessage()); + LOG.error("invalid request: " + e.getMessage()); response.sendError(HttpServletResponse.SC_BAD_REQUEST); } } + @SuppressWarnings({"ConstantConditions"}) private Document getMultiStatusRespons(FileObject object, List requestedProperties, URL baseUrl, @@ -116,7 +130,7 @@ public class PropFindHandler extends WebdavHandler { Element responseEl = multiStatus.addElement(TAG_RESPONSE); try { URL url = new URL(baseUrl, URLEncoder.encode(child.getName().getPath(), "UTF-8")); - log("!! " + url); + LOG.debug(url); responseEl.addElement(TAG_HREF).addText(url.toExternalForm()); } catch (Exception e) { e.printStackTrace(); blob - 9848117271155f8ff4227471f202c991479dffba blob + 47200c23bde07c62df6a59cebb06f1d458fe4661 --- src/main/java/com/thinkberg/moxo/dav/PropPatchHandler.java +++ src/main/java/com/thinkberg/moxo/dav/PropPatchHandler.java @@ -16,10 +16,11 @@ package com.thinkberg.moxo.dav; -import com.thinkberg.moxo.ResourceManager; import com.thinkberg.moxo.dav.data.DavResource; import com.thinkberg.moxo.dav.lock.LockException; import com.thinkberg.moxo.dav.lock.LockManager; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.apache.commons.vfs.FileObject; import org.dom4j.Document; import org.dom4j.DocumentException; @@ -42,8 +43,10 @@ import java.util.List; * @author Matthias L. Jugel */ public class PropPatchHandler extends WebdavHandler { + private static final Log LOG = LogFactory.getLog(PropPatchHandler.class); + public void service(HttpServletRequest request, HttpServletResponse response) throws IOException { - FileObject object = ResourceManager.getFileObject(request.getPathInfo()); + FileObject object = getVFSObject(request.getPathInfo()); try { LockManager.getInstance().checkCondition(object, getIf(request)); @@ -71,7 +74,7 @@ public class PropPatchHandler extends WebdavHandler { Element responseEl = multiStatusResponse.addElement("response"); try { URL url = new URL(getBaseUrl(request), URLEncoder.encode(object.getName().getPath(), "UTF-8")); - log("!! " + url); + LOG.debug(url); responseEl.addElement("href").addText(url.toExternalForm()); } catch (Exception e) { e.printStackTrace(); @@ -103,11 +106,11 @@ public class PropPatchHandler extends WebdavHandler { writer.flush(); writer.close(); } else { - log("!! " + object.getName().getPath() + " NOT FOUND"); + LOG.error(object.getName().getPath() + " NOT FOUND"); response.sendError(HttpServletResponse.SC_NOT_FOUND); } } catch (DocumentException e) { - log("!! inavlid request: " + e.getMessage()); + LOG.error("invalid request: " + e.getMessage()); response.sendError(HttpServletResponse.SC_BAD_REQUEST); } } blob - 7a8e901869c402cbbb6c27b78bb16ebe5cec3292 blob + fc92a3d6e348a399694d0d684681d25c85f99d27 --- src/main/java/com/thinkberg/moxo/dav/PutHandler.java +++ src/main/java/com/thinkberg/moxo/dav/PutHandler.java @@ -16,9 +16,10 @@ package com.thinkberg.moxo.dav; -import com.thinkberg.moxo.ResourceManager; import com.thinkberg.moxo.dav.lock.LockException; import com.thinkberg.moxo.dav.lock.LockManager; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.apache.commons.vfs.FileObject; import org.apache.commons.vfs.FileType; @@ -33,8 +34,10 @@ import java.io.OutputStream; * @version $Id$ */ public class PutHandler extends WebdavHandler { + private static final Log LOG = LogFactory.getLog(PutHandler.class); + public void service(HttpServletRequest request, HttpServletResponse response) throws IOException { - FileObject object = ResourceManager.getFileObject(request.getPathInfo()); + FileObject object = getVFSObject(request.getPathInfo()); try { LockManager.getInstance().checkCondition(object, getIf(request)); @@ -66,8 +69,8 @@ public class PutHandler extends WebdavHandler { InputStream is = request.getInputStream(); OutputStream os = object.getContent().getOutputStream(); - log("PUT sends " + request.getHeader("Content-length") + " bytes"); - log("PUT copied " + Util.copyStream(is, os) + " bytes"); + int bytesCopied = Util.copyStream(is, os); + LOG.debug("sending " + bytesCopied + "/" + request.getHeader("Content-length") + " bytes"); os.flush(); object.close(); blob - 7e66661da892e8d3514f76702c740496e62ced5d blob + cdf9f6df05dd32310e05a5e0ab104c03779b15ea --- src/main/java/com/thinkberg/moxo/dav/URLEncoder.java +++ src/main/java/com/thinkberg/moxo/dav/URLEncoder.java @@ -26,7 +26,7 @@ import java.util.BitSet; */ class URLEncoder { - private static BitSet keepPlain; + private static final BitSet keepPlain; static { keepPlain = new BitSet(256); @@ -50,7 +50,6 @@ class URLEncoder { } - @SuppressWarnings({"SameParameterValue"}) public static String encode(String s, String enc) throws UnsupportedEncodingException { byte[] buf = s.getBytes(enc); StringBuffer result = new StringBuffer(); blob - c9b1dbfa79cede571c23e5fbce3af2951df4c49e blob + e9810818ac9e79873202dae184ec9ad09b813804 --- src/main/java/com/thinkberg/moxo/dav/UnlockHandler.java +++ src/main/java/com/thinkberg/moxo/dav/UnlockHandler.java @@ -16,8 +16,9 @@ package com.thinkberg.moxo.dav; -import com.thinkberg.moxo.ResourceManager; import com.thinkberg.moxo.dav.lock.LockManager; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.apache.commons.vfs.FileObject; import javax.servlet.http.HttpServletRequest; @@ -29,12 +30,13 @@ import java.io.IOException; * @version $Id$ */ public class UnlockHandler extends WebdavHandler { + private static final Log LOG = LogFactory.getLog(UnlockHandler.class); public void service(HttpServletRequest request, HttpServletResponse response) throws IOException { - FileObject object = ResourceManager.getFileObject(request.getPathInfo()); + FileObject object = getVFSObject(request.getPathInfo()); String lockTokenHeader = request.getHeader("Lock-Token"); String lockToken = lockTokenHeader.substring(1, lockTokenHeader.length() - 1); - log("UNLOCK(" + lockToken + ")"); + LOG.debug("UNLOCK(" + lockToken + ")"); if (LockManager.getInstance().releaseLock(object, lockToken)) { response.setStatus(HttpServletResponse.SC_NO_CONTENT); blob - 635e944e7bab4630c048790a9115f02f07481a7c blob + 6cc9911ce6b996e0c0610c4987c090772f356817 --- src/main/java/com/thinkberg/moxo/dav/Util.java +++ src/main/java/com/thinkberg/moxo/dav/Util.java @@ -36,7 +36,7 @@ public class Util { } // public static String getISODateString(long time) { -// return ""; +// return ""; 4 // } blob - a74e1a9ff4bbc10d2647532ca2252c2a48acd7c8 blob + bb559777fd0928f6c9ee3f7bb12b897d76ffc0d7 --- src/main/java/com/thinkberg/moxo/dav/WebdavHandler.java +++ src/main/java/com/thinkberg/moxo/dav/WebdavHandler.java @@ -16,17 +16,16 @@ package com.thinkberg.moxo.dav; -import com.thinkberg.moxo.ResourceManager; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.apache.commons.vfs.FileObject; import org.apache.commons.vfs.FileSystemException; -import org.dom4j.Node; -import org.dom4j.io.OutputFormat; -import org.dom4j.io.XMLWriter; +import org.apache.commons.vfs.FileSystemManager; +import org.apache.commons.vfs.VFS; +import org.jets3t.service.Jets3tProperties; -import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import java.io.ByteArrayOutputStream; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; @@ -37,34 +36,35 @@ import java.util.Arrays; * @version $Id$ */ public abstract class WebdavHandler { + private static final Log LOG = LogFactory.getLog(WebdavHandler.class); + + static final int SC_CREATED = 201; static final int SC_LOCKED = 423; static final int SC_MULTI_STATUS = 207; - private HttpServlet servlet; + private static FileObject fileSystemRoot; - public void setServlet(HttpServlet servlet) { - this.servlet = servlet; - } - - public abstract void service(HttpServletRequest request, HttpServletResponse response) throws IOException; - - void log(Node element) { - ByteArrayOutputStream bos = new ByteArrayOutputStream(); + static { try { - XMLWriter xmlWriter = new XMLWriter(bos, OutputFormat.createPrettyPrint()); - xmlWriter.write(element); - System.out.print(bos.toString()); - } catch (IOException e) { - servlet.log("!! " + e.getMessage()); + String propertiesFileName = System.getProperty("moxo.properties", "moxo.properties"); + Jets3tProperties properties = Jets3tProperties.getInstance(propertiesFileName); + FileSystemManager fsm = VFS.getManager(); + + // create a virtual filesystemusing the url provided or fall back to RAM + fileSystemRoot = fsm.resolveFile(properties.getStringProperty("vfs.url", "ram:/")); + + LOG.info("created virtual file system: " + fileSystemRoot); + } catch (FileSystemException e) { + LOG.error("can't create virtual file system: " + e.getMessage()); + e.printStackTrace(); } } - void log(String message) { - servlet.log("## " + message); + protected static FileObject getVFSObject(String path) throws FileSystemException { + return fileSystemRoot.resolveFile(path); } - - static URL getBaseUrl(HttpServletRequest request) { + protected static URL getBaseUrl(HttpServletRequest request) { try { String requestUrl = request.getRequestURL().toString(); String requestUri = request.getRequestURI(); @@ -76,6 +76,7 @@ public abstract class WebdavHandler { return null; } + public abstract void service(HttpServletRequest request, HttpServletResponse response) throws IOException; /** * Get the depth header value. This value defines how operations @@ -96,7 +97,7 @@ public abstract class WebdavHandler { depthValue = Integer.parseInt(depth); } - log("Depth: " + depthValue); + LOG.debug("request header: Depth: " + (depthValue == Integer.MAX_VALUE ? "infinity" : depthValue)); return depthValue; } @@ -110,7 +111,8 @@ public abstract class WebdavHandler { boolean getOverwrite(HttpServletRequest request) { String overwrite = request.getHeader("Overwrite"); boolean overwriteValue = overwrite == null || "T".equals(overwrite); - log("Overwrite: " + overwriteValue); + + LOG.debug("request header: Overwrite: " + overwriteValue); return overwriteValue; } @@ -128,8 +130,8 @@ public abstract class WebdavHandler { FileObject targetObject = null; if (null != targetUrlStr) { URL target = new URL(targetUrlStr); - targetObject = ResourceManager.getFileObject(target.getPath()); - log("Destination: " + targetObject.getName().getPath()); + targetObject = getVFSObject(target.getPath()); + LOG.debug("request header: Destination: " + targetObject.getName().getPath()); } return targetObject; @@ -142,7 +144,12 @@ public abstract class WebdavHandler { * @return the value if the If: header. */ String getIf(HttpServletRequest request) { - return request.getHeader("If"); + String getIfHeader = request.getHeader("If"); + + if (null != getIfHeader) { + LOG.debug("request header: If: " + getIfHeader); + } + return getIfHeader; } /** @@ -155,7 +162,7 @@ public abstract class WebdavHandler { String timeout = request.getHeader("Timeout"); if (null != timeout) { String[] timeoutValues = timeout.split(",[ ]*"); - log(Arrays.asList(timeoutValues).toString()); + LOG.debug("request header: Timeout: " + Arrays.asList(timeoutValues).toString()); if ("infinity".equalsIgnoreCase(timeoutValues[0])) { return -1; } else { blob - 4356ce41848ea62de23b8a036e7aea950df89046 blob + 82ec809f38ec9a22f32b81ba769787173ef5df2d --- src/main/java/com/thinkberg/moxo/dav/data/AbstractDavResource.java +++ src/main/java/com/thinkberg/moxo/dav/data/AbstractDavResource.java @@ -35,7 +35,6 @@ public abstract class AbstractDavResource { private static final String TAG_PROP = "prop"; private static final String TAG_STATUS = "status"; - @SuppressWarnings({"UnusedReturnValue"}) public Element serializeToXml(Element root, List requestedProperties) { Element propStatEl = root.addElement(TAG_PROPSTAT); Element propEl = propStatEl.addElement(TAG_PROP); @@ -61,5 +60,6 @@ public abstract class AbstractDavResource { return root; } + @SuppressWarnings({"BooleanMethodIsAlwaysInverted"}) protected abstract boolean addPropertyValue(Element root, String propertyName); } blob - 918da1c04a6de60ad3be17615e2e920da8a2975b blob + fcd185c553c3e877a601f195e39e4d1687e16c32 --- src/main/java/com/thinkberg/moxo/dav/data/DavCollection.java +++ src/main/java/com/thinkberg/moxo/dav/data/DavCollection.java @@ -71,7 +71,7 @@ public class DavCollection extends DavResource { } protected boolean addQuotaProperty(Element root) { - root.addElement(PROP_QUOTA).addText("1000000"); + root.addElement(PROP_QUOTA).addText("" + Long.MAX_VALUE); return true; } @@ -82,7 +82,7 @@ public class DavCollection extends DavResource { } protected boolean addQuotaAvailableBytesProperty(Element root) { - root.addElement(PROP_QUOTA_AVAILABLE_BYTES).addText("1000000"); + root.addElement(PROP_QUOTA_AVAILABLE_BYTES).addText("" + Long.MAX_VALUE); return true; } blob - 220a25349e7c8e941c9ae4944459052216833000 blob + 60ddbc7d9240cdb82e2d97eba5c93761a077ca9d --- src/main/java/com/thinkberg/moxo/dav/data/DavResource.java +++ src/main/java/com/thinkberg/moxo/dav/data/DavResource.java @@ -30,7 +30,6 @@ import java.util.List; * @author Matthias L. Jugel * @version $Id$ */ -@SuppressWarnings({"SameReturnValue"}) public class DavResource extends AbstractDavResource { // @see http://www.webdav.org/specs/rfc2518.html#dav.properties @@ -64,11 +63,12 @@ public class DavResource extends AbstractDavResource { PROP_LOCK_DISCOVERY, PROP_RESOURCETYPE, PROP_SOURCE, - PROP_SUPPORTED_LOCK + PROP_SUPPORTED_LOCK, + PROP_QUOTA_AVAILABLE_BYTES ); - private final FileObject object; - private boolean ignoreValues = false; + protected final FileObject object; + protected boolean ignoreValues = false; public DavResource(FileObject object) { this(object, false); @@ -138,12 +138,10 @@ public class DavResource extends AbstractDavResource { return false; } - @SuppressWarnings({"WeakerAccess", "UnusedParameters"}) protected boolean addCreationDateProperty(Element root) { return false; } - @SuppressWarnings({"WeakerAccess"}) protected boolean addGetDisplayNameProperty(Element root) { Element el = root.addElement(PROP_DISPLAY_NAME); if (!ignoreValues) { @@ -152,12 +150,10 @@ public class DavResource extends AbstractDavResource { return true; } - @SuppressWarnings({"WeakerAccess", "UnusedParameters"}) protected boolean addGetContentLanguageProperty(Element root) { return false; } - @SuppressWarnings({"WeakerAccess"}) protected boolean addGetContentLengthProperty(Element root) { try { Element el = root.addElement(PROP_GET_CONTENT_LENGTH); @@ -171,7 +167,6 @@ public class DavResource extends AbstractDavResource { } } - @SuppressWarnings({"WeakerAccess"}) protected boolean addGetContentTypeProperty(Element root) { try { String contentType = object.getContent().getContentInfo().getContentType(); @@ -190,12 +185,10 @@ public class DavResource extends AbstractDavResource { } } - @SuppressWarnings({"WeakerAccess", "UnusedParameters"}) protected boolean addGetETagProperty(Element root) { return false; } - @SuppressWarnings({"WeakerAccess"}) protected boolean addGetLastModifiedProperty(Element root) { try { Element el = root.addElement(PROP_GET_LAST_MODIFIED); @@ -209,7 +202,6 @@ public class DavResource extends AbstractDavResource { } } - @SuppressWarnings({"WeakerAccess"}) protected boolean addLockDiscoveryProperty(Element root) { Element lockdiscoveryEl = root.addElement(PROP_LOCK_DISCOVERY); try { @@ -229,18 +221,15 @@ public class DavResource extends AbstractDavResource { } } - @SuppressWarnings({"WeakerAccess"}) protected boolean addResourceTypeProperty(Element root) { root.addElement(PROP_RESOURCETYPE); return true; } - @SuppressWarnings({"WeakerAccess", "UnusedParameters"}) protected boolean addSourceProperty(Element root) { return false; } - @SuppressWarnings({"WeakerAccess"}) protected boolean addSupportedLockProperty(Element root) { Element supportedlockEl = root.addElement(PROP_SUPPORTED_LOCK); if (!ignoreValues) { @@ -255,22 +244,18 @@ public class DavResource extends AbstractDavResource { return true; } - @SuppressWarnings({"WeakerAccess"}) protected boolean addQuotaProperty(Element root) { return false; } - @SuppressWarnings({"WeakerAccess"}) protected boolean addQuotaUsedProperty(Element root) { return false; } - @SuppressWarnings({"WeakerAccess"}) protected boolean addQuotaAvailableBytesProperty(Element root) { return false; } - @SuppressWarnings({"WeakerAccess"}) protected boolean addQuotaUsedBytesProperty(Element root) { return false; } blob - 44f4c9aaa4abefb4b0565650ccaa2960ed875225 blob + 28d71a7844d3ecca4d5bc448fb9e7c6e47913291 --- src/main/java/com/thinkberg/moxo/dav/lock/Lock.java +++ src/main/java/com/thinkberg/moxo/dav/lock/Lock.java @@ -72,7 +72,6 @@ public class Lock { return depth; } - @SuppressWarnings({"WeakerAccess"}) public String getDepthValue() { switch (depth) { case 0: @@ -84,7 +83,6 @@ public class Lock { } } - @SuppressWarnings({"WeakerAccess"}) public String getTimeout() { if (timeout == -1) { return "Infinity"; @@ -103,7 +101,6 @@ public class Lock { * @param root the root element to add the activelock to * @return the root element */ - @SuppressWarnings({"UnusedReturnValue"}) public Element serializeToXml(Element root) { Element activelockEl = root.addElement("activelock"); activelockEl.addElement("locktype").addElement(getType()); @@ -130,7 +127,7 @@ public class Lock { * @return whether this lock is for the same file object */ public boolean equals(Object other) { - return object.equals(((Lock) other).object); + return other instanceof Lock && object.equals(((Lock) other).object); } blob - ee85960287fcb8693e420e89092915792c5c13e3 (mode 644) blob + /dev/null --- src/main/java/com/thinkberg/moxo/servlet/MoxoS3WebdavServlet.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright 2007 Matthias L. Jugel. - * - * Licensed 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 com.thinkberg.moxo.servlet; - -import com.thinkberg.moxo.dav.CopyHandler; -import com.thinkberg.moxo.dav.DeleteHandler; -import com.thinkberg.moxo.dav.GetHandler; -import com.thinkberg.moxo.dav.HeadHandler; -import com.thinkberg.moxo.dav.LockHandler; -import com.thinkberg.moxo.dav.MkColHandler; -import com.thinkberg.moxo.dav.MoveHandler; -import com.thinkberg.moxo.dav.OptionsHandler; -import com.thinkberg.moxo.dav.PostHandler; -import com.thinkberg.moxo.dav.PropFindHandler; -import com.thinkberg.moxo.dav.PropPatchHandler; -import com.thinkberg.moxo.dav.PutHandler; -import com.thinkberg.moxo.dav.UnlockHandler; -import com.thinkberg.moxo.dav.WebdavHandler; -import org.mortbay.jetty.Response; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; - -/** - * @author Matthias L. Jugel - * @version $Id$ - */ -public class MoxoS3WebdavServlet extends HttpServlet { - private final Map handlers = new HashMap(); - - public MoxoS3WebdavServlet() { - handlers.put("COPY", new CopyHandler()); - handlers.put("DELETE", new DeleteHandler()); - handlers.put("GET", new GetHandler()); - handlers.put("HEAD", new HeadHandler()); - handlers.put("LOCK", new LockHandler()); - handlers.put("MKCOL", new MkColHandler()); - handlers.put("MOVE", new MoveHandler()); - handlers.put("OPTIONS", new OptionsHandler()); - handlers.put("POST", new PostHandler()); - handlers.put("PROPFIND", new PropFindHandler()); - handlers.put("PROPPATCH", new PropPatchHandler()); - handlers.put("PUT", new PutHandler()); - handlers.put("UNLOCK", new UnlockHandler()); - - for (WebdavHandler handler : handlers.values()) { - handler.setServlet(this); - } - } - - public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { - String method = request.getMethod(); - log(">> " + request.getMethod() + " " + request.getPathInfo()); - if (request.getHeader("X-Litmus") != null) { - log("!! " + request.getHeader("X-Litmus")); - } - if (handlers.containsKey(method)) { - handlers.get(method).service(request, response); - } else { - response.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED); - } - Response jettyResponse = ((Response) response); - String reason = jettyResponse.getReason(); - log("<< " + jettyResponse.getStatus() + (reason != null ? ": " + reason : "")); - } -} blob - /dev/null blob + c8a306a053d53a8a29bdcfae8a10e3c852f7f3b0 (mode 644) --- /dev/null +++ src/main/java/com/thinkberg/moxo/servlet/MoxoWebDAVServlet.java @@ -0,0 +1,95 @@ +/* + * Copyright 2007 Matthias L. Jugel. + * + * Licensed 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 com.thinkberg.moxo.servlet; + +import com.thinkberg.moxo.dav.*; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.commons.vfs.FileObject; +import org.mortbay.jetty.Response; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +/** + * @author Matthias L. Jugel + * @version $Id$ + */ +public class MoxoWebDAVServlet extends HttpServlet { + private static final Log LOG = LogFactory.getLog(MoxoWebDAVServlet.class); + + private final Map handlers = new HashMap(); + private FileObject fileSystemRoot = null; + + public MoxoWebDAVServlet() { + handlers.put("COPY", new CopyHandler()); + handlers.put("DELETE", new DeleteHandler()); + handlers.put("GET", new GetHandler()); + handlers.put("HEAD", new HeadHandler()); + handlers.put("LOCK", new LockHandler()); + handlers.put("MKCOL", new MkColHandler()); + handlers.put("MOVE", new MoveHandler()); + handlers.put("OPTIONS", new OptionsHandler()); + handlers.put("POST", new PostHandler()); + handlers.put("PROPFIND", new PropFindHandler()); + handlers.put("PROPPATCH", new PropPatchHandler()); + handlers.put("PUT", new PutHandler()); + handlers.put("UNLOCK", new UnlockHandler()); + } + + protected FileObject getFileSystemRoot() { + return fileSystemRoot; + } + + public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { +// String auth = request.getHeader("Authorization"); +// String login = "", password = ""; +// +// if (auth != null) { +// auth = new String(Base64.decodeBase64(auth.substring(auth.indexOf(' ') + 1).getBytes())); +// login = auth.substring(0, auth.indexOf(':')); +// password = auth.substring(auth.indexOf(':') + 1); +// } +// +// AWSCredentials credentials = AWSCredentials.load(password, )) +// if (user == null) { +// response.setHeader("WWW-Authenticate", "Basic realm=\"Moxo\""); +// response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); +// return; +// } + + + String method = request.getMethod(); + if (request.getHeader("X-Litmus") != null) { + LOG.info(String.format("WebDAV Litmus Test: %s", request.getHeader("X-Litmus"))); + } + LOG.debug(String.format(">> %s %s", request.getMethod(), request.getPathInfo())); + if (handlers.containsKey(method)) { + handlers.get(method).service(request, response); + } else { + response.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED); + } + Response jettyResponse = ((Response) response); + String reason = jettyResponse.getReason(); + LOG.debug(String.format("<< %s (%b%s)", request.getMethod(), jettyResponse.getStatus(), reason != null ? ": " + reason : "")); + } +} blob - c955d451826291a42e1b6aac6197ae8efee01db4 blob + 6e622e49ceb530d686040b60ba8b310b252b7d62 --- src/main/java/com/thinkberg/moxo/vfs/DepthFileSelector.java +++ src/main/java/com/thinkberg/moxo/vfs/DepthFileSelector.java @@ -47,7 +47,6 @@ public class DepthFileSelector implements FileSelector this(0, depth); } - @SuppressWarnings({"SameParameterValue"}) public DepthFileSelector(int min, int max) { minDepth = min; maxDepth = max; blob - 5768fc6965485ff468abf9e84001279acbb70358 blob + 1dd702d68b6fbe36e2acde95debb98faa1b29a0f --- src/main/java/com/thinkberg/moxo/vfs/S3FileName.java +++ src/main/java/com/thinkberg/moxo/vfs/S3FileName.java @@ -23,7 +23,6 @@ import org.apache.commons.vfs.provider.local.LocalFile * @author Matthias L. Jugel */ public class S3FileName extends LocalFileName { - @SuppressWarnings({"WeakerAccess"}) protected S3FileName(final String scheme, final String rootFile, final String path, final FileType type) { super(scheme, rootFile, path, type); } blob - 9c5d272ffd3f18b369af876efa3fa7762060d730 blob + 34a5d56d0239c568932ce009f30c10cda2b451c7 --- src/main/java/com/thinkberg/moxo/vfs/S3FileNameParser.java +++ src/main/java/com/thinkberg/moxo/vfs/S3FileNameParser.java @@ -37,7 +37,6 @@ public class S3FileNameParser extends AbstractFileName } - public FileName parseUri(final VfsComponentContext context, final FileName base, final String filename) throws FileSystemException { StringBuffer name = new StringBuffer(); blob - 1f34a86342e7cb4329618df20eb9bd5c024e96ca blob + 8caafbfd75cd2ba1fa4dbd73d893b8cd3df66fd1 --- src/main/java/com/thinkberg/moxo/vfs/S3FileProvider.java +++ src/main/java/com/thinkberg/moxo/vfs/S3FileProvider.java @@ -16,11 +16,7 @@ package com.thinkberg.moxo.vfs; -import org.apache.commons.vfs.Capability; -import org.apache.commons.vfs.FileName; -import org.apache.commons.vfs.FileSystem; -import org.apache.commons.vfs.FileSystemException; -import org.apache.commons.vfs.FileSystemOptions; +import org.apache.commons.vfs.*; import org.apache.commons.vfs.provider.AbstractOriginatingFileProvider; import java.util.Arrays; @@ -35,7 +31,7 @@ import java.util.Collections; */ public class S3FileProvider extends AbstractOriginatingFileProvider { - public final static Collection capabilities = Collections.unmodifiableCollection(Arrays.asList( + public final static Collection capabilities = Collections.unmodifiableCollection(Arrays.asList( Capability.CREATE, Capability.DELETE, Capability.RENAME, @@ -53,7 +49,6 @@ public class S3FileProvider extends AbstractOriginatin )); - public S3FileProvider() { super(); setFileNameParser(S3FileNameParser.getInstance()); blob - 8352c585cb21de0f0c73b65170f9e14120ae23b0 blob + 1f080072887e8f54191f85b14ae1e3d922de11bc --- src/main/java/com/thinkberg/moxo/vfs/jets3t/Jets3tConnector.java +++ src/main/java/com/thinkberg/moxo/vfs/jets3t/Jets3tConnector.java @@ -16,6 +16,8 @@ package com.thinkberg.moxo.vfs.jets3t; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.jets3t.service.Jets3tProperties; import org.jets3t.service.S3Service; import org.jets3t.service.S3ServiceException; @@ -26,6 +28,8 @@ import org.jets3t.service.security.AWSCredentials; * @author Matthias L. Jugel */ public class Jets3tConnector { + private static final Log LOG = LogFactory.getLog(Jets3tConnector.class); + private static final String APPLICATION_DESCRIPTION = "S3 VFS Connector/1.0"; private static Jets3tConnector instance; @@ -54,7 +58,6 @@ public class Jets3tConnector { * if the service cannot be accessed */ private Jets3tConnector() throws S3ServiceException { - System.err.print("Authenticated to Amazon S3: "); String propertiesFileName = System.getProperty("moxo.properties", "moxo.properties"); Jets3tProperties properties = Jets3tProperties.getInstance(propertiesFileName); @@ -62,13 +65,14 @@ public class Jets3tConnector { throw new S3ServiceException("can't find S3 configuration: " + propertiesFileName); } + AWSCredentials awsCredentials = new AWSCredentials( properties.getStringProperty("accesskey", null), properties.getStringProperty("secretkey", null)); service = new RestS3Service(awsCredentials, APPLICATION_DESCRIPTION, null); - System.err.println("OK"); + LOG.info("S3 authentication succeeded"); } public S3Service getService() { blob - f5fd3a29646ca8af31028d47e7e86e0dec740e6d blob + e5e4ff824521e982ee015ee38c6ab14d746cbc0a --- src/main/java/com/thinkberg/moxo/vfs/jets3t/Jets3tFileObject.java +++ src/main/java/com/thinkberg/moxo/vfs/jets3t/Jets3tFileObject.java @@ -16,91 +16,116 @@ package com.thinkberg.moxo.vfs.jets3t; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.apache.commons.vfs.FileName; import org.apache.commons.vfs.FileObject; -import org.apache.commons.vfs.FileSystemException; import org.apache.commons.vfs.FileType; import org.apache.commons.vfs.provider.AbstractFileObject; +import org.apache.commons.vfs.util.MonitorOutputStream; +import org.jets3t.service.Constants; import org.jets3t.service.S3Service; import org.jets3t.service.S3ServiceException; import org.jets3t.service.model.S3Bucket; import org.jets3t.service.model.S3Object; import org.jets3t.service.utils.Mimetypes; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.RandomAccessFile; +import java.io.*; import java.nio.channels.Channels; import java.nio.channels.FileChannel; import java.nio.channels.ReadableByteChannel; import java.util.Date; + /** * Implementation of the virtual S3 file system object using the Jets3t library. * * @author Matthias L. Jugel */ public class Jets3tFileObject extends AbstractFileObject { + private static final Log LOG = LogFactory.getLog(Jets3tFileObject.class); + + private static final String VFS_LAST_MODIFIED_TIME = "vfs-last-modified-time"; + private final S3Service service; private final S3Bucket bucket; private boolean attached = false; - private boolean changed = false; + private boolean dirty = false; + private boolean contentCached = false; + private S3Object object; private File cacheFile; public Jets3tFileObject(FileName fileName, Jets3tFileSystem fileSystem, - S3Service service, S3Bucket bucket) - throws FileSystemException { + S3Service service, S3Bucket bucket) { super(fileName, fileSystem); this.service = service; this.bucket = bucket; } + /** + * Attach S3 Object to VFS object. + * This method only downloads the meta-data without the actual content. + * If the object does not exist, it will be created locally. + * + * @throws Exception if the S3 access fails for some reason + */ protected void doAttach() throws Exception { if (!attached) { try { - object = service.getObject(bucket, getS3Key()); - System.err.println("Attached file to S3 Object: " + object); - InputStream is = object.getDataInputStream(); - if (object.getContentLength() > 0) { - ReadableByteChannel rbc = Channels.newChannel(is); - FileChannel cacheFc = getCacheFileChannel(); - cacheFc.transferFrom(rbc, 0, object.getContentLength()); - cacheFc.close(); - rbc.close(); - } else { - is.close(); + object = service.getObjectDetails(bucket, getS3Key()); + if (object.getMetadata(VFS_LAST_MODIFIED_TIME) == null) { + // it is possible the bucket has no last-modified data, use the S3 data then + object.addMetadata(Constants.REST_METADATA_PREFIX + VFS_LAST_MODIFIED_TIME, "" + object.getLastModifiedDate().getTime()); } + contentCached = false; + dirty = false; + + LOG.debug(String.format("attaching (existing) '%s'", object.getKey())); } catch (S3ServiceException e) { object = new S3Object(bucket, getS3Key()); - object.setLastModifiedDate(new Date()); - System.err.println("Attached file to new S3 Object: " + object); + object.addMetadata(Constants.REST_METADATA_PREFIX + VFS_LAST_MODIFIED_TIME, "" + new Date().getTime()); + contentCached = true; + dirty = true; + + LOG.debug(String.format("attaching (new) '%s'", object.getKey())); } + attached = true; } } protected void doDetach() throws Exception { - // TODO do not send immediately but put in some kind of upload queue - if (attached && changed) { - System.err.println("Detaching changed object: " + object); + if (attached) { + LOG.debug(String.format("detaching '%s' (dirty=%b, cached=%b)", object.getKey(), dirty, (cacheFile != null))); + object = null; if (cacheFile != null) { - FileChannel cacheFc = getCacheFileChannel(); - object.setContentLength(cacheFc.size()); - object.setDataInputStream(getInputStream()); + cacheFile.delete(); + cacheFile = null; + contentCached = false; } - System.err.println(object); - service.putObject(bucket, object); + dirty = false; attached = false; } } protected void doDelete() throws Exception { + // do not delete the root folder + if ("".equals(object.getKey())) { + LOG.warn(String.format("ignored attempt to delete root folder '%s' ", bucket.getName())); + return; + } + LOG.debug(String.format("deleting '%s'", object.getKey())); service.deleteObject(bucket, object.getKey()); + if (cacheFile != null) { + cacheFile.delete(); + cacheFile = null; + contentCached = false; + } + dirty = false; + attached = false; } protected void doRename(FileObject newfile) throws Exception { @@ -110,27 +135,63 @@ public class Jets3tFileObject extends AbstractFileObje protected void doCreateFolder() throws Exception { if (!Mimetypes.MIMETYPE_JETS3T_DIRECTORY.equals(object.getContentType())) { object.setContentType(Mimetypes.MIMETYPE_JETS3T_DIRECTORY); + + LOG.debug(String.format("creating folder '%s'", object.getKey())); service.putObject(bucket, object); - changed = false; } } protected long doGetLastModifiedTime() throws Exception { - return object.getLastModifiedDate().getTime(); + String timeStamp = (String) object.getMetadata(VFS_LAST_MODIFIED_TIME); + if (null != timeStamp) { + return Long.parseLong(timeStamp); + } + return 0; } protected void doSetLastModifiedTime(final long modtime) throws Exception { - changed = true; - object.setLastModifiedDate(new Date(modtime)); + object.addMetadata(Constants.REST_METADATA_PREFIX + VFS_LAST_MODIFIED_TIME, modtime); + dirty = true; } protected InputStream doGetInputStream() throws Exception { - return Channels.newInputStream(getCacheFileChannel()); + if (!contentCached) { + object = service.getObject(bucket, getS3Key()); + LOG.debug(String.format("caching content of '%s'", object.getKey())); + + InputStream objectInputStream = object.getDataInputStream(); + if (object.getContentLength() > 0) { + ReadableByteChannel rbc = Channels.newChannel(objectInputStream); + FileChannel cacheFc = getCacheFile().getChannel(); + cacheFc.transferFrom(rbc, 0, object.getContentLength()); + cacheFc.close(); + rbc.close(); + } else { + objectInputStream.close(); + } + contentCached = true; + } + + return Channels.newInputStream(getCacheFile().getChannel()); } protected OutputStream doGetOutputStream(boolean bAppend) throws Exception { - changed = true; - return Channels.newOutputStream(getCacheFileChannel()); + dirty = true; + return new MonitorOutputStream(Channels.newOutputStream(getCacheFile().getChannel())) { + protected void onClose() throws IOException { + try { + LOG.debug(String.format("sending '%s' to storage (dirty=%b, cached=%b)", object.getKey(), dirty, cacheFile)); + if (cacheFile != null) { + FileChannel cacheFc = getCacheFile().getChannel(); + object.setContentLength(cacheFc.size()); + object.setDataInputStream(Channels.newInputStream(cacheFc)); + } + service.putObject(bucket, object); + } catch (S3ServiceException e) { + LOG.error(String.format("can't send object '%s' to storage", object.getKey()), e); + } + } + }; } protected FileType doGetType() throws Exception { @@ -161,6 +222,7 @@ public class Jets3tFileObject extends AbstractFileObje childrenNames[i] = children[i].getKey().replaceAll("[^/]*//*", ""); } } + return childrenNames; } @@ -184,10 +246,10 @@ public class Jets3tFileObject extends AbstractFileObje } } - private FileChannel getCacheFileChannel() throws IOException { + private RandomAccessFile getCacheFile() throws IOException, S3ServiceException { if (cacheFile == null) { cacheFile = File.createTempFile("moxo.", ".s3"); } - return new RandomAccessFile(cacheFile, "rw").getChannel(); + return new RandomAccessFile(cacheFile, "rw"); } } blob - e78aada5f0071545a49f52fb1f86aa003f038a87 blob + 5c2181514077735de9eaee6f6f59f9db52ebc405 --- src/main/java/com/thinkberg/moxo/vfs/jets3t/Jets3tFileSystem.java +++ src/main/java/com/thinkberg/moxo/vfs/jets3t/Jets3tFileSystem.java @@ -18,6 +18,8 @@ package com.thinkberg.moxo.vfs.jets3t; import com.thinkberg.moxo.vfs.S3FileName; import com.thinkberg.moxo.vfs.S3FileProvider; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.apache.commons.vfs.FileName; import org.apache.commons.vfs.FileObject; import org.apache.commons.vfs.FileSystemException; @@ -35,6 +37,8 @@ import java.util.Collection; * @author Matthias L. Jugel */ public class Jets3tFileSystem extends AbstractFileSystem { + private static final Log LOG = LogFactory.getLog(Jets3tFileSystem.class); + private S3Service service; private S3Bucket bucket; @@ -43,11 +47,13 @@ public class Jets3tFileSystem extends AbstractFileSyst String bucketId = fileName.getRootFile(); try { service = Jets3tConnector.getInstance().getService(); - bucket = new S3Bucket(bucketId); if (!service.isBucketAccessible(bucketId)) { + LOG.info("creating new S3 bucket (" + bucketId + ") for file system"); bucket = service.createBucket(bucketId); + } else { + LOG.info("using existing S3 bucket: " + bucketId); + bucket = new S3Bucket(bucketId); } - System.err.println("Created new S3 FileSystem: " + bucketId); } catch (S3ServiceException e) { throw new FileSystemException(e); } blob - ae39e881510681e8eb8b08d6c28510f4eec11b1d blob + 3067e4fa327fbd14e218e7adccae96656857cc6b --- src/main/resources/jetty.xml +++ src/main/resources/jetty.xml @@ -12,163 +12,178 @@ - - - - - - - 10 - 50 - 250 - + + + + + + + 10 + 50 + 250 + - + + + + + + + + + + - + + + + + + + 30000 + 2 + 8443 + + + + + + + 8443 + 30000 + /.keystore + + OBF:1fvu20731x191vul1vup1x1d20731ftg + OBF:1fvu20731x191vul1vup1x1d20731ftg + /.keystore + + OBF:1fvu20731x191vul1vup1x1d20731ftg + + + - - - - - + - - - - - - - - 30000 - 2 - 8443 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + / + + + + + com.thinkberg.moxo.servlet.MoxoWebDAVServlet + /* + - - - --> + - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + - - - - - - - - / - - - - - com.thinkberg.moxo.servlet.MoxoS3WebdavServlet - /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - /yyyy_mm_dd.request.log - - 90 - true - false - GMT - - - - - - true - - true + + + + + + + + + + + + + /yyyy_mm_dd.request.log + + 90 + true + false + GMT + + + + + + + true + + true + blob - cf3d423ee160e82b17ab56a44e55faddac0f384d blob + 2431b8fe9d36132a3fa0f91baef89bc9df06ccc6 --- src/main/resources/moxo.template.properties +++ src/main/resources/moxo.template.properties @@ -35,4 +35,5 @@ acl=PRIVATE password= # the bucket that contains the file system -bucket= \ No newline at end of file +s3.url=s3://TESTBUCKET/ +#s3.url=ram:/ \ No newline at end of file blob - 253190f1ea5939f131d17688ef3a6e947791f8eb blob + 5b43b0aee4de7daf1be61d57c1bd4be286fef0fd --- src/main/resources/simplelog.properties +++ src/main/resources/simplelog.properties @@ -14,4 +14,5 @@ # limitations under the License. # -org.apache.commons.logging.simplelog.defaultlog=info \ No newline at end of file +org.apache.commons.logging.simplelog.defaultlog=error +org.apache.commons.logging.simplelog.log.com.thinkberg.moxo=debug \ No newline at end of file blob - 75d3440d7341f1159ea710440ef5a4d9ab1c7e4a blob + 9ac36182f7b6d695e49901c76968ce5efc0a39bf --- src/test/java/com/thinkberg/moxo/MoxoTest.java +++ src/test/java/com/thinkberg/moxo/MoxoTest.java @@ -38,8 +38,8 @@ public class MoxoTest extends TestCase { String propertiesFileName = System.getProperty("moxo.properties", "moxo.properties"); Jets3tProperties properties = Jets3tProperties.getInstance(propertiesFileName); - String bucketId = properties.getStringProperty("bucket", null); - if (null != bucketId) { + String vfsUrl = properties.getStringProperty("vfs.url", null); + if (null != vfsUrl && vfsUrl.startsWith("s3:")) { s.addTestSuite(S3FileNameTest.class); s.addTestSuite(S3FileProviderTest.class); } blob - 111a1dbd66bf028541af96c6cc04d9feef45c600 (mode 644) blob + /dev/null --- src/test/java/com/thinkberg/moxo/S3TestCase.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2007 Matthias L. Jugel. - * - * Licensed 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 com.thinkberg.moxo; - -import junit.framework.TestCase; -import org.jets3t.service.Jets3tProperties; - -/** - * @author Matthias L. Jugel - */ -public class S3TestCase extends TestCase { - protected final static String BUCKETID; - protected static final String ROOT; - - static { - String propertiesFileName = System.getProperty("moxo.properties", "moxo.properties"); - Jets3tProperties properties = Jets3tProperties.getInstance(propertiesFileName); - - BUCKETID = properties.getStringProperty("bucket", null); - ROOT = "s3://" + BUCKETID; - - } -} blob - 0a640610fa6e6e3de857f625d04981a4eaa3f1d3 blob + c348a78e06fa4feda0222993ce6a971a7d0994fa --- src/test/java/com/thinkberg/moxo/dav/DavTestCase.java +++ src/test/java/com/thinkberg/moxo/dav/DavTestCase.java @@ -39,7 +39,6 @@ public class DavTestCase extends TestCase { aDirectory.createFolder(); } - @SuppressWarnings({"SameParameterValue"}) protected void testPropertyValue(FileObject object, String propertyName, String propertyValue) throws FileSystemException { Element root = serializeDavResource(object, propertyName); assertEquals(propertyValue, selectExistingPropertyValue(root, propertyName)); @@ -58,7 +57,6 @@ public class DavTestCase extends TestCase { return root.selectSingleNode(PROP_MISSING + propertyName); } - @SuppressWarnings({"SameParameterValue"}) String selectMissingPropertyName(Element root, String propertyName) { return selectMissingProperty(root, propertyName).getName(); } blob - 91cc77a793bd5a99291d9625ec74622b90b9102d blob + cad1af21c05c18a65efeb78b403be26e71fca272 --- src/test/java/com/thinkberg/moxo/vfs/S3FileNameTest.java +++ src/test/java/com/thinkberg/moxo/vfs/S3FileNameTest.java @@ -16,20 +16,20 @@ package com.thinkberg.moxo.vfs; -import junit.framework.TestCase; -import org.apache.commons.vfs.FileSystemException; import org.apache.commons.vfs.FileName; -import org.jets3t.service.Jets3tProperties; -import com.thinkberg.moxo.S3TestCase; +import org.apache.commons.vfs.FileSystemException; +import java.net.URI; + /** * @author Matthias L. Jugel */ public class S3FileNameTest extends S3TestCase { public void testGetBucketFromUri() throws FileSystemException { - String uri = ROOT + "/junk.txt"; - FileName fileName = S3FileNameParser.getInstance().parseUri(null, null, uri); - assertEquals(BUCKETID, ((S3FileName)fileName).getRootFile()); + String uriString = ROOT + "/junk.txt"; + String bucketId = URI.create(uriString).getHost(); + FileName fileName = S3FileNameParser.getInstance().parseUri(null, null, uriString); + assertEquals(bucketId, ((S3FileName) fileName).getRootFile()); } public void testGetRootFolderFromUri() throws FileSystemException { blob - 9f9b360ec733337b7a07da2071e596cd97c791fb blob + 38485aeefa013dff633c31b5e00104bd1efcdd46 --- src/test/java/com/thinkberg/moxo/vfs/S3FileProviderTest.java +++ src/test/java/com/thinkberg/moxo/vfs/S3FileProviderTest.java @@ -16,43 +16,97 @@ package com.thinkberg.moxo.vfs; -import com.thinkberg.moxo.S3TestCase; -import org.apache.commons.vfs.FileObject; -import org.apache.commons.vfs.FileSelectInfo; -import org.apache.commons.vfs.FileSelector; -import org.apache.commons.vfs.FileSystem; -import org.apache.commons.vfs.FileSystemException; -import org.apache.commons.vfs.FileType; -import org.apache.commons.vfs.VFS; +import org.apache.commons.vfs.*; import java.io.IOException; +import java.io.OutputStream; +import java.net.URI; +import java.util.Arrays; /** * @author Matthias L. Jugel */ public class S3FileProviderTest extends S3TestCase { + private static final FileSelector ALL_FILE_SELECTOR = new FileSelector() { + + public boolean includeFile(FileSelectInfo fileInfo) throws Exception { + return true; + } + + public boolean traverseDescendents(FileSelectInfo fileInfo) throws Exception { + return true; + } + }; + private static final String FOLDER = "/directory"; + private static final String FILE = FOLDER + "/newfile.txt"; + + static { + try { + FileObject rootFs = VFS.getManager().resolveFile(ROOT); + rootFs.delete(ALL_FILE_SELECTOR); + } catch (FileSystemException e) { + // just delete, ignore the rest + } + } + public void testDoCreateFileSystem() throws FileSystemException { FileObject object = VFS.getManager().resolveFile(ROOT); - assertEquals(BUCKETID, ((S3FileName) object.getName()).getRootFile()); + String bucketId = URI.create(ROOT).getHost(); + assertEquals(bucketId, ((S3FileName) object.getName()).getRootFile()); } + + public void testFileSystemIsEmpty() throws FileSystemException { + FileObject object = VFS.getManager().resolveFile(ROOT); + assertEquals(1, object.findFiles(ALL_FILE_SELECTOR).length); + } + public void testRootDirectoryIsFolder() throws FileSystemException { FileObject object = VFS.getManager().resolveFile(ROOT); assertEquals(FileType.FOLDER, object.getType()); } - public void testGetDirectory() throws FileSystemException { - FileObject object = VFS.getManager().resolveFile(ROOT + "/Sites"); + public void testCreateFolder() throws FileSystemException { + FileObject object = VFS.getManager().resolveFile(ROOT + FOLDER); + assertFalse(object.exists()); + object.createFolder(); + assertTrue(object.exists()); assertEquals(FileType.FOLDER, object.getType()); } - public void testGetDirectoryListing() throws FileSystemException { - FileObject object = VFS.getManager().resolveFile(ROOT + "/Sites/Sites/images"); + public void testGetFolder() throws FileSystemException { + FileObject object = VFS.getManager().resolveFile(ROOT + FOLDER); + assertTrue(object.exists()); + assertEquals(FileType.FOLDER, object.getType()); + } + + public void testCreateFile() throws IOException { + FileObject object = VFS.getManager().resolveFile(ROOT + FILE); + assertFalse(object.exists()); + OutputStream os = object.getContent().getOutputStream(); + os.write(0xfc); + os.close(); + assertTrue(object.exists()); + assertEquals(FileType.FILE, object.getType()); + } + + public void testCreateEmptyFile() throws IOException { + FileObject object = VFS.getManager().resolveFile(ROOT + FILE + ".empty"); + assertFalse(object.exists()); + object.createFile(); + assertTrue(object.exists()); + assertEquals(FileType.FILE, object.getType()); + } + + public void testFileHasLastModifiedTimestamp() throws FileSystemException { + FileObject object = VFS.getManager().resolveFile(ROOT + FILE); + object.getContent().getLastModifiedTime(); + } + + public void testGetFolderListing() throws FileSystemException { + FileObject object = VFS.getManager().resolveFile(ROOT + FOLDER); FileObject[] files = object.findFiles(new DepthFileSelector(1)); - for (FileObject file : files) { - System.out.println("Found file: " + file.getName().getPath()); - } - assertEquals(4, files.length); + assertEquals(3, files.length); } public void testMissingFile() throws FileSystemException { @@ -60,38 +114,67 @@ public class S3FileProviderTest extends S3TestCase { assertFalse(object.exists()); } + public void testGetLastModifiedTimeFolder() throws FileSystemException { + FileObject object = VFS.getManager().resolveFile(ROOT + FOLDER); + object.getContent().getLastModifiedTime(); + } + + public void testGetLastModifiedTimeFile() throws FileSystemException { + FileObject object = VFS.getManager().resolveFile(ROOT + FILE); + object.getContent().getLastModifiedTime(); + } + public void testDeleteFile() throws FileSystemException { - FileObject object = VFS.getManager().resolveFile(ROOT + "/newfile.txt"); + FileObject object = VFS.getManager().resolveFile(ROOT + FILE); object.delete(); + assertFalse(object.exists()); } public void testDeleteFolder() throws FileSystemException { - FileObject object = VFS.getManager().resolveFile(ROOT + "/newfolder"); - object.delete(new FileSelector() { + FileObject object = VFS.getManager().resolveFile(ROOT + FOLDER); + object.delete(ALL_FILE_SELECTOR); + assertFalse(object.exists()); + } - public boolean includeFile(FileSelectInfo fileInfo) throws Exception { - return true; - } + public void testCopyFolder() throws FileSystemException { + FileObject origFolder = VFS.getManager().resolveFile(ROOT + FOLDER); + origFolder.createFolder(); - public boolean traverseDescendents(FileSelectInfo fileInfo) throws Exception { - return true; - } - }); - } + origFolder.resolveFile("file.0").createFile(); + origFolder.resolveFile("file.1").createFile(); + origFolder.resolveFile("file.2").createFile(); - public void testCreateFolder() throws FileSystemException { - FileObject object = VFS.getManager().resolveFile(ROOT + "/newfolder"); - object.createFolder(); + FileObject[] origFiles = origFolder.findFiles(new DepthFileSelector(1)); + assertEquals(4, origFiles.length); + + FileObject destFolder = VFS.getManager().resolveFile(ROOT + FOLDER + "_dest"); + assertFalse(destFolder.exists()); + destFolder.copyFrom(origFolder, new DepthFileSelector(1)); + assertTrue(destFolder.exists()); + + FileObject[] destFiles = destFolder.findFiles(new DepthFileSelector(1)); + System.err.println(Arrays.asList(destFiles)); + assertEquals(4, destFiles.length); + + for (int i = 0; i < origFiles.length; i++) { + assertEquals(origFiles[i].getName().getRelativeName(origFolder.getName()), + destFiles[i].getName().getRelativeName(destFolder.getName())); + } + + origFolder.delete(ALL_FILE_SELECTOR); + destFolder.delete(ALL_FILE_SELECTOR); + + assertFalse(origFolder.exists()); + assertFalse(destFolder.exists()); } - public void testCreateFile() throws IOException { - FileObject object = VFS.getManager().resolveFile(ROOT + "/newfile.txt"); - object.getContent().getOutputStream().write(0xfc); - object.close(); + public void testMoveFolder() throws FileSystemException { + } public void testCloseFileSystem() throws FileSystemException { FileSystem fs = VFS.getManager().resolveFile(ROOT).getFileSystem(); VFS.getManager().closeFileSystem(fs); } + } blob - /dev/null blob + 790d3007daff25069746237120ced9b14239a05a (mode 644) --- /dev/null +++ src/test/java/com/thinkberg/moxo/vfs/S3TestCase.java @@ -0,0 +1,33 @@ +/* + * Copyright 2007 Matthias L. Jugel. + * + * Licensed 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 com.thinkberg.moxo.vfs; + +import junit.framework.TestCase; +import org.jets3t.service.Jets3tProperties; + +/** + * @author Matthias L. Jugel + */ +public class S3TestCase extends TestCase { + protected static final String ROOT; + + static { + String propertiesFileName = System.getProperty("moxo.properties", "moxo.properties"); + Jets3tProperties properties = Jets3tProperties.getInstance(propertiesFileName); + ROOT = properties.getStringProperty("vfs.url", "ram:/"); + } +}