1 package org
.argeo
.cms
.acr
;
3 import java
.io
.PrintStream
;
4 import java
.util
.ArrayList
;
6 import java
.util
.StringJoiner
;
7 import java
.util
.function
.BiConsumer
;
9 import javax
.security
.auth
.login
.LoginContext
;
10 import javax
.security
.auth
.login
.LoginException
;
11 import javax
.xml
.namespace
.QName
;
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
;
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);
29 public static void traverse(Content content
, BiConsumer
<Content
, Integer
> doIt
, Integer maxDepth
) {
30 doTraverse(content
, doIt
, 0, maxDepth
);
33 private static void doTraverse(Content content
, BiConsumer
<Content
, Integer
> doIt
, int currentDepth
,
35 doIt
.accept(content
, currentDepth
);
36 if (maxDepth
!= null && currentDepth
== maxDepth
)
38 int nextDepth
= currentDepth
+ 1;
39 for (Content child
: content
) {
40 doTraverse(child
, doIt
, nextDepth
, maxDepth
);
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
++) {
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
));
55 if (content
.hasText()) {
56 out
.println("<![CDATA[" + content
.getText().trim() + "]]>");
61 // public static <T> boolean isString(T t) {
62 // return t instanceof String;
65 public static final char SLASH
= '/';
66 public static final String ROOT_SLASH
= "" + SLASH
;
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 '/').
73 public static String
[] getParentPath(String path
) {
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
);
85 if (parentIndex
== -1) // no '/'
86 return new String
[] { "", path
};
88 return new String
[] { parentIndex
!= 0 ? path
.substring(0, parentIndex
) : "" + SLASH
,
89 path
.substring(parentIndex
+ 1) };
92 public static String
toPath(List
<String
> segments
) {
94 StringJoiner sj
= new StringJoiner("/");
95 segments
.forEach((s
) -> sj
.add(s
));
99 public static List
<String
> toPathSegments(String path
) {
100 List
<String
> res
= new ArrayList
<>();
101 if ("".equals(path
) || ROOT_SLASH
.equals(path
))
103 collectPathSegments(path
, res
);
107 private static void collectPathSegments(String path
, List
<String
> segments
) {
108 String
[] parent
= getParentPath(path
);
109 if ("".equals(parent
[1])) // root
111 segments
.add(0, parent
[1]);
112 if ("".equals(parent
[0])) // end
114 collectPathSegments(parent
[0], segments
);
117 public static void checkDoubleSlash(String path
) {
118 if (path
.contains(SLASH
+ "" + SLASH
))
119 throw new IllegalArgumentException("Path " + path
+ " contains //");
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
);
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");
143 String
[] parentPath
= getParentPath(path
);
144 Content parent
= createCollections(session
, parentPath
[0]);
145 Content content
= parent
.add(parentPath
[1], CrName
.collection
.qName());
150 public static ContentSession
openDataAdminSession(ContentRepository repository
) {
151 LoginContext loginContext
;
153 loginContext
= CmsAuth
.DATA_ADMIN
.newLoginContext();
154 loginContext
.login();
155 } catch (LoginException e1
) {
156 throw new RuntimeException("Could not login as data admin", e1
);
160 ClassLoader currentCl
= Thread
.currentThread().getContextClassLoader();
162 Thread
.currentThread().setContextClassLoader(ContentUtils
.class.getClassLoader());
163 return CurrentSubject
.callAs(loginContext
.getSubject(), () -> repository
.get());
165 Thread
.currentThread().setContextClassLoader(currentCl
);
170 private ContentUtils() {