Work on CMS file system implementation
[lgpl/argeo-commons.git] / org.argeo.cms / src / org / argeo / cms / file / provider / CmsFileSystemProvider.java
index 51eb84e713204f057f509ae5613949192436dfe4..5d93b7b580ac5b51223f74d83f64b99b1189a71f 100644 (file)
@@ -1,26 +1,53 @@
 package org.argeo.cms.file.provider;
 
 import java.io.IOException;
+import java.io.UncheckedIOException;
 import java.net.URI;
 import java.nio.channels.SeekableByteChannel;
 import java.nio.file.AccessMode;
 import java.nio.file.CopyOption;
 import java.nio.file.DirectoryStream;
 import java.nio.file.DirectoryStream.Filter;
+import java.nio.file.FileAlreadyExistsException;
 import java.nio.file.FileStore;
 import java.nio.file.FileSystem;
+import java.nio.file.FileSystemAlreadyExistsException;
 import java.nio.file.LinkOption;
+import java.nio.file.NoSuchFileException;
 import java.nio.file.OpenOption;
 import java.nio.file.Path;
 import java.nio.file.attribute.BasicFileAttributes;
 import java.nio.file.attribute.FileAttribute;
 import java.nio.file.attribute.FileAttributeView;
 import java.nio.file.spi.FileSystemProvider;
+import java.util.Collections;
+import java.util.HashMap;
 import java.util.Map;
 import java.util.Set;
 
+import javax.xml.namespace.QName;
+
+import org.argeo.api.acr.DName;
+import org.argeo.api.acr.NamespaceUtils;
+import org.argeo.api.acr.spi.ProvidedRepository;
+import org.argeo.api.acr.spi.ProvidedSession;
+import org.argeo.api.cms.CmsSession;
+import org.argeo.cms.CurrentUser;
+
 public class CmsFileSystemProvider extends FileSystemProvider {
+       private Map<CmsSession, CmsFileSystem> fileSystems = Collections.synchronizedMap(new HashMap<>());
 
+       private ProvidedRepository contentRepository;
+
+       
+       public void start() {
+               
+       }
+       
+       public void stop() {
+               
+       }
+       
        @Override
        public String getScheme() {
                return "cms";
@@ -28,20 +55,48 @@ public class CmsFileSystemProvider extends FileSystemProvider {
 
        @Override
        public FileSystem newFileSystem(URI uri, Map<String, ?> env) throws IOException {
-               // TODO Auto-generated method stub
-               return null;
+               CmsSession cmsSession = CurrentUser.getCmsSession();
+               if (cmsSession.isAnonymous()) {
+                       // TODO deal with anonymous
+                       return null;
+               }
+               if (fileSystems.containsKey(cmsSession))
+                       throw new FileSystemAlreadyExistsException("CMS file system already exists for user " + cmsSession);
+
+               String host = uri.getHost();
+               if (host != null && !host.trim().equals("")) {
+//                             URI repoUri = new URI("http", uri.getUserInfo(), uri.getHost(), uri.getPort(), "/jcr/node", null, null);
+                       // FIXME deal with remote
+                       CmsFileSystem fileSystem = null;
+                       fileSystems.put(cmsSession, fileSystem);
+                       return fileSystem;
+               } else {
+                       // FIXME send exception if it exists already
+                       CmsFileSystem fileSystem = new CmsFileSystem(this, contentRepository, cmsSession);
+                       fileSystems.put(cmsSession, fileSystem);
+                       cmsSession.addOnCloseCallback((s) -> {
+                               fileSystems.remove(s);
+                       });
+                       return fileSystem;
+               }
        }
 
        @Override
        public FileSystem getFileSystem(URI uri) {
-               // TODO Auto-generated method stub
-               return null;
+               return currentUserFileSystem();
        }
 
        @Override
        public Path getPath(URI uri) {
-               // TODO Auto-generated method stub
-               return null;
+               CmsFileSystem fileSystem = currentUserFileSystem();
+               String path = uri.getPath();
+               if (fileSystem == null)
+                       try {
+                               fileSystem = (CmsFileSystem) newFileSystem(uri, new HashMap<String, Object>());
+                       } catch (IOException e) {
+                               throw new UncheckedIOException("Could not autocreate file system for " + uri, e);
+                       }
+               return fileSystem.getPath(path);
        }
 
        @Override
@@ -53,20 +108,34 @@ public class CmsFileSystemProvider extends FileSystemProvider {
 
        @Override
        public DirectoryStream<Path> newDirectoryStream(Path dir, Filter<? super Path> filter) throws IOException {
-               // TODO Auto-generated method stub
-               return null;
+               CmsPath cmsPath = (CmsPath) dir;
+               return new ContentDirectoryStream(cmsPath, filter);
        }
 
        @Override
        public void createDirectory(Path dir, FileAttribute<?>... attrs) throws IOException {
-               // TODO Auto-generated method stub
+               CmsPath cmsPath = (CmsPath) dir;
+               ProvidedSession contentSession = cmsPath.getContentSession();
+               if (contentSession.exists(dir.toString()))
+                       throw new FileAlreadyExistsException(dir.toString());
 
+               CmsPath parent = (CmsPath) cmsPath.getParent();
+               if (!contentSession.exists(parent.toString()))
+                       throw new NoSuchFileException(parent.toString());
+               // TODO use a proper naming context
+               QName fileName = NamespaceUtils.parsePrefixedName(dir.getFileName().toString());
+               parent.getContent().add(fileName, DName.collection);
        }
 
        @Override
        public void delete(Path path) throws IOException {
-               // TODO Auto-generated method stub
-
+               CmsPath cmsPath = (CmsPath) path;
+               ProvidedSession contentSession = cmsPath.getContentSession();
+               if (!contentSession.exists(cmsPath.toString()))
+                       throw new NoSuchFileException(cmsPath.toString());
+               contentSession.edit((s) -> {
+                       cmsPath.getContent().remove();
+               });
        }
 
        @Override
@@ -83,26 +152,23 @@ public class CmsFileSystemProvider extends FileSystemProvider {
 
        @Override
        public boolean isSameFile(Path path, Path path2) throws IOException {
-               // TODO Auto-generated method stub
-               return false;
+               // TODO make it smarter
+               return path.toString().equals(path2.toString());
        }
 
        @Override
        public boolean isHidden(Path path) throws IOException {
-               // TODO Auto-generated method stub
                return false;
        }
 
        @Override
        public FileStore getFileStore(Path path) throws IOException {
-               // TODO Auto-generated method stub
-               return null;
+               CmsFileSystem fileSystem = (CmsFileSystem) path.getFileSystem();
+               return fileSystem.getFileStore(path.toString());
        }
 
        @Override
        public void checkAccess(Path path, AccessMode... modes) throws IOException {
-               // TODO Auto-generated method stub
-
        }
 
        @Override
@@ -130,4 +196,26 @@ public class CmsFileSystemProvider extends FileSystemProvider {
 
        }
 
+       /*
+        * UTILITIES
+        */
+
+       CmsFileSystem currentUserFileSystem() {
+               CmsSession cmsSession = CurrentUser.getCmsSession();
+               return fileSystems.get(cmsSession);
+       }
+
+       void close(CmsFileSystem fileSystem) {
+               CmsSession cmsSession = fileSystem.getCmsSession();
+               CmsFileSystem ref = fileSystems.remove(cmsSession);
+               assert ref == fileSystem;
+       }
+
+       /*
+        * DEPENDENCY INJECTION
+        */
+       public void setContentRepository(ProvidedRepository contentRepository) {
+               this.contentRepository = contentRepository;
+       }
+
 }