WebdavFileStore Example

org.apache.slide.simple.reference.WebdavFileStore is the reference implementation (example) that you want to look at. The source is listed below -

public class WebdavFileStore implements BasicWebdavStore, WebdavStoreLockExtension, WebdavStoreBulkPropertyExtension,
        WebdavStoreMacroCopyExtension, WebdavStoreMacroMoveExtension, WebdavStoreMacroDeleteExtension {

    private static final String ROOTPATH_PARAMETER = "rootpath";

    private static final String LOCK_FILE_EXTENSION = ".lck";

    private static final String PROPERTY_FILE_PREFIX = ".";

    private static void save(InputStream is, File file) throws IOException {
        OutputStream os = new BufferedOutputStream(new FileOutputStream(file));
        try {
            FileHelper.copy(is, os);
        } finally {
            try {
                is.close();
            } finally {
                os.close();
            }
        }
    }

    private static File root = null;

    private static Service service = null;

    private static LoggerFacade logger = null;

    public synchronized void begin(Service service, Principal principal, Object connection, LoggerFacade logger,
            Hashtable parameters) throws ServiceAccessException, ServiceParameterErrorException,
            ServiceParameterMissingException {
        // set parameters only once...
        if (WebdavFileStore.root == null) {
            WebdavFileStore.service = service;
            WebdavFileStore.logger = logger;
            String rootPath = (String) parameters.get(ROOTPATH_PARAMETER);
            if (rootPath == null)
                throw new ServiceParameterMissingException(service, ROOTPATH_PARAMETER);

            WebdavFileStore.root = new File(rootPath);
            if (!WebdavFileStore.root.exists()) {
                if (!WebdavFileStore.root.mkdirs()) {
                    throw new ServiceParameterErrorException(service, ROOTPATH_PARAMETER + ": " + WebdavFileStore.root
                            + " does not exist and could not be created");
                } else {
                    logger.logInfo("Created root folder at: " + rootPath);
                }
            }
        }
    }

    public void commit() throws ServiceAccessException {
    }

    public void rollback() throws ServiceAccessException {
    }

    public void macroCopy(String sourceUri, String targetUri, boolean overwrite, boolean recursive) throws ServiceAccessException, AccessDeniedException,
            ObjectNotFoundException, ObjectAlreadyExistsException {
        try {
            File fromFile = getFile(sourceUri);
            File toFile = getFile(targetUri);
            if (toFile.exists() && !overwrite) {
                throw new ObjectAlreadyExistsException(targetUri);
            }
            if (!toFile.getParentFile().exists()) {
                throw new ObjectNotFoundException(toFile.getParentFile().toString());
            }
            if (fromFile.isDirectory() && !recursive) {
                //  copy directory only, which means create dir and copy properties
                if (!toFile.exists()) {
                    toFile.mkdirs();
                }
            } else {
                FileHelper.copyRec(fromFile, toFile);
            }
            File propertyFile = getPropertyFile(sourceUri);
            File destPropertyFile = getPropertyFile(targetUri);
            if (propertyFile.exists()) FileHelper.copy(propertyFile, destPropertyFile);
            // XXX is it correct not to take over locking information on copy? I guess so (OZ)
//            File lockFile = getLockFile(sourceUri);
//            File destLockFile = getLockFile(targetUri);
//            if (lockFile.exists()) FileHelper.copy(propertyFile, destPropertyFile);
        } catch (FileNotFoundException e) {
            throw new ObjectNotFoundException(targetUri);
        } catch (IOException e) {
            throw new ServiceAccessException(service, e);
        } catch (SecurityException e) {
            throw new AccessDeniedException(targetUri, e.getMessage(), "/actions/write");
        }
    }

    public void macroMove(String sourceUri, String targetUri, boolean overwrite) throws ServiceAccessException, AccessDeniedException,
            ObjectNotFoundException, ObjectAlreadyExistsException {
        try {
            File fromFile = getFile(sourceUri);
            File toFile = getFile(targetUri);
            if (toFile.exists() && !overwrite) {
                throw new ObjectAlreadyExistsException(targetUri);
            }
            if (!toFile.getParentFile().exists()) {
                throw new ObjectNotFoundException(toFile.getParentFile().toString());
            }
            renameOrMove(fromFile, toFile);
            File propertyFile = getPropertyFile(sourceUri);
            File destPropertyFile = getPropertyFile(targetUri);
            renameOrMove(propertyFile, destPropertyFile);
            File lockFile = getLockFile(sourceUri);
            File destLockFile = getLockFile(targetUri);
            renameOrMove(lockFile, destLockFile);
        } catch (FileNotFoundException e) {
            throw new ObjectNotFoundException(targetUri);
        } catch (IOException e) {
            throw new ServiceAccessException(service, e);
        } catch (SecurityException e) {
            throw new AccessDeniedException(targetUri, e.getMessage(), "/actions/write");
        }
    }

    protected void renameOrMove(File from, File to) throws IOException,
            ObjectAlreadyExistsException {
        if (from.exists()) {
            if (to.exists()) {
                boolean success = to.delete();
                if (!success) {
                    new ObjectAlreadyExistsException(to.toString());
                }
            }
            boolean success = from.renameTo(to);
            if (!success) {
                FileHelper.moveRec(from, to);
            }
        }
    }
    
    public void macroDelete(String targetUri) throws ServiceAccessException, AccessDeniedException,
            ObjectNotFoundException {
        try {
            File file = getFile(targetUri);
            FileHelper.removeRec(file);
            File propertyFile = getPropertyFile(targetUri);
            if (propertyFile.exists()) propertyFile.delete();    
            File lockFile = getLockFile(targetUri);
            if (lockFile.exists()) lockFile.delete();    
        } catch (SecurityException e) {
            throw new AccessDeniedException(targetUri, e.getMessage(), "/actions/write");
        }
    }

    public boolean objectExists(String uri) throws ServiceAccessException, AccessDeniedException {
        try {
            return getFile(uri).exists();
        } catch (SecurityException e) {
            throw new AccessDeniedException(uri, e.getMessage(), "read");
        }
    }

    public boolean isFolder(String uri) throws ServiceAccessException, AccessDeniedException {
        try {
            return (getFile(uri).exists() && getFile(uri).isDirectory());
        } catch (SecurityException e) {
            throw new AccessDeniedException(uri, e.getMessage(), "read");
        }

    }

    public boolean isResource(String uri) throws ServiceAccessException, AccessDeniedException {
        try {
            return (getFile(uri).exists() && !getFile(uri).isDirectory());
        } catch (SecurityException e) {
            throw new AccessDeniedException(uri, e.getMessage(), "read");
        }
    }

    public void createFolder(String folderUri) throws ServiceAccessException, AccessDeniedException,
            ObjectAlreadyExistsException {
        try {
            if (!getFile(folderUri).mkdir())
                throw new ServiceAccessException(service, "Can not create directory " + folderUri);

        } catch (SecurityException e) {
            throw new AccessDeniedException(folderUri, e.getMessage(), "create");
        }
    }

    public String[] getChildrenNames(String folderUri) throws ServiceAccessException, AccessDeniedException,
            ObjectNotFoundException {
        try {

            File file = getFile(folderUri);
            if (file.isDirectory()) {

                File[] children = file.listFiles();
                List childList = new ArrayList();
                for (int i = 0; i < children.length; i++) {
                    String name = children[i].getName();
                    // locking and property information should not be displayed
                    // as a resource
                    if (!isLockFilename(name) && !isPropertyFilename(name)) {
                        childList.add(name);
                    }
                }
                String[] childrenNames = new String[childList.size()];
                childrenNames = (String[]) childList.toArray(childrenNames);
                return childrenNames;
            } else {
                return null;
            }
        } catch (SecurityException e) {
            throw new AccessDeniedException(folderUri, e.getMessage(), "read");
        }
    }

    public void createResource(String resourceUri) throws ServiceAccessException, AccessDeniedException,
            ObjectAlreadyExistsException {
        try {
            File file = getFile(resourceUri);
            if (file.exists())
                throw new ObjectAlreadyExistsException(resourceUri);
            if (!file.createNewFile())
                throw new ServiceAccessException(service, "Can not create file " + resourceUri);
        } catch (IOException e) {
            throw new ServiceAccessException(service, e);
        } catch (SecurityException e) {
            throw new AccessDeniedException(resourceUri, e.getMessage(), "create");
        }
    }

    public void setResourceContent(String resourceUri, InputStream content, String contentType, String characterEncoding) throws ServiceAccessException,
            AccessDeniedException, ObjectNotFoundException {
        try {

            File file = getFile(resourceUri);
            if (!file.exists())
                throw new ObjectNotFoundException(resourceUri);
            try {
                save(content, file);
            } catch (FileNotFoundException e) {
                // XXX this really indicates a denied access
                throw new AccessDeniedException(resourceUri, e.getMessage(), "store");
            } catch (IOException e) {
                throw new ServiceAccessException(service, e);
            }
        } catch (SecurityException e) {
            throw new AccessDeniedException(resourceUri, e.getMessage(), "store");
        }
    }

    public long getResourceLength(String resourceUri) throws ServiceAccessException, AccessDeniedException,
            ObjectNotFoundException {
        try {
            File file = getFile(resourceUri);
            if (!file.exists())
                throw new ObjectNotFoundException(resourceUri);
            return file.length();
        } catch (SecurityException e) {
            throw new AccessDeniedException(resourceUri, e.getMessage(), "read");
        }

    }

    public InputStream getResourceContent(String resourceUri) throws ServiceAccessException, AccessDeniedException,
            ObjectNotFoundException {
        try {
            File file = getFile(resourceUri);
            if (!file.exists())
                throw new ObjectNotFoundException(resourceUri);
            InputStream in;
            try {
                in = new BufferedInputStream(new FileInputStream(file));
                return in;
            } catch (FileNotFoundException e) {
                throw new ObjectNotFoundException(resourceUri);
            }
        } catch (SecurityException e) {
            throw new AccessDeniedException(resourceUri, e.getMessage(), "read");
        }
    }

    public void removeObject(String uri) throws ServiceAccessException, AccessDeniedException, ObjectNotFoundException {
        try {
            File file = getFile(uri);
            if (!file.exists())
                throw new ObjectNotFoundException(uri);

            if (!file.delete())
                throw new ServiceAccessException(service, "Unable to delete " + uri);
            getPropertyFile(uri).delete();
            getLockFile(uri).delete();
        } catch (SecurityException e) {
            throw new AccessDeniedException(uri, e.getMessage(), "delete");
        }
    }

    public Date getLastModified(String uri) throws ServiceAccessException, AccessDeniedException,
            ObjectNotFoundException {
        try {
            File file = getFile(uri);
            if (!file.exists())
                throw new ObjectNotFoundException(uri);
            long lastModified = file.lastModified();
            return new Date(lastModified);
        } catch (SecurityException e) {
            throw new AccessDeniedException(uri, e.getMessage(), "read");
        }
    }

    public Date getCreationDate(String uri) throws ServiceAccessException, AccessDeniedException,
            ObjectNotFoundException {
        // XXX we do not have this information
        return getLastModified(uri);
    }

    public Map getProperties(String uri) throws ServiceAccessException, AccessDeniedException {
        File file = getPropertyFile(uri);
        if (!file.exists()) {
            return null;
        }
        return readProperties(file);
    }

    public void setProperties(String uri, Map properties) throws ServiceAccessException, AccessDeniedException {
        File file = getPropertyFile(uri);
        assureCreated(file, uri);
        Properties props = new Properties();
        props.putAll(properties);
        saveProperties(file, props, "WebDAV properties");
    }

    public void addOrUpdateProperty(String uri, String name, String value) throws ServiceAccessException,
            AccessDeniedException, ObjectNotFoundException {
    }

    public void removeProperty(String uri, String name) throws ServiceAccessException, AccessDeniedException,
            ObjectNotFoundException {
    }

    public void lockObject(String uri, String lockId, String subject, Date expiration, boolean exclusive,
            boolean inheritable) throws ServiceAccessException, AccessDeniedException {
        File file = getLockFile(uri);
        assureCreated(file, uri);
        Properties properties = readProperties(file);
        String lockString = expiration.getTime() + "|" + String.valueOf(exclusive) + "|" + String.valueOf(inheritable)
                + "|" + subject;
        properties.setProperty(lockId, lockString);
        saveProperties(file, properties, "WebDAV locks");
    }

    public void unlockObject(String uri, String lockId) throws ServiceAccessException, AccessDeniedException {
        File file = getLockFile(uri);
        if (!file.exists()) {
            throw new ServiceAccessException(service, "There nothing to unlock for " + uri);
        }
        Properties properties = readProperties(file);
        properties.remove(lockId);
        // do a special trick and remove the lock file when there are no more
        // locks
        if (properties.size() != 0) {
            saveProperties(file, properties, "WebDAV locks");
        } else {
            if (!file.delete())
                throw new ServiceAccessException(service, "Could not delete lock file for " + uri);
        }
    }

    public Lock[] getLockInfo(String uri) throws ServiceAccessException, AccessDeniedException {
        File file = getLockFile(uri);
        if (!file.exists()) {
            return null;
        }
        Properties properties = readProperties(file);
        List locks = new ArrayList();
        Enumeration enum = properties.propertyNames();
        while (enum.hasMoreElements()) {
            String id = (String) enum.nextElement();
            String value = properties.getProperty(id);
            if (value == null) {
                throw new ServiceAccessException(service, "Invalid lockId " + id);
            }
            StringTokenizer tokenizer = new StringTokenizer(value, "|");
            int tokens = tokenizer.countTokens();
            if (tokens != 4) {
                throw new ServiceAccessException(service, "Invalid lock information for lockId " + id);
            }
            String dateString = tokenizer.nextToken();
            String exclusiveString = tokenizer.nextToken();
            String inheritableString = tokenizer.nextToken();
            String subject = tokenizer.nextToken();
            Date date = new Date(Long.valueOf(dateString).longValue());
            boolean exclusive = Boolean.valueOf(exclusiveString).booleanValue();
            boolean inheritable = Boolean.valueOf(inheritableString).booleanValue();
            Lock lock = new SimpleLock(id, exclusive, inheritable, date, subject);
            locks.add(lock);
        }
        Lock[] lockArray = new Lock[locks.size()];
        lockArray = (Lock[]) locks.toArray(lockArray);
        return lockArray;
    }

    protected File getFile(String uri) {
        File file = new File(root, uri);
        return file;
    }

    protected File getPropertyFile(String uri) {
        String dir;
        String name;
        int lastSlash = uri.lastIndexOf('/');
        if (lastSlash != -1) {
            dir = uri.substring(0, lastSlash + 1);
            name = uri.substring(lastSlash + 1);
        } else {
            dir = "";
            name = uri;
        }
        String path = dir + PROPERTY_FILE_PREFIX + name;
        File file = new File(root, path);
        return file;
    }

    protected boolean isPropertyFilename(String uri) {
        return uri.startsWith(PROPERTY_FILE_PREFIX);
    }

    protected File getLockFile(String uri) {
        File file = new File(root, uri + LOCK_FILE_EXTENSION);
        return file;
    }

    protected boolean isLockFilename(String uri) {
        return uri.endsWith(LOCK_FILE_EXTENSION);
    }

    protected void assureCreated(File file, String uri) throws ServiceAccessException {
        if (!file.exists()) {
            try {
                if (!file.createNewFile())
                    throw new ServiceAccessException(service, "Can not create file " + uri);
            } catch (IOException e) {
                throw new ServiceAccessException(service, e);
            }
        }
    }

    protected String getLockEntry(String uri, String lockId) throws ServiceAccessException, ObjectNotFoundException {
        File file = getLockFile(uri);
        if (!file.exists()) {
            throw new ObjectNotFoundException(uri);
        }
        Properties properties = readProperties(file);
        String value = properties.getProperty(lockId);
        if (value == null) {
            throw new ServiceAccessException(service, "Invalid lockId " + lockId);
        }
        return value;
    }

    protected void saveProperties(File file, Properties properties, String header) throws ServiceAccessException {
        OutputStream os = null;
        try {
            os = new BufferedOutputStream(new FileOutputStream(file));
            properties.store(os, header);
        } catch (FileNotFoundException e) {
            throw new ServiceAccessException(service, e);
        } catch (IOException e) {
            throw new ServiceAccessException(service, e);
        } finally {
            if (os != null)
                try {
                    os.close();
                } catch (IOException e) {
                }
        }
    }

    protected Properties readProperties(File file) throws ServiceAccessException {
        InputStream is = null;
        try {
            is = new BufferedInputStream(new FileInputStream(file));
            Properties properties = new Properties();
            properties.load(is);
            return properties;
        } catch (FileNotFoundException e) {
            throw new ServiceAccessException(service, e);
        } catch (IOException e) {
            throw new ServiceAccessException(service, e);
        } finally {
            if (is != null)
                try {
                    is.close();
                } catch (IOException e) {
                }
        }
    }

    private static class SimpleLock implements Lock {

        public String id;

        public boolean exclusive;

        public boolean inheritable;

        public Date expirationDate;

        public String subject;

        public SimpleLock(String id, boolean exclusive, boolean inheritable, Date expirationDate, String subject) {
            this.id = id;
            this.exclusive = exclusive;
            this.inheritable = inheritable;
            this.expirationDate = expirationDate;
            this.subject = subject;
        }

        public boolean isExclusive() {
            return exclusive;
        }

        public Date getExpirationDate() {
            return expirationDate;
        }

        public String getId() {
            return id;
        }

        public boolean isInheritable() {
            return inheritable;
        }

        public String getSubject() {
            return subject;
        }

    }
}

WebdavFileStore (last edited 2009-09-20 22:02:31 by localhost)