From 60bf0339227cc064a4ead694e3a699581a025233 Mon Sep 17 00:00:00 2001 From: Mathieu Baudier Date: Sun, 22 Oct 2023 11:22:21 +0200 Subject: [PATCH] Work on CMS file system implementation --- .../src/org/argeo/api/acr/Content.java | 23 ++-- .../OSGI-INF/cmsFileSystemProvider.xml | 8 ++ org.argeo.cms/bnd.bnd | 1 + org.argeo.cms/build.properties | 3 +- .../argeo/cms/file/provider/CmsFileStore.java | 22 +++- .../cms/file/provider/CmsFileSystem.java | 85 ++++++++---- .../file/provider/CmsFileSystemProvider.java | 124 +++++++++++++++--- .../org/argeo/cms/file/provider/CmsPath.java | 23 ++++ .../file/provider/ContentAttributeView.java | 24 ++++ .../file/provider/ContentDirectoryStream.java | 88 +++++++++++++ .../internal/runtime/CmsDeploymentImpl.java | 5 + sdk/cms-rcp.properties | 28 ++-- swt/org.argeo.cms.swt/OSGI-INF/cmsUserApp.xml | 1 + .../src/org/argeo/cms/swt/app/CmsUserApp.java | 17 ++- 14 files changed, 379 insertions(+), 73 deletions(-) create mode 100644 org.argeo.cms/OSGI-INF/cmsFileSystemProvider.xml create mode 100644 org.argeo.cms/src/org/argeo/cms/file/provider/ContentAttributeView.java create mode 100644 org.argeo.cms/src/org/argeo/cms/file/provider/ContentDirectoryStream.java diff --git a/org.argeo.api.acr/src/org/argeo/api/acr/Content.java b/org.argeo.api.acr/src/org/argeo/api/acr/Content.java index f7600f540..7ec295947 100644 --- a/org.argeo.api.acr/src/org/argeo/api/acr/Content.java +++ b/org.argeo.api.acr/src/org/argeo/api/acr/Content.java @@ -90,7 +90,11 @@ public interface Content extends Iterable, Map { * CONTENT OPERATIONS */ /** Adds a new empty {@link Content} to this {@link Content}. */ - Content add(QName name, QName... classes); + Content add(QName name, QName... contentClass); + + default Content add(QName name, QNamed... contentClass) { + return add(name, toQNames(contentClass)); + } /** * Adds a new {@link Content} to this {@link Content}, setting the provided @@ -135,10 +139,7 @@ public interface Content extends Iterable, Map { /** AND */ default boolean isContentClass(QNamed... contentClass) { - List lst = new ArrayList<>(); - for (QNamed qNamed : contentClass) - lst.add(qNamed.qName()); - return isContentClass(lst.toArray(new QName[lst.size()])); + return isContentClass(toQNames(contentClass)); } /** OR */ @@ -153,10 +154,14 @@ public interface Content extends Iterable, Map { /** OR */ default boolean hasContentClass(QNamed... contentClass) { - List lst = new ArrayList<>(); - for (QNamed qNamed : contentClass) - lst.add(qNamed.qName()); - return hasContentClass(lst.toArray(new QName[lst.size()])); + return hasContentClass(toQNames(contentClass)); + } + + static QName[] toQNames(QNamed... names) { + QName[] res = new QName[names.length]; + for (int i = 0; i < names.length; i++) + res[i] = names[i].qName(); + return res; } /* diff --git a/org.argeo.cms/OSGI-INF/cmsFileSystemProvider.xml b/org.argeo.cms/OSGI-INF/cmsFileSystemProvider.xml new file mode 100644 index 000000000..b1402fae8 --- /dev/null +++ b/org.argeo.cms/OSGI-INF/cmsFileSystemProvider.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/org.argeo.cms/bnd.bnd b/org.argeo.cms/bnd.bnd index ade2f3aa9..01443b5e8 100644 --- a/org.argeo.cms/bnd.bnd +++ b/org.argeo.cms/bnd.bnd @@ -16,4 +16,5 @@ OSGI-INF/cmsContentRepository.xml,\ OSGI-INF/cmsAcrHttpHandler.xml,\ OSGI-INF/cmsDeployment.xml,\ OSGI-INF/cmsContext.xml,\ +OSGI-INF/cmsFileSystemProvider.xml,\ diff --git a/org.argeo.cms/build.properties b/org.argeo.cms/build.properties index 6ca041a2a..04d4cb94a 100644 --- a/org.argeo.cms/build.properties +++ b/org.argeo.cms/build.properties @@ -2,6 +2,7 @@ bin.includes = META-INF/,\ .,\ bin/,\ OSGI-INF/,\ - OSGI-INF/cmsEventBus.xml + OSGI-INF/cmsEventBus.xml,\ + OSGI-INF/cmsFileSystemProvider.xml source.. = src/ output.. = bin/ diff --git a/org.argeo.cms/src/org/argeo/cms/file/provider/CmsFileStore.java b/org.argeo.cms/src/org/argeo/cms/file/provider/CmsFileStore.java index a4da893b6..7abeec4e6 100644 --- a/org.argeo.cms/src/org/argeo/cms/file/provider/CmsFileStore.java +++ b/org.argeo.cms/src/org/argeo/cms/file/provider/CmsFileStore.java @@ -5,24 +5,30 @@ import java.nio.file.attribute.FileAttributeView; import java.nio.file.attribute.FileStoreAttributeView; import org.argeo.api.acr.fs.AbstractFsStore; +import org.argeo.api.acr.spi.ContentProvider; public class CmsFileStore extends AbstractFsStore { + private final ContentProvider contentProvider; + + public CmsFileStore(ContentProvider contentProvider) { + this.contentProvider = contentProvider; + } @Override public String name() { - // TODO Auto-generated method stub - return null; + // TODO return an URI + String name = contentProvider.getMountPath(); + return name; } @Override public String type() { - // TODO Auto-generated method stub - return null; + String type = contentProvider.getClass().getName(); + return type; } @Override public boolean isReadOnly() { - // TODO Auto-generated method stub return false; } @@ -46,13 +52,15 @@ public class CmsFileStore extends AbstractFsStore { @Override public boolean supportsFileAttributeView(Class type) { - // TODO Auto-generated method stub + if (ContentAttributeView.class.isAssignableFrom(type)) + return true; return false; } @Override public boolean supportsFileAttributeView(String name) { - // TODO Auto-generated method stub + if (ContentAttributeView.NAME.equals(name)) + return true; return false; } diff --git a/org.argeo.cms/src/org/argeo/cms/file/provider/CmsFileSystem.java b/org.argeo.cms/src/org/argeo/cms/file/provider/CmsFileSystem.java index 6d4eea279..f581ea1c4 100644 --- a/org.argeo.cms/src/org/argeo/cms/file/provider/CmsFileSystem.java +++ b/org.argeo.cms/src/org/argeo/cms/file/provider/CmsFileSystem.java @@ -7,94 +7,131 @@ import java.nio.file.PathMatcher; import java.nio.file.WatchService; import java.nio.file.attribute.UserPrincipalLookupService; import java.nio.file.spi.FileSystemProvider; +import java.util.Collections; import java.util.Set; import org.argeo.api.acr.fs.AbstractFsSystem; +import org.argeo.api.acr.spi.ProvidedContent; +import org.argeo.api.acr.spi.ProvidedRepository; +import org.argeo.api.acr.spi.ProvidedSession; +import org.argeo.api.cms.CmsSession; +import org.argeo.cms.acr.ContentUtils; public class CmsFileSystem extends AbstractFsSystem { + private final CmsFileSystemProvider provider; +// private final ProvidedRepository contentRepository; + private final CmsSession cmsSession; + private final ProvidedSession contentSession; + + private final CmsPath rootPath; + private final CmsFileStore baseFileStore; + + public CmsFileSystem(CmsFileSystemProvider provider, ProvidedRepository contentRepository, CmsSession cmsSession) { + this.provider = provider; +// this.contentRepository = contentRepository; + this.cmsSession = cmsSession; + this.contentSession = (ProvidedSession) ContentUtils.openSession(contentRepository, cmsSession); + + rootPath = new CmsPath(this, ProvidedContent.ROOT_PATH); + baseFileStore = new CmsFileStore(rootPath.getContent().getProvider()); + } @Override public CmsFileStore getBaseFileStore() { - // TODO Auto-generated method stub - return null; + return baseFileStore; } @Override public CmsFileStore getFileStore(String path) { - // TODO Auto-generated method stub - return null; + ProvidedContent c = (ProvidedContent) contentSession.get(path); + return new CmsFileStore(c.getProvider()); } @Override public FileSystemProvider provider() { - // TODO Auto-generated method stub - return null; + return provider; } @Override public void close() throws IOException { - // TODO Auto-generated method stub - + // TODO close content session? + provider.close(this); } @Override public boolean isOpen() { - // TODO Auto-generated method stub - return false; + // TODO check provider + return true; } @Override public boolean isReadOnly() { - // TODO Auto-generated method stub return false; } @Override public String getSeparator() { - // TODO Auto-generated method stub - return null; + return CmsPath.SEPARATOR; } @Override public Iterable getRootDirectories() { - // TODO Auto-generated method stub - return null; + return Collections.singleton(rootPath); } @Override public Iterable getFileStores() { - // TODO Auto-generated method stub - return null; + // TODO return all mount points + return Collections.singleton(baseFileStore); } @Override public Set supportedFileAttributeViews() { - // TODO Auto-generated method stub - return null; + return Collections.singleton(ContentAttributeView.NAME); } @Override public Path getPath(String first, String... more) { - // TODO Auto-generated method stub - return null; + StringBuilder sb = new StringBuilder(first); + // TODO Make it more robust + for (String part : more) + sb.append('/').append(part); + return new CmsPath(this, sb.toString()); } @Override public PathMatcher getPathMatcher(String syntaxAndPattern) { - // TODO Auto-generated method stub return null; } @Override public UserPrincipalLookupService getUserPrincipalLookupService() { - // TODO Auto-generated method stub return null; } @Override public WatchService newWatchService() throws IOException { - // TODO Auto-generated method stub return null; } + /* + * ACR + */ + + ProvidedContent getContent(String acrPath) { + return (ProvidedContent) contentSession.get(acrPath); + } + + ProvidedSession getContentSession() { + return contentSession; + } + + /* + * CMS + */ + + CmsSession getCmsSession() { + return cmsSession; + } + } diff --git a/org.argeo.cms/src/org/argeo/cms/file/provider/CmsFileSystemProvider.java b/org.argeo.cms/src/org/argeo/cms/file/provider/CmsFileSystemProvider.java index 51eb84e71..5d93b7b58 100644 --- a/org.argeo.cms/src/org/argeo/cms/file/provider/CmsFileSystemProvider.java +++ b/org.argeo.cms/src/org/argeo/cms/file/provider/CmsFileSystemProvider.java @@ -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 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 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()); + } 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 newDirectoryStream(Path dir, Filter 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; + } + } diff --git a/org.argeo.cms/src/org/argeo/cms/file/provider/CmsPath.java b/org.argeo.cms/src/org/argeo/cms/file/provider/CmsPath.java index 504e69bff..ce5e4b9e5 100644 --- a/org.argeo.cms/src/org/argeo/cms/file/provider/CmsPath.java +++ b/org.argeo.cms/src/org/argeo/cms/file/provider/CmsPath.java @@ -1,8 +1,27 @@ package org.argeo.cms.file.provider; +import org.argeo.api.acr.Content; import org.argeo.api.acr.fs.AbstractFsPath; +import org.argeo.api.acr.spi.ProvidedContent; +import org.argeo.api.acr.spi.ProvidedSession; public class CmsPath extends AbstractFsPath { + final static String SEPARATOR = "/"; + + // lazy loaded + private ProvidedContent content; + + ProvidedContent getContent() { + if (content == null) { + content = getFileSystem().getContent(toString()); + } + return content; + } + + CmsPath(CmsFileSystem fileSystem, Content content) { + this(fileSystem, content.getPath()); + this.content = (ProvidedContent) content; + } public CmsPath(CmsFileSystem filesSystem, CmsFileStore fileStore, String[] segments, boolean absolute) { super(filesSystem, fileStore, segments, absolute); @@ -22,4 +41,8 @@ public class CmsPath extends AbstractFsPath { return new CmsPath(getFileSystem(), getFileStore(), segments, absolute); } + ProvidedSession getContentSession() { + return getFileSystem().getContentSession(); + } + } diff --git a/org.argeo.cms/src/org/argeo/cms/file/provider/ContentAttributeView.java b/org.argeo.cms/src/org/argeo/cms/file/provider/ContentAttributeView.java new file mode 100644 index 000000000..9bce0424a --- /dev/null +++ b/org.argeo.cms/src/org/argeo/cms/file/provider/ContentAttributeView.java @@ -0,0 +1,24 @@ +package org.argeo.cms.file.provider; + +import java.nio.file.attribute.FileAttributeView; + +import org.argeo.api.acr.Content; + +public class ContentAttributeView implements FileAttributeView { + final static String NAME = "content"; + + private final Content content; + + public ContentAttributeView(Content content) { + this.content = content; + } + + @Override + public String name() { + return NAME; + } + + public Content getContent() { + return content; + } +} diff --git a/org.argeo.cms/src/org/argeo/cms/file/provider/ContentDirectoryStream.java b/org.argeo.cms/src/org/argeo/cms/file/provider/ContentDirectoryStream.java new file mode 100644 index 000000000..2cddf6275 --- /dev/null +++ b/org.argeo.cms/src/org/argeo/cms/file/provider/ContentDirectoryStream.java @@ -0,0 +1,88 @@ +package org.argeo.cms.file.provider; + +import java.io.IOException; +import java.io.UncheckedIOException; +import java.nio.file.DirectoryStream; +import java.nio.file.Path; +import java.util.Iterator; + +import org.argeo.api.acr.Content; +import org.argeo.api.acr.DName; + +public class ContentDirectoryStream implements DirectoryStream { + private final CmsPath dir; + private final Filter filter; + + private FilesAndCollectionsIterator iterator; + + public ContentDirectoryStream(CmsPath dir, Filter filter) { + this.dir = dir; + this.filter = filter; + } + + @Override + public void close() throws IOException { + } + + @Override + public Iterator iterator() { + if (iterator == null) + iterator = new FilesAndCollectionsIterator(); + return iterator; + } + + static boolean isFile(Content c) { + return !c.get(DName.getcontenttype, String.class).isEmpty(); + } + + static boolean isDirectory(Content c) { + return c.isContentClass(DName.collection); + } + + class FilesAndCollectionsIterator implements Iterator { + private Content next; + private final Iterator it; + + public FilesAndCollectionsIterator() { + Content content = dir.getContent(); + if (!content.isContentClass(DName.collection)) + throw new IllegalStateException("Content " + content + " is not a collection"); + it = content.iterator(); + findNext(); + } + + private void findNext() { + next = null; + while (it.hasNext() && next != null) { + Content n = it.next(); + if (isFile(n) || isDirectory(n)) { + if (filter != null) { + try { + if (filter.accept(new CmsPath(dir.getFileSystem(), n))) + next = n; + } catch (IOException e) { + throw new UncheckedIOException("Cannot filter " + dir, e); + } + } else { + next = n; + } + } + } + } + + @Override + public boolean hasNext() { + return next != null; + } + + @Override + public Path next() { + if (next == null) + throw new IllegalStateException("Iterator doesn't have more elements"); + CmsPath p = new CmsPath(dir.getFileSystem(), next); + findNext(); + return p; + } + + } +} diff --git a/org.argeo.cms/src/org/argeo/cms/internal/runtime/CmsDeploymentImpl.java b/org.argeo.cms/src/org/argeo/cms/internal/runtime/CmsDeploymentImpl.java index 265cb34a0..f9a1dc368 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/runtime/CmsDeploymentImpl.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/runtime/CmsDeploymentImpl.java @@ -90,6 +90,11 @@ public class CmsDeploymentImpl implements CmsDeployment { } public void createHttpContext(String contextPath, HttpHandler httpHandler, CmsAuthenticator authenticator) { + if (!httpExpected) { + if (log.isTraceEnabled()) + log.warn("Ignore HTTP context " + contextPath + " as we don't provide an HTTP server"); + return; + } HttpContext httpContext = httpServer.join().createContext(contextPath); // we want to set the authenticator BEFORE the handler actually becomes active httpContext.setAuthenticator(authenticator); diff --git a/sdk/cms-rcp.properties b/sdk/cms-rcp.properties index df8363b76..da2e68a43 100644 --- a/sdk/cms-rcp.properties +++ b/sdk/cms-rcp.properties @@ -1,21 +1,20 @@ -argeo.osgi.start.2.node=\ -org.eclipse.equinox.metatype,\ -org.eclipse.equinox.cm,\ -org.eclipse.equinox.ds,\ +argeo.osgi.start.2=\ +org.apache.felix.scr,\ org.argeo.init -argeo.osgi.start.3.node=\ +argeo.osgi.start.3=\ org.argeo.cms,\ -org.argeo.cms.jcr,\ -org.argeo.cms.ui.rcp +org.argeo.cms.swt.rcp,\ +org.argeo.cms.ee,\ +org.argeo.cms.lib.dbus,\ +argeo.osgi.start.5=\ +org.argeo.app.profile.acr.fs,\ -# Local -argeo.node.repo.type=h2 -org.osgi.service.http.port=7070 -#org.osgi.service.http.port.secure=7073 -argeo.node.useradmin.uris=os:/// + +#argeo.node.useradmin.uris=os:/// +argeo.directory=ipa:/// #argeo.node.useradmin.uris=ldap://cn=Directory%20Manager:argeoargeo@localhost:10389/dc=example,dc=com @@ -31,7 +30,10 @@ log.org.argeo=DEBUG # DON'T CHANGE BELOW org.eclipse.equinox.http.jetty.autostart=false -org.osgi.framework.bootdelegation=com.sun.jndi.ldap,\ +org.osgi.framework.bootdelegation=\ +sun.security.internal.spec,\ +sun.security.provider,\ +com.sun.jndi.ldap,\ com.sun.jndi.ldap.sasl,\ com.sun.security.jgss,\ com.sun.jndi.dns,\ diff --git a/swt/org.argeo.cms.swt/OSGI-INF/cmsUserApp.xml b/swt/org.argeo.cms.swt/OSGI-INF/cmsUserApp.xml index 4f2a405d5..b656accf4 100644 --- a/swt/org.argeo.cms.swt/OSGI-INF/cmsUserApp.xml +++ b/swt/org.argeo.cms.swt/OSGI-INF/cmsUserApp.xml @@ -7,4 +7,5 @@ + diff --git a/swt/org.argeo.cms.swt/src/org/argeo/cms/swt/app/CmsUserApp.java b/swt/org.argeo.cms.swt/src/org/argeo/cms/swt/app/CmsUserApp.java index add6e9edb..d8d0f3043 100644 --- a/swt/org.argeo.cms.swt/src/org/argeo/cms/swt/app/CmsUserApp.java +++ b/swt/org.argeo.cms.swt/src/org/argeo/cms/swt/app/CmsUserApp.java @@ -1,23 +1,28 @@ package org.argeo.cms.swt.app; +import java.net.URI; +import java.nio.file.Path; +import java.nio.file.spi.FileSystemProvider; import java.util.HashSet; import java.util.Set; import org.argeo.api.acr.Content; import org.argeo.api.acr.ContentRepository; -import org.argeo.api.cms.CmsContext; import org.argeo.api.cms.ux.CmsUi; import org.argeo.api.cms.ux.CmsView; import org.argeo.cms.AbstractCmsApp; import org.argeo.cms.swt.CmsSwtUi; import org.argeo.cms.swt.CmsSwtUtils; import org.argeo.cms.swt.auth.CmsLogin; +import org.argeo.eclipse.ui.fs.SimpleFsBrowser; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Composite; public class CmsUserApp extends AbstractCmsApp { private ContentRepository contentRepository; + private FileSystemProvider cmsFileSystemProvider; + @Override public Set getUiNames() { Set uiNames = new HashSet<>(); @@ -41,6 +46,12 @@ public class CmsUserApp extends AbstractCmsApp { AcrContentTreeView view = new AcrContentTreeView(cmsUi, 0, rootContent); view.setLayoutData(CmsSwtUtils.fillAll()); + } else if ("app".equals(uiName)) { + Path rootPath = cmsFileSystemProvider.getPath(URI.create("cms:///")); + SimpleFsBrowser view = new SimpleFsBrowser(parent, 0); + view.setInput(rootPath); + view.setLayoutData(CmsSwtUtils.fillAll()); + } return cmsUi; } @@ -59,4 +70,8 @@ public class CmsUserApp extends AbstractCmsApp { this.contentRepository = contentRepository; } + public void setCmsFileSystemProvider(FileSystemProvider cmsFileSystemProvider) { + this.cmsFileSystemProvider = cmsFileSystemProvider; + } + } \ No newline at end of file -- 2.30.2