import javax.xml.namespace.NamespaceContext;
import org.argeo.api.acr.Content;
+import org.argeo.api.acr.ContentNotFoundException;
import org.argeo.api.acr.search.BasicSearch;
+/**
+ * A prover of {@link Content}, which can be mounted in a
+ * {@link ProvidedRepository}.
+ */
public interface ContentProvider extends NamespaceContext {
- ProvidedContent get(ProvidedSession session, String relativePath);
-
- boolean exists(ProvidedSession session, String relativePath);
+ /**
+ * Return the content at this path, relative to the mount path.
+ *
+ * @return the content at this relative path, never <code>null</code>
+ * @throws ContentNotFoundException if there is no content at this relative path
+ */
+ ProvidedContent get(ProvidedSession session, String relativePath) throws ContentNotFoundException;
+
+ /**
+ * Whether a content exist at his relative path. The default implementation call
+ * {@link #get(ProvidedSession, String)} and check whether a
+ * {@link ContentNotFoundException} is thrown or not. It should be overridden as
+ * soon as there is a mechanism to check existence before actually getting the
+ * content.
+ */
+ default boolean exists(ProvidedSession session, String relativePath) {
+ try {
+ get(session, relativePath);
+ return true;
+ } catch (ContentNotFoundException e) {
+ return false;
+ }
+ }
+ /** The absolute path where this provider is mounted. */
String getMountPath();
+ /**
+ * Search content within this provider. The default implementation throws an
+ * {@link UnsupportedOperationException}.
+ */
+ default Spliterator<Content> search(ProvidedSession session, BasicSearch search, String relPath) {
+ throw new UnsupportedOperationException();
+ }
+
/*
* NAMESPACE CONTEXT
*/
return prefixes.hasNext() ? prefixes.next() : null;
}
- default Spliterator<Content> search(ProvidedSession session, BasicSearch search, String relPath) {
- throw new UnsupportedOperationException();
- }
-
-// default ContentName parsePrefixedName(String nameWithPrefix) {
-// return NamespaceUtils.parsePrefixedName(this, nameWithPrefix);
-// }
-//
-// default String toPrefixedName(QName name) {
-// return NamespaceUtils.toPrefixedName(this, name);
-// }
-
}
--- /dev/null
+package org.argeo.cms.acr;
+
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import javax.xml.namespace.QName;
+
+import org.argeo.api.acr.Content;
+import org.argeo.api.acr.ContentName;
+import org.argeo.api.acr.spi.ContentProvider;
+import org.argeo.api.acr.spi.ProvidedContent;
+import org.argeo.api.acr.spi.ProvidedSession;
+import org.argeo.api.cms.CmsConstants;
+
+/**
+ * Base for simple content providers based on a service supporting only one
+ * namespace. Typically used in higher level applications for domain-specific
+ * modelling.
+ */
+public abstract class AbstractSimpleContentProvider<SERVICE> implements ContentProvider {
+ private final String namespaceUri;
+ private final String defaultPrefix;
+ private SERVICE service;
+ private String mountPath;
+ private String mountName;
+
+ protected AbstractSimpleContentProvider(String namespaceUri, String defaultPrefix) {
+ this(namespaceUri, defaultPrefix, null, null);
+ }
+
+ protected AbstractSimpleContentProvider(String namespaceUri, String defaultPrefix, SERVICE service,
+ String mountPath) {
+ this.namespaceUri = namespaceUri;
+ this.defaultPrefix = defaultPrefix;
+ this.service = service;
+ setMountPath(mountPath);
+ }
+
+ /** The first level of content provided by the service. */
+ protected abstract Iterator<Content> firstLevel(ProvidedSession session);
+
+ /**
+ * Retrieve the content at this relative path. Root content is already dealt
+ * with.
+ */
+ protected abstract ProvidedContent get(ProvidedSession session, List<String> segments);
+
+ @Override
+ public final ProvidedContent get(ProvidedSession session, String relativePath) {
+ List<String> segments = ContentUtils.toPathSegments(relativePath);
+ if (segments.size() == 0)
+ return new ServiceContent(session);
+ return get(session, segments);
+ }
+
+ public void start(Map<String, String> properties) {
+ mountPath = properties.get(CmsConstants.ACR_MOUNT_PATH);
+ if (mountPath == null)
+ throw new IllegalStateException(CmsConstants.ACR_MOUNT_PATH + " must be specified.");
+ setMountPath(mountPath);
+ }
+
+ private void setMountPath(String mountPath) {
+ if (mountPath == null)
+ return;
+ this.mountPath = mountPath;
+ List<String> mountSegments = ContentUtils.toPathSegments(mountPath);
+ this.mountName = mountSegments.get(mountSegments.size() - 1);
+
+ }
+
+ @Override
+ public String getNamespaceURI(String prefix) {
+ if (defaultPrefix.equals(prefix))
+ return namespaceUri;
+ throw new IllegalArgumentException("Only prefix " + defaultPrefix + " is supported");
+ }
+
+ @Override
+ public Iterator<String> getPrefixes(String namespaceURI) {
+ if (namespaceUri.equals(namespaceURI))
+ return Collections.singletonList(defaultPrefix).iterator();
+ throw new IllegalArgumentException("Only namespace URI " + namespaceUri + " is supported");
+ }
+
+ @Override
+ public String getMountPath() {
+ return mountPath;
+ }
+
+ protected String getMountName() {
+ return mountName;
+ }
+
+ protected SERVICE getService() {
+ return service;
+ }
+
+ public void setService(SERVICE service) {
+ this.service = service;
+ }
+
+ protected class ServiceContent extends AbstractContent {
+
+ public ServiceContent(ProvidedSession session) {
+ super(session);
+ }
+
+ @Override
+ public ContentProvider getProvider() {
+ return AbstractSimpleContentProvider.this;
+ }
+
+ @Override
+ public QName getName() {
+ return new ContentName(getMountName());
+ }
+
+ @Override
+ public Content getParent() {
+ return null;
+ }
+
+ @Override
+ public Iterator<Content> iterator() {
+ return firstLevel(getSession());
+ }
+
+ }
+
+}
package org.argeo.cms.acr.directory;
import java.util.ArrayList;
-import java.util.Collections;
import java.util.Iterator;
import java.util.List;
-import javax.xml.namespace.QName;
-
import org.argeo.api.acr.ArgeoNamespace;
import org.argeo.api.acr.Content;
-import org.argeo.api.acr.ContentName;
import org.argeo.api.acr.ContentNotFoundException;
import org.argeo.api.acr.spi.ContentProvider;
import org.argeo.api.acr.spi.ProvidedContent;
import org.argeo.api.cms.directory.CmsUserManager;
import org.argeo.api.cms.directory.HierarchyUnit;
import org.argeo.api.cms.directory.UserDirectory;
-import org.argeo.cms.acr.AbstractContent;
+import org.argeo.cms.acr.AbstractSimpleContentProvider;
import org.argeo.cms.acr.ContentUtils;
import org.osgi.service.useradmin.User;
-public class DirectoryContentProvider implements ContentProvider {
- private String mountPath;
- private String mountName;
+/** A {@link ContentProvider} based on a {@link CmsUserManager} service. */
+public class DirectoryContentProvider extends AbstractSimpleContentProvider<CmsUserManager> {
- private CmsUserManager userManager;
+ public DirectoryContentProvider(CmsUserManager service, String mountPath) {
+ super(ArgeoNamespace.LDAP_NAMESPACE_URI, ArgeoNamespace.LDAP_DEFAULT_PREFIX, service, mountPath);
+ }
- public DirectoryContentProvider(String mountPath, CmsUserManager userManager) {
- this.mountPath = mountPath;
- List<String> mountSegments = ContentUtils.toPathSegments(mountPath);
- this.mountName = mountSegments.get(mountSegments.size() - 1);
- this.userManager = userManager;
+ @Override
+ protected Iterator<Content> firstLevel(ProvidedSession session) {
+ List<Content> res = new ArrayList<>();
+ for (UserDirectory userDirectory : getService().getUserDirectories()) {
+ DirectoryContent content = new DirectoryContent(session, DirectoryContentProvider.this, userDirectory);
+ res.add(content);
+ }
+ return res.iterator();
}
@Override
- public ProvidedContent get(ProvidedSession session, String relativePath) {
- List<String> segments = ContentUtils.toPathSegments(relativePath);
- if (segments.size() == 0)
- return new UserManagerContent(session);
+ public ProvidedContent get(ProvidedSession session, List<String> segments) {
String userDirectoryName = segments.get(0);
UserDirectory userDirectory = null;
- userDirectories: for (UserDirectory ud : userManager.getUserDirectories()) {
+ userDirectories: for (UserDirectory ud : getService().getUserDirectories()) {
if (userDirectoryName.equals(ud.getName())) {
userDirectory = ud;
break userDirectories;
}
}
if (userDirectory == null)
- throw new ContentNotFoundException(session, mountPath + "/" + relativePath,
+ throw new ContentNotFoundException(session, getMountPath() + "/" + ContentUtils.toPath(segments),
"Cannot find user directory " + userDirectoryName);
if (segments.size() == 1) {
return new DirectoryContent(session, this, userDirectory);
HierarchyUnit hierarchyUnit = userDirectory.getHierarchyUnit(pathWithinUserDirectory);
if (hierarchyUnit == null)
throw new ContentNotFoundException(session,
- mountPath + "/" + relativePath + "/" + pathWithinUserDirectory,
+ getMountPath() + "/" + ContentUtils.toPath(segments) + "/" + pathWithinUserDirectory,
"Cannot find " + pathWithinUserDirectory + " within " + userDirectoryName);
return new HierarchyUnitContent(session, this, hierarchyUnit);
}
@Override
public boolean exists(ProvidedSession session, String relativePath) {
- // TODO Auto-generated method stub
- return false;
- }
-
- @Override
- public String getMountPath() {
- return mountPath;
- }
-
- @Override
- public String getNamespaceURI(String prefix) {
- if (ArgeoNamespace.LDAP_DEFAULT_PREFIX.equals(prefix))
- return ArgeoNamespace.LDAP_NAMESPACE_URI;
- throw new IllegalArgumentException("Only prefix " + ArgeoNamespace.LDAP_DEFAULT_PREFIX + " is supported");
- }
-
- @Override
- public Iterator<String> getPrefixes(String namespaceURI) {
- if (ArgeoNamespace.LDAP_NAMESPACE_URI.equals(namespaceURI))
- return Collections.singletonList(ArgeoNamespace.LDAP_DEFAULT_PREFIX).iterator();
- throw new IllegalArgumentException("Only namespace URI " + ArgeoNamespace.LDAP_NAMESPACE_URI + " is supported");
- }
-
- public void setUserManager(CmsUserManager userManager) {
- this.userManager = userManager;
+ // TODO optimise?
+ return exists(session, relativePath);
}
- public CmsUserManager getUserManager() {
- return userManager;
- }
+// public void setUserManager(CmsUserManager userManager) {
+// this.userManager = userManager;
+// }
- UserManagerContent getRootContent(ProvidedSession session) {
- return new UserManagerContent(session);
+ CmsUserManager getUserManager() {
+ return getService();
}
- /*
- * COMMON UTILITIES
- */
- class UserManagerContent extends AbstractContent {
-
- public UserManagerContent(ProvidedSession session) {
- super(session);
- }
-
- @Override
- public ContentProvider getProvider() {
- return DirectoryContentProvider.this;
- }
-
- @Override
- public QName getName() {
- return new ContentName(mountName);
- }
-
- @Override
- public Content getParent() {
- return null;
- }
-
- @Override
- public Iterator<Content> iterator() {
- List<Content> res = new ArrayList<>();
- for (UserDirectory userDirectory : userManager.getUserDirectories()) {
- DirectoryContent content = new DirectoryContent(getSession(), DirectoryContentProvider.this,
- userDirectory);
- res.add(content);
- }
- return res.iterator();
- }
-
+ ServiceContent getRootContent(ProvidedSession session) {
+ return new ServiceContent(session);
}
}
try {
super.start();
// FIXME does not work on Windows
- //Path rootXml = KernelUtils.getOsgiInstancePath(ROOT_XML);
+ // Path rootXml = KernelUtils.getOsgiInstancePath(ROOT_XML);
initRootContentProvider(null);
// Path srvPath = KernelUtils.getOsgiInstancePath(CmsConstants.SRV_WORKSPACE);
}
// users
- DirectoryContentProvider directoryContentProvider = new DirectoryContentProvider(
- CmsContentRepository.DIRECTORY_BASE, userManager);
+ DirectoryContentProvider directoryContentProvider = new DirectoryContentProvider(userManager,
+ CmsContentRepository.DIRECTORY_BASE);
addProvider(directoryContentProvider);
// remote