]> git.argeo.org Git - lgpl/argeo-commons.git/blob - org.argeo.cms/src/org/argeo/cms/acr/AbstractContentRepository.java
8ff14169868c2d4878cef8152166aa5e60a3c549
[lgpl/argeo-commons.git] / org.argeo.cms / src / org / argeo / cms / acr / AbstractContentRepository.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.HashSet;
9 import java.util.Set;
10
11 import javax.xml.namespace.QName;
12 import javax.xml.parsers.DocumentBuilder;
13 import javax.xml.transform.OutputKeys;
14 import javax.xml.transform.Transformer;
15 import javax.xml.transform.TransformerException;
16 import javax.xml.transform.TransformerFactory;
17 import javax.xml.transform.dom.DOMSource;
18 import javax.xml.transform.stream.StreamResult;
19
20 import org.argeo.api.acr.Content;
21 import org.argeo.api.acr.CrName;
22 import org.argeo.api.acr.NamespaceUtils;
23 import org.argeo.api.acr.RuntimeNamespaceContext;
24 import org.argeo.api.acr.spi.ContentProvider;
25 import org.argeo.api.acr.spi.ProvidedContent;
26 import org.argeo.api.acr.spi.ProvidedRepository;
27 import org.argeo.api.cms.CmsLog;
28 import org.argeo.cms.acr.xml.DomContentProvider;
29 import org.argeo.cms.acr.xml.DomUtils;
30 import org.w3c.dom.DOMException;
31 import org.w3c.dom.Document;
32 import org.w3c.dom.Element;
33 import org.xml.sax.SAXException;
34
35 /**
36 * Base implementation of a {@link ProvidedRepository}.
37 */
38 public abstract class AbstractContentRepository implements ProvidedRepository {
39 private final static CmsLog log = CmsLog.getLog(AbstractContentRepository.class);
40
41 private MountManager mountManager;
42 private TypesManager typesManager;
43
44 private CmsContentSession systemSession;
45
46 private Set<ContentProvider> providersToAdd = new HashSet<>();
47
48 // utilities
49 /** Should be used only to copy source and results. */
50 private TransformerFactory identityTransformerFactory = TransformerFactory.newInstance();
51
52 // public final static String ACR_MOUNT_PATH_PROPERTY = "acr.mount.path";
53
54 public AbstractContentRepository() {
55 // types
56 typesManager = new TypesManager();
57 typesManager.init();
58 Set<QName> types = typesManager.listTypes();
59 if (log.isTraceEnabled())
60 for (QName type : types) {
61 log.trace(type + " - " + typesManager.getAttributeTypes(type));
62 }
63
64 }
65
66 protected abstract CmsContentSession newSystemSession();
67
68 public void start() {
69 systemSession = newSystemSession();
70 // mounts
71 mountManager = new MountManager(systemSession);
72 }
73
74 public void stop() {
75 systemSession.close();
76 systemSession = null;
77 }
78
79 /*
80 * REPOSITORY
81 */
82 @Override
83 public void addProvider(ContentProvider provider) {
84 if (mountManager == null)
85 providersToAdd.add(provider);
86 else
87 mountManager.addStructuralContentProvider(provider);
88 }
89
90 public void registerTypes(String prefix, String namespaceURI, String schemaSystemId) {
91 typesManager.registerTypes(prefix, namespaceURI, schemaSystemId);
92 }
93
94 /*
95 * FACTORIES
96 */
97 public void initRootContentProvider(Path path) {
98 try {
99 // DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
100 // factory.setNamespaceAware(true);
101 // factory.setXIncludeAware(true);
102 // factory.setSchema(contentTypesManager.getSchema());
103 //
104 DocumentBuilder dBuilder = typesManager.newDocumentBuilder();
105
106 Document document;
107 // if (path != null && Files.exists(path)) {
108 // InputSource inputSource = new InputSource(path.toAbsolutePath().toUri().toString());
109 // inputSource.setEncoding(StandardCharsets.UTF_8.name());
110 // // TODO public id as well?
111 // document = dBuilder.parse(inputSource);
112 // } else {
113 document = dBuilder.newDocument();
114 Element root = document.createElementNS(CrName.CR_NAMESPACE_URI,
115 NamespaceUtils.toPrefixedName(CrName.root.qName()));
116
117 for (String prefix : RuntimeNamespaceContext.getPrefixes().keySet()) {
118 // root.setAttributeNS(XMLConstants.XMLNS_ATTRIBUTE_NS_URI, XMLConstants.XMLNS_ATTRIBUTE + ":" + prefix,
119 // contentTypesManager.getPrefixes().get(prefix));
120 DomUtils.addNamespace(root, prefix,
121 RuntimeNamespaceContext.getNamespaceContext().getNamespaceURI(prefix));
122 }
123
124 document.appendChild(root);
125
126 // write it
127 if (path != null) {
128 try (OutputStream out = Files.newOutputStream(path)) {
129 writeDom(document, out);
130 }
131 }
132 // }
133
134 String mountPath = "/";
135 DomContentProvider contentProvider = new DomContentProvider(mountPath, document);
136 addProvider(contentProvider);
137 } catch (DOMException | IOException e) {
138 throw new IllegalStateException("Cannot init ACR root " + path, e);
139 }
140
141 // add content providers already notified
142 for (ContentProvider contentProvider : providersToAdd)
143 addProvider(contentProvider);
144 providersToAdd.clear();
145 }
146
147 public void writeDom(Document document, OutputStream out) throws IOException {
148 try {
149 Transformer transformer = identityTransformerFactory.newTransformer();
150 transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
151 transformer.setOutputProperty(OutputKeys.INDENT, "yes");
152
153 DOMSource source = new DOMSource(document);
154 typesManager.validate(source);
155 StreamResult result = new StreamResult(out);
156 transformer.transform(source, result);
157 } catch (TransformerException e) {
158 throw new IOException("Cannot write dom", e);
159 }
160 }
161
162 /*
163 * MOUNT MANAGEMENT
164 */
165
166 @Override
167 public ContentProvider getMountContentProvider(Content mountPoint, boolean initialize, QName... types) {
168 String mountPath = mountPoint.getPath();
169 // TODO check consistency with types
170
171 return mountManager.getOrAddMountedProvider(mountPath, (path) -> {
172 DocumentBuilder dBuilder = typesManager.newDocumentBuilder();
173 Document document;
174 if (initialize) {
175 QName firstType = types[0];
176 document = dBuilder.newDocument();
177 String prefix = ((ProvidedContent) mountPoint).getSession().getPrefix(firstType.getNamespaceURI());
178 Element root = document.createElementNS(firstType.getNamespaceURI(),
179 prefix + ":" + firstType.getLocalPart());
180 DomUtils.addNamespace(root, prefix, firstType.getNamespaceURI());
181 document.appendChild(root);
182 } else {
183 try (InputStream in = mountPoint.open(InputStream.class)) {
184 document = dBuilder.parse(in);
185 // TODO check consistency with types
186 } catch (IOException | SAXException e) {
187 throw new IllegalStateException("Cannot load mount from " + mountPoint, e);
188 }
189 }
190 DomContentProvider contentProvider = new DomContentProvider(path, document);
191 return contentProvider;
192 });
193 }
194
195 @Override
196 public boolean shouldMount(QName... types) {
197 if (types.length == 0)
198 return false;
199 QName firstType = types[0];
200 Set<QName> registeredTypes = typesManager.listTypes();
201 if (registeredTypes.contains(firstType))
202 return true;
203 return false;
204 }
205
206 MountManager getMountManager() {
207 return mountManager;
208 }
209
210 TypesManager getTypesManager() {
211 return typesManager;
212 }
213 }