]> git.argeo.org Git - lgpl/argeo-commons.git/blob - org.argeo.cms/src/org/argeo/cms/acr/CmsContentRepository.java
Do not log all types.
[lgpl/argeo-commons.git] / org.argeo.cms / src / org / argeo / cms / acr / CmsContentRepository.java
1 package org.argeo.cms.acr;
2
3 import java.io.IOException;
4 import java.io.InputStream;
5 import java.io.OutputStream;
6 import java.nio.file.Files;
7 import java.nio.file.Path;
8 import java.util.Collections;
9 import java.util.HashMap;
10 import java.util.Locale;
11 import java.util.Map;
12 import java.util.Set;
13
14 import javax.security.auth.login.LoginContext;
15 import javax.security.auth.login.LoginException;
16 import javax.xml.namespace.QName;
17 import javax.xml.parsers.DocumentBuilder;
18 import javax.xml.transform.OutputKeys;
19 import javax.xml.transform.Transformer;
20 import javax.xml.transform.TransformerException;
21 import javax.xml.transform.TransformerFactory;
22 import javax.xml.transform.dom.DOMSource;
23 import javax.xml.transform.stream.StreamResult;
24
25 import org.argeo.api.acr.Content;
26 import org.argeo.api.acr.ContentSession;
27 import org.argeo.api.acr.CrName;
28 import org.argeo.api.acr.spi.ContentProvider;
29 import org.argeo.api.acr.spi.ProvidedContent;
30 import org.argeo.api.acr.spi.ProvidedRepository;
31 import org.argeo.api.cms.CmsAuth;
32 import org.argeo.api.cms.CmsLog;
33 import org.argeo.api.cms.CmsSession;
34 import org.argeo.cms.acr.xml.DomContentProvider;
35 import org.argeo.cms.acr.xml.DomUtils;
36 import org.argeo.cms.auth.CurrentUser;
37 import org.argeo.cms.internal.runtime.CmsContextImpl;
38 import org.w3c.dom.DOMException;
39 import org.w3c.dom.Document;
40 import org.w3c.dom.Element;
41 import org.xml.sax.SAXException;
42
43 /**
44 * Base implementation of a {@link ProvidedRepository} integrated with a CMS.
45 */
46 public class CmsContentRepository implements ProvidedRepository {
47 private final static CmsLog log = CmsLog.getLog(CmsContentRepository.class);
48
49 private final MountManager mountManager;
50 private final TypesManager typesManager;
51
52 private CmsContentSession systemSession;
53
54 private Map<CmsSession, CmsContentSession> userSessions = Collections.synchronizedMap(new HashMap<>());
55
56 // utilities
57 private TransformerFactory transformerFactory = TransformerFactory.newInstance();
58
59 public final static String ACR_MOUNT_PATH_PROPERTY = "acr.mount.path";
60
61 public CmsContentRepository() {
62 // types
63 typesManager = new TypesManager();
64 typesManager.init();
65 Set<QName> types = typesManager.listTypes();
66 // for (QName type : types) {
67 // log.debug(type + " - " + typesManager.getAttributeTypes(type));
68 // }
69
70 systemSession = newSystemSession();
71
72 // mounts
73 mountManager = new MountManager(systemSession);
74
75 }
76
77 protected CmsContentSession newSystemSession() {
78 LoginContext loginContext;
79 try {
80 loginContext = new LoginContext(CmsAuth.DATA_ADMIN.getLoginContextName());
81 loginContext.login();
82 } catch (LoginException e1) {
83 throw new RuntimeException("Could not login as data admin", e1);
84 } finally {
85 }
86 return new CmsContentSession(this, loginContext.getSubject(), Locale.getDefault());
87 }
88
89 public void start() {
90 }
91
92 public void stop() {
93
94 }
95
96 /*
97 * REPOSITORY
98 */
99
100 @Override
101 public ContentSession get() {
102 return get(CmsContextImpl.getCmsContext().getDefaultLocale());
103 }
104
105 @Override
106 public ContentSession get(Locale locale) {
107 // Subject subject = Subject.getSubject(AccessController.getContext());
108 CmsSession cmsSession = CurrentUser.getCmsSession();
109 CmsContentSession contentSession = userSessions.get(cmsSession);
110 if (contentSession == null) {
111 final CmsContentSession newContentSession = new CmsContentSession(this, cmsSession.getSubject(), locale);
112 cmsSession.addOnCloseCallback((c) -> {
113 newContentSession.close();
114 userSessions.remove(cmsSession);
115 });
116 contentSession = newContentSession;
117 }
118 return contentSession;
119 }
120
121 public void addProvider(ContentProvider provider) {
122 mountManager.addStructuralContentProvider(provider);
123 }
124
125 public void registerTypes(String prefix, String namespaceURI, String schemaSystemId) {
126 typesManager.registerTypes(prefix, namespaceURI, schemaSystemId);
127 }
128
129 /*
130 * FACTORIES
131 */
132 public void initRootContentProvider(Path path) {
133 try {
134 // DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
135 // factory.setNamespaceAware(true);
136 // factory.setXIncludeAware(true);
137 // factory.setSchema(contentTypesManager.getSchema());
138 //
139 DocumentBuilder dBuilder = typesManager.newDocumentBuilder();
140
141 Document document;
142 // if (path != null && Files.exists(path)) {
143 // InputSource inputSource = new InputSource(path.toAbsolutePath().toUri().toString());
144 // inputSource.setEncoding(StandardCharsets.UTF_8.name());
145 // // TODO public id as well?
146 // document = dBuilder.parse(inputSource);
147 // } else {
148 document = dBuilder.newDocument();
149 Element root = document.createElementNS(CrName.CR_NAMESPACE_URI, CrName.ROOT.get().toPrefixedString());
150
151 for (String prefix : typesManager.getPrefixes().keySet()) {
152 // root.setAttributeNS(XMLConstants.XMLNS_ATTRIBUTE_NS_URI, XMLConstants.XMLNS_ATTRIBUTE + ":" + prefix,
153 // contentTypesManager.getPrefixes().get(prefix));
154 DomUtils.addNamespace(root, prefix, typesManager.getPrefixes().get(prefix));
155 }
156
157 document.appendChild(root);
158
159 // write it
160 if (path != null) {
161 try (OutputStream out = Files.newOutputStream(path)) {
162 writeDom(document, out);
163 }
164 }
165 // }
166
167 String mountPath = "/";
168 DomContentProvider contentProvider = new DomContentProvider(mountPath, document);
169 addProvider(contentProvider);
170 } catch (DOMException | IOException e) {
171 throw new IllegalStateException("Cannot init ACR root " + path, e);
172 }
173
174 }
175
176 public void writeDom(Document document, OutputStream out) throws IOException {
177 try {
178 Transformer transformer = transformerFactory.newTransformer();
179 transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
180 transformer.setOutputProperty(OutputKeys.INDENT, "yes");
181
182 DOMSource source = new DOMSource(document);
183 typesManager.validate(source);
184 StreamResult result = new StreamResult(out);
185 transformer.transform(source, result);
186 } catch (TransformerException e) {
187 throw new IOException("Cannot write dom", e);
188 }
189 }
190
191 /*
192 * MOUNT MANAGEMENT
193 */
194
195 @Override
196 public ContentProvider getMountContentProvider(Content mountPoint, boolean initialize, QName... types) {
197 String mountPath = mountPoint.getPath();
198 // TODO check consistency with types
199
200 return mountManager.getOrAddMountedProvider(mountPath, (path) -> {
201 DocumentBuilder dBuilder = typesManager.newDocumentBuilder();
202 Document document;
203 if (initialize) {
204 QName firstType = types[0];
205 document = dBuilder.newDocument();
206 String prefix = ((ProvidedContent) mountPoint).getSession().getPrefix(firstType.getNamespaceURI());
207 Element root = document.createElementNS(firstType.getNamespaceURI(),
208 prefix + ":" + firstType.getLocalPart());
209 DomUtils.addNamespace(root, prefix, firstType.getNamespaceURI());
210 document.appendChild(root);
211 } else {
212 try (InputStream in = mountPoint.open(InputStream.class)) {
213 document = dBuilder.parse(in);
214 // TODO check consistency with types
215 } catch (IOException | SAXException e) {
216 throw new IllegalStateException("Cannot load mount from " + mountPoint, e);
217 }
218 }
219 DomContentProvider contentProvider = new DomContentProvider(path, document);
220 return contentProvider;
221 });
222 }
223
224 @Override
225 public boolean shouldMount(QName... types) {
226 if (types.length == 0)
227 return false;
228 QName firstType = types[0];
229 Set<QName> registeredTypes = typesManager.listTypes();
230 if (registeredTypes.contains(firstType))
231 return true;
232 return false;
233 }
234
235 MountManager getMountManager() {
236 return mountManager;
237 }
238
239 TypesManager getTypesManager() {
240 return typesManager;
241 }
242
243 }