Date: 2004-11-04T15:24:19 Editor: BrianLee <[EMAIL PROTECTED]> Wiki: Jakarta-Slide Wiki Page: WebDavConstructionKit URL: http://wiki.apache.org/jakarta-slide/WebDavConstructionKit
no comment Change Log: ------------------------------------------------------------------------------ @@ -8,7 +8,9 @@ Currently, WCK is only available from CVS. For more information on accessing Slide from CVS, check http://jakarta.apache.org/site/cvsindex.html -==== Build Details ==== +==== Build Notes ==== + +The easiest way to get everything done on any platform (downloading from CVS, buidling from ant, etc...) is to use [http://www.eclipse.org Eclipse] IDE. ===== Full Working build.properties Example ===== @@ -93,9 +95,568 @@ commons-transaction-20041031.jar with the version you find in the 2.1b2 lib directory" -==== Example Store ==== +==== Store Implementation ==== + +Any concrete store must implement the [http://jakarta.apache.org/slide/wck/javadoc/org/apache/slide/simple/store/BasicWebdavStore.html org.apache.slide.simple.store.BasicWebdavStore] interface. + +===== Call Back Methods List ===== + +The following functions are basically all Slide and WCK need to make basic WebDAV operations work. + + 1.begin, commit, rollback: begins, commits, aborts a request / transaction + + 2.objectExists, isFolder, isResource: existence checks, collection vs. content checks + + 3.createFolder, createResource: creation of a collection or a content resource + + 4.removeObject: deletion of a collection or a content resource + + 5.setResourceContent, getResourceContent: storing and retrieval of a content resource -Any concrete store must implement the [http://jakarta.apache.org/slide/wck/javadoc/org/apache/slide/simple/store/BasicWebdavStore.html org.apache.slide.simple.store.BasicWebdavStore] + 6.getLastModified, getCreationDate, getResourceLength: retrieval of basic meta data + 7.getChildrenNames: retrieval of the children of a collection + +===== WebdavFileStore Example ===== +[http://jakarta.apache.org/slide/wck/javadoc/org/apache/slide/simple/reference/WebdavFileStore.html 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; + } + + } +} +}}} -[http://jakarta.apache.org/slide/wck/javadoc/org/apache/slide/simple/reference/WebdavFileStore.html org.apache.slide.simple.reference.WebdavFileStore] is the reference implementation (example) that you want to look at. --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
