X-Git-Url: https://git.argeo.org/?a=blobdiff_plain;f=org.argeo.cms%2Fsrc%2Forg%2Fargeo%2Fcms%2Facr%2FContentUtils.java;h=a6acb8a34bc9505e2c44badbbfe65b94941c2d5e;hb=54df376a9c2dd458a82eaa09bfbb718fe699dd0d;hp=2dcaeafaada5349810b0b659de825ffd3b390871;hpb=dcdbf77c4ec46f1dcad5d3fa011fe072e921f187;p=lgpl%2Fargeo-commons.git diff --git a/org.argeo.cms/src/org/argeo/cms/acr/ContentUtils.java b/org.argeo.cms/src/org/argeo/cms/acr/ContentUtils.java index 2dcaeafaa..a6acb8a34 100644 --- a/org.argeo.cms/src/org/argeo/cms/acr/ContentUtils.java +++ b/org.argeo.cms/src/org/argeo/cms/acr/ContentUtils.java @@ -1,11 +1,26 @@ package org.argeo.cms.acr; import java.io.PrintStream; +import java.util.ArrayList; +import java.util.List; +import java.util.StringJoiner; import java.util.function.BiConsumer; +import javax.security.auth.login.LoginContext; +import javax.security.auth.login.LoginException; import javax.xml.namespace.QName; import org.argeo.api.acr.Content; +import org.argeo.api.acr.ContentRepository; +import org.argeo.api.acr.ContentSession; +import org.argeo.api.acr.DName; +import org.argeo.api.cms.CmsAuth; +import org.argeo.api.cms.directory.Directory; +import org.argeo.api.cms.directory.HierarchyUnit; +import org.argeo.cms.CmsUserManager; +import org.argeo.cms.osgi.useradmin.UserDirectory; +import org.argeo.cms.util.CurrentSubject; +import org.osgi.service.useradmin.Role; /** Utilities and routines around {@link Content}. */ public class ContentUtils { @@ -49,18 +64,137 @@ public class ContentUtils { // return t instanceof String; // } + public static final char SLASH = '/'; + public static final String SLASH_STRING = Character.toString(SLASH); + public static final String ROOT_SLASH = "" + SLASH; + public static final String EMPTY = ""; + /** * Split a path (with '/' separator) in an array of length 2, the first part * being the parent path (which could be either absolute or relative), the - * second one being the last segment, (guaranteed to be with '/'). + * second one being the last segment, (guaranteed to be without a '/'). */ public static String[] getParentPath(String path) { - int parentIndex = path.lastIndexOf('/'); - // TODO make it more robust - return new String[] { parentIndex != 0 ? path.substring(0, parentIndex) : "/", + if (path == null) + throw new IllegalArgumentException("Path cannot be null"); + if (path.length() == 0) + throw new IllegalArgumentException("Path cannot be empty"); + checkDoubleSlash(path); + int parentIndex = path.lastIndexOf(SLASH); + if (parentIndex == path.length() - 1) {// trailing '/' + path = path.substring(0, path.length() - 1); + parentIndex = path.lastIndexOf(SLASH); + } + + if (parentIndex == -1) // no '/' + return new String[] { EMPTY, path }; + + return new String[] { parentIndex != 0 ? path.substring(0, parentIndex) : "" + SLASH, path.substring(parentIndex + 1) }; } + public static String toPath(List segments) { + // TODO checks + StringJoiner sj = new StringJoiner("/"); + segments.forEach((s) -> sj.add(s)); + return sj.toString(); + } + + public static List toPathSegments(String path) { + List res = new ArrayList<>(); + if (EMPTY.equals(path) || ROOT_SLASH.equals(path)) + return res; + collectPathSegments(path, res); + return res; + } + + private static void collectPathSegments(String path, List segments) { + String[] parent = getParentPath(path); + if (EMPTY.equals(parent[1])) // root + return; + segments.add(0, parent[1]); + if (EMPTY.equals(parent[0])) // end + return; + collectPathSegments(parent[0], segments); + } + + public static void checkDoubleSlash(String path) { + if (path.contains(SLASH + "" + SLASH)) + throw new IllegalArgumentException("Path " + path + " contains //"); + } + + /* + * DIRECTORY + */ + + public static Content roleToContent(CmsUserManager userManager, ContentSession contentSession, Role role) { + UserDirectory userDirectory = userManager.getDirectory(role); + String path = directoryPath(userDirectory) + userDirectory.getRolePath(role); + Content content = contentSession.get(path); + return content; + } + + public static Content hierarchyUnitToContent(ContentSession contentSession, HierarchyUnit hierarchyUnit) { + Directory directory = hierarchyUnit.getDirectory(); + StringJoiner relativePath = new StringJoiner(SLASH_STRING); + buildHierarchyUnitPath(hierarchyUnit, relativePath); + String path = directoryPath(directory) + relativePath.toString(); + Content content = contentSession.get(path); + return content; + } + + /** The path to this {@link Directory}. Ends with a /. */ + private static String directoryPath(Directory directory) { + return CmsContentRepository.DIRECTORY_BASE + SLASH + directory.getName() + SLASH; + } + + /** Recursively build a relative path of a {@link HierarchyUnit}. */ + private static void buildHierarchyUnitPath(HierarchyUnit current, StringJoiner relativePath) { + if (current.getParent() == null) // directory + return; + buildHierarchyUnitPath(current.getParent(), relativePath); + relativePath.add(current.getHierarchyUnitName()); + } + + /* + * CONSUMER UTILS + */ + + public static Content createCollections(ContentSession session, String path) { + if (session.exists(path)) { + Content content = session.get(path); + if (!content.isContentClass(DName.collection.qName())) { + throw new IllegalStateException("Content " + path + " already exists, but is not a collection"); + } else { + return content; + } + } else { + String[] parentPath = getParentPath(path); + Content parent = createCollections(session, parentPath[0]); + Content content = parent.add(parentPath[1], DName.collection.qName()); + return content; + } + } + + public static ContentSession openDataAdminSession(ContentRepository repository) { + LoginContext loginContext; + try { + loginContext = CmsAuth.DATA_ADMIN.newLoginContext(); + loginContext.login(); + } catch (LoginException e1) { + throw new RuntimeException("Could not login as data admin", e1); + } finally { + } + + ClassLoader currentCl = Thread.currentThread().getContextClassLoader(); + try { + Thread.currentThread().setContextClassLoader(ContentUtils.class.getClassLoader()); + return CurrentSubject.callAs(loginContext.getSubject(), () -> repository.get()); + } finally { + Thread.currentThread().setContextClassLoader(currentCl); + } + } + /** Singleton. */ private ContentUtils() {