]> git.argeo.org Git - lgpl/argeo-commons.git/blob - ContentUtils.java
17144cfdb660cfceaf84c54016b46b6f44c1ac8e
[lgpl/argeo-commons.git] / ContentUtils.java
1 package org.argeo.cms.acr;
2
3 import java.io.PrintStream;
4 import java.util.ArrayList;
5 import java.util.List;
6 import java.util.StringJoiner;
7 import java.util.function.BiConsumer;
8
9 import javax.security.auth.login.LoginContext;
10 import javax.security.auth.login.LoginException;
11 import javax.xml.namespace.QName;
12
13 import org.argeo.api.acr.Content;
14 import org.argeo.api.acr.ContentRepository;
15 import org.argeo.api.acr.ContentSession;
16 import org.argeo.api.acr.CrName;
17 import org.argeo.api.cms.CmsAuth;
18 import org.argeo.cms.CmsUserManager;
19 import org.argeo.osgi.useradmin.UserDirectory;
20 import org.argeo.util.CurrentSubject;
21 import org.osgi.service.useradmin.Role;
22
23 /** Utilities and routines around {@link Content}. */
24 public class ContentUtils {
25 public static void traverse(Content content, BiConsumer<Content, Integer> doIt) {
26 traverse(content, doIt, (Integer) null);
27 }
28
29 public static void traverse(Content content, BiConsumer<Content, Integer> doIt, Integer maxDepth) {
30 doTraverse(content, doIt, 0, maxDepth);
31 }
32
33 private static void doTraverse(Content content, BiConsumer<Content, Integer> doIt, int currentDepth,
34 Integer maxDepth) {
35 doIt.accept(content, currentDepth);
36 if (maxDepth != null && currentDepth == maxDepth)
37 return;
38 int nextDepth = currentDepth + 1;
39 for (Content child : content) {
40 doTraverse(child, doIt, nextDepth, maxDepth);
41 }
42 }
43
44 public static void print(Content content, PrintStream out, int depth, boolean printText) {
45 StringBuilder sb = new StringBuilder();
46 for (int i = 0; i < depth; i++) {
47 sb.append(" ");
48 }
49 String prefix = sb.toString();
50 out.println(prefix + content.getName());
51 for (QName key : content.keySet()) {
52 out.println(prefix + " " + key + "=" + content.get(key));
53 }
54 if (printText) {
55 if (content.hasText()) {
56 out.println("<![CDATA[" + content.getText().trim() + "]]>");
57 }
58 }
59 }
60
61 // public static <T> boolean isString(T t) {
62 // return t instanceof String;
63 // }
64
65 public static final char SLASH = '/';
66 public static final String ROOT_SLASH = "" + SLASH;
67
68 /**
69 * Split a path (with '/' separator) in an array of length 2, the first part
70 * being the parent path (which could be either absolute or relative), the
71 * second one being the last segment, (guaranteed to be without a '/').
72 */
73 public static String[] getParentPath(String path) {
74 if (path == null)
75 throw new IllegalArgumentException("Path cannot be null");
76 if (path.length() == 0)
77 throw new IllegalArgumentException("Path cannot be empty");
78 checkDoubleSlash(path);
79 int parentIndex = path.lastIndexOf(SLASH);
80 if (parentIndex == path.length() - 1) {// trailing '/'
81 path = path.substring(0, path.length() - 1);
82 parentIndex = path.lastIndexOf(SLASH);
83 }
84
85 if (parentIndex == -1) // no '/'
86 return new String[] { "", path };
87
88 return new String[] { parentIndex != 0 ? path.substring(0, parentIndex) : "" + SLASH,
89 path.substring(parentIndex + 1) };
90 }
91
92 public static String toPath(List<String> segments) {
93 // TODO checks
94 StringJoiner sj = new StringJoiner("/");
95 segments.forEach((s) -> sj.add(s));
96 return sj.toString();
97 }
98
99 public static List<String> toPathSegments(String path) {
100 List<String> res = new ArrayList<>();
101 if ("".equals(path) || ROOT_SLASH.equals(path))
102 return res;
103 collectPathSegments(path, res);
104 return res;
105 }
106
107 private static void collectPathSegments(String path, List<String> segments) {
108 String[] parent = getParentPath(path);
109 if ("".equals(parent[1])) // root
110 return;
111 segments.add(0, parent[1]);
112 if ("".equals(parent[0])) // end
113 return;
114 collectPathSegments(parent[0], segments);
115 }
116
117 public static void checkDoubleSlash(String path) {
118 if (path.contains(SLASH + "" + SLASH))
119 throw new IllegalArgumentException("Path " + path + " contains //");
120 }
121
122 public static Content roleToContent(CmsUserManager userManager, ContentSession contentSession, Role role) {
123 UserDirectory userDirectory = userManager.getDirectory(role);
124 String path = CmsContentRepository.DIRECTORY_BASE + SLASH + userDirectory.getName() + SLASH
125 + userDirectory.getRolePath(role);
126 Content content = contentSession.get(path);
127 return content;
128 }
129
130 /*
131 * CONSUMER UTILS
132 */
133
134 public static Content createCollections(ContentSession session, String path) {
135 if (session.exists(path)) {
136 Content content = session.get(path);
137 if (!content.isContentClass(CrName.collection.qName())) {
138 throw new IllegalStateException("Content " + path + " already exists, but is not a collection");
139 } else {
140 return content;
141 }
142 } else {
143 String[] parentPath = getParentPath(path);
144 Content parent = createCollections(session, parentPath[0]);
145 Content content = parent.add(parentPath[1], CrName.collection.qName());
146 return content;
147 }
148 }
149
150 public static ContentSession openDataAdminSession(ContentRepository repository) {
151 LoginContext loginContext;
152 try {
153 loginContext = CmsAuth.DATA_ADMIN.newLoginContext();
154 loginContext.login();
155 } catch (LoginException e1) {
156 throw new RuntimeException("Could not login as data admin", e1);
157 } finally {
158 }
159
160 ClassLoader currentCl = Thread.currentThread().getContextClassLoader();
161 try {
162 Thread.currentThread().setContextClassLoader(ContentUtils.class.getClassLoader());
163 return CurrentSubject.callAs(loginContext.getSubject(), () -> repository.get());
164 } finally {
165 Thread.currentThread().setContextClassLoader(currentCl);
166 }
167 }
168
169 /** Singleton. */
170 private ContentUtils() {
171
172 }
173
174 }