Adapt to MS Windows
authorMathieu Baudier <mbaudier@argeo.org>
Thu, 22 Dec 2022 10:09:07 +0000 (11:09 +0100)
committerMathieu Baudier <mbaudier@argeo.org>
Thu, 22 Dec 2022 10:09:07 +0000 (11:09 +0100)
org.argeo.cms.lib.dbus/src/org/argeo/cms/dbus/CmsDBusImpl.java
org.argeo.cms/src/org/argeo/cms/acr/fs/FsContent.java
org.argeo.cms/src/org/argeo/cms/acr/fs/FsContentProvider.java
org.argeo.cms/src/org/argeo/cms/internal/runtime/CmsStateImpl.java
org.argeo.cms/src/org/argeo/cms/internal/runtime/DeployedContentRepository.java

index b9a202be9d7d2ab3e581f60bc9080fcae52c38da..cf939648af96e55c48439e3ec246b04bdbfac892 100644 (file)
@@ -19,6 +19,7 @@ public class CmsDBusImpl implements CmsDBus {
        private BusAddress sessionBusAddress;
 
        private EmbeddedDBusDaemon dBusDaemon;
+       private Path dBusDaemonSocket;
 
        private CmsEventBus cmsEventBus;
 
@@ -27,8 +28,9 @@ public class CmsDBusImpl implements CmsDBus {
                        final String envSessionBusAddress = System.getenv(DBUS_SESSION_BUS_ADDRESS);
                        if (envSessionBusAddress != null) {
                                sessionBusAddress = BusAddress.of(envSessionBusAddress);
-                               
-                               // !! We must first initialise a connection, otherwise there are classloader issues later on 
+
+                               // !! We must first initialise a connection, otherwise there are classloader
+                               // issues later on
                                try (DBusConnection dBusConnection = DBusConnectionBuilder.forAddress(sessionBusAddress)
                                                .withShared(false).build()) {
 
@@ -36,11 +38,15 @@ public class CmsDBusImpl implements CmsDBus {
                                log.debug(() -> "Found session DBus with address " + sessionBusAddress);
                        } else {
                                Path socketLocation = Paths.get(System.getProperty("user.home"), ".cache", "argeo", "bus");
-                               Files.createDirectories(socketLocation.getParent());
-                               // TODO escape : on Windows?
-                               String embeddedSessionBusAddress = "unix:path=" + socketLocation.toUri().getPath();
-                               dBusDaemon = new EmbeddedDBusDaemon(embeddedSessionBusAddress);
+                               if (Files.exists(socketLocation))
+                                       Files.delete(socketLocation);
+                               else
+                                       Files.createDirectories(socketLocation.getParent());
+
+                               String embeddedSessionBusAddress = "unix:path=" + socketLocation.toString();
+                               dBusDaemon = new EmbeddedDBusDaemon(embeddedSessionBusAddress + ",listen=true");
                                dBusDaemon.startInBackgroundAndWait(30 * 1000);
+                               dBusDaemonSocket = socketLocation;
 
                                sessionBusAddress = BusAddress.of(embeddedSessionBusAddress);
                                try (DBusConnection dBusConnection = DBusConnectionBuilder.forAddress(sessionBusAddress)
@@ -63,6 +69,11 @@ public class CmsDBusImpl implements CmsDBus {
                        } catch (IOException e) {
                                log.error("Cannot close embedded DBus daemon", e);
                        }
+                       try {
+                               Files.delete(dBusDaemonSocket);
+                       } catch (IOException e) {
+                               log.error("Cannot delete DBus daemon socket " + dBusDaemonSocket, e);
+                       }
                }
        }
 
index 43cae85721bf6b96c3f577f157f64b56845c11b2..5920c420370c78a4051f9000820af7d16c1c34da 100644 (file)
@@ -90,7 +90,7 @@ public class FsContent extends AbstractContent implements ProvidedContent {
                } else {
 
                        // TODO should we support prefixed name for known types?
-                       QName providerName = NamespaceUtils.parsePrefixedName(provider, path.getFileName().toString());
+                       QName providerName = provider.fromFsPrefixedName(path.getFileName().toString());
 //                     QName providerName = new QName(path.getFileName().toString());
                        // TODO remove extension if mounted?
                        this.name = new ContentName(providerName, session);
@@ -126,7 +126,7 @@ public class FsContent extends AbstractContent implements ProvidedContent {
                        } else {
                                UserDefinedFileAttributeView udfav = Files.getFileAttributeView(path,
                                                UserDefinedFileAttributeView.class);
-                               String prefixedName = NamespaceUtils.toPrefixedName(provider, key);
+                               String prefixedName = provider.toFsPrefixedName(key);
                                if (!udfav.list().contains(prefixedName))
                                        return Optional.empty();
                                ByteBuffer buf = ByteBuffer.allocate(udfav.size(prefixedName));
@@ -198,7 +198,7 @@ public class FsContent extends AbstractContent implements ProvidedContent {
                if (udfav != null) {
                        try {
                                for (String name : udfav.list()) {
-                                       QName providerName = NamespaceUtils.parsePrefixedName(provider, name);
+                                       QName providerName = provider.fromFsPrefixedName(name);
                                        if (providerName.getNamespaceURI().equals(XMLConstants.XMLNS_ATTRIBUTE_NS_URI))
                                                continue; // skip prefix mapping
                                        QName sessionName = new ContentName(providerName, getSession());
@@ -215,7 +215,7 @@ public class FsContent extends AbstractContent implements ProvidedContent {
        protected void removeAttr(QName key) {
                UserDefinedFileAttributeView udfav = Files.getFileAttributeView(path, UserDefinedFileAttributeView.class);
                try {
-                       udfav.delete(NamespaceUtils.toPrefixedName(provider, key));
+                       udfav.delete(provider.toFsPrefixedName(key));
                } catch (IOException e) {
                        throw new ContentResourceException("Cannot delete attribute " + key + " for " + path, e);
                }
@@ -239,7 +239,7 @@ public class FsContent extends AbstractContent implements ProvidedContent {
                UserDefinedFileAttributeView udfav = Files.getFileAttributeView(path, UserDefinedFileAttributeView.class);
                ByteBuffer bb = ByteBuffer.wrap(toWrite.getBytes(StandardCharsets.UTF_8));
                try {
-                       udfav.write(NamespaceUtils.toPrefixedName(provider, key), bb);
+                       udfav.write(provider.toFsPrefixedName(key), bb);
                } catch (IOException e) {
                        throw new ContentResourceException("Cannot delete attribute " + key + " for " + path, e);
                }
@@ -250,7 +250,7 @@ public class FsContent extends AbstractContent implements ProvidedContent {
                if (POSIX_KEYS.containsKey(key))
                        return POSIX_KEYS.get(key);
                else
-                       return USER_ + NamespaceUtils.toPrefixedName(provider, key);
+                       return USER_ + provider.toFsPrefixedName(key);
        }
 
        /*
@@ -285,7 +285,7 @@ public class FsContent extends AbstractContent implements ProvidedContent {
        public Content add(QName name, QName... classes) {
                FsContent fsContent;
                try {
-                       Path newPath = path.resolve(NamespaceUtils.toPrefixedName(provider, name));
+                       Path newPath = path.resolve(provider.toFsPrefixedName(name));
                        if (ContentName.contains(classes, DName.collection.qName()))
                                Files.createDirectory(newPath);
                        else
index 9b1b9668303f066e2106de3aa4a296edcabbf55d..47cd64af343dc2aec976cb554b82be229c6547ad 100644 (file)
@@ -13,6 +13,8 @@ import java.util.Objects;
 import java.util.TreeMap;
 import java.util.stream.Collectors;
 
+import javax.xml.namespace.QName;
+
 import org.argeo.api.acr.ArgeoNamespace;
 import org.argeo.api.acr.ContentResourceException;
 import org.argeo.api.acr.NamespaceUtils;
@@ -20,28 +22,36 @@ import org.argeo.api.acr.RuntimeNamespaceContext;
 import org.argeo.api.acr.spi.ContentProvider;
 import org.argeo.api.acr.spi.ProvidedContent;
 import org.argeo.api.acr.spi.ProvidedSession;
+import org.argeo.cms.util.OS;
 
 /** Access a file system as a {@link ContentProvider}. */
 public class FsContentProvider implements ContentProvider {
-       final static String XMLNS_ = "xmlns:";
 
        protected String mountPath;
        protected Path rootPath;
 
        private NavigableMap<String, String> prefixes = new TreeMap<>();
 
+       private final boolean isNtfs;
+       private final String XMLNS_;
+
        public FsContentProvider(String mountPath, Path rootPath) {
                Objects.requireNonNull(mountPath);
                Objects.requireNonNull(rootPath);
 
                this.mountPath = mountPath;
                this.rootPath = rootPath;
+
+               this.isNtfs = OS.LOCAL.isMSWindows();
+               this.XMLNS_ = isNtfs ? "xmlns%3A" : "xmlns:";
+
                // FIXME make it more robust
                initNamespaces();
        }
 
        protected FsContentProvider() {
-
+               this.isNtfs = OS.LOCAL.isMSWindows();
+               this.XMLNS_ = isNtfs ? "xmlns%3A" : "xmlns:";
        }
 
        protected void initNamespaces() {
@@ -117,6 +127,27 @@ public class FsContentProvider implements ContentProvider {
                return Files.exists(rootPath.resolve(relativePath));
        }
 
+       /*
+        * ATTRIBUTE NAMES
+        */
+       /**
+        * Make sure that the prefixed name is compatible with the underlying file
+        * system for file names/attributes (NTFS does not accept :)
+        */
+       String toFsPrefixedName(QName key) {
+               return isNtfs ? NamespaceUtils.toPrefixedName(this, key).replace(":", "%3A")
+                               : NamespaceUtils.toPrefixedName(this, key);
+       }
+
+       /**
+        * PArse a prefixed name which is compatible with the underlying file system for
+        * file names/attributes (NTFS does not accept :)
+        */
+       QName fromFsPrefixedName(String name) {
+               return isNtfs ? NamespaceUtils.parsePrefixedName(this, name.replace("%3A", ":"))
+                               : NamespaceUtils.parsePrefixedName(this, name);
+       }
+
        /*
         * NAMESPACE CONTEXT
         */
index d364620f56f09118a99cd36564146c1f61919a8f..c1f92deb40b3ea7743098bcb0c8e4bbdacc028af 100644 (file)
@@ -39,6 +39,7 @@ import org.argeo.api.uuid.UuidFactory;
 import org.argeo.cms.CmsDeployProperty;
 import org.argeo.cms.auth.ident.IdentClient;
 import org.argeo.cms.util.FsUtils;
+import org.argeo.cms.util.OS;
 
 /**
  * Implementation of a {@link CmsState}, initialising the required services.
@@ -168,7 +169,8 @@ public class CmsStateImpl implements CmsState {
                        try {
                                if (!Files.exists(privateDir))
                                        Files.createDirectories(privateDir);
-                               Files.setPosixFilePermissions(privateDir, posixPermissions);
+                               if (!OS.LOCAL.isMSWindows())
+                                       Files.setPosixFilePermissions(privateDir, posixPermissions);
                        } catch (IOException e) {
                                log.error("Cannot set permissions on " + privateDir, e);
                        }
index 0fd0a63edb4cb47acce19bbb38f4fc07b4edd672..bb1f6112a927616caec811bb98d61321fc7319ea 100644 (file)
@@ -9,9 +9,10 @@ import org.argeo.api.cms.directory.CmsUserManager;
 import org.argeo.cms.acr.CmsContentRepository;
 import org.argeo.cms.acr.directory.DirectoryContentProvider;
 import org.argeo.cms.acr.fs.FsContentProvider;
+import org.argeo.cms.util.OS;
 
 public class DeployedContentRepository extends CmsContentRepository {
-       private final static String ROOT_XML = "cr:root.xml";
+       private final static String ROOT_XML = OS.LOCAL.isMSWindows() ? "cr%3Aroot.xml" : "cr:root.xml";
 
        private final static CmsLog log = CmsLog.getLog(DeployedContentRepository.class);
 
@@ -22,7 +23,8 @@ public class DeployedContentRepository extends CmsContentRepository {
                long begin = System.currentTimeMillis();
                try {
                        super.start();
-                       Path rootXml = KernelUtils.getOsgiInstancePath(ROOT_XML);
+                       // FIXME does not work on Windows
+                       //Path rootXml = KernelUtils.getOsgiInstancePath(ROOT_XML);
                        initRootContentProvider(null);
 
 //             Path srvPath = KernelUtils.getOsgiInstancePath(CmsConstants.SRV_WORKSPACE);