Improve namespace management
authorMathieu Baudier <mbaudier@argeo.org>
Tue, 24 May 2022 06:05:41 +0000 (08:05 +0200)
committerMathieu Baudier <mbaudier@argeo.org>
Tue, 24 May 2022 06:05:41 +0000 (08:05 +0200)
org.argeo.cms/src/org/argeo/cms/acr/CmsContentRepository.java
org.argeo.cms/src/org/argeo/cms/acr/fs/FsContentProvider.java
org.argeo.cms/src/org/argeo/cms/acr/xml/DomContent.java
org.argeo.cms/src/org/argeo/cms/acr/xml/DomContentProvider.java
org.argeo.cms/src/org/argeo/cms/auth/CmsAuthUtils.java
org.argeo.cms/src/org/argeo/cms/internal/runtime/CmsContextImpl.java

index 923142c82333ec02d7d566cb3a9503065c2d5c93..b1f715ae3d7d8805325874ce6b41ddcb14f6f548 100644 (file)
@@ -11,7 +11,6 @@ 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;
@@ -29,7 +28,6 @@ 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.Schema;
 
 import org.argeo.api.acr.Content;
 import org.argeo.api.acr.ContentSession;
@@ -64,7 +62,7 @@ public class CmsContentRepository implements ProvidedRepository {
        // TODO synchronize ?
        private NavigableMap<String, String> prefixes = new TreeMap<>();
 
-       private Schema schema;
+//     private Schema schema;
 
        private CmsContentSession systemSession;
 
@@ -176,7 +174,7 @@ public class CmsContentRepository implements ProvidedRepository {
                        });
 
                        Document document;
-                       if (Files.exists(path)) {
+                       if (path != null && Files.exists(path)) {
                                InputSource inputSource = new InputSource(path.toAbsolutePath().toUri().toString());
                                inputSource.setEncoding(StandardCharsets.UTF_8.name());
                                // TODO public id as well?
@@ -194,10 +192,11 @@ public class CmsContentRepository implements ProvidedRepository {
                                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);
-                               }
+                               if (path != null)
+                                       try (Writer writer = Files.newBufferedWriter(path, StandardCharsets.UTF_8)) {
+                                               StreamResult result = new StreamResult(writer);
+                                               transformer.transform(source, result);
+                                       }
                        }
 
                        DomContentProvider contentProvider = new DomContentProvider(document);
@@ -240,6 +239,8 @@ public class CmsContentRepository implements ProvidedRepository {
                @Override
                public Content get(String path) {
                        Map.Entry<String, ContentProvider> entry = partitions.floorEntry(path);
+                       if (entry == null)
+                               throw new IllegalArgumentException("No entry provider found for " + path);
                        String mountPath = entry.getKey();
                        ContentProvider provider = entry.getValue();
                        String relativePath = path.substring(mountPath.length());
index 65bdd343ef72b213289e982008f917940877c8c2..37401a29c7f894117a2a0240910ee0cd3c5fe595 100644 (file)
@@ -64,11 +64,24 @@ public class FsContentProvider implements ContentProvider {
                        throws IOException {
                if (!prefixes.containsKey(prefix)) {
                        ByteBuffer bb = ByteBuffer.wrap(namespace.getBytes(StandardCharsets.UTF_8));
-                       int size = udfav.write(XMLNS_ + prefix, bb);
+                       udfav.write(XMLNS_ + prefix, bb);
                        prefixes.put(prefix, namespace);
                }
        }
 
+       public void registerPrefix(String prefix, String namespace) {
+               if (prefixes.containsKey(prefix))
+                       prefixes.remove(prefix);
+               try {
+                       UserDefinedFileAttributeView udfav = Files.getFileAttributeView(rootPath,
+                                       UserDefinedFileAttributeView.class);
+                       addDefaultNamespace(udfav, prefix, namespace);
+               } catch (IOException e) {
+                       throw new RuntimeException("Cannot register namespace " + prefix + " " + namespace + " on " + rootPath, e);
+               }
+
+       }
+
        boolean isRoot(Path path) {
                try {
                        return isRoot && Files.isSameFile(rootPath, path);
index 5cb4583624c59fc41dd17956ab5ec355013a0cdf..9e370db0c07ebfd552186300c59b677ff87952c3 100644 (file)
@@ -55,27 +55,27 @@ public class DomContent extends AbstractContent implements ProvidedContent {
                        if (namespaceURI == null) {
                                return toQName(node, node.getLocalName());
                        } else {
-                               String contextPrefix = session.getPrefix(namespaceURI);
+                               String contextPrefix = provider.getPrefix(namespaceURI);
                                if (contextPrefix == null)
                                        throw new IllegalStateException("Namespace " + namespaceURI + " is unbound");
-                               return toQName(node, namespaceURI, node.getLocalName(), session);
+                               return toQName(node, namespaceURI, node.getLocalName(), provider);
                        }
                } else {
                        String namespaceURI = node.getNamespaceURI();
                        if (namespaceURI == null)
                                namespaceURI = node.getOwnerDocument().lookupNamespaceURI(prefix);
                        if (namespaceURI == null) {
-                               namespaceURI = session.getNamespaceURI(prefix);
+                               namespaceURI = provider.getNamespaceURI(prefix);
                                if (XMLConstants.NULL_NS_URI.equals(namespaceURI))
                                        throw new IllegalStateException("Prefix " + prefix + " is unbound");
                                // TODO bind the prefix in the document?
                        }
-                       return toQName(node, namespaceURI, node.getLocalName(), session);
+                       return toQName(node, namespaceURI, node.getLocalName(), provider);
                }
        }
 
        protected QName toQName(Node source, String namespaceURI, String localName, NamespaceContext namespaceContext) {
-               return new ContentName(namespaceURI, localName, session);
+               return new ContentName(namespaceURI, localName, namespaceContext);
        }
 
        protected QName toQName(Node source, String localName) {
@@ -98,6 +98,7 @@ public class DomContent extends AbstractContent implements ProvidedContent {
                return result;
        }
 
+       @SuppressWarnings("unchecked")
        @Override
        public <A> Optional<A> get(QName key, Class<A> clss) {
                String namespaceUriOrNull = XMLConstants.NULL_NS_URI.equals(key.getNamespaceURI()) ? null
index efca3effdd7737e9dc13c464a74d41e640d3d472..4db49343386902e40bdd2e15f7a61bf2996b823a 100644 (file)
@@ -6,8 +6,6 @@ import java.util.Iterator;
 import java.util.List;
 
 import javax.xml.namespace.NamespaceContext;
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.xpath.XPath;
 import javax.xml.xpath.XPathConstants;
 import javax.xml.xpath.XPathExpressionException;
@@ -15,15 +13,12 @@ import javax.xml.xpath.XPathFactory;
 
 import org.argeo.api.acr.Content;
 import org.argeo.api.acr.ContentNotFoundException;
-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.ProvidedSession;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 import org.w3c.dom.NodeList;
-import org.xml.sax.ErrorHandler;
-import org.xml.sax.SAXException;
-import org.xml.sax.SAXParseException;
 
 public class DomContentProvider implements ContentProvider, NamespaceContext {
        private Document document;
@@ -41,7 +36,7 @@ public class DomContentProvider implements ContentProvider, NamespaceContext {
                        @Override
                        protected XPath initialValue() {
                                // TODO set the document as namespace context?
-                               XPath res= xPathFactory.newXPath();
+                               XPath res = xPathFactory.newXPath();
                                res.setNamespaceContext(DomContentProvider.this);
                                return res;
                        }
@@ -87,11 +82,17 @@ public class DomContentProvider implements ContentProvider, NamespaceContext {
         */
        @Override
        public String getNamespaceURI(String prefix) {
+               String namespaceURI = NamespaceUtils.getStandardNamespaceURI(prefix);
+               if (namespaceURI != null)
+                       return namespaceURI;
                return document.lookupNamespaceURI(prefix);
        }
 
        @Override
        public String getPrefix(String namespaceURI) {
+               String prefix = NamespaceUtils.getStandardPrefix(namespaceURI);
+               if (prefix != null)
+                       return prefix;
                return document.lookupPrefix(namespaceURI);
        }
 
@@ -102,5 +103,4 @@ public class DomContentProvider implements ContentProvider, NamespaceContext {
                return Collections.unmodifiableList(res).iterator();
        }
 
-       
 }
index 46adcf8a516db80a509476947cbcb4c9ee5cd364..4998c89ff818fea5beb1877f583ebf87b6c9f4a9 100644 (file)
@@ -1,7 +1,6 @@
 package org.argeo.cms.auth;
 
 import java.security.Principal;
-import java.util.Collection;
 import java.util.Locale;
 import java.util.Set;
 import java.util.UUID;
@@ -11,20 +10,16 @@ import javax.naming.ldap.LdapName;
 import javax.security.auth.Subject;
 import javax.security.auth.x500.X500Principal;
 
-import org.argeo.api.cms.CmsSession;
-import org.argeo.api.cms.CmsSessionId;
-import org.argeo.api.cms.DataAdminPrincipal;
 import org.argeo.api.cms.AnonymousPrincipal;
 import org.argeo.api.cms.CmsConstants;
+import org.argeo.api.cms.CmsSessionId;
+import org.argeo.api.cms.DataAdminPrincipal;
 import org.argeo.cms.internal.auth.CmsSessionImpl;
 import org.argeo.cms.internal.auth.ImpliedByPrincipal;
 import org.argeo.cms.internal.http.WebCmsSessionImpl;
 import org.argeo.cms.internal.runtime.CmsContextImpl;
 import org.argeo.cms.security.NodeSecurityUtils;
 import org.argeo.osgi.useradmin.AuthenticatingUser;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.InvalidSyntaxException;
-import org.osgi.framework.ServiceReference;
 import org.osgi.service.http.HttpContext;
 import org.osgi.service.useradmin.Authorization;
 
@@ -44,6 +39,8 @@ class CmsAuthUtils {
        final static String SHARED_STATE_REMOTE_ADDR = "org.argeo.cms.auth.remote.addr";
        final static String SHARED_STATE_REMOTE_PORT = "org.argeo.cms.auth.remote.port";
 
+       final static String SINGLE_USER_LOCAL_ID = "single-user";
+
        static void addAuthorization(Subject subject, Authorization authorization) {
                assert subject != null;
                checkSubjectEmpty(subject);
@@ -182,8 +179,11 @@ class CmsAuthUtils {
                                                "Subject already logged with session " + storedSessionId + " (not " + nodeSessionId + ")");
                        }
                } else {
-                       CmsSessionImpl cmsSession = new CmsSessionImpl(subject, authorization, locale, "desktop");
-                       CmsContextImpl.getCmsContext().registerCmsSession(cmsSession);
+                       CmsSessionImpl cmsSession = CmsContextImpl.getCmsContext().getCmsSessionByLocalId(SINGLE_USER_LOCAL_ID);
+                       if (cmsSession == null) {
+                               cmsSession = new CmsSessionImpl(subject, authorization, locale, SINGLE_USER_LOCAL_ID);
+                               CmsContextImpl.getCmsContext().registerCmsSession(cmsSession);
+                       }
                        CmsSessionId nodeSessionId = new CmsSessionId(cmsSession.getUuid());
                        subject.getPrivateCredentials().add(nodeSessionId);
                }
index ef9f0ec9a8df203ad6a50a588a1cf9b79ec88fa3..93ed319f153d61df8af7650c504b7b9336b0a373 100644 (file)
@@ -242,10 +242,18 @@ public class CmsContextImpl implements CmsContext {
                cmsSessionsByLocalId.remove(cmsSession.getLocalId());
        }
 
+       /**
+        * The {@link CmsSession} related to this UUID, or <code>null</null> if not
+        * registered.
+        */
        public synchronized CmsSessionImpl getCmsSessionByUuid(UUID uuid) {
                return cmsSessionsByUuid.get(uuid);
        }
 
+       /**
+        * The {@link CmsSession} related to this local id, or <code>null</null> if not
+        * registered.
+        */
        public synchronized CmsSessionImpl getCmsSessionByLocalId(String localId) {
                return cmsSessionsByLocalId.get(localId);
        }