X-Git-Url: https://git.argeo.org/?a=blobdiff_plain;f=org.argeo.cms%2Fsrc%2Forg%2Fargeo%2Fcms%2Facr%2FCmsContentRepository.java;h=d91fb16fec9ae8936fe28e72c6e889b88d27bf88;hb=e3db2eba9a7f8380a6f76d7b0e6cd4825e91893e;hp=50438e89a094b4cf7411c3bb86a7358eb93a5b30;hpb=ceb6d574e9ea49fcac490d0923d23f259f271f8d;p=lgpl%2Fargeo-commons.git diff --git a/org.argeo.cms/src/org/argeo/cms/acr/CmsContentRepository.java b/org.argeo.cms/src/org/argeo/cms/acr/CmsContentRepository.java index 50438e89a..d91fb16fe 100644 --- a/org.argeo.cms/src/org/argeo/cms/acr/CmsContentRepository.java +++ b/org.argeo.cms/src/org/argeo/cms/acr/CmsContentRepository.java @@ -1,8 +1,8 @@ package org.argeo.cms.acr; import java.io.IOException; -import java.io.Writer; -import java.nio.charset.StandardCharsets; +import java.io.InputStream; +import java.io.OutputStream; import java.nio.file.Files; import java.nio.file.Path; import java.util.Collections; @@ -11,24 +11,25 @@ import java.util.Iterator; import java.util.Locale; import java.util.Map; import java.util.NavigableMap; +import java.util.Set; import java.util.TreeMap; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionStage; +import java.util.function.Consumer; import java.util.stream.Collectors; import javax.security.auth.Subject; import javax.security.auth.login.LoginContext; import javax.security.auth.login.LoginException; -import javax.xml.XMLConstants; +import javax.xml.namespace.QName; import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.OutputKeys; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; -import javax.xml.transform.TransformerFactoryConfigurationError; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; +import javax.xml.validation.Validator; import org.argeo.api.acr.Content; import org.argeo.api.acr.ContentSession; @@ -36,21 +37,20 @@ import org.argeo.api.acr.ContentUtils; import org.argeo.api.acr.CrName; import org.argeo.api.acr.NamespaceUtils; import org.argeo.api.acr.spi.ContentProvider; +import org.argeo.api.acr.spi.ProvidedContent; import org.argeo.api.acr.spi.ProvidedRepository; import org.argeo.api.acr.spi.ProvidedSession; import org.argeo.api.cms.CmsAuth; import org.argeo.api.cms.CmsLog; import org.argeo.api.cms.CmsSession; import org.argeo.cms.acr.xml.DomContentProvider; +import org.argeo.cms.acr.xml.DomUtils; import org.argeo.cms.auth.CurrentUser; import org.argeo.cms.internal.runtime.CmsContextImpl; import org.w3c.dom.DOMException; import org.w3c.dom.Document; import org.w3c.dom.Element; -import org.xml.sax.ErrorHandler; -import org.xml.sax.InputSource; import org.xml.sax.SAXException; -import org.xml.sax.SAXParseException; /** * Base implementation of a {@link ProvidedRepository} integrated with a CMS. @@ -70,11 +70,19 @@ public class CmsContentRepository implements ProvidedRepository { private Map userSessions = Collections.synchronizedMap(new HashMap<>()); + // utilities + private TransformerFactory transformerFactory = TransformerFactory.newInstance(); + + public final static String ACR_MOUNT_PATH_PROPERTY = "acr.mount.path"; + public CmsContentRepository() { contentTypesManager = new ContentTypesManager(); contentTypesManager.init(); - contentTypesManager.listTypes(); - + Set types = contentTypesManager.listTypes(); + for (QName type : types) { + log.debug(type); + } + systemSession = newSystemSession(); } @@ -152,30 +160,12 @@ public class CmsContentRepository implements ProvidedRepository { */ public void initRootContentProvider(Path path) { try { - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - factory.setNamespaceAware(true); - factory.setXIncludeAware(true); - // factory.setSchema(schema); - - factory.setSchema(contentTypesManager.getSchema()); - - DocumentBuilder dBuilder = factory.newDocumentBuilder(); - dBuilder.setErrorHandler(new ErrorHandler() { - - @Override - public void warning(SAXParseException exception) throws SAXException { - } - - @Override - public void fatalError(SAXParseException exception) throws SAXException { - } - - @Override - public void error(SAXParseException exception) throws SAXException { - log.error(exception); - - } - }); +// DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); +// factory.setNamespaceAware(true); +// factory.setXIncludeAware(true); +// factory.setSchema(contentTypesManager.getSchema()); +// + DocumentBuilder dBuilder = contentTypesManager.newDocumentBuilder(); Document document; // if (path != null && Files.exists(path)) { @@ -188,33 +178,93 @@ public class CmsContentRepository implements ProvidedRepository { Element root = document.createElementNS(CrName.CR_NAMESPACE_URI, CrName.ROOT.get().toPrefixedString()); for (String prefix : contentTypesManager.getPrefixes().keySet()) { - root.setAttributeNS(XMLConstants.XMLNS_ATTRIBUTE_NS_URI, XMLConstants.XMLNS_ATTRIBUTE + ":" + prefix, - contentTypesManager.getPrefixes().get(prefix)); +// root.setAttributeNS(XMLConstants.XMLNS_ATTRIBUTE_NS_URI, XMLConstants.XMLNS_ATTRIBUTE + ":" + prefix, +// contentTypesManager.getPrefixes().get(prefix)); + DomUtils.addNamespace(root, prefix, contentTypesManager.getPrefixes().get(prefix)); } document.appendChild(root); // write it if (path != null) { - TransformerFactory transformerFactory = TransformerFactory.newInstance(); - Transformer transformer = transformerFactory.newTransformer(); - DOMSource source = new DOMSource(document); - try (Writer writer = Files.newBufferedWriter(path, StandardCharsets.UTF_8)) { - StreamResult result = new StreamResult(writer); - transformer.transform(source, result); + try (OutputStream out = Files.newOutputStream(path)) { + writeDom(document, out); } } // } - DomContentProvider contentProvider = new DomContentProvider(document); + DomContentProvider contentProvider = new DomContentProvider(null, document); addProvider("/", contentProvider); - } catch (DOMException | ParserConfigurationException | IOException | TransformerFactoryConfigurationError - | TransformerException e) { + } catch (DOMException | IOException e) { throw new IllegalStateException("Cannot init ACR root " + path, e); } } + public void writeDom(Document document, OutputStream out) throws IOException { + try { + Transformer transformer = transformerFactory.newTransformer(); + transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); + transformer.setOutputProperty(OutputKeys.INDENT, "yes"); + + DOMSource source = new DOMSource(document); + contentTypesManager.validate(source); + StreamResult result = new StreamResult(out); + transformer.transform(source, result); + } catch (TransformerException e) { + throw new IOException("Cannot write dom", e); + } + } + + /* + * MOUNT MANAGEMENT + */ + + @Override + public ContentProvider getMountContentProvider(Content mountPoint, boolean initialize, QName... types) { + String mountPath = mountPoint.getPath(); + if (partitions.containsKey(mountPath)) + // TODO check consistency with types + return partitions.get(mountPath); + DocumentBuilder dBuilder = contentTypesManager.newDocumentBuilder(); + Document document; + if (initialize) { + QName firstType = types[0]; + document = dBuilder.newDocument(); + String prefix = ((ProvidedContent) mountPoint).getSession().getPrefix(firstType.getNamespaceURI()); + Element root = document.createElementNS(firstType.getNamespaceURI(), + prefix + ":" + firstType.getLocalPart()); + DomUtils.addNamespace(root, prefix, firstType.getNamespaceURI()); + document.appendChild(root); +// try (OutputStream out = mountPoint.open(OutputStream.class)) { +// writeDom(document, out); +// } catch (IOException e) { +// throw new IllegalStateException("Cannot write mount from " + mountPoint, e); +// } + } else { + try (InputStream in = mountPoint.open(InputStream.class)) { + document = dBuilder.parse(in); + // TODO check consistency with types + } catch (IOException | SAXException e) { + throw new IllegalStateException("Cannot load mount from " + mountPoint, e); + } + } + DomContentProvider contentProvider = new DomContentProvider(mountPath, document); + partitions.put(mountPath, contentProvider); + return contentProvider; + } + + @Override + public boolean shouldMount(QName... types) { + if (types.length == 0) + throw new IllegalArgumentException("Types must be provided"); + QName firstType = types[0]; + Set registeredTypes = contentTypesManager.listTypes(); + if (registeredTypes.contains(firstType)) + return true; + return false; + } + /* * NAMESPACE CONTEXT */ @@ -229,6 +279,8 @@ public class CmsContentRepository implements ProvidedRepository { private CompletableFuture closed = new CompletableFuture<>(); + private CompletableFuture edition; + public CmsContentSession(Subject subject, Locale locale) { this.subject = subject; this.locale = locale; @@ -271,6 +323,17 @@ public class CmsContentRepository implements ProvidedRepository { return CmsContentRepository.this; } + /* + * MOUNT MANAGEMENT + */ + @Override + public Content getMountPoint(String path) { + String[] parent = ContentUtils.getParentPath(path); + ProvidedContent mountParent = (ProvidedContent) get(parent[0]); +// Content mountPoint = mountParent.getProvider().get(CmsContentSession.this, null, path); + return mountParent.getMountPoint(parent[1]); + } + /* * NAMESPACE CONTEXT */ @@ -288,6 +351,28 @@ public class CmsContentRepository implements ProvidedRepository { namespaceURI); } + @Override + public CompletionStage edit(Consumer work) { + edition = CompletableFuture.supplyAsync(() -> { + work.accept(this); + return this; + }).thenApply((s) -> { + // TODO optimise + for (ContentProvider provider : partitions.values()) { + if (provider instanceof DomContentProvider) { + ((DomContentProvider) provider).persist(s); + } + } + return s; + }); + return edition.minimalCompletionStage(); + } + + @Override + public boolean isEditing() { + return edition != null && !edition.isDone(); + } + // @Override // public String findNamespace(String prefix) { // return prefixes.get(prefix);