X-Git-Url: https://git.argeo.org/?a=blobdiff_plain;f=org.argeo.cms%2Fsrc%2Forg%2Fargeo%2Fcms%2Facr%2FCmsContentRepository.java;h=2b4de14da254ba933ab409f01dc9464cf3e7a503;hb=54df376a9c2dd458a82eaa09bfbb718fe699dd0d;hp=6d17ea87dd4d6fc463e01cfcee3f75ca0c061549;hpb=c615307d7b87bcb260d8a9f402c6e0a880862f38;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 6d17ea87d..2b4de14da 100644 --- a/org.argeo.cms/src/org/argeo/cms/acr/CmsContentRepository.java +++ b/org.argeo.cms/src/org/argeo/cms/acr/CmsContentRepository.java @@ -1,102 +1,35 @@ package org.argeo.cms.acr; -import java.io.IOException; -import java.io.Writer; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; import java.util.Collections; import java.util.HashMap; -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.stream.Collectors; -import javax.security.auth.Subject; import javax.security.auth.login.LoginContext; import javax.security.auth.login.LoginException; -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; -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.Schema; -import org.argeo.api.acr.Content; import org.argeo.api.acr.ContentSession; -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.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.api.cms.CmsState; +import org.argeo.api.cms.DataAdminPrincipal; +import org.argeo.api.uuid.UuidFactory; 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; +import org.argeo.cms.util.CurrentSubject; /** - * Base implementation of a {@link ProvidedRepository} integrated with a CMS. + * Multi-session {@link ProvidedRepository}, integrated with a CMS. */ -public class CmsContentRepository implements ProvidedRepository { - private final static CmsLog log = CmsLog.getLog(CmsContentRepository.class); - - private NavigableMap partitions = new TreeMap<>(); - - // TODO synchronize ? - private NavigableMap prefixes = new TreeMap<>(); - - private Schema schema; - - private CmsContentSession systemSession; +public class CmsContentRepository extends AbstractContentRepository { + public final static String RUN_BASE = "/run"; + public final static String DIRECTORY_BASE = "/directory"; private Map userSessions = Collections.synchronizedMap(new HashMap<>()); - public CmsContentRepository() { - prefixes.put(CrName.CR_DEFAULT_PREFIX, CrName.CR_NAMESPACE_URI); - prefixes.put("basic", CrName.CR_NAMESPACE_URI); - prefixes.put("owner", CrName.CR_NAMESPACE_URI); - prefixes.put("posix", CrName.CR_NAMESPACE_URI); - - systemSession = newSystemSession(); - } - - protected CmsContentSession newSystemSession() { - LoginContext loginContext; - try { - loginContext = new LoginContext(CmsAuth.DATA_ADMIN.getLoginContextName()); - loginContext.login(); - } catch (LoginException e1) { - throw new RuntimeException("Could not login as data admin", e1); - } finally { - } - return new CmsContentSession(loginContext.getSubject(), Locale.getDefault()); - } - - public void start() { - } - - public void stop() { - - } + private CmsState cmsState; + private UuidFactory uuidFactory; /* * REPOSITORY @@ -109,11 +42,19 @@ public class CmsContentRepository implements ProvidedRepository { @Override public ContentSession get(Locale locale) { - // Subject subject = Subject.getSubject(AccessController.getContext()); + if (!CmsSession.hasCmsSession(CurrentSubject.current())) { + if (DataAdminPrincipal.isDataAdmin(CurrentSubject.current())) { + // TODO open multiple data admin sessions? + return getSystemSession(); + } + throw new IllegalStateException("Caller must be authenticated"); + } + CmsSession cmsSession = CurrentUser.getCmsSession(); CmsContentSession contentSession = userSessions.get(cmsSession); if (contentSession == null) { - final CmsContentSession newContentSession = new CmsContentSession(cmsSession.getSubject(), locale); + final CmsContentSession newContentSession = new CmsContentSession(this, cmsSession.getUuid(), + cmsSession.getSubject(), locale, uuidFactory); cmsSession.addOnCloseCallback((c) -> { newContentSession.close(); userSessions.remove(cmsSession); @@ -123,179 +64,30 @@ public class CmsContentRepository implements ProvidedRepository { return contentSession; } - public void addProvider(String base, ContentProvider provider) { - partitions.put(base, provider); - if ("/".equals(base))// root - return; - String[] parentPath = ContentUtils.getParentPath(base); - Content parent = systemSession.get(parentPath[0]); - Content mount = parent.add(parentPath[1]); - // TODO use a boolean - // ContentName name = new ContentName(CrName.MOUNT.getNamespaceURI(), - // CrName.MOUNT.name(), systemSession); - mount.put(CrName.MOUNT.get(), "true"); - } - - public void registerPrefix(String prefix, String namespaceURI) { - String registeredUri = prefixes.get(prefix); - if (registeredUri == null) { - prefixes.put(prefix, namespaceURI); - return; - } - if (!registeredUri.equals(namespaceURI)) - throw new IllegalStateException("Prefix " + prefix + " is already registred for " + registeredUri); - // do nothing if same namespace is already registered - } - - /* - * FACTORIES - */ - public void initRootContentProvider(Path path) { + @Override + protected CmsContentSession newSystemSession() { + LoginContext loginContext; try { - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - factory.setNamespaceAware(true); - factory.setXIncludeAware(true); - // factory.setSchema(schema); - - 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); - - } - }); - - Document document; - if (Files.exists(path)) { - InputSource inputSource = new InputSource(path.toAbsolutePath().toUri().toString()); - inputSource.setEncoding(StandardCharsets.UTF_8.name()); - // TODO public id as well? - document = dBuilder.parse(inputSource); - } else { - document = dBuilder.newDocument(); -// Element root = document.createElementNS(CrName.ROOT.getNamespaceURI(), -// CrName.ROOT.get().toPrefixedString()); - Element root = document.createElement(CrName.ROOT.get().toPrefixedString()); - // root.setAttribute("xmlns", ""); - root.setAttribute("xmlns:" + CrName.CR_DEFAULT_PREFIX, CrName.CR_NAMESPACE_URI); - document.appendChild(root); - - // write it - 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); - } - } - - DomContentProvider contentProvider = new DomContentProvider(document); - addProvider("/", contentProvider); - } catch (DOMException | ParserConfigurationException | SAXException | IOException - | TransformerFactoryConfigurationError | TransformerException e) { - throw new IllegalStateException("Cannot init ACR root " + path, e); + loginContext = new LoginContext(CmsAuth.DATA_ADMIN.getLoginContextName()); + loginContext.login(); + } catch (LoginException e1) { + throw new RuntimeException("Could not login as data admin", e1); + } finally { } - + return new CmsContentSession(this, getCmsState().getUuid(), loginContext.getSubject(), Locale.getDefault(), + uuidFactory); } - /* - * NAMESPACE CONTEXT - */ - - /* - * SESSION - */ - - class CmsContentSession implements ProvidedSession { - private Subject subject; - private Locale locale; - - private CompletableFuture closed = new CompletableFuture<>(); - - public CmsContentSession(Subject subject, Locale locale) { - this.subject = subject; - this.locale = locale; - } - - public void close() { - closed.complete(this); - } - - @Override - public CompletionStage onClose() { - return closed.minimalCompletionStage(); - } - - @Override - public Content get(String path) { - Map.Entry entry = partitions.floorEntry(path); - String mountPath = entry.getKey(); - ContentProvider provider = entry.getValue(); - String relativePath = path.substring(mountPath.length()); - return provider.get(CmsContentSession.this, mountPath, relativePath); - } - - @Override - public Subject getSubject() { - return subject; - } - - @Override - public Locale getLocale() { - return locale; - } - - @Override - public ProvidedRepository getRepository() { - return CmsContentRepository.this; - } - - /* - * NAMESPACE CONTEXT - */ - - @Override - public String getNamespaceURI(String prefix) { - return NamespaceUtils.getNamespaceURI((p) -> prefixes.get(p), prefix); - } - - @Override - public Iterator getPrefixes(String namespaceURI) { - return NamespaceUtils.getPrefixes((ns) -> prefixes.entrySet().stream().filter(e -> e.getValue().equals(ns)) - .map(Map.Entry::getKey).collect(Collectors.toUnmodifiableSet()), namespaceURI); - } + protected CmsState getCmsState() { + return cmsState; + } -// @Override -// public String findNamespace(String prefix) { -// return prefixes.get(prefix); -// } -// -// @Override -// public Set findPrefixes(String namespaceURI) { -// Set res = prefixes.entrySet().stream().filter(e -> e.getValue().equals(namespaceURI)) -// .map(Map.Entry::getKey).collect(Collectors.toUnmodifiableSet()); -// -// return res; -// } -// -// @Override -// public String findPrefix(String namespaceURI) { -// if (CrName.CR_NAMESPACE_URI.equals(namespaceURI) && prefixes.containsKey(CrName.CR_DEFAULT_PREFIX)) -// return CrName.CR_DEFAULT_PREFIX; -// return ProvidedSession.super.findPrefix(namespaceURI); -// } + public void setCmsState(CmsState cmsState) { + this.cmsState = cmsState; + } + public void setUuidFactory(UuidFactory uuidFactory) { + this.uuidFactory = uuidFactory; } }