From: Mathieu Baudier Date: Thu, 30 Jun 2022 09:39:55 +0000 (+0200) Subject: Refactor deploy properties and move legacy CMS exception. X-Git-Tag: v2.3.10~146 X-Git-Url: https://git.argeo.org/?a=commitdiff_plain;h=dca2b13e0e3ca3e7a9469e089b980c48c880ad1a;p=lgpl%2Fargeo-commons.git Refactor deploy properties and move legacy CMS exception. --- diff --git a/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/CmsE4Utils.java b/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/CmsE4Utils.java index 21abf5828..a997de748 100644 --- a/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/CmsE4Utils.java +++ b/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/CmsE4Utils.java @@ -2,7 +2,7 @@ package org.argeo.cms.e4; import java.util.List; -import org.argeo.cms.CmsException; +import org.argeo.cms.swt.CmsException; import org.eclipse.e4.ui.model.application.MApplication; import org.eclipse.e4.ui.model.application.commands.MCommand; import org.eclipse.e4.ui.model.application.ui.basic.MPart; diff --git a/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/OsgiFilterContextFunction.java b/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/OsgiFilterContextFunction.java index c42a02a14..1e3e75cec 100644 --- a/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/OsgiFilterContextFunction.java +++ b/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/OsgiFilterContextFunction.java @@ -1,6 +1,6 @@ package org.argeo.cms.e4; -import org.argeo.cms.CmsException; +import org.argeo.cms.swt.CmsException; import org.eclipse.e4.core.contexts.ContextFunction; import org.eclipse.e4.core.contexts.IEclipseContext; import org.eclipse.e4.core.di.IInjector; diff --git a/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/addons/AuthAddon.java b/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/addons/AuthAddon.java index 3d57e1659..e84b18c0b 100644 --- a/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/addons/AuthAddon.java +++ b/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/addons/AuthAddon.java @@ -8,8 +8,8 @@ import javax.security.auth.Subject; import javax.servlet.http.HttpServletRequest; import org.argeo.api.cms.CmsLog; -import org.argeo.cms.CmsException; import org.argeo.cms.auth.CurrentUser; +import org.argeo.cms.swt.CmsException; import org.eclipse.e4.ui.model.application.MApplication; import org.eclipse.e4.ui.model.application.ui.MElementContainer; import org.eclipse.e4.ui.model.application.ui.MUIElement; diff --git a/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/files/NodeFsBrowserView.java b/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/files/NodeFsBrowserView.java index cb9f9b97a..579d35d6a 100644 --- a/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/files/NodeFsBrowserView.java +++ b/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/files/NodeFsBrowserView.java @@ -9,8 +9,8 @@ import java.nio.file.spi.FileSystemProvider; import javax.annotation.PostConstruct; import javax.inject.Inject; -import org.argeo.cms.CmsException; import org.argeo.cms.jcr.CmsJcrUtils; +import org.argeo.cms.swt.CmsException; import org.argeo.eclipse.ui.fs.AdvancedFsBrowser; import org.argeo.eclipse.ui.fs.SimpleFsBrowser; import org.eclipse.swt.SWT; diff --git a/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/handlers/ChangePassword.java b/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/handlers/ChangePassword.java index a6cdcf620..7ef8c59da 100644 --- a/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/handlers/ChangePassword.java +++ b/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/handlers/ChangePassword.java @@ -12,9 +12,9 @@ import javax.inject.Inject; import javax.naming.InvalidNameException; import javax.naming.ldap.LdapName; -import org.argeo.cms.CmsException; import org.argeo.cms.auth.CurrentUser; import org.argeo.cms.security.CryptoKeyring; +import org.argeo.cms.swt.CmsException; import org.argeo.cms.swt.dialogs.CmsMessageDialog; import org.argeo.eclipse.ui.dialogs.ErrorFeedback; import org.argeo.util.transaction.WorkTransaction; diff --git a/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/handlers/CloseWorkbench.java b/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/handlers/CloseWorkbench.java index a365f3d7d..c2ae4bff7 100644 --- a/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/handlers/CloseWorkbench.java +++ b/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/handlers/CloseWorkbench.java @@ -4,8 +4,8 @@ import java.security.AccessController; import javax.security.auth.Subject; -import org.argeo.cms.CmsException; import org.argeo.cms.auth.CurrentUser; +import org.argeo.cms.swt.CmsException; import org.eclipse.e4.core.di.annotations.Execute; import org.eclipse.e4.ui.workbench.IWorkbench; diff --git a/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/jcr/JcrBrowserView.java b/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/jcr/JcrBrowserView.java index 46e1b6507..0b77c0732 100644 --- a/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/jcr/JcrBrowserView.java +++ b/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/jcr/JcrBrowserView.java @@ -17,9 +17,9 @@ import javax.jcr.observation.EventListener; import javax.jcr.observation.ObservationManager; import org.argeo.api.cms.CmsConstants; -import org.argeo.cms.CmsException; import org.argeo.cms.security.CryptoKeyring; import org.argeo.cms.security.Keyring; +import org.argeo.cms.swt.CmsException; import org.argeo.cms.swt.CmsSwtUtils; import org.argeo.cms.ui.jcr.JcrBrowserUtils; import org.argeo.cms.ui.jcr.NodeContentProvider; diff --git a/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/jcr/JcrE4DClickListener.java b/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/jcr/JcrE4DClickListener.java index ad6a547da..f4ee2e8da 100644 --- a/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/jcr/JcrE4DClickListener.java +++ b/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/jcr/JcrE4DClickListener.java @@ -3,7 +3,7 @@ package org.argeo.cms.e4.jcr; import javax.jcr.Node; import javax.jcr.RepositoryException; -import org.argeo.cms.CmsException; +import org.argeo.cms.swt.CmsException; import org.argeo.cms.ui.jcr.JcrDClickListener; import org.eclipse.e4.ui.model.application.ui.basic.MPart; import org.eclipse.e4.ui.workbench.modeling.EPartService; diff --git a/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/maintenance/Browse.java b/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/maintenance/Browse.java index 40a3c4e8b..a536da066 100644 --- a/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/maintenance/Browse.java +++ b/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/maintenance/Browse.java @@ -16,7 +16,7 @@ import javax.jcr.RepositoryException; import javax.jcr.Value; import org.argeo.api.cms.ux.Cms2DSize; -import org.argeo.cms.CmsException; +import org.argeo.cms.swt.CmsException; import org.argeo.cms.swt.CmsSwtUtils; import org.argeo.cms.ui.CmsUiProvider; import org.argeo.cms.ui.util.CmsLink; diff --git a/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/monitoring/OsgiConfigurationsView.java b/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/monitoring/OsgiConfigurationsView.java index 759b3e955..5db8bd151 100644 --- a/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/monitoring/OsgiConfigurationsView.java +++ b/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/monitoring/OsgiConfigurationsView.java @@ -9,7 +9,7 @@ import java.util.List; import javax.annotation.PostConstruct; -import org.argeo.cms.CmsException; +import org.argeo.cms.swt.CmsException; import org.argeo.util.LangUtils; import org.eclipse.jface.viewers.ColumnLabelProvider; import org.eclipse.jface.viewers.ITreeContentProvider; diff --git a/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/users/GroupsView.java b/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/users/GroupsView.java index ddad34fd1..3bf48918d 100644 --- a/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/users/GroupsView.java +++ b/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/users/GroupsView.java @@ -9,12 +9,12 @@ import javax.inject.Inject; import org.argeo.api.cms.CmsConstants; import org.argeo.api.cms.CmsLog; -import org.argeo.cms.CmsException; import org.argeo.cms.auth.CurrentUser; import org.argeo.cms.e4.users.providers.CommonNameLP; import org.argeo.cms.e4.users.providers.DomainNameLP; import org.argeo.cms.e4.users.providers.RoleIconLP; import org.argeo.cms.e4.users.providers.UserDragListener; +import org.argeo.cms.swt.CmsException; //import org.argeo.cms.ui.workbench.WorkbenchUiPlugin; //import org.argeo.cms.ui.workbench.internal.useradmin.UiUserAdminListener; //import org.argeo.cms.ui.workbench.internal.useradmin.UserAdminWrapper; diff --git a/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/users/UserAdminWrapper.java b/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/users/UserAdminWrapper.java index 1e0fc6eb3..d120ae9a2 100644 --- a/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/users/UserAdminWrapper.java +++ b/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/users/UserAdminWrapper.java @@ -9,7 +9,7 @@ import java.util.List; import java.util.Map; import org.argeo.api.cms.CmsConstants; -import org.argeo.cms.CmsException; +import org.argeo.cms.swt.CmsException; import org.argeo.osgi.useradmin.UserDirectory; import org.argeo.util.directory.DirectoryConf; import org.argeo.util.transaction.WorkTransaction; diff --git a/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/users/UserBatchUpdateWizard.java b/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/users/UserBatchUpdateWizard.java index 01ccc7d73..4fc59d30d 100644 --- a/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/users/UserBatchUpdateWizard.java +++ b/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/users/UserBatchUpdateWizard.java @@ -7,13 +7,13 @@ import java.util.Map; import org.argeo.api.cms.CmsConstants; import org.argeo.api.cms.CmsLog; -import org.argeo.cms.CmsException; import org.argeo.cms.auth.CurrentUser; import org.argeo.cms.auth.UserAdminUtils; import org.argeo.cms.e4.users.providers.CommonNameLP; import org.argeo.cms.e4.users.providers.DomainNameLP; import org.argeo.cms.e4.users.providers.MailLP; import org.argeo.cms.e4.users.providers.UserNameLP; +import org.argeo.cms.swt.CmsException; import org.argeo.eclipse.ui.ColumnDefinition; import org.argeo.eclipse.ui.EclipseUiUtils; import org.argeo.eclipse.ui.parts.LdifUsersTable; diff --git a/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/users/UsersView.java b/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/users/UsersView.java index 877a925c6..720945c4c 100644 --- a/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/users/UsersView.java +++ b/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/users/UsersView.java @@ -8,13 +8,13 @@ import javax.annotation.PreDestroy; import javax.inject.Inject; import org.argeo.api.cms.CmsConstants; -import org.argeo.cms.CmsException; import org.argeo.cms.auth.CurrentUser; import org.argeo.cms.e4.users.providers.CommonNameLP; import org.argeo.cms.e4.users.providers.DomainNameLP; import org.argeo.cms.e4.users.providers.MailLP; import org.argeo.cms.e4.users.providers.UserDragListener; import org.argeo.cms.e4.users.providers.UserNameLP; +import org.argeo.cms.swt.CmsException; import org.argeo.eclipse.ui.ColumnDefinition; import org.argeo.eclipse.ui.EclipseUiUtils; import org.argeo.eclipse.ui.parts.LdifUsersTable; diff --git a/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/users/handlers/NewGroup.java b/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/users/handlers/NewGroup.java index f02a26b1c..41e14e097 100644 --- a/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/users/handlers/NewGroup.java +++ b/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/users/handlers/NewGroup.java @@ -5,8 +5,8 @@ import java.util.Map; import javax.inject.Inject; -import org.argeo.cms.CmsException; import org.argeo.cms.e4.users.UserAdminWrapper; +import org.argeo.cms.swt.CmsException; import org.argeo.eclipse.ui.EclipseUiUtils; import org.argeo.eclipse.ui.dialogs.ErrorFeedback; import org.argeo.util.directory.DirectoryConf; diff --git a/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/users/handlers/NewUser.java b/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/users/handlers/NewUser.java index 24f7e6250..40a446006 100644 --- a/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/users/handlers/NewUser.java +++ b/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/users/handlers/NewUser.java @@ -9,10 +9,10 @@ import javax.naming.InvalidNameException; import javax.naming.ldap.LdapName; import javax.naming.ldap.Rdn; -import org.argeo.cms.CmsException; import org.argeo.cms.auth.UserAdminUtils; import org.argeo.cms.e4.users.UiAdminUtils; import org.argeo.cms.e4.users.UserAdminWrapper; +import org.argeo.cms.swt.CmsException; import org.argeo.eclipse.ui.EclipseUiUtils; import org.argeo.eclipse.ui.dialogs.ErrorFeedback; import org.argeo.util.directory.DirectoryConf; diff --git a/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/users/providers/UserAdminAbstractLP.java b/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/users/providers/UserAdminAbstractLP.java index e33b1531d..29873db2f 100644 --- a/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/users/providers/UserAdminAbstractLP.java +++ b/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/users/providers/UserAdminAbstractLP.java @@ -3,8 +3,8 @@ package org.argeo.cms.e4.users.providers; import javax.naming.InvalidNameException; import javax.naming.ldap.LdapName; -import org.argeo.cms.CmsException; import org.argeo.cms.auth.UserAdminUtils; +import org.argeo.cms.swt.CmsException; import org.eclipse.jface.resource.JFaceResources; import org.eclipse.jface.viewers.ColumnLabelProvider; import org.eclipse.swt.SWT; diff --git a/eclipse/org.argeo.cms.servlet/src/org/argeo/cms/servlet/internal/jetty/InternalHttpConstants.java b/eclipse/org.argeo.cms.servlet/src/org/argeo/cms/servlet/internal/jetty/InternalHttpConstants.java deleted file mode 100644 index 462bf7a6b..000000000 --- a/eclipse/org.argeo.cms.servlet/src/org/argeo/cms/servlet/internal/jetty/InternalHttpConstants.java +++ /dev/null @@ -1,23 +0,0 @@ -package org.argeo.cms.servlet.internal.jetty; - -/** Compatible with Jetty. */ -public interface InternalHttpConstants { - static final String HTTP_ENABLED = "http.enabled"; - static final String HTTP_PORT = "http.port"; - static final String HTTP_HOST = "http.host"; - static final String HTTPS_ENABLED = "https.enabled"; - static final String HTTPS_HOST = "https.host"; - static final String HTTPS_PORT = "https.port"; - static final String SSL_KEYSTORE = "ssl.keystore"; - static final String SSL_PASSWORD = "ssl.password"; - static final String SSL_KEYPASSWORD = "ssl.keypassword"; - static final String SSL_NEEDCLIENTAUTH = "ssl.needclientauth"; - static final String SSL_WANTCLIENTAUTH = "ssl.wantclientauth"; - static final String SSL_PROTOCOL = "ssl.protocol"; - static final String SSL_ALGORITHM = "ssl.algorithm"; - static final String SSL_KEYSTORETYPE = "ssl.keystoretype"; - static final String JETTY_PROPERTY_PREFIX = "org.eclipse.equinox.http.jetty."; - // Argeo specific - static final String WEBSOCKET_ENABLED = "websocket.enabled"; - -} diff --git a/eclipse/org.argeo.cms.servlet/src/org/argeo/cms/servlet/internal/jetty/JettyConfig.java b/eclipse/org.argeo.cms.servlet/src/org/argeo/cms/servlet/internal/jetty/JettyConfig.java index ad93fad61..64e33d3ec 100644 --- a/eclipse/org.argeo.cms.servlet/src/org/argeo/cms/servlet/internal/jetty/JettyConfig.java +++ b/eclipse/org.argeo.cms.servlet/src/org/argeo/cms/servlet/internal/jetty/JettyConfig.java @@ -1,11 +1,5 @@ package org.argeo.cms.servlet.internal.jetty; -import java.io.IOException; -import java.io.Reader; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.security.KeyStore; import java.util.Dictionary; import java.util.Hashtable; import java.util.Map; @@ -18,7 +12,7 @@ import javax.websocket.server.ServerEndpointConfig; import org.argeo.api.cms.CmsConstants; import org.argeo.api.cms.CmsLog; import org.argeo.api.cms.CmsState; -import org.argeo.cms.security.PkiUtils; +import org.argeo.cms.CmsDeployProperty; import org.argeo.cms.websocket.javax.server.CmsWebSocketConfigurator; import org.argeo.cms.websocket.javax.server.TestEndpoint; import org.argeo.util.LangUtils; @@ -32,13 +26,13 @@ public class JettyConfig { private final static CmsLog log = CmsLog.getLog(JettyConfig.class); final static String CMS_JETTY_CUSTOMIZER_CLASS = "org.argeo.equinox.jetty.CmsJettyCustomizer"; - // Argeo specific - final static String WEBSOCKET_ENABLED = "websocket.enabled"; private CmsState cmsState; private final BundleContext bc = FrameworkUtil.getBundle(JettyConfig.class).getBundleContext(); + //private static final String JETTY_PROPERTY_PREFIX = "org.eclipse.equinox.http.jetty."; + public void start() { // We need to start asynchronously so that Jetty bundle get started by lazy init // due to the non-configurable behaviour of its activator @@ -103,10 +97,10 @@ public class JettyConfig { config.put("customizer.class", CMS_JETTY_CUSTOMIZER_CLASS); // TODO centralise with Jetty extender - Object webSocketEnabled = config.get(WEBSOCKET_ENABLED); + Object webSocketEnabled = config.get(CmsDeployProperty.WEBSOCKET_ENABLED.getProperty()); if (webSocketEnabled != null && webSocketEnabled.toString().equals("true")) { bc.registerService(ServerEndpointConfig.Configurator.class, new CmsWebSocketConfigurator(), null); - config.put(WEBSOCKET_ENABLED, "true"); + // config.put(WEBSOCKET_ENABLED, "true"); } } @@ -117,8 +111,8 @@ public class JettyConfig { // FIXME deal with multiple ids JettyConfigurator.startServer(CmsConstants.DEFAULT, new Hashtable<>(config)); - Object httpPort = config.get(InternalHttpConstants.HTTP_PORT); - Object httpsPort = config.get(InternalHttpConstants.HTTPS_PORT); + Object httpPort = config.get(JettyHttpConstants.HTTP_PORT); + Object httpsPort = config.get(JettyHttpConstants.HTTPS_PORT); log.info(httpPortsMsg(httpPort, httpsPort)); // Explicitly starts Jetty OSGi HTTP bundle, so that it gets triggered if OSGi @@ -148,94 +142,57 @@ public class JettyConfig { /** Override the provided config with the framework properties */ public Dictionary getHttpServerConfig() { - String httpPort = getFrameworkProp("org.osgi.service.http.port"); - String httpsPort = getFrameworkProp("org.osgi.service.http.port.secure"); + String httpPort = getFrameworkProp(CmsDeployProperty.HTTP_PORT); + String httpsPort = getFrameworkProp(CmsDeployProperty.HTTPS_PORT); /// TODO make it more generic - String httpHost = getFrameworkProp( - InternalHttpConstants.JETTY_PROPERTY_PREFIX + InternalHttpConstants.HTTP_HOST); - String httpsHost = getFrameworkProp( - InternalHttpConstants.JETTY_PROPERTY_PREFIX + InternalHttpConstants.HTTPS_HOST); - String webSocketEnabled = getFrameworkProp( - InternalHttpConstants.JETTY_PROPERTY_PREFIX + InternalHttpConstants.WEBSOCKET_ENABLED); + String httpHost = getFrameworkProp(CmsDeployProperty.HOST); +// String httpsHost = getFrameworkProp( +// JettyConfig.JETTY_PROPERTY_PREFIX + CmsHttpConstants.HTTPS_HOST); + String webSocketEnabled = getFrameworkProp(CmsDeployProperty.WEBSOCKET_ENABLED); final Hashtable props = new Hashtable(); // try { if (httpPort != null || httpsPort != null) { boolean httpEnabled = httpPort != null; - props.put(InternalHttpConstants.HTTP_ENABLED, httpEnabled); + props.put(JettyHttpConstants.HTTP_ENABLED, httpEnabled); boolean httpsEnabled = httpsPort != null; - props.put(InternalHttpConstants.HTTPS_ENABLED, httpsEnabled); + props.put(JettyHttpConstants.HTTPS_ENABLED, httpsEnabled); if (httpEnabled) { - props.put(InternalHttpConstants.HTTP_PORT, httpPort); + props.put(JettyHttpConstants.HTTP_PORT, httpPort); if (httpHost != null) - props.put(InternalHttpConstants.HTTP_HOST, httpHost); + props.put(JettyHttpConstants.HTTP_HOST, httpHost); } if (httpsEnabled) { - props.put(InternalHttpConstants.HTTPS_PORT, httpsPort); - if (httpsHost != null) - props.put(InternalHttpConstants.HTTPS_HOST, httpsHost); - - // server certificate - Path keyStorePath = cmsState.getDataPath(PkiUtils.DEFAULT_KEYSTORE_PATH); - Path pemKeyPath = cmsState.getDataPath(PkiUtils.DEFAULT_PEM_KEY_PATH); - Path pemCertPath = cmsState.getDataPath(PkiUtils.DEFAULT_PEM_CERT_PATH); - String keyStorePasswordStr = getFrameworkProp( - InternalHttpConstants.JETTY_PROPERTY_PREFIX + InternalHttpConstants.SSL_PASSWORD); - char[] keyStorePassword; - if (keyStorePasswordStr == null) - keyStorePassword = "changeit".toCharArray(); - else - keyStorePassword = keyStorePasswordStr.toCharArray(); - - // if PEM files both exists, update the PKCS12 file - if (Files.exists(pemCertPath) && Files.exists(pemKeyPath)) { - // TODO check certificate update time? monitor changes? - KeyStore keyStore = PkiUtils.getKeyStore(keyStorePath, keyStorePassword, PkiUtils.PKCS12); - try (Reader key = Files.newBufferedReader(pemKeyPath, StandardCharsets.US_ASCII); - Reader cert = Files.newBufferedReader(pemCertPath, StandardCharsets.US_ASCII);) { - PkiUtils.loadPem(keyStore, key, keyStorePassword, cert); - PkiUtils.saveKeyStore(keyStorePath, keyStorePassword, keyStore); - if (log.isDebugEnabled()) - log.debug("PEM certificate stored in " + keyStorePath); - } catch (IOException e) { - log.error("Cannot read PEM files " + pemKeyPath + " and " + pemCertPath, e); - } - } - - if (!Files.exists(keyStorePath)) - PkiUtils.createSelfSignedKeyStore(keyStorePath, keyStorePassword, PkiUtils.PKCS12); - props.put(InternalHttpConstants.SSL_KEYSTORETYPE, PkiUtils.PKCS12); - props.put(InternalHttpConstants.SSL_KEYSTORE, keyStorePath.toString()); - props.put(InternalHttpConstants.SSL_PASSWORD, new String(keyStorePassword)); + props.put(JettyHttpConstants.HTTPS_PORT, httpsPort); + if (httpHost != null) + props.put(JettyHttpConstants.HTTPS_HOST, httpHost); -// props.put(InternalHttpConstants.SSL_KEYSTORETYPE, "PKCS11"); -// props.put(InternalHttpConstants.SSL_KEYSTORE, "../../nssdb"); -// props.put(InternalHttpConstants.SSL_PASSWORD, keyStorePassword); + props.put(JettyHttpConstants.SSL_KEYSTORETYPE, getFrameworkProp(CmsDeployProperty.SSL_KEYSTORETYPE)); + props.put(JettyHttpConstants.SSL_KEYSTORE, getFrameworkProp(CmsDeployProperty.SSL_KEYSTORE)); + props.put(JettyHttpConstants.SSL_PASSWORD, getFrameworkProp(CmsDeployProperty.SSL_PASSWORD)); // client certificate authentication - String wantClientAuth = getFrameworkProp( - InternalHttpConstants.JETTY_PROPERTY_PREFIX + InternalHttpConstants.SSL_WANTCLIENTAUTH); + String wantClientAuth = getFrameworkProp(CmsDeployProperty.SSL_WANTCLIENTAUTH); if (wantClientAuth != null) - props.put(InternalHttpConstants.SSL_WANTCLIENTAUTH, Boolean.parseBoolean(wantClientAuth)); - String needClientAuth = getFrameworkProp( - InternalHttpConstants.JETTY_PROPERTY_PREFIX + InternalHttpConstants.SSL_NEEDCLIENTAUTH); + props.put(JettyHttpConstants.SSL_WANTCLIENTAUTH, Boolean.parseBoolean(wantClientAuth)); + String needClientAuth = getFrameworkProp(CmsDeployProperty.SSL_NEEDCLIENTAUTH); if (needClientAuth != null) - props.put(InternalHttpConstants.SSL_NEEDCLIENTAUTH, Boolean.parseBoolean(needClientAuth)); + props.put(JettyHttpConstants.SSL_NEEDCLIENTAUTH, Boolean.parseBoolean(needClientAuth)); } // web socket if (webSocketEnabled != null && webSocketEnabled.equals("true")) - props.put(InternalHttpConstants.WEBSOCKET_ENABLED, true); + props.put(CmsDeployProperty.WEBSOCKET_ENABLED.getProperty(), true); props.put(CmsConstants.CN, CmsConstants.DEFAULT); } return props; } - private String getFrameworkProp(String key) { - return cmsState.getDeployProperty(key); + private String getFrameworkProp(CmsDeployProperty deployProperty) { + return cmsState.getDeployProperty(deployProperty.getProperty()); } public void setCmsState(CmsState cmsState) { diff --git a/eclipse/org.argeo.cms.servlet/src/org/argeo/cms/servlet/internal/jetty/JettyHttpConstants.java b/eclipse/org.argeo.cms.servlet/src/org/argeo/cms/servlet/internal/jetty/JettyHttpConstants.java new file mode 100644 index 000000000..155e6c882 --- /dev/null +++ b/eclipse/org.argeo.cms.servlet/src/org/argeo/cms/servlet/internal/jetty/JettyHttpConstants.java @@ -0,0 +1,19 @@ +package org.argeo.cms.servlet.internal.jetty; + +/** Compatible with Jetty. */ +interface JettyHttpConstants { + static final String HTTP_ENABLED = "http.enabled"; + static final String HTTP_PORT = "http.port"; + static final String HTTP_HOST = "http.host"; + static final String HTTPS_ENABLED = "https.enabled"; + static final String HTTPS_HOST = "https.host"; + static final String HTTPS_PORT = "https.port"; + static final String SSL_KEYSTORE = "ssl.keystore"; + static final String SSL_PASSWORD = "ssl.password"; + static final String SSL_KEYPASSWORD = "ssl.keypassword"; + static final String SSL_NEEDCLIENTAUTH = "ssl.needclientauth"; + static final String SSL_WANTCLIENTAUTH = "ssl.wantclientauth"; + static final String SSL_PROTOCOL = "ssl.protocol"; + static final String SSL_ALGORITHM = "ssl.algorithm"; + static final String SSL_KEYSTORETYPE = "ssl.keystoretype"; +} diff --git a/eclipse/org.argeo.cms.swt/src/org/argeo/cms/swt/CmsException.java b/eclipse/org.argeo.cms.swt/src/org/argeo/cms/swt/CmsException.java new file mode 100644 index 000000000..874ea9691 --- /dev/null +++ b/eclipse/org.argeo.cms.swt/src/org/argeo/cms/swt/CmsException.java @@ -0,0 +1,16 @@ +package org.argeo.cms.swt; + +/** @deprecated Use standard Java {@link RuntimeException} instead. */ +@Deprecated +public class CmsException extends RuntimeException { + private static final long serialVersionUID = -5341764743356771313L; + + public CmsException(String message) { + super(message); + } + + public CmsException(String message, Throwable e) { + super(message, e); + } + +} diff --git a/eclipse/org.argeo.cms.swt/src/org/argeo/cms/swt/auth/CmsLogin.java b/eclipse/org.argeo.cms.swt/src/org/argeo/cms/swt/auth/CmsLogin.java index afd1b5499..b313222d5 100644 --- a/eclipse/org.argeo.cms.swt/src/org/argeo/cms/swt/auth/CmsLogin.java +++ b/eclipse/org.argeo.cms.swt/src/org/argeo/cms/swt/auth/CmsLogin.java @@ -4,9 +4,24 @@ import static org.argeo.cms.CmsMsg.password; import static org.argeo.cms.CmsMsg.username; import java.io.IOException; +import java.net.Authenticator; +import java.net.PasswordAuthentication; +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.net.http.HttpResponse.BodyHandler; +import java.net.http.HttpResponse.BodyHandlers; +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; +import java.security.PrivilegedAction; +import java.security.cert.X509Certificate; import java.util.List; import java.util.Locale; +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; import javax.security.auth.Subject; import javax.security.auth.callback.Callback; import javax.security.auth.callback.CallbackHandler; @@ -24,6 +39,7 @@ import org.argeo.api.cms.ux.CmsView; import org.argeo.cms.CmsMsg; import org.argeo.cms.LocaleUtils; import org.argeo.cms.auth.RemoteAuthCallback; +import org.argeo.cms.auth.RemoteAuthUtils; import org.argeo.cms.servlet.ServletHttpRequest; import org.argeo.cms.servlet.ServletHttpResponse; import org.argeo.cms.swt.CmsStyles; @@ -277,6 +293,11 @@ public class CmsLogin implements CmsStyles, CallbackHandler { else loginContext = new LoginContext(CmsAuth.LOGIN_CONTEXT_USER, subject, this); loginContext.login(); +// try { +// openHttpClient(loginContext.getSubject(), "id-internal.work.argeo.net"); +// } catch (Exception e) { +// e.printStackTrace(); +// } cmsView.authChange(loginContext); return true; } catch (LoginException e) { @@ -299,6 +320,70 @@ public class CmsLogin implements CmsStyles, CallbackHandler { // } } + private static HttpClient openHttpClient(Subject subject, String server) { + try { + String domain = "WORK.ARGEO.ORG"; + // disable https check + // jdk.internal.httpclient.disableHostnameVerification=true + HttpClient client = HttpClient.newBuilder().sslContext(insecureContext()) + .authenticator(new Authenticator() { + public PasswordAuthentication getPasswordAuthentication() { + // I haven't checked getRequestingScheme() here, since for NTLM + // and Negotiate, the usrname and password are all the same. + System.err.println("Feeding username and password for " + getRequestingScheme()); + return (new PasswordAuthentication("mbaudier@" + domain, null)); + } + + }).build(); + + String token = RemoteAuthUtils.getGssToken(subject, "HTTP/" + server + "@" + domain); + + HttpRequest request = HttpRequest.newBuilder(URI.create("https://" + server + "/ipa/session/json")).GET() + .header("Authorization", "Negotiate " + token).build(); + BodyHandler bodyHandler = BodyHandlers.ofString(); + HttpResponse response = client.send(request, bodyHandler); + System.out.println(response.body()); + return client; + + // return client; +// AuthPolicy.registerAuthScheme(SpnegoAuthScheme.NAME, SpnegoAuthScheme.class); +// HttpParams params = DefaultHttpParams.getDefaultParams(); +// ArrayList schemes = new ArrayList<>(); +// schemes.add(SpnegoAuthScheme.NAME); +// params.setParameter(AuthPolicy.AUTH_SCHEME_PRIORITY, schemes); +// params.setParameter(CredentialsProvider.PROVIDER, new HttpCredentialProvider()); +// HttpClient httpClient = new HttpClient(); +// httpClient.executeMethod(new GetMethod(("https://" + server + "/ipa/session/json"))); +// return httpClient; + } catch ( + + Exception e) { + throw new IllegalStateException("Cannot open client to IPA server " + server, e); + } + + } + + private static SSLContext insecureContext() { + TrustManager[] noopTrustManager = new TrustManager[] { new X509TrustManager() { + public void checkClientTrusted(X509Certificate[] xcs, String string) { + } + + public void checkServerTrusted(X509Certificate[] xcs, String string) { + } + + public X509Certificate[] getAcceptedIssuers() { + return null; + } + } }; + try { + SSLContext sc = SSLContext.getInstance("ssl"); + sc.init(null, noopTrustManager, null); + return sc; + } catch (KeyManagementException | NoSuchAlgorithmException e) { + throw new IllegalStateException("Cannot create insecure SSL context ", e); + } + } + protected void logout() { cmsView.logout(); cmsView.navigateTo("~"); diff --git a/eclipse/org.argeo.cms.swt/src/org/argeo/cms/swt/auth/LocaleChoice.java b/eclipse/org.argeo.cms.swt/src/org/argeo/cms/swt/auth/LocaleChoice.java index e98e390ee..3ce5ae516 100644 --- a/eclipse/org.argeo.cms.swt/src/org/argeo/cms/swt/auth/LocaleChoice.java +++ b/eclipse/org.argeo.cms.swt/src/org/argeo/cms/swt/auth/LocaleChoice.java @@ -6,10 +6,10 @@ import java.util.Locale; import javax.security.auth.callback.LanguageCallback; -import org.argeo.cms.CmsException; -import org.argeo.cms.LocaleUtils; +import org.argeo.cms.swt.CmsException; /** Choose in a list of locales. TODO: replace with {@link LanguageCallback} */ +@Deprecated public class LocaleChoice { private final List locales; @@ -36,13 +36,13 @@ public class LocaleChoice { this.selectedIndex = defaultIndex; } - /** - * Convenience constructor based on a comma separated list of iso codes (en, - * en_US, fr_CA, etc.). Default selection is default locale. - */ - public LocaleChoice(String locales, Locale defaultLocale) { - this(LocaleUtils.asLocaleList(locales), defaultLocale); - } +// /** +// * Convenience constructor based on a comma separated list of iso codes (en, +// * en_US, fr_CA, etc.). Default selection is default locale. +// */ +// public LocaleChoice(String locales, Locale defaultLocale) { +// this(LocaleUtils.asLocaleList(locales), defaultLocale); +// } public String[] getSupportedLocalesLabels() { String[] labels = new String[locales.size()]; diff --git a/eclipse/org.argeo.ext.equinox.jetty/src/org/argeo/equinox/jetty/CmsJettyCustomizer.java b/eclipse/org.argeo.ext.equinox.jetty/src/org/argeo/equinox/jetty/CmsJettyCustomizer.java index 8ad95c9e3..9d15143d7 100644 --- a/eclipse/org.argeo.ext.equinox.jetty/src/org/argeo/equinox/jetty/CmsJettyCustomizer.java +++ b/eclipse/org.argeo.ext.equinox.jetty/src/org/argeo/equinox/jetty/CmsJettyCustomizer.java @@ -17,7 +17,7 @@ import org.osgi.framework.FrameworkUtil; public class CmsJettyCustomizer extends JettyCustomizer { private BundleContext bc = FrameworkUtil.getBundle(CmsJettyCustomizer.class).getBundleContext(); - public final static String WEBSOCKET_ENABLED = "websocket.enabled"; + public final static String WEBSOCKET_ENABLED = "argeo.websocket.enabled"; @Override public Object customizeContext(Object context, Dictionary settings) { diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/internal/jcr/JcrInitUtils.java b/jcr/org.argeo.cms.jcr/src/org/argeo/cms/internal/jcr/JcrInitUtils.java deleted file mode 100644 index a1cba1a62..000000000 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/internal/jcr/JcrInitUtils.java +++ /dev/null @@ -1,124 +0,0 @@ -package org.argeo.cms.internal.jcr; - -import java.net.URI; -import java.net.URISyntaxException; -import java.util.Dictionary; -import java.util.HashMap; -import java.util.Hashtable; -import java.util.Map; - -import javax.jcr.Repository; -import javax.jcr.RepositoryException; -import javax.jcr.RepositoryFactory; - -import org.argeo.api.cms.CmsDeployment; -import org.argeo.api.cms.CmsLog; -import org.argeo.api.cms.CmsConstants; -import org.argeo.jackrabbit.client.ClientDavexRepositoryFactory; -import org.argeo.jcr.JcrException; -import org.argeo.util.naming.LdapAttrs; -import org.osgi.framework.BundleContext; -import org.osgi.framework.Constants; -import org.osgi.framework.FrameworkUtil; - -/** JCR specific init utilities. */ -@Deprecated -public class JcrInitUtils { - private final static CmsLog log = CmsLog.getLog(JcrInitUtils.class); - private final static BundleContext bundleContext = FrameworkUtil.getBundle(JcrInitUtils.class).getBundleContext(); - -// public static void addToDeployment(CmsDeployment nodeDeployment) { -// // node repository -//// Dictionary provided = null; -// Dictionary provided = nodeDeployment.getProps(CmsConstants.NODE_REPOS_FACTORY_PID, -// CmsConstants.NODE); -// Dictionary nodeConfig = JcrInitUtils.getNodeRepositoryConfig(provided); -// // node repository is mandatory -// nodeDeployment.addFactoryDeployConfig(CmsConstants.NODE_REPOS_FACTORY_PID, nodeConfig); -// -// // additional repositories -//// dataModels: for (DataModels.DataModel dataModel : dataModels.getNonAbstractDataModels()) { -//// if (NodeConstants.NODE_REPOSITORY.equals(dataModel.getName())) -//// continue dataModels; -//// Dictionary config = JcrInitUtils.getRepositoryConfig(dataModel.getName(), -//// getProps(NodeConstants.NODE_REPOS_FACTORY_PID, dataModel.getName())); -//// if (config.size() != 0) -//// putFactoryDeployConfig(NodeConstants.NODE_REPOS_FACTORY_PID, config); -//// } -// -// } - - /** Override the provided config with the framework properties */ - public static Dictionary getNodeRepositoryConfig(Dictionary provided) { - Dictionary props = provided != null ? provided : new Hashtable(); - for (RepoConf repoConf : RepoConf.values()) { - Object value = getFrameworkProp(CmsConstants.NODE_REPO_PROP_PREFIX + repoConf.name()); - if (value != null) { - props.put(repoConf.name(), value); - if (log.isDebugEnabled()) - log.debug("Set node repo configuration " + repoConf.name() + " to " + value); - } - } - props.put(CmsConstants.CN, CmsConstants.NODE_REPOSITORY); - return props; - } - -// public static Dictionary getRepositoryConfig(String dataModelName, -// Dictionary provided) { -// if (dataModelName.equals(CmsConstants.NODE_REPOSITORY) || dataModelName.equals(CmsConstants.EGO_REPOSITORY)) -// throw new IllegalArgumentException("Data model '" + dataModelName + "' is reserved."); -// Dictionary props = provided != null ? provided : new Hashtable(); -// for (RepoConf repoConf : RepoConf.values()) { -// Object value = getFrameworkProp( -// CmsConstants.NODE_REPOS_PROP_PREFIX + dataModelName + '.' + repoConf.name()); -// if (value != null) { -// props.put(repoConf.name(), value); -// if (log.isDebugEnabled()) -// log.debug("Set " + dataModelName + " repo configuration " + repoConf.name() + " to " + value); -// } -// } -// if (props.size() != 0) -// props.put(CmsConstants.CN, dataModelName); -// return props; -// } - - private static void registerRemoteInit(String uri) { - try { - Repository repository = createRemoteRepository(new URI(uri)); - Hashtable properties = new Hashtable<>(); - properties.put(CmsConstants.CN, CmsConstants.NODE_INIT); - properties.put(LdapAttrs.labeledURI.name(), uri); - properties.put(Constants.SERVICE_RANKING, -1000); - bundleContext.registerService(Repository.class, repository, properties); - } catch (RepositoryException e) { - throw new JcrException(e); - } catch (URISyntaxException e) { - throw new IllegalArgumentException(e); - } - } - - private static Repository createRemoteRepository(URI uri) throws RepositoryException { - RepositoryFactory repositoryFactory = new ClientDavexRepositoryFactory(); - Map params = new HashMap(); - params.put(ClientDavexRepositoryFactory.JACKRABBIT_DAVEX_URI, uri.toString()); - // TODO make it configurable - params.put(ClientDavexRepositoryFactory.JACKRABBIT_REMOTE_DEFAULT_WORKSPACE, CmsConstants.SYS_WORKSPACE); - return repositoryFactory.getRepository(params); - } - - private static String getFrameworkProp(String key, String def) { - String value; - if (bundleContext != null) - value = bundleContext.getProperty(key); - else - value = System.getProperty(key); - if (value == null) - return def; - return value; - } - - private static String getFrameworkProp(String key) { - return getFrameworkProp(key, null); - } - -} diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/internal/jcr/RepoConf.java b/jcr/org.argeo.cms.jcr/src/org/argeo/cms/internal/jcr/RepoConf.java index a45656cf5..336ec8239 100644 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/internal/jcr/RepoConf.java +++ b/jcr/org.argeo.cms.jcr/src/org/argeo/cms/internal/jcr/RepoConf.java @@ -1,11 +1,9 @@ package org.argeo.cms.internal.jcr; import org.argeo.api.cms.CmsConstants; -import org.argeo.osgi.metatype.EnumAD; -import org.argeo.osgi.metatype.EnumOCD; /** JCR repository configuration */ -public enum RepoConf implements EnumAD { +public enum RepoConf { /** Repository type */ type("h2"), /** Default workspace */ @@ -41,10 +39,8 @@ public enum RepoConf implements EnumAD { /** The default value. */ private Object def; - private String oid; RepoConf(String oid, Object def) { - this.oid = oid; this.def = def; } @@ -56,17 +52,4 @@ public enum RepoConf implements EnumAD { return def; } - @Override - public String getID() { - if (oid != null) - return oid; - return EnumAD.super.getID(); - } - - public static class OCD extends EnumOCD { - public OCD(String locale) { - super(RepoConf.class, locale); - } - } - } diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/CmsJcrDeployment.java b/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/CmsJcrDeployment.java index 6fdd2009b..ca25ddbdf 100644 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/CmsJcrDeployment.java +++ b/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/CmsJcrDeployment.java @@ -12,15 +12,12 @@ import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collection; import java.util.HashSet; import java.util.Hashtable; -import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; -import javax.jcr.NamespaceRegistry; import javax.jcr.Repository; import javax.jcr.RepositoryException; import javax.jcr.Session; @@ -30,14 +27,10 @@ import javax.servlet.Servlet; import org.apache.jackrabbit.commons.cnd.CndImporter; import org.apache.jackrabbit.core.RepositoryContext; import org.apache.jackrabbit.core.RepositoryImpl; -import org.argeo.api.acr.spi.ProvidedRepository; import org.argeo.api.cms.CmsConstants; -import org.argeo.api.cms.CmsDeployment; import org.argeo.api.cms.CmsLog; import org.argeo.cms.ArgeoNames; -import org.argeo.cms.internal.jcr.JcrInitUtils; import org.argeo.cms.jcr.CmsJcrUtils; -import org.argeo.cms.jcr.acr.JcrContentProvider; import org.argeo.cms.jcr.internal.servlet.CmsRemotingServlet; import org.argeo.cms.jcr.internal.servlet.CmsWebDavServlet; import org.argeo.cms.jcr.internal.servlet.JcrHttpUtils; @@ -48,7 +41,6 @@ import org.argeo.jcr.Jcr; import org.argeo.jcr.JcrException; import org.argeo.jcr.JcrUtils; import org.argeo.util.LangUtils; -import org.argeo.util.naming.LdapAttrs; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import org.osgi.framework.Constants; @@ -165,23 +157,23 @@ public class CmsJcrDeployment { // } // init from repository - Collection> initRepositorySr; - try { - initRepositorySr = bc.getServiceReferences(Repository.class, - "(" + CmsConstants.CN + "=" + CmsConstants.NODE_INIT + ")"); - } catch (InvalidSyntaxException e1) { - throw new IllegalArgumentException(e1); - } - Iterator> it = initRepositorySr.iterator(); - while (it.hasNext()) { - ServiceReference sr = it.next(); - Object labeledUri = sr.getProperties().get(LdapAttrs.labeledURI.name()); - Repository initRepository = bc.getService(sr); - if (log.isDebugEnabled()) - log.debug("Found init repository " + labeledUri + ", copying it..."); - initFromRepository(deployedNodeRepository, initRepository); - log.info("Node repository initialised from " + labeledUri); - } +// Collection> initRepositorySr; +// try { +// initRepositorySr = bc.getServiceReferences(Repository.class, +// "(" + CmsConstants.CN + "=" + CmsConstants.NODE_INIT + ")"); +// } catch (InvalidSyntaxException e1) { +// throw new IllegalArgumentException(e1); +// } +// Iterator> it = initRepositorySr.iterator(); +// while (it.hasNext()) { +// ServiceReference sr = it.next(); +// Object labeledUri = sr.getProperties().get(LdapAttrs.labeledURI.name()); +// Repository initRepository = bc.getService(sr); +// if (log.isDebugEnabled()) +// log.debug("Found init repository " + labeledUri + ", copying it..."); +// initFromRepository(deployedNodeRepository, initRepository); +// log.info("Node repository initialised from " + labeledUri); +// } } /** Init from a (typically remote) repository. */ diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/CmsPaths.java b/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/CmsPaths.java index e7f5a55af..090ec67ef 100644 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/CmsPaths.java +++ b/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/CmsPaths.java @@ -3,6 +3,7 @@ package org.argeo.cms.jcr.internal; import java.nio.file.Path; /** Centralises access to the default node deployment directories. */ +@Deprecated public class CmsPaths { public static Path getRepoDirPath(String cn) { return KernelUtils.getOsgiInstancePath(KernelConstants.DIR_REPOS + '/' + cn); diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/EgoRepository.java b/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/EgoRepository.java index 298025096..abf1a6418 100644 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/EgoRepository.java +++ b/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/EgoRepository.java @@ -19,7 +19,6 @@ import javax.security.auth.login.LoginContext; import org.argeo.api.cms.CmsAuth; import org.argeo.api.cms.CmsConstants; -import org.argeo.cms.CmsException; import org.argeo.cms.jcr.CmsJcrUtils; import org.argeo.jcr.JcrException; import org.argeo.jcr.JcrRepositoryWrapper; @@ -28,7 +27,7 @@ import org.argeo.jcr.JcrUtils; /** * Make sure each user has a home directory available. */ -class EgoRepository extends JcrRepositoryWrapper implements KernelConstants { +class EgoRepository extends JcrRepositoryWrapper { /** The home base path. */ // private String homeBasePath = KernelConstants.DEFAULT_HOME_BASE_PATH; @@ -145,7 +144,7 @@ class EgoRepository extends JcrRepositoryWrapper implements KernelConstants { // JcrUtils.addPrivilege(adminSession, groupsBasePath, NodeConstants.ROLE_USER_ADMIN, Privilege.JCR_READ); adminSession.save(); } catch (RepositoryException e) { - throw new CmsException("Cannot initialize home repository", e); + throw new JcrException("Cannot initialize home repository", e); } finally { JcrUtils.logoutQuietly(adminSession); } @@ -197,7 +196,7 @@ class EgoRepository extends JcrRepositoryWrapper implements KernelConstants { try { dn = new LdapName(username); } catch (InvalidNameException e) { - throw new CmsException("Invalid name " + username, e); + throw new IllegalArgumentException("Invalid name " + username, e); } String userId = dn.getRdn(dn.size() - 1).getValue().toString(); return '/' + userId; @@ -214,7 +213,7 @@ class EgoRepository extends JcrRepositoryWrapper implements KernelConstants { try { dn = new LdapName(username); } catch (InvalidNameException e) { - throw new CmsException("Invalid name " + username, e); + throw new IllegalArgumentException("Invalid name " + username, e); } String userId = dn.getRdn(dn.size() - 1).getValue().toString(); return userId; @@ -233,7 +232,7 @@ class EgoRepository extends JcrRepositoryWrapper implements KernelConstants { Node newWorkgroup = CmsJcrUtils.getGroupHome(adminSession, cn); if (newWorkgroup != null) { JcrUtils.logoutQuietly(adminSession); - throw new CmsException("Workgroup " + newWorkgroup + " already exists for " + dn); + throw new IllegalStateException("Workgroup " + newWorkgroup + " already exists for " + dn); } try { // TODO enhance transformation of cn to a valid node name @@ -251,7 +250,7 @@ class EgoRepository extends JcrRepositoryWrapper implements KernelConstants { JcrUtils.addPrivilege(adminSession, newWorkgroup.getPath(), dn.toString(), Privilege.JCR_ALL); adminSession.save(); } catch (RepositoryException e) { - throw new CmsException("Cannot create workgroup", e); + throw new JcrException("Cannot create workgroup", e); } finally { JcrUtils.logoutQuietly(adminSession); } diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/RepositoryContextsFactory.java b/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/RepositoryContextsFactory.java index 11e9a9e92..f3a099b08 100644 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/RepositoryContextsFactory.java +++ b/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/RepositoryContextsFactory.java @@ -16,6 +16,7 @@ import org.apache.jackrabbit.core.RepositoryContext; import org.argeo.api.cms.CmsConstants; import org.argeo.api.cms.CmsLog; import org.argeo.api.cms.CmsState; +import org.argeo.cms.CmsDeployProperty; import org.argeo.cms.internal.jcr.RepoConf; import org.argeo.cms.internal.jcr.RepositoryBuilder; import org.argeo.cms.jcr.internal.osgi.CmsJcrActivator; @@ -25,6 +26,7 @@ import org.osgi.service.cm.ManagedServiceFactory; /** A {@link ManagedServiceFactory} creating or referencing JCR repositories. */ public class RepositoryContextsFactory { private final static CmsLog log = CmsLog.getLog(RepositoryContextsFactory.class); + private final static String NODE_REPO_PROP_PREFIX = "argeo.node.repo."; // private final BundleContext bc = FrameworkUtil.getBundle(RepositoryServiceFactory.class).getBundleContext(); // private Map repositories = new HashMap(); @@ -68,8 +70,11 @@ public class RepositoryContextsFactory { /** Override the provided config with the framework properties */ private Dictionary getNodeRepositoryConfig() { Dictionary props = new Hashtable(); + addDeployProperty(CmsDeployProperty.DB_URL, RepoConf.dburl, props); + addDeployProperty(CmsDeployProperty.DB_USER, RepoConf.dbuser, props); + addDeployProperty(CmsDeployProperty.DB_PASSWORD, RepoConf.dbpassword, props); for (RepoConf repoConf : RepoConf.values()) { - Object value = getFrameworkProp(CmsConstants.NODE_REPO_PROP_PREFIX + repoConf.name()); + Object value = getFrameworkProp(NODE_REPO_PROP_PREFIX + repoConf.name()); if (value != null) { props.put(repoConf.name(), value); if (log.isDebugEnabled()) @@ -80,6 +85,15 @@ public class RepositoryContextsFactory { return props; } + private void addDeployProperty(CmsDeployProperty deployProperty, RepoConf repoConf, + Dictionary props) { + String value = getFrameworkProp(deployProperty.getProperty()); + if (value != null) { + props.put(repoConf.name(), value); + } + + } + // @Override // public void updated(String pid, Dictionary properties) throws ConfigurationException { protected void deployRepository(Dictionary properties) { diff --git a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/servlet/LinkServlet.java b/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/servlet/LinkServlet.java index 62cdc5f6b..be5684acc 100644 --- a/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/servlet/LinkServlet.java +++ b/jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/servlet/LinkServlet.java @@ -27,7 +27,6 @@ import javax.servlet.http.HttpServletResponse; import org.argeo.api.cms.CmsAuth; import org.argeo.api.cms.CmsConstants; -import org.argeo.cms.CmsException; import org.argeo.cms.jcr.CmsJcrUtils; import org.argeo.jcr.JcrUtils; import org.osgi.framework.BundleContext; @@ -137,7 +136,7 @@ public class LinkServlet extends HttpServlet { response.setHeader("Content-Type", "text/html"); writer.flush(); } catch (Exception e) { - throw new CmsException("Cannot write canonical answer", e); + throw new IllegalStateException("Cannot write canonical answer", e); } finally { JcrUtils.logoutQuietly(session); } @@ -190,7 +189,7 @@ public class LinkServlet extends HttpServlet { buf.append(':').append(url.getPort()); return buf; } catch (MalformedURLException e) { - throw new CmsException("Cannot extract server base URL from " + request.getRequestURL(), e); + throw new IllegalArgumentException("Cannot extract server base URL from " + request.getRequestURL(), e); } } @@ -200,7 +199,7 @@ public class LinkServlet extends HttpServlet { buf.append(CmsJcrUtils.getDataPath(CmsConstants.EGO_REPOSITORY, node)); return new URL(buf.toString()).toString(); } catch (MalformedURLException e) { - throw new CmsException("Cannot build data URL for " + node, e); + throw new IllegalArgumentException("Cannot build data URL for " + node, e); } } @@ -238,7 +237,7 @@ public class LinkServlet extends HttpServlet { buf.append('/').append('!').append(node.getPath()); return new URL(buf.toString()).toString(); } catch (MalformedURLException e) { - throw new CmsException("Cannot build data URL for " + node, e); + throw new IllegalArgumentException("Cannot build data URL for " + node, e); } // return request.getRequestURL().append('!').append(node.getPath()) // .toString(); @@ -252,7 +251,7 @@ public class LinkServlet extends HttpServlet { lc.login(); return subject; } catch (LoginException e) { - throw new CmsException("Cannot login as anonymous", e); + throw new IllegalStateException("Cannot login as anonymous", e); } } diff --git a/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/forms/FormUtils.java b/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/forms/FormUtils.java index d5914d209..ef49c8ae5 100644 --- a/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/forms/FormUtils.java +++ b/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/forms/FormUtils.java @@ -11,7 +11,7 @@ import javax.jcr.RepositoryException; import org.argeo.api.cms.CmsLog; import org.argeo.api.cms.ux.CmsView; -import org.argeo.cms.CmsException; +import org.argeo.cms.swt.CmsException; import org.argeo.cms.ui.util.CmsUiUtils; import org.argeo.eclipse.ui.EclipseUiUtils; import org.eclipse.jface.fieldassist.ControlDecoration; diff --git a/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/fs/CmsFsBrowser.java b/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/fs/CmsFsBrowser.java index 5a5ecdb8b..d9c1c1221 100644 --- a/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/fs/CmsFsBrowser.java +++ b/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/fs/CmsFsBrowser.java @@ -18,9 +18,9 @@ import javax.jcr.Node; import javax.jcr.Repository; import javax.jcr.Session; -import org.argeo.cms.CmsException; import org.argeo.cms.auth.CurrentUser; import org.argeo.cms.jcr.CmsJcrUtils; +import org.argeo.cms.swt.CmsException; import org.argeo.cms.swt.CmsSwtUtils; import org.argeo.eclipse.ui.ColumnDefinition; import org.argeo.eclipse.ui.EclipseUiUtils; diff --git a/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/fs/FsContextMenu.java b/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/fs/FsContextMenu.java index c548e2aa0..1fb3c2a05 100644 --- a/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/fs/FsContextMenu.java +++ b/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/fs/FsContextMenu.java @@ -16,7 +16,7 @@ import java.util.Map; import org.apache.commons.io.IOUtils; import org.argeo.api.cms.CmsLog; -import org.argeo.cms.CmsException; +import org.argeo.cms.swt.CmsException; import org.argeo.cms.swt.CmsSwtUtils; import org.argeo.eclipse.ui.EclipseUiUtils; import org.argeo.eclipse.ui.dialogs.SingleValue; diff --git a/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/internal/JcrContentProvider.java b/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/internal/JcrContentProvider.java index 44885b1ca..ea0abdf5d 100644 --- a/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/internal/JcrContentProvider.java +++ b/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/internal/JcrContentProvider.java @@ -6,7 +6,7 @@ import javax.jcr.Node; import javax.jcr.NodeIterator; import javax.jcr.RepositoryException; -import org.argeo.cms.CmsException; +import org.argeo.cms.swt.CmsException; import org.eclipse.jface.viewers.ITreeContentProvider; import org.eclipse.jface.viewers.Viewer; diff --git a/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/util/SimpleCmsHeader.java b/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/util/SimpleCmsHeader.java index e8bf66297..ab6a29f7d 100644 --- a/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/util/SimpleCmsHeader.java +++ b/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/util/SimpleCmsHeader.java @@ -6,7 +6,7 @@ import java.util.List; import javax.jcr.Node; import javax.jcr.RepositoryException; -import org.argeo.cms.CmsException; +import org.argeo.cms.swt.CmsException; import org.argeo.cms.swt.CmsStyles; import org.argeo.cms.swt.CmsSwtUtils; import org.argeo.cms.ui.CmsUiProvider; diff --git a/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/util/SimpleDynamicPages.java b/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/util/SimpleDynamicPages.java index 8e0e7c179..c61a2fc9e 100644 --- a/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/util/SimpleDynamicPages.java +++ b/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/util/SimpleDynamicPages.java @@ -11,7 +11,7 @@ import javax.jcr.PropertyType; import javax.jcr.RepositoryException; import javax.jcr.Value; -import org.argeo.cms.CmsException; +import org.argeo.cms.swt.CmsException; import org.argeo.cms.ui.CmsUiProvider; import org.argeo.jcr.JcrUtils; import org.eclipse.rap.rwt.RWT; diff --git a/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/util/StyleSheetResourceLoader.java b/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/util/StyleSheetResourceLoader.java index ad1523c1a..1e17dc930 100644 --- a/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/util/StyleSheetResourceLoader.java +++ b/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/util/StyleSheetResourceLoader.java @@ -9,7 +9,7 @@ import java.util.LinkedHashMap; import java.util.Map; import org.apache.commons.io.IOUtils; -import org.argeo.cms.CmsException; +import org.argeo.cms.swt.CmsException; import org.eclipse.rap.rwt.service.ResourceLoader; import org.osgi.framework.Bundle; diff --git a/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/util/SystemNotifications.java b/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/util/SystemNotifications.java index 156a6082f..5a0078163 100644 --- a/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/util/SystemNotifications.java +++ b/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/util/SystemNotifications.java @@ -8,7 +8,7 @@ import java.text.SimpleDateFormat; import java.util.Date; import org.apache.commons.io.IOUtils; -import org.argeo.cms.CmsException; +import org.argeo.cms.swt.CmsException; import org.argeo.cms.swt.CmsStyles; import org.argeo.cms.swt.CmsSwtUtils; import org.eclipse.rap.rwt.RWT; diff --git a/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/util/UserMenu.java b/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/util/UserMenu.java index 008ec2c16..09aeff60f 100644 --- a/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/util/UserMenu.java +++ b/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/util/UserMenu.java @@ -2,7 +2,7 @@ package org.argeo.cms.ui.util; import javax.jcr.Node; -import org.argeo.cms.CmsException; +import org.argeo.cms.swt.CmsException; import org.argeo.cms.swt.auth.CmsLoginShell; import org.eclipse.swt.SWT; import org.eclipse.swt.events.ShellAdapter; diff --git a/org.argeo.api.cms/src/org/argeo/api/cms/CmsConstants.java b/org.argeo.api.cms/src/org/argeo/api/cms/CmsConstants.java index 8fe9846f4..7b89813fd 100644 --- a/org.argeo.api.cms/src/org/argeo/api/cms/CmsConstants.java +++ b/org.argeo.api.cms/src/org/argeo/api/cms/CmsConstants.java @@ -82,31 +82,31 @@ public interface CmsConstants { /* * INIT FRAMEWORK PROPERTIES */ - String NODE_INIT = "argeo.node.init"; - String I18N_DEFAULT_LOCALE = "argeo.i18n.defaultLocale"; - String I18N_LOCALES = "argeo.i18n.locales"; +// String NODE_INIT = "argeo.node.init"; +// String I18N_DEFAULT_LOCALE = "argeo.i18n.defaultLocale"; +// String I18N_LOCALES = "argeo.i18n.locales"; // Node Security - String ROLES_URI = "argeo.node.roles.uri"; - String TOKENS_URI = "argeo.node.tokens.uri"; - /** URI to an LDIF file or LDAP server used as initialization or backend */ - String USERADMIN_URIS = "argeo.node.useradmin.uris"; +// String ROLES_URI = "argeo.node.roles.uri"; +// String TOKENS_URI = "argeo.node.tokens.uri"; +// /** URI to an LDIF file or LDAP server used as initialization or backend */ +// String USERADMIN_URIS = "argeo.node.useradmin.uris"; // Transaction manager - String TRANSACTION_MANAGER = "argeo.node.transaction.manager"; - String TRANSACTION_MANAGER_SIMPLE = "simple"; - String TRANSACTION_MANAGER_BITRONIX = "bitronix"; +// String TRANSACTION_MANAGER = "argeo.node.transaction.manager"; +// String TRANSACTION_MANAGER_SIMPLE = "simple"; +// String TRANSACTION_MANAGER_BITRONIX = "bitronix"; // Node - /** Properties configuring the node repository */ - String NODE_REPO_PROP_PREFIX = "argeo.node.repo."; - /** Additional standalone repositories, related to data models. */ - String NODE_REPOS_PROP_PREFIX = "argeo.node.repos."; +// /** Properties configuring the node repository */ +// String NODE_REPO_PROP_PREFIX = "argeo.node.repo."; +// /** Additional standalone repositories, related to data models. */ +// String NODE_REPOS_PROP_PREFIX = "argeo.node.repos."; // HTTP - String HTTP_PORT = "org.osgi.service.http.port"; - String HTTP_PORT_SECURE = "org.osgi.service.http.port.secure"; - /** - * The HTTP header used to convey the DN of a client verified by a reverse - * proxy. Typically SSL_CLIENT_S_DN for Apache. - */ - String HTTP_PROXY_SSL_DN = "argeo.http.proxy.ssl.dn"; +// String HTTP_PORT = "org.osgi.service.http.port"; +// String HTTP_PORT_SECURE = "org.osgi.service.http.port.secure"; +// /** +// * The HTTP header used to convey the DN of a client verified by a reverse +// * proxy. Typically SSL_CLIENT_S_DN for Apache. +// */ +// String HTTP_PROXY_SSL_DN = "argeo.http.proxy.ssl.dn"; /* * PIDs diff --git a/org.argeo.api.cms/src/org/argeo/api/cms/CmsDeployment.java b/org.argeo.api.cms/src/org/argeo/api/cms/CmsDeployment.java index c69be8eeb..d557816cb 100644 --- a/org.argeo.api.cms/src/org/argeo/api/cms/CmsDeployment.java +++ b/org.argeo.api.cms/src/org/argeo/api/cms/CmsDeployment.java @@ -1,7 +1,5 @@ package org.argeo.api.cms; -import java.util.Dictionary; - /** A configured node deployment. */ public interface CmsDeployment { diff --git a/org.argeo.api.cms/src/org/argeo/api/cms/CmsState.java b/org.argeo.api.cms/src/org/argeo/api/cms/CmsState.java index 3e0e8b757..181e4b9c6 100644 --- a/org.argeo.api.cms/src/org/argeo/api/cms/CmsState.java +++ b/org.argeo.api.cms/src/org/argeo/api/cms/CmsState.java @@ -1,6 +1,7 @@ package org.argeo.api.cms; import java.nio.file.Path; +import java.util.List; import java.util.UUID; /** A running node process. */ @@ -11,7 +12,13 @@ public interface CmsState { UUID getUuid(); - String getDeployProperty(String key); - + String getDeployProperty(String property); + + /** + * A list of size of the max count for this property, with null values when the + * property is not set, or an empty list (size 0) if this property is unknown. + */ + List getDeployProperties(String property); + Path getDataPath(String relativePath); } diff --git a/org.argeo.cms/src/org/argeo/cms/ArgeoNames.java b/org.argeo.cms/src/org/argeo/cms/ArgeoNames.java index 90260c314..4e869b7fd 100644 --- a/org.argeo.cms/src/org/argeo/cms/ArgeoNames.java +++ b/org.argeo.cms/src/org/argeo/cms/ArgeoNames.java @@ -1,6 +1,7 @@ package org.argeo.cms; /** JCR names in the http://www.argeo.org/argeo namespace */ +@Deprecated public interface ArgeoNames { public final static String ARGEO_NAMESPACE = "http://www.argeo.org/ns/argeo"; diff --git a/org.argeo.cms/src/org/argeo/cms/ArgeoTypes.java b/org.argeo.cms/src/org/argeo/cms/ArgeoTypes.java index ce0439102..9995725d8 100644 --- a/org.argeo.cms/src/org/argeo/cms/ArgeoTypes.java +++ b/org.argeo.cms/src/org/argeo/cms/ArgeoTypes.java @@ -1,9 +1,10 @@ package org.argeo.cms; /** JCR types in the http://www.argeo.org/argeo namespace */ +@Deprecated public interface ArgeoTypes { public final static String ARGEO_REMOTE_REPOSITORY = "argeo:remoteRepository"; - + // tabular public final static String ARGEO_TABLE = "argeo:table"; public final static String ARGEO_COLUMN = "argeo:column"; diff --git a/org.argeo.cms/src/org/argeo/cms/CmsDeployProperty.java b/org.argeo.cms/src/org/argeo/cms/CmsDeployProperty.java new file mode 100644 index 000000000..ef1edcc1d --- /dev/null +++ b/org.argeo.cms/src/org/argeo/cms/CmsDeployProperty.java @@ -0,0 +1,147 @@ +package org.argeo.cms; + +import java.util.Objects; + +/** A property that can be used to configure a CMS node deployment. */ +public enum CmsDeployProperty { + // + // DIRECTORY + // + DIRECTORY("argeo.directory", 64), + // + // DATABASE + // + /** URL of the database backend. */ + DB_URL("argeo.db.url"), + /** DB user of the database backend. */ + DB_USER("argeo.db.user"), + /** DB user password of the database backend. */ + DB_PASSWORD("argeo.db.password"), + // + // NETWORK + // + /** Either a host or an IP address. Restricts all servers to it. */ + HOST("argeo.host"), + // + // HTTP + // + /** Request an HTTP server on this port. */ + HTTP_PORT("argeo.http.port"), + /** Request an HTTPS server on this port. */ + HTTPS_PORT("argeo.https.port"), + /** + * The HTTP header used to convey the DN of a client verified by a reverse + * proxy. Typically SSL_CLIENT_S_DN for Apache. + */ + HTTP_PROXY_SSL_HEADER_DN("argeo.http.proxy.ssl.header.dn"), + // + // SSL + // + /** SSL keystore for the system. */ + SSL_KEYSTORE("argeo.ssl.keystore"), + /** SSL keystore password for the system. */ + SSL_PASSWORD("argeo.ssl.password"), + /** SSL keystore type password for the system. */ + SSL_KEYSTORETYPE("argeo.ssl.keystoretype"), + /** SSL password for the private key. */ + SSL_KEYPASSWORD("argeo.ssl.keypassword"), + /** Whether a client certificate is required. */ + SSL_NEEDCLIENTAUTH("argeo.ssl.needclientauth"), + /** Whether a client certificate can be used. */ + SSL_WANTCLIENTAUTH("argeo.ssl.wantclientauth"), + /** SSL protocol to use. */ + SSL_PROTOCOL("argeo.ssl.protocol"), + /** SSL algorithm to use. */ + SSL_ALGORITHM("argeo.ssl.algorithm"), + // + // WEBSOCKET + // + /** Whether web socket should be enables in web server. */ + WEBSOCKET_ENABLED("argeo.websocket.enabled"), + // + // INTERNATIONALIZATION + // + /** Locales enabled for this system, the first one is considered the default. */ + LOCALE("argeo.locale", 256), + // + // NODE + // + /** Directories to copy to the data area during the first initialisation. */ + NODE_INIT("argeo.node.init", 64), + // + // JAVA + // + /** Custom JAAS config. */ + JAVA_LOGIN_CONFIG("java.security.auth.login.config", true), + // + // OSGi + // + /** OSGi writable data area. */ + OSGI_INSTANCE_AREA("osgi.instance.area"), + /** OSGi writable configuration area. */ + OSGI_CONFIGURATION_AREA("osgi.configuration.area"), + // + ; + + private String property; + private boolean systemPropertyOnly = false; + + private int maxCount = 1; + + CmsDeployProperty(String property) { + this(property, 1, false); + } + + CmsDeployProperty(String property, int maxCount) { + this(property, maxCount, false); + } + + CmsDeployProperty(String property, boolean systemPropertyOnly) { + this.property = property; + } + + CmsDeployProperty(String property, int maxCount, boolean systemPropertyOnly) { + this.property = property; + this.systemPropertyOnly = systemPropertyOnly; + this.maxCount = maxCount; + } + + public String getProperty() { + return property; + } + + public boolean isSystemPropertyOnly() { + return systemPropertyOnly; + } + + public int getMaxCount() { + return maxCount; + } + + public static CmsDeployProperty find(String property) { + int index = getPropertyIndex(property); + String propertyName = index == 0 ? property : property.substring(0, property.lastIndexOf('.')); + for (CmsDeployProperty deployProperty : values()) { + if (deployProperty.getProperty().equals(propertyName)) + return deployProperty; + } + return null; + } + + public static int getPropertyIndex(String property) { + Objects.requireNonNull(property); + int lastDot = property.lastIndexOf('.'); + if (lastDot <= 0 || lastDot == (property.length() - 1)) { + throw new IllegalArgumentException("Property " + property + " is not qualified (must contain a dot)."); + } + String lastSegment = property.substring(lastDot + 1); + int index; + try { + index = Integer.parseInt(lastSegment); + } catch (NumberFormatException e) { + index = 0; + } + return index; + } + +} diff --git a/org.argeo.cms/src/org/argeo/cms/CmsException.java b/org.argeo.cms/src/org/argeo/cms/CmsException.java deleted file mode 100644 index 09d55c227..000000000 --- a/org.argeo.cms/src/org/argeo/cms/CmsException.java +++ /dev/null @@ -1,16 +0,0 @@ -package org.argeo.cms; - -/** @deprecated Use standard Java {@link RuntimeException} instead. */ -@Deprecated -public class CmsException extends RuntimeException { - private static final long serialVersionUID = -5341764743356771313L; - - public CmsException(String message) { - super(message); - } - - public CmsException(String message, Throwable e) { - super(message, e); - } - -} diff --git a/org.argeo.cms/src/org/argeo/cms/LocaleUtils.java b/org.argeo.cms/src/org/argeo/cms/LocaleUtils.java index f02e6a2b4..415a0954d 100644 --- a/org.argeo.cms/src/org/argeo/cms/LocaleUtils.java +++ b/org.argeo.cms/src/org/argeo/cms/LocaleUtils.java @@ -1,13 +1,8 @@ package org.argeo.cms; -import java.security.AccessController; -import java.util.ArrayList; -import java.util.List; import java.util.Locale; import java.util.ResourceBundle; -import javax.security.auth.Subject; - import org.argeo.api.cms.CmsLog; import org.argeo.cms.auth.CurrentUser; @@ -102,7 +97,7 @@ public class LocaleUtils { static Locale getCurrentLocale() { Locale currentLocale = null; - if (Subject.getSubject(AccessController.getContext()) != null) + if (CurrentUser.isAvailable()) currentLocale = CurrentUser.locale(); else if (threadLocale.get() != null) { currentLocale = threadLocale.get(); @@ -118,26 +113,4 @@ public class LocaleUtils { // return Locale.getDefault(); } - /** Returns null if argument is null. */ - public static List asLocaleList(Object locales) { - if (locales == null) - return null; - ArrayList availableLocales = new ArrayList(); - String[] codes = locales.toString().split(","); - for (int i = 0; i < codes.length; i++) { - String code = codes[i]; - // variant not supported - int indexUnd = code.indexOf("_"); - Locale locale; - if (indexUnd > 0) { - String language = code.substring(0, indexUnd); - String country = code.substring(indexUnd + 1); - locale = new Locale(language, country); - } else { - locale = new Locale(code); - } - availableLocales.add(locale); - } - return availableLocales; - } } 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 3e01aee8b..6285710e8 100644 --- a/org.argeo.cms/src/org/argeo/cms/acr/CmsContentRepository.java +++ b/org.argeo.cms/src/org/argeo/cms/acr/CmsContentRepository.java @@ -45,7 +45,7 @@ public class CmsContentRepository extends AbstractContentRepository { CmsContentSession contentSession = userSessions.get(cmsSession); if (contentSession == null) { final CmsContentSession newContentSession = new CmsContentSession(this, cmsSession.getUuid(), - cmsSession.getSubject(), locale); + cmsSession.getSubject(), locale, uuidFactory); cmsSession.addOnCloseCallback((c) -> { newContentSession.close(); userSessions.remove(cmsSession); @@ -65,8 +65,8 @@ public class CmsContentRepository extends AbstractContentRepository { throw new RuntimeException("Could not login as data admin", e1); } finally { } - return new CmsContentSession(this, getCmsState().getUuid(), loginContext.getSubject(), - Locale.getDefault()); + return new CmsContentSession(this, getCmsState().getUuid(), loginContext.getSubject(), Locale.getDefault(), + uuidFactory); } protected CmsState getCmsState() { diff --git a/org.argeo.cms/src/org/argeo/cms/acr/CmsContentSession.java b/org.argeo.cms/src/org/argeo/cms/acr/CmsContentSession.java index b82507d6f..f811642c7 100644 --- a/org.argeo.cms/src/org/argeo/cms/acr/CmsContentSession.java +++ b/org.argeo.cms/src/org/argeo/cms/acr/CmsContentSession.java @@ -1,27 +1,23 @@ package org.argeo.cms.acr; -import java.util.Iterator; import java.util.Locale; -import java.util.Map; import java.util.Set; import java.util.TreeSet; import java.util.UUID; 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 org.argeo.api.acr.Content; import org.argeo.api.acr.ContentSession; import org.argeo.api.acr.CrName; -import org.argeo.api.acr.NamespaceUtils; -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.ProvidedRepository; import org.argeo.api.acr.spi.ProvidedSession; +import org.argeo.api.uuid.UuidFactory; import org.argeo.cms.acr.xml.DomContentProvider; /** Implements {@link ProvidedSession}. */ @@ -32,6 +28,8 @@ class CmsContentSession implements ProvidedSession { private Subject subject; private Locale locale; + private UuidFactory uuidFactory; + private CompletableFuture closed = new CompletableFuture<>(); private CompletableFuture edition; @@ -40,12 +38,13 @@ class CmsContentSession implements ProvidedSession { private Content sessionRunDir; - public CmsContentSession(AbstractContentRepository contentRepository, UUID uuid, Subject subject, Locale locale) { + public CmsContentSession(AbstractContentRepository contentRepository, UUID uuid, Subject subject, Locale locale, + UuidFactory uuidFactory) { this.contentRepository = contentRepository; this.subject = subject; this.locale = locale; this.uuid = uuid; - + this.uuidFactory = uuidFactory; } public void close() { @@ -99,6 +98,10 @@ class CmsContentSession implements ProvidedSession { return contentRepository; } + public UuidFactory getUuidFactory() { + return uuidFactory; + } + /* * MOUNT MANAGEMENT */ diff --git a/org.argeo.cms/src/org/argeo/cms/acr/SingleUserContentRepository.java b/org.argeo.cms/src/org/argeo/cms/acr/SingleUserContentRepository.java index cac407495..8125555f9 100644 --- a/org.argeo.cms/src/org/argeo/cms/acr/SingleUserContentRepository.java +++ b/org.argeo.cms/src/org/argeo/cms/acr/SingleUserContentRepository.java @@ -11,6 +11,8 @@ import javax.security.auth.x500.X500Principal; import org.argeo.api.acr.ContentSession; import org.argeo.api.acr.spi.ProvidedRepository; +import org.argeo.api.uuid.MacAddressUuidFactory; +import org.argeo.api.uuid.UuidFactory; import org.argeo.cms.acr.fs.FsContentProvider; import org.argeo.util.naming.LdapAttrs; @@ -24,6 +26,8 @@ public class SingleUserContentRepository extends AbstractContentRepository { private UUID uuid; + private UuidFactory uuidFactory = MacAddressUuidFactory.DEFAULT; + // the single session private CmsContentSession contentSession; @@ -51,7 +55,7 @@ public class SingleUserContentRepository extends AbstractContentRepository { initRootContentProvider(null); if (contentSession != null) throw new IllegalStateException("Repository is already started, stop it first."); - contentSession = new CmsContentSession(this, uuid, subject, locale); + contentSession = new CmsContentSession(this, uuid, subject, locale, uuidFactory); } @Override @@ -76,7 +80,7 @@ public class SingleUserContentRepository extends AbstractContentRepository { @Override protected CmsContentSession newSystemSession() { - return new CmsContentSession(this, uuid, subject, Locale.getDefault()); + return new CmsContentSession(this, uuid, subject, Locale.getDefault(), uuidFactory); } public static void main(String... args) { diff --git a/org.argeo.cms/src/org/argeo/cms/auth/CurrentUser.java b/org.argeo.cms/src/org/argeo/cms/auth/CurrentUser.java index 13b54a549..68ea5ff28 100644 --- a/org.argeo.cms/src/org/argeo/cms/auth/CurrentUser.java +++ b/org.argeo.cms/src/org/argeo/cms/auth/CurrentUser.java @@ -138,11 +138,18 @@ public final class CurrentUser { return CmsContextImpl.getCmsContext().getCmsSessionByUuid(cmsSessionId.getUuid()); } + public static boolean isAvailable() { + return CurrentSubject.current() != null; + } + /* * HELPERS */ private static Subject currentSubject() { - return CurrentSubject.current(); + Subject subject = CurrentSubject.current(); + if (subject == null) + throw new IllegalStateException("Cannot find related subject"); + return subject; } private static Authorization getAuthorization(Subject subject) { diff --git a/org.argeo.cms/src/org/argeo/cms/auth/RemoteAuthUtils.java b/org.argeo.cms/src/org/argeo/cms/auth/RemoteAuthUtils.java index 6274bb146..0bb199dfd 100644 --- a/org.argeo.cms/src/org/argeo/cms/auth/RemoteAuthUtils.java +++ b/org.argeo.cms/src/org/argeo/cms/auth/RemoteAuthUtils.java @@ -3,12 +3,19 @@ package org.argeo.cms.auth; import java.security.AccessControlContext; import java.security.AccessController; import java.security.PrivilegedAction; +import java.util.Base64; import java.util.function.Supplier; import javax.security.auth.Subject; +import javax.security.auth.kerberos.KerberosTicket; import org.argeo.api.cms.CmsSession; import org.argeo.cms.internal.runtime.CmsContextImpl; +import org.ietf.jgss.GSSContext; +import org.ietf.jgss.GSSException; +import org.ietf.jgss.GSSManager; +import org.ietf.jgss.GSSName; +import org.ietf.jgss.Oid; /** Remote authentication utilities. */ public class RemoteAuthUtils { @@ -59,4 +66,50 @@ public class RemoteAuthUtils { CmsSession cmsSession = CmsContextImpl.getCmsContext().getCmsSession(subject); return cmsSession; } + + private final static Oid KERBEROS_OID; + static { + try { + KERBEROS_OID = new Oid("1.3.6.1.5.5.2"); + } catch (GSSException e) { + throw new IllegalStateException("Cannot create Kerberos OID", e); + } + } + + public static String getGssToken(Subject subject, String serverPrinc) { + if (subject.getPrivateCredentials(KerberosTicket.class).isEmpty()) + throw new IllegalArgumentException("Subject " + subject + " is not GSS authenticated."); + return Subject.doAs(subject, (PrivilegedAction) () -> { + GSSContext context = null; + String tokenStr = null; + + try { + // Get service's principal name + GSSManager manager = GSSManager.getInstance(); + GSSName serverName = manager.createName(serverPrinc, GSSName.NT_HOSTBASED_SERVICE, KERBEROS_OID); + + // Get the context for authentication + context = manager.createContext(serverName, KERBEROS_OID, null, GSSContext.DEFAULT_LIFETIME); + // context.requestMutualAuth(true); // Request mutual authentication + // context.requestConf(true); // Request confidentiality + context.requestCredDeleg(true); + + byte[] token = new byte[0]; + + // token is ignored on the first call + token = context.initSecContext(token, 0, token.length); + + // Send a token to the server if one was generated by + // initSecContext + if (token != null) { + tokenStr = Base64.getEncoder().encodeToString(token); + // complete=true; + } + return tokenStr; + + } catch (GSSException e) { + throw new IllegalStateException("Cannot authenticate to " + serverPrinc, e); + } + }); + } } diff --git a/org.argeo.cms/src/org/argeo/cms/auth/RemoteSessionLoginModule.java b/org.argeo.cms/src/org/argeo/cms/auth/RemoteSessionLoginModule.java index 05c5cf442..3abcf8c94 100644 --- a/org.argeo.cms/src/org/argeo/cms/auth/RemoteSessionLoginModule.java +++ b/org.argeo.cms/src/org/argeo/cms/auth/RemoteSessionLoginModule.java @@ -16,8 +16,10 @@ import javax.security.auth.spi.LoginModule; import org.argeo.api.cms.CmsConstants; import org.argeo.api.cms.CmsLog; +import org.argeo.cms.CmsDeployProperty; import org.argeo.cms.internal.auth.CmsSessionImpl; import org.argeo.cms.internal.runtime.CmsContextImpl; +import org.argeo.cms.internal.runtime.CmsStateImpl; import org.osgi.service.http.HttpContext; import org.osgi.service.useradmin.Authorization; @@ -210,8 +212,8 @@ public class RemoteSessionLoginModule implements LoginModule { if (log.isDebugEnabled()) log.debug("Client certificate " + certDn + " verified by servlet container"); } // Reverse proxy verified the client certificate - String clientDnHttpHeader = CmsContextImpl.getCmsContext().getCmsState() - .getDeployProperty(CmsConstants.HTTP_PROXY_SSL_DN); + String clientDnHttpHeader = CmsStateImpl.getDeployProperty(CmsContextImpl.getCmsContext().getCmsState(), + CmsDeployProperty.HTTP_PROXY_SSL_HEADER_DN); if (clientDnHttpHeader != null) { String certDn = req.getHeader(clientDnHttpHeader); // TODO retrieve more cf. https://httpd.apache.org/docs/current/mod/mod_ssl.html diff --git a/org.argeo.cms/src/org/argeo/cms/internal/http/client/SpnegoAuthScheme.java b/org.argeo.cms/src/org/argeo/cms/internal/http/client/SpnegoAuthScheme.java index 4abdd1458..27ed2ec3e 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/http/client/SpnegoAuthScheme.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/http/client/SpnegoAuthScheme.java @@ -20,7 +20,6 @@ import org.apache.commons.httpclient.auth.MalformedChallengeException; import org.apache.commons.httpclient.methods.GetMethod; import org.apache.commons.httpclient.params.DefaultHttpParams; import org.apache.commons.httpclient.params.HttpParams; -import org.argeo.cms.internal.runtime.KernelConstants; import org.ietf.jgss.GSSContext; import org.ietf.jgss.GSSException; import org.ietf.jgss.GSSManager; @@ -41,6 +40,8 @@ public class SpnegoAuthScheme implements AuthScheme { } } + private final static String DEFAULT_KERBEROS_SERVICE = "HTTP"; + private boolean complete = false; private String realm; @@ -100,7 +101,7 @@ public class SpnegoAuthScheme implements AuthScheme { } catch (URIException e1) { throw new IllegalStateException("Cannot authenticate", e1); } - String serverPrinc = KernelConstants.DEFAULT_KERBEROS_SERVICE + "@" + hostname; + String serverPrinc = DEFAULT_KERBEROS_SERVICE + "@" + hostname; try { // Get service's principal name diff --git a/org.argeo.cms/src/org/argeo/cms/internal/osgi/CmsOsgiLogger.java b/org.argeo.cms/src/org/argeo/cms/internal/osgi/CmsOsgiLogger.java index c167af025..2936df28a 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/osgi/CmsOsgiLogger.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/osgi/CmsOsgiLogger.java @@ -25,9 +25,7 @@ import org.argeo.api.cms.CmsConstants; import org.argeo.api.cms.CmsLog; import org.argeo.cms.ArgeoLogListener; import org.argeo.cms.ArgeoLogger; -import org.argeo.cms.CmsException; import org.argeo.cms.auth.CurrentUser; -import org.argeo.cms.internal.runtime.KernelConstants; import org.argeo.util.directory.DirectoryConf; import org.osgi.framework.Bundle; import org.osgi.framework.Constants; @@ -40,6 +38,9 @@ import org.osgi.service.log.LogReaderService; /** Not meant to be used directly in standard log4j config */ public class CmsOsgiLogger implements ArgeoLogger, LogListener { + private final static String WHITEBOARD_PATTERN_PROP = "osgi.http.whiteboard.servlet.pattern"; + private final static String CONTEXT_NAME_PROP = "contextName"; + /** Internal debug for development purposes. */ private static Boolean debug = false; @@ -120,7 +121,7 @@ public class CmsOsgiLogger implements ArgeoLogger, LogListener { logDispatcherThread = new LogDispatcherThread(); logDispatcherThread.start(); } catch (Exception e) { - throw new CmsException("Cannot initialize log4j"); + throw new IllegalStateException("Cannot initialize log4j"); } } @@ -203,19 +204,18 @@ public class CmsOsgiLogger implements ArgeoLogger, LogListener { // sb.append(" " + Constants.SERVICE_PID + ": " + servicePid); // } // servlets - Object whiteBoardPattern = sr.getProperty(KernelConstants.WHITEBOARD_PATTERN_PROP); + Object whiteBoardPattern = sr.getProperty(WHITEBOARD_PATTERN_PROP); if (whiteBoardPattern != null) { if (whiteBoardPattern instanceof String) { - sb.append(" " + KernelConstants.WHITEBOARD_PATTERN_PROP + ": " + whiteBoardPattern); + sb.append(" " + WHITEBOARD_PATTERN_PROP + ": " + whiteBoardPattern); } else { - sb.append(" " + KernelConstants.WHITEBOARD_PATTERN_PROP + ": " - + arrayToString((String[]) whiteBoardPattern)); + sb.append(" " + WHITEBOARD_PATTERN_PROP + ": " + arrayToString((String[]) whiteBoardPattern)); } } // RWT - Object contextName = sr.getProperty(KernelConstants.CONTEXT_NAME_PROP); + Object contextName = sr.getProperty(CONTEXT_NAME_PROP); if (contextName != null) - sb.append(" " + KernelConstants.CONTEXT_NAME_PROP + ": " + contextName); + sb.append(" " + CONTEXT_NAME_PROP + ": " + contextName); // user directories Object baseDn = sr.getProperty(DirectoryConf.baseDn.name()); @@ -254,7 +254,7 @@ public class CmsOsgiLogger implements ArgeoLogger, LogListener { public synchronized void register(ArgeoLogListener listener, Integer numberOfPreviousEvents) { String username = CurrentUser.getUsername(); if (username == null) - throw new CmsException("Only authenticated users can register a log listener"); + throw new IllegalStateException("Only authenticated users can register a log listener"); if (!userListeners.containsKey(username)) { List lst = Collections.synchronizedList(new ArrayList()); diff --git a/org.argeo.cms/src/org/argeo/cms/internal/osgi/DeployConfig.java b/org.argeo.cms/src/org/argeo/cms/internal/osgi/DeployConfig.java index e5a504889..7f8db5a06 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/osgi/DeployConfig.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/osgi/DeployConfig.java @@ -23,9 +23,6 @@ import javax.naming.ldap.Rdn; import org.argeo.api.cms.CmsConstants; import org.argeo.api.cms.CmsLog; -import org.argeo.cms.internal.runtime.InitUtils; -import org.argeo.cms.internal.runtime.KernelConstants; -import org.argeo.cms.internal.runtime.KernelUtils; import org.argeo.util.directory.DirectoryConf; import org.argeo.util.directory.ldap.AttributesDictionary; import org.argeo.util.directory.ldap.LdifParser; @@ -42,7 +39,7 @@ public class DeployConfig { private final CmsLog log = CmsLog.getLog(getClass()); // private final BundleContext bc = FrameworkUtil.getBundle(getClass()).getBundleContext(); - private static Path deployConfigPath = KernelUtils.getOsgiInstancePath(KernelConstants.DEPLOY_CONFIG_PATH); + private static Path deployConfigPath;// = KernelUtils.getOsgiInstancePath(KernelConstants.DEPLOY_CONFIG_PATH); private SortedMap deployConfigs = new TreeMap<>(); // private final DataModels dataModels; @@ -57,7 +54,7 @@ public class DeployConfig { Files.createDirectories(deployConfigPath.getParent()); // FirstInit firstInit = new FirstInit(); - InitUtils.prepareFirstInitInstanceArea(); + //InitUtils.prepareFirstInitInstanceArea(); if (!Files.exists(deployConfigPath)) deployConfigs = new TreeMap<>(); diff --git a/org.argeo.cms/src/org/argeo/cms/internal/osgi/NodeUserAdmin.java b/org.argeo.cms/src/org/argeo/cms/internal/osgi/NodeUserAdmin.java index e534d9fe3..da67c733d 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/osgi/NodeUserAdmin.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/osgi/NodeUserAdmin.java @@ -8,7 +8,6 @@ import java.util.Map; import org.argeo.api.cms.CmsConstants; import org.argeo.api.cms.CmsLog; import org.argeo.cms.internal.runtime.CmsUserAdmin; -import org.argeo.cms.internal.runtime.KernelConstants; import org.argeo.osgi.useradmin.UserDirectory; import org.argeo.util.directory.DirectoryConf; import org.osgi.framework.Constants; @@ -20,7 +19,8 @@ import org.osgi.service.useradmin.UserAdmin; * Aggregates multiple {@link UserDirectory} and integrates them with system * roles. */ -public class NodeUserAdmin extends CmsUserAdmin implements ManagedServiceFactory, KernelConstants { +@Deprecated +public class NodeUserAdmin extends CmsUserAdmin implements ManagedServiceFactory { private final static CmsLog log = CmsLog.getLog(NodeUserAdmin.class); // OSGi diff --git a/org.argeo.cms/src/org/argeo/cms/internal/runtime/CmsContextImpl.java b/org.argeo.cms/src/org/argeo/cms/internal/runtime/CmsContextImpl.java index 2a81b6a7d..e14b21e70 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/runtime/CmsContextImpl.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/runtime/CmsContextImpl.java @@ -3,6 +3,7 @@ package org.argeo.cms.internal.runtime; import static java.util.Locale.ENGLISH; import java.lang.management.ManagementFactory; +import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Locale; @@ -13,8 +14,6 @@ import java.util.concurrent.ExecutionException; import javax.security.auth.Subject; -import org.argeo.api.acr.spi.ProvidedContent; -import org.argeo.api.acr.spi.ProvidedRepository; import org.argeo.api.cms.CmsConstants; import org.argeo.api.cms.CmsContext; import org.argeo.api.cms.CmsDeployment; @@ -23,6 +22,7 @@ import org.argeo.api.cms.CmsSession; import org.argeo.api.cms.CmsSessionId; import org.argeo.api.cms.CmsState; import org.argeo.api.uuid.UuidFactory; +import org.argeo.cms.CmsDeployProperty; import org.argeo.cms.LocaleUtils; import org.argeo.cms.internal.auth.CmsSessionImpl; import org.ietf.jgss.GSSCredential; @@ -56,10 +56,14 @@ public class CmsContextImpl implements CmsContext { // } public void start() { - Object defaultLocaleValue = KernelUtils.getFrameworkProp(CmsConstants.I18N_DEFAULT_LOCALE); - defaultLocale = defaultLocaleValue != null ? new Locale(defaultLocaleValue.toString()) - : new Locale(ENGLISH.getLanguage()); - locales = LocaleUtils.asLocaleList(KernelUtils.getFrameworkProp(CmsConstants.I18N_LOCALES)); + List codes = CmsStateImpl.getDeployProperties(cmsState, CmsDeployProperty.LOCALE); + locales = getLocaleList(codes); + if (locales.size() == 0) + throw new IllegalStateException("At least one locale must be set"); + defaultLocale = locales.get(0); +// Object defaultLocaleValue = KernelUtils.getFrameworkProp(CmsConstants.I18N_DEFAULT_LOCALE); +// defaultLocale = defaultLocaleValue != null ? new Locale(defaultLocaleValue.toString()) +// : new Locale(ENGLISH.getLanguage()); // node repository // new ServiceTracker(bc, Repository.class, null) { // @Override @@ -145,6 +149,29 @@ public class CmsContextImpl implements CmsContext { throw new UnsupportedOperationException(); } + /** Returns null if argument is null. */ + private static List getLocaleList(List codes) { + if (codes == null) + return null; + ArrayList availableLocales = new ArrayList(); + for (String code : codes) { + if (code == null) + continue; + // variant not supported + int indexUnd = code.indexOf("_"); + Locale locale; + if (indexUnd > 0) { + String language = code.substring(0, indexUnd); + String country = code.substring(indexUnd + 1); + locale = new Locale(language, country); + } else { + locale = new Locale(code); + } + availableLocales.add(locale); + } + return availableLocales; + } + public void setCmsDeployment(CmsDeployment cmsDeployment) { this.cmsDeployment = cmsDeployment; } diff --git a/org.argeo.cms/src/org/argeo/cms/internal/runtime/CmsDeploymentImpl.java b/org.argeo.cms/src/org/argeo/cms/internal/runtime/CmsDeploymentImpl.java index d01bc8554..2353250c5 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/runtime/CmsDeploymentImpl.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/runtime/CmsDeploymentImpl.java @@ -3,6 +3,7 @@ package org.argeo.cms.internal.runtime; import org.argeo.api.cms.CmsDeployment; import org.argeo.api.cms.CmsLog; import org.argeo.api.cms.CmsState; +import org.argeo.cms.CmsDeployProperty; import org.osgi.service.http.HttpService; /** Implementation of a CMS deployment. */ @@ -64,8 +65,8 @@ public class CmsDeploymentImpl implements CmsDeployment { public void setCmsState(CmsState cmsState) { this.cmsState = cmsState; - String httpPort = this.cmsState.getDeployProperty("org.osgi.service.http.port"); - String httpsPort = this.cmsState.getDeployProperty("org.osgi.service.http.port.secure"); + String httpPort = this.cmsState.getDeployProperty(CmsDeployProperty.HTTP_PORT.getProperty()); + String httpsPort = this.cmsState.getDeployProperty(CmsDeployProperty.HTTPS_PORT.getProperty()); httpExpected = httpPort != null || httpsPort != null; } diff --git a/org.argeo.cms/src/org/argeo/cms/internal/runtime/CmsStateImpl.java b/org.argeo.cms/src/org/argeo/cms/internal/runtime/CmsStateImpl.java index b3ef895f1..792885756 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/runtime/CmsStateImpl.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/runtime/CmsStateImpl.java @@ -1,23 +1,36 @@ package org.argeo.cms.internal.runtime; +import java.io.File; +import java.io.FileFilter; import java.io.IOException; -import java.io.InputStream; +import java.io.Reader; import java.net.InetAddress; import java.net.URL; import java.net.UnknownHostException; +import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; -import java.util.TreeMap; +import java.security.KeyStore; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Objects; +import java.util.StringJoiner; import java.util.UUID; import javax.security.auth.login.Configuration; +import org.apache.commons.io.FileUtils; import org.argeo.api.cms.CmsConstants; import org.argeo.api.cms.CmsLog; import org.argeo.api.cms.CmsState; import org.argeo.api.uuid.UuidFactory; +import org.argeo.cms.CmsDeployProperty; import org.argeo.cms.auth.ident.IdentClient; -import org.argeo.util.directory.ldap.LdifParser; /** * Implementation of a {@link CmsState}, initialising the required services. @@ -34,6 +47,16 @@ public class CmsStateImpl implements CmsState { private UuidFactory uuidFactory; + private final Map deployPropertyDefaults; + + public CmsStateImpl() { + Map deployPropertyDefaults = new HashMap<>(); + deployPropertyDefaults.put(CmsDeployProperty.SSL_KEYSTORETYPE, PkiUtils.PKCS12); + deployPropertyDefaults.put(CmsDeployProperty.NODE_INIT, "../../init"); + deployPropertyDefaults.put(CmsDeployProperty.LOCALE, Locale.getDefault().toString()); + this.deployPropertyDefaults = Collections.unmodifiableMap(deployPropertyDefaults); + } + public void start() { // Runtime.getRuntime().addShutdownHook(new CmsShutdown()); @@ -55,11 +78,27 @@ public class CmsStateImpl implements CmsState { } availableSince = System.currentTimeMillis(); - if (log.isDebugEnabled()) + if (log.isDebugEnabled()) { // log.debug("## CMS starting... stateUuid=" + this.stateUuid + (cleanState ? " // (clean state) " : " ")); - log.debug("## CMS starting... (" + uuid + ")"); - + StringJoiner sb = new StringJoiner("\n"); + CmsDeployProperty[] deployProperties = CmsDeployProperty.values(); + Arrays.sort(deployProperties, (o1, o2) -> o1.name().compareTo(o2.name())); + for (CmsDeployProperty deployProperty : deployProperties) { + List values = getDeployProperties(deployProperty); + for (int i = 0; i < values.size(); i++) { + String value = values.get(i); + if (value != null) { + boolean isDefault = deployPropertyDefaults.containsKey(deployProperty) + && value.equals(deployPropertyDefaults.get(deployProperty)); + String line = deployProperty.getProperty() + (i == 0 ? "" : "." + i) + "=" + value + + (isDefault ? " (default)" : ""); + sb.add(line); + } + } + } + log.debug("## CMS starting... (" + uuid + ")\n" + sb + "\n"); + } // initI18n(); // initServices(); @@ -73,7 +112,7 @@ public class CmsStateImpl implements CmsState { } private void initSecurity() { - if (System.getProperty(KernelConstants.JAAS_CONFIG_PROP) == null) { + if (getDeployProperty(CmsDeployProperty.JAVA_LOGIN_CONFIG) == null) { String jaasConfig = KernelConstants.JAAS_CONFIG; URL url = getClass().getResource(jaasConfig); // System.setProperty(KernelConstants.JAAS_CONFIG_PROP, @@ -82,6 +121,50 @@ public class CmsStateImpl implements CmsState { } // explicitly load JAAS configuration Configuration.getConfiguration(); + + boolean initSsl = getDeployProperty(CmsDeployProperty.HTTPS_PORT) != null; + if (initSsl) { + initCertificates(); + } + } + + private void initCertificates() { + // server certificate + Path keyStorePath = getDataPath(PkiUtils.DEFAULT_KEYSTORE_PATH); + Path pemKeyPath = getDataPath(PkiUtils.DEFAULT_PEM_KEY_PATH); + Path pemCertPath = getDataPath(PkiUtils.DEFAULT_PEM_CERT_PATH); + String keyStorePasswordStr = doGetDeployProperty(CmsDeployProperty.SSL_PASSWORD.getProperty()); + char[] keyStorePassword; + if (keyStorePasswordStr == null) + keyStorePassword = "changeit".toCharArray(); + else + keyStorePassword = keyStorePasswordStr.toCharArray(); + + // if PEM files both exists, update the PKCS12 file + if (Files.exists(pemCertPath) && Files.exists(pemKeyPath)) { + // TODO check certificate update time? monitor changes? + KeyStore keyStore = PkiUtils.getKeyStore(keyStorePath, keyStorePassword, PkiUtils.PKCS12); + try (Reader key = Files.newBufferedReader(pemKeyPath, StandardCharsets.US_ASCII); + Reader cert = Files.newBufferedReader(pemCertPath, StandardCharsets.US_ASCII);) { + PkiUtils.loadPem(keyStore, key, keyStorePassword, cert); + PkiUtils.saveKeyStore(keyStorePath, keyStorePassword, keyStore); + if (log.isDebugEnabled()) + log.debug("PEM certificate stored in " + keyStorePath); + } catch (IOException e) { + log.error("Cannot read PEM files " + pemKeyPath + " and " + pemCertPath, e); + } + } + + if (!Files.exists(keyStorePath)) + PkiUtils.createSelfSignedKeyStore(keyStorePath, keyStorePassword, PkiUtils.PKCS12); +// props.put(JettyHttpConstants.SSL_KEYSTORETYPE, PkiUtils.PKCS12); +// props.put(JettyHttpConstants.SSL_KEYSTORE, keyStorePath.toString()); +// props.put(JettyHttpConstants.SSL_PASSWORD, new String(keyStorePassword)); + +// props.put(InternalHttpConstants.SSL_KEYSTORETYPE, "PKCS11"); +// props.put(InternalHttpConstants.SSL_KEYSTORE, "../../nssdb"); +// props.put(InternalHttpConstants.SSL_PASSWORD, keyStorePassword); + } public void stop() { @@ -94,13 +177,116 @@ public class CmsStateImpl implements CmsState { private void firstInit() throws IOException { log.info("## FIRST INIT ##"); - // FirstInit firstInit = new FirstInit(); - InitUtils.prepareFirstInitInstanceArea(); + List nodeInits = getDeployProperties(CmsDeployProperty.NODE_INIT); +// if (nodeInits == null) +// nodeInits = "../../init"; + CmsStateImpl.prepareFirstInitInstanceArea(nodeInits); } @Override - public String getDeployProperty(String key) { - return KernelUtils.getFrameworkProp(key); + public String getDeployProperty(String property) { + CmsDeployProperty deployProperty = CmsDeployProperty.find(property); + if (deployProperty == null) { + // legacy + if (property.startsWith("argeo.node.")) { + return doGetDeployProperty(property); + } + if (property.equals("argeo.i18n.locales")) { + String value = doGetDeployProperty(property); + if (value != null) { + log.warn("Property " + property + " was ignored (value=" + value + ")"); + + } + return null; + } + throw new IllegalArgumentException("Unsupported deploy property " + property); + } + int index = CmsDeployProperty.getPropertyIndex(property); + return getDeployProperty(deployProperty, index); + } + + @Override + public List getDeployProperties(String property) { + CmsDeployProperty deployProperty = CmsDeployProperty.find(property); + if (deployProperty == null) + return new ArrayList<>(); + return getDeployProperties(deployProperty); + } + + public static List getDeployProperties(CmsState cmsState, CmsDeployProperty deployProperty) { + return ((CmsStateImpl) cmsState).getDeployProperties(deployProperty); + } + + public List getDeployProperties(CmsDeployProperty deployProperty) { + List res = new ArrayList<>(deployProperty.getMaxCount()); + for (int i = 0; i < deployProperty.getMaxCount(); i++) { + // String propertyName = i == 0 ? deployProperty.getProperty() : + // deployProperty.getProperty() + "." + i; + String value = getDeployProperty(deployProperty, i); + res.add(i, value); + } + return res; + } + + public static String getDeployProperty(CmsState cmsState, CmsDeployProperty deployProperty) { + return ((CmsStateImpl) cmsState).getDeployProperty(deployProperty); + } + + public String getDeployProperty(CmsDeployProperty deployProperty) { + String value = getDeployProperty(deployProperty, 0); + return value; + } + + public String getDeployProperty(CmsDeployProperty deployProperty, int index) { + String propertyName = deployProperty.getProperty() + (index == 0 ? "" : "." + index); + String value = doGetDeployProperty(propertyName); + if (value == null && index == 0) { + // try defaults + if (deployPropertyDefaults.containsKey(deployProperty)) { + value = deployPropertyDefaults.get(deployProperty); + } + // try legacy properties + String legacyProperty = switch (deployProperty) { + case DIRECTORY -> "argeo.node.useradmin.uris"; + case DB_URL -> "argeo.node.dburl"; + case DB_USER -> "argeo.node.dbuser"; + case DB_PASSWORD -> "argeo.node.dbpassword"; + case HTTP_PORT -> "org.osgi.service.http.port"; + case HTTPS_PORT -> "org.osgi.service.http.port.secure"; + case HOST -> "org.eclipse.equinox.http.jetty.http.host"; + case LOCALE -> "argeo.i18n.defaultLocale"; + + default -> null; + }; + if (legacyProperty != null) { + value = doGetDeployProperty(legacyProperty); + if (value != null) { + log.warn("Retrieved deploy property " + deployProperty.getProperty() + + " through deprecated property " + legacyProperty); + } + } + } + if (index == 0 && deployProperty.isSystemPropertyOnly()) { + String systemPropertyValue = System.getProperty(deployProperty.getProperty()); + if (!Objects.equals(value, systemPropertyValue)) + throw new IllegalStateException( + "Property " + deployProperty + " must be a ssystem property, but its value is " + value + + ", while the system property value is " + systemPropertyValue); + } + return value != null ? value.toString() : null; + } + + protected String getLegacyProperty(String legacyProperty, CmsDeployProperty deployProperty) { + String value = doGetDeployProperty(legacyProperty); + if (value != null) { + log.warn("Retrieved deploy property " + deployProperty.getProperty() + " through deprecated property " + + legacyProperty + "."); + } + return value; + } + + protected String doGetDeployProperty(String property) { + return KernelUtils.getFrameworkProp(property); } @Override @@ -129,6 +315,47 @@ public class CmsStateImpl implements CmsState { this.uuidFactory = uuidFactory; } + /** + * Called before node initialisation, in order populate OSGi instance are with + * some files (typically LDIF, etc). + */ + public static void prepareFirstInitInstanceArea(List nodeInits) { + + for (String nodeInit : nodeInits) { + + if (nodeInit.startsWith("http")) { + // TODO reconnect it + // registerRemoteInit(nodeInit); + } else { + + // TODO use java.nio.file + File initDir; + if (nodeInit.startsWith(".")) + initDir = KernelUtils.getExecutionDir(nodeInit); + else + initDir = new File(nodeInit); + // TODO also uncompress archives + if (initDir.exists()) + try { + // TODO use NIO utilities + FileUtils.copyDirectory(initDir, KernelUtils.getOsgiInstancePath("").toFile(), + new FileFilter() { + + @Override + public boolean accept(File pathname) { + if (pathname.getName().equals(".svn") || pathname.getName().equals(".git")) + return false; + return true; + } + }); + log.info("CMS initialized from " + initDir.getCanonicalPath()); + } catch (IOException e) { + throw new RuntimeException("Cannot initialize from " + initDir, e); + } + } + } + } + /* * STATIC */ diff --git a/org.argeo.cms/src/org/argeo/cms/internal/runtime/CmsUserAdmin.java b/org.argeo.cms/src/org/argeo/cms/internal/runtime/CmsUserAdmin.java index e73d96f65..9ebc42917 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/runtime/CmsUserAdmin.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/runtime/CmsUserAdmin.java @@ -1,5 +1,6 @@ package org.argeo.cms.internal.runtime; +import java.io.File; import java.io.IOException; import java.net.Inet6Address; import java.net.InetAddress; @@ -30,10 +31,12 @@ import org.apache.commons.httpclient.auth.CredentialsProvider; import org.apache.commons.httpclient.params.DefaultHttpParams; import org.apache.commons.httpclient.params.HttpMethodParams; import org.apache.commons.httpclient.params.HttpParams; +import org.apache.commons.io.FileUtils; import org.argeo.api.cms.CmsAuth; import org.argeo.api.cms.CmsConstants; import org.argeo.api.cms.CmsLog; import org.argeo.api.cms.CmsState; +import org.argeo.cms.CmsDeployProperty; import org.argeo.cms.internal.http.client.HttpCredentialProvider; import org.argeo.cms.internal.http.client.SpnegoAuthScheme; import org.argeo.osgi.useradmin.AggregatingUserAdmin; @@ -76,7 +79,7 @@ public class CmsUserAdmin extends AggregatingUserAdmin { public void start() { super.start(); - List> configs = InitUtils.getUserDirectoryConfigs(); + List> configs = getUserDirectoryConfigs(); for (Dictionary config : configs) { UserDirectory userDirectory = enableUserDirectory(config); if (userDirectory.getRealm().isPresent()) @@ -92,6 +95,106 @@ public class CmsUserAdmin extends AggregatingUserAdmin { super.stop(); } + protected List> getUserDirectoryConfigs() { + List> res = new ArrayList<>(); + File nodeBaseDir = cmsState.getDataPath(KernelConstants.DIR_NODE).toFile(); + List uris = new ArrayList<>(); + + // node roles + String nodeRolesUri = null;// getFrameworkProp(CmsConstants.ROLES_URI); + String baseNodeRoleDn = CmsConstants.ROLES_BASEDN; + if (nodeRolesUri == null) { + nodeRolesUri = baseNodeRoleDn + ".ldif"; + File nodeRolesFile = new File(nodeBaseDir, nodeRolesUri); + if (!nodeRolesFile.exists()) + try { + FileUtils.copyInputStreamToFile(CmsUserAdmin.class.getResourceAsStream(baseNodeRoleDn + ".ldif"), + nodeRolesFile); + } catch (IOException e) { + throw new RuntimeException("Cannot copy demo resource", e); + } + // nodeRolesUri = nodeRolesFile.toURI().toString(); + } + uris.add(nodeRolesUri); + + // node tokens + String nodeTokensUri = null;// getFrameworkProp(CmsConstants.TOKENS_URI); + String baseNodeTokensDn = CmsConstants.TOKENS_BASEDN; + if (nodeTokensUri == null) { + nodeTokensUri = baseNodeTokensDn + ".ldif"; + File nodeTokensFile = new File(nodeBaseDir, nodeTokensUri); + if (!nodeTokensFile.exists()) + try { + FileUtils.copyInputStreamToFile(CmsUserAdmin.class.getResourceAsStream(baseNodeTokensDn + ".ldif"), + nodeTokensFile); + } catch (IOException e) { + throw new RuntimeException("Cannot copy demo resource", e); + } + // nodeRolesUri = nodeRolesFile.toURI().toString(); + } + uris.add(nodeTokensUri); + + // Business roles +// String userAdminUris = getFrameworkProp(CmsConstants.USERADMIN_URIS); + List userAdminUris = CmsStateImpl.getDeployProperties(cmsState, CmsDeployProperty.DIRECTORY);// getFrameworkProp(CmsConstants.USERADMIN_URIS); + for (String userAdminUri : userAdminUris) { + if (userAdminUri == null) + continue; +// if (!userAdminUri.trim().equals("")) + uris.add(userAdminUri); + } + + if (uris.size() == 0) { + // TODO put this somewhere else + String demoBaseDn = "dc=example,dc=com"; + String userAdminUri = demoBaseDn + ".ldif"; + File businessRolesFile = new File(nodeBaseDir, userAdminUri); + File systemRolesFile = new File(nodeBaseDir, "ou=roles,ou=node.ldif"); + if (!businessRolesFile.exists()) + try { + FileUtils.copyInputStreamToFile(CmsUserAdmin.class.getResourceAsStream(demoBaseDn + ".ldif"), + businessRolesFile); + if (!systemRolesFile.exists()) + FileUtils.copyInputStreamToFile( + CmsUserAdmin.class.getResourceAsStream("example-ou=roles,ou=node.ldif"), + systemRolesFile); + } catch (IOException e) { + throw new RuntimeException("Cannot copy demo resources", e); + } + // userAdminUris = businessRolesFile.toURI().toString(); + log.warn("## DEV Using dummy base DN " + demoBaseDn); + // TODO downgrade security level + } + + // Interprets URIs + for (String uri : uris) { + URI u; + try { + u = new URI(uri); + if (u.getPath() == null) + throw new IllegalArgumentException( + "URI " + uri + " must have a path in order to determine base DN"); + if (u.getScheme() == null) { + if (uri.startsWith("/") || uri.startsWith("./") || uri.startsWith("../")) + u = new File(uri).getCanonicalFile().toURI(); + else if (!uri.contains("/")) { + // u = KernelUtils.getOsgiInstanceUri(KernelConstants.DIR_NODE + '/' + uri); + u = new URI(uri); + } else + throw new IllegalArgumentException("Cannot interpret " + uri + " as an uri"); + } else if (u.getScheme().equals(DirectoryConf.SCHEME_FILE)) { + u = new File(u).getCanonicalFile().toURI(); + } + } catch (Exception e) { + throw new RuntimeException("Cannot interpret " + uri + " as an uri", e); + } + Dictionary properties = DirectoryConf.uriAsProperties(u.toString()); + res.add(properties); + } + + return res; + } + public UserDirectory enableUserDirectory(Dictionary properties) { String uri = (String) properties.get(DirectoryConf.uri.name()); Object realm = properties.get(DirectoryConf.realm.name()); @@ -224,7 +327,7 @@ public class CmsUserAdmin extends AggregatingUserAdmin { } private void loadIpaJaasConfiguration() { - if (System.getProperty(KernelConstants.JAAS_CONFIG_PROP) == null) { + if (CmsStateImpl.getDeployProperty(cmsState, CmsDeployProperty.JAVA_LOGIN_CONFIG) == null) { String jaasConfig = KernelConstants.JAAS_CONFIG_IPA; URL url = getClass().getClassLoader().getResource(jaasConfig); KernelUtils.setJaasConfiguration(url); diff --git a/org.argeo.cms/src/org/argeo/cms/internal/runtime/InitUtils.java b/org.argeo.cms/src/org/argeo/cms/internal/runtime/InitUtils.java deleted file mode 100644 index f634e43b5..000000000 --- a/org.argeo.cms/src/org/argeo/cms/internal/runtime/InitUtils.java +++ /dev/null @@ -1,250 +0,0 @@ -package org.argeo.cms.internal.runtime; - -import static org.argeo.cms.internal.runtime.KernelUtils.getFrameworkProp; - -import java.io.File; -import java.io.FileFilter; -import java.io.IOException; -import java.net.URI; -import java.util.ArrayList; -import java.util.Dictionary; -import java.util.List; - -import org.apache.commons.io.FileUtils; -import org.argeo.api.cms.CmsConstants; -import org.argeo.api.cms.CmsLog; -import org.argeo.util.directory.DirectoryConf; - -/** - * Interprets framework properties in order to generate the initial deploy - * configuration. - */ -public class InitUtils { - private final static CmsLog log = CmsLog.getLog(InitUtils.class); - - /** Override the provided config with the framework properties */ -// public static Dictionary getHttpServerConfig(Dictionary provided) { -// String httpPort = getFrameworkProp("org.osgi.service.http.port"); -// String httpsPort = getFrameworkProp("org.osgi.service.http.port.secure"); -// /// TODO make it more generic -// String httpHost = getFrameworkProp( -// InternalHttpConstants.JETTY_PROPERTY_PREFIX + InternalHttpConstants.HTTP_HOST); -// String httpsHost = getFrameworkProp( -// InternalHttpConstants.JETTY_PROPERTY_PREFIX + InternalHttpConstants.HTTPS_HOST); -// String webSocketEnabled = getFrameworkProp( -// InternalHttpConstants.JETTY_PROPERTY_PREFIX + InternalHttpConstants.WEBSOCKET_ENABLED); -// -// final Hashtable props = new Hashtable(); -// // try { -// if (httpPort != null || httpsPort != null) { -// boolean httpEnabled = httpPort != null; -// props.put(InternalHttpConstants.HTTP_ENABLED, httpEnabled); -// boolean httpsEnabled = httpsPort != null; -// props.put(InternalHttpConstants.HTTPS_ENABLED, httpsEnabled); -// -// if (httpEnabled) { -// props.put(InternalHttpConstants.HTTP_PORT, httpPort); -// if (httpHost != null) -// props.put(InternalHttpConstants.HTTP_HOST, httpHost); -// } -// -// if (httpsEnabled) { -// props.put(InternalHttpConstants.HTTPS_PORT, httpsPort); -// if (httpsHost != null) -// props.put(InternalHttpConstants.HTTPS_HOST, httpsHost); -// -// // server certificate -// Path keyStorePath = KernelUtils.getOsgiInstancePath(KernelConstants.DEFAULT_KEYSTORE_PATH); -// Path pemKeyPath = KernelUtils.getOsgiInstancePath(KernelConstants.DEFAULT_PEM_KEY_PATH); -// Path pemCertPath = KernelUtils.getOsgiInstancePath(KernelConstants.DEFAULT_PEM_CERT_PATH); -// String keyStorePasswordStr = getFrameworkProp( -// InternalHttpConstants.JETTY_PROPERTY_PREFIX + InternalHttpConstants.SSL_PASSWORD); -// char[] keyStorePassword; -// if (keyStorePasswordStr == null) -// keyStorePassword = "changeit".toCharArray(); -// else -// keyStorePassword = keyStorePasswordStr.toCharArray(); -// -// // if PEM files both exists, update the PKCS12 file -// if (Files.exists(pemCertPath) && Files.exists(pemKeyPath)) { -// // TODO check certificate update time? monitor changes? -// KeyStore keyStore = PkiUtils.getKeyStore(keyStorePath, keyStorePassword, PkiUtils.PKCS12); -// try (Reader key = Files.newBufferedReader(pemKeyPath, StandardCharsets.US_ASCII); -// Reader cert = Files.newBufferedReader(pemCertPath, StandardCharsets.US_ASCII);) { -// PkiUtils.loadPem(keyStore, key, keyStorePassword, cert); -// PkiUtils.saveKeyStore(keyStorePath, keyStorePassword, keyStore); -// if (log.isDebugEnabled()) -// log.debug("PEM certificate stored in " + keyStorePath); -// } catch (IOException e) { -// log.error("Cannot read PEM files " + pemKeyPath + " and " + pemCertPath, e); -// } -// } -// -// if (!Files.exists(keyStorePath)) -// createSelfSignedKeyStore(keyStorePath, keyStorePassword, PkiUtils.PKCS12); -// props.put(InternalHttpConstants.SSL_KEYSTORETYPE, PkiUtils.PKCS12); -// props.put(InternalHttpConstants.SSL_KEYSTORE, keyStorePath.toString()); -// props.put(InternalHttpConstants.SSL_PASSWORD, new String(keyStorePassword)); -// -//// props.put(InternalHttpConstants.SSL_KEYSTORETYPE, "PKCS11"); -//// props.put(InternalHttpConstants.SSL_KEYSTORE, "../../nssdb"); -//// props.put(InternalHttpConstants.SSL_PASSWORD, keyStorePassword); -// -// // client certificate authentication -// String wantClientAuth = getFrameworkProp( -// InternalHttpConstants.JETTY_PROPERTY_PREFIX + InternalHttpConstants.SSL_WANTCLIENTAUTH); -// if (wantClientAuth != null) -// props.put(InternalHttpConstants.SSL_WANTCLIENTAUTH, Boolean.parseBoolean(wantClientAuth)); -// String needClientAuth = getFrameworkProp( -// InternalHttpConstants.JETTY_PROPERTY_PREFIX + InternalHttpConstants.SSL_NEEDCLIENTAUTH); -// if (needClientAuth != null) -// props.put(InternalHttpConstants.SSL_NEEDCLIENTAUTH, Boolean.parseBoolean(needClientAuth)); -// } -// -// // web socket -// if (webSocketEnabled != null && webSocketEnabled.equals("true")) -// props.put(InternalHttpConstants.WEBSOCKET_ENABLED, true); -// -// props.put(CmsConstants.CN, CmsConstants.DEFAULT); -// } -// return props; -// } - - public static List> getUserDirectoryConfigs() { - List> res = new ArrayList<>(); - File nodeBaseDir = KernelUtils.getOsgiInstancePath(KernelConstants.DIR_NODE).toFile(); - List uris = new ArrayList<>(); - - // node roles - String nodeRolesUri = getFrameworkProp(CmsConstants.ROLES_URI); - String baseNodeRoleDn = CmsConstants.ROLES_BASEDN; - if (nodeRolesUri == null) { - nodeRolesUri = baseNodeRoleDn + ".ldif"; - File nodeRolesFile = new File(nodeBaseDir, nodeRolesUri); - if (!nodeRolesFile.exists()) - try { - FileUtils.copyInputStreamToFile(InitUtils.class.getResourceAsStream(baseNodeRoleDn + ".ldif"), - nodeRolesFile); - } catch (IOException e) { - throw new RuntimeException("Cannot copy demo resource", e); - } - // nodeRolesUri = nodeRolesFile.toURI().toString(); - } - uris.add(nodeRolesUri); - - // node tokens - String nodeTokensUri = getFrameworkProp(CmsConstants.TOKENS_URI); - String baseNodeTokensDn = CmsConstants.TOKENS_BASEDN; - if (nodeTokensUri == null) { - nodeTokensUri = baseNodeTokensDn + ".ldif"; - File nodeTokensFile = new File(nodeBaseDir, nodeTokensUri); - if (!nodeTokensFile.exists()) - try { - FileUtils.copyInputStreamToFile(InitUtils.class.getResourceAsStream(baseNodeTokensDn + ".ldif"), - nodeTokensFile); - } catch (IOException e) { - throw new RuntimeException("Cannot copy demo resource", e); - } - // nodeRolesUri = nodeRolesFile.toURI().toString(); - } - uris.add(nodeTokensUri); - - // Business roles - String userAdminUris = getFrameworkProp(CmsConstants.USERADMIN_URIS); - if (userAdminUris == null) { - String demoBaseDn = "dc=example,dc=com"; - userAdminUris = demoBaseDn + ".ldif"; - File businessRolesFile = new File(nodeBaseDir, userAdminUris); - File systemRolesFile = new File(nodeBaseDir, "ou=roles,ou=node.ldif"); - if (!businessRolesFile.exists()) - try { - FileUtils.copyInputStreamToFile(InitUtils.class.getResourceAsStream(demoBaseDn + ".ldif"), - businessRolesFile); - if (!systemRolesFile.exists()) - FileUtils.copyInputStreamToFile( - InitUtils.class.getResourceAsStream("example-ou=roles,ou=node.ldif"), systemRolesFile); - } catch (IOException e) { - throw new RuntimeException("Cannot copy demo resources", e); - } - // userAdminUris = businessRolesFile.toURI().toString(); - log.warn("## DEV Using dummy base DN " + demoBaseDn); - // TODO downgrade security level - } - for (String userAdminUri : userAdminUris.split(" ")) - if (!userAdminUri.trim().equals("")) - uris.add(userAdminUri); - - // Interprets URIs - for (String uri : uris) { - URI u; - try { - u = new URI(uri); - if (u.getPath() == null) - throw new IllegalArgumentException( - "URI " + uri + " must have a path in order to determine base DN"); - if (u.getScheme() == null) { - if (uri.startsWith("/") || uri.startsWith("./") || uri.startsWith("../")) - u = new File(uri).getCanonicalFile().toURI(); - else if (!uri.contains("/")) { - // u = KernelUtils.getOsgiInstanceUri(KernelConstants.DIR_NODE + '/' + uri); - u = new URI(uri); - } else - throw new IllegalArgumentException("Cannot interpret " + uri + " as an uri"); - } else if (u.getScheme().equals(DirectoryConf.SCHEME_FILE)) { - u = new File(u).getCanonicalFile().toURI(); - } - } catch (Exception e) { - throw new RuntimeException("Cannot interpret " + uri + " as an uri", e); - } - Dictionary properties = DirectoryConf.uriAsProperties(u.toString()); - res.add(properties); - } - - return res; - } - - /** - * Called before node initialisation, in order populate OSGi instance are with - * some files (typically LDIF, etc). - */ - public static void prepareFirstInitInstanceArea() { - String nodeInits = getFrameworkProp(CmsConstants.NODE_INIT); - if (nodeInits == null) - nodeInits = "../../init"; - - for (String nodeInit : nodeInits.split(",")) { - - if (nodeInit.startsWith("http")) { - // TODO reconnect it - // registerRemoteInit(nodeInit); - } else { - - // TODO use java.nio.file - File initDir; - if (nodeInit.startsWith(".")) - initDir = KernelUtils.getExecutionDir(nodeInit); - else - initDir = new File(nodeInit); - // TODO also uncompress archives - if (initDir.exists()) - try { - // TODO use NIO utilities - FileUtils.copyDirectory(initDir, KernelUtils.getOsgiInstancePath("").toFile(), - new FileFilter() { - - @Override - public boolean accept(File pathname) { - if (pathname.getName().equals(".svn") || pathname.getName().equals(".git")) - return false; - return true; - } - }); - log.info("CMS initialized from " + initDir.getCanonicalPath()); - } catch (IOException e) { - throw new RuntimeException("Cannot initialize from " + initDir, e); - } - } - } - } - -} diff --git a/org.argeo.cms/src/org/argeo/cms/internal/runtime/KernelConstants.java b/org.argeo.cms/src/org/argeo/cms/internal/runtime/KernelConstants.java index a02c557f2..1a1c076c2 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/runtime/KernelConstants.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/runtime/KernelConstants.java @@ -1,17 +1,15 @@ package org.argeo.cms.internal.runtime; -import org.argeo.api.cms.CmsConstants; - /** Internal CMS constants. */ -public interface KernelConstants { +interface KernelConstants { // Directories String DIR_NODE = "node"; - String DIR_REPOS = "repos"; - String DIR_INDEXES = "indexes"; - String DIR_TRANSACTIONS = "transactions"; +// String DIR_REPOS = "repos"; +// String DIR_INDEXES = "indexes"; +// String DIR_TRANSACTIONS = "transactions"; // Files - String DEPLOY_CONFIG_PATH = DIR_NODE + '/' + CmsConstants.DEPLOY_BASEDN + ".ldif"; +// String DEPLOY_CONFIG_PATH = DIR_NODE + '/' + CmsConstants.DEPLOY_BASEDN + ".ldif"; String NODE_KEY_TAB_PATH = DIR_NODE + "/krb5.keytab"; // Security @@ -19,12 +17,12 @@ public interface KernelConstants { String JAAS_CONFIG_IPA = "/org/argeo/cms/internal/runtime/jaas-ipa.cfg"; // Java - String JAAS_CONFIG_PROP = "java.security.auth.login.config"; +// String JAAS_CONFIG_PROP = "java.security.auth.login.config"; // DEFAULTS JCR PATH - String DEFAULT_HOME_BASE_PATH = "/home"; - String DEFAULT_USERS_BASE_PATH = "/users"; - String DEFAULT_GROUPS_BASE_PATH = "/groups"; +// String DEFAULT_HOME_BASE_PATH = "/home"; +// String DEFAULT_USERS_BASE_PATH = "/users"; +// String DEFAULT_GROUPS_BASE_PATH = "/groups"; // KERBEROS String DEFAULT_KERBEROS_SERVICE = "HTTP"; @@ -37,14 +35,12 @@ public interface KernelConstants { // String PATH_WORKBENCH_PUBLIC = PATH_WORKBENCH + "/public"; // String JETTY_FACTORY_PID = "org.eclipse.equinox.http.jetty.config"; - String JETTY_FACTORY_PID = "org.argeo.equinox.jetty.config"; - String WHITEBOARD_PATTERN_PROP = "osgi.http.whiteboard.servlet.pattern"; +// String JETTY_FACTORY_PID = "org.argeo.equinox.jetty.config"; // default Jetty server configured via JettyConfigurator - String DEFAULT_JETTY_SERVER = "default"; - String CMS_JETTY_CUSTOMIZER_CLASS = "org.argeo.equinox.jetty.CmsJettyCustomizer"; +// String DEFAULT_JETTY_SERVER = "default"; +// String CMS_JETTY_CUSTOMIZER_CLASS = "org.argeo.equinox.jetty.CmsJettyCustomizer"; // avoid dependencies - String CONTEXT_NAME_PROP = "contextName"; - String JACKRABBIT_REPOSITORY_URI = "org.apache.jackrabbit.repository.uri"; - String JACKRABBIT_REMOTE_DEFAULT_WORKSPACE = "org.apache.jackrabbit.spi2davex.WorkspaceNameDefault"; +// String JACKRABBIT_REPOSITORY_URI = "org.apache.jackrabbit.repository.uri"; +// String JACKRABBIT_REMOTE_DEFAULT_WORKSPACE = "org.apache.jackrabbit.spi2davex.WorkspaceNameDefault"; } diff --git a/org.argeo.cms/src/org/argeo/cms/internal/runtime/KernelUtils.java b/org.argeo.cms/src/org/argeo/cms/internal/runtime/KernelUtils.java index 5635bccfe..2ada3c726 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/runtime/KernelUtils.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/runtime/KernelUtils.java @@ -19,7 +19,7 @@ import org.argeo.api.cms.CmsLog; import org.argeo.cms.internal.osgi.CmsActivator; /** Package utilities */ -public class KernelUtils implements KernelConstants { +class KernelUtils implements KernelConstants { final static String OSGI_INSTANCE_AREA = "osgi.instance.area"; final static String OSGI_CONFIGURATION_AREA = "osgi.configuration.area"; diff --git a/org.argeo.cms/src/org/argeo/cms/internal/runtime/PkiUtils.java b/org.argeo.cms/src/org/argeo/cms/internal/runtime/PkiUtils.java new file mode 100644 index 000000000..a90d59891 --- /dev/null +++ b/org.argeo.cms/src/org/argeo/cms/internal/runtime/PkiUtils.java @@ -0,0 +1,299 @@ +package org.argeo.cms.internal.runtime; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.Reader; +import java.math.BigInteger; +import java.net.InetAddress; +import java.nio.file.Files; +import java.nio.file.Path; +import java.security.GeneralSecurityException; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.PrivateKey; +import java.security.SecureRandom; +import java.security.Security; +import java.security.cert.Certificate; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.util.Arrays; +import java.util.Date; + +import javax.security.auth.x500.X500Principal; + +import org.argeo.api.cms.CmsConstants; +import org.argeo.api.cms.CmsLog; +import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; +import org.bouncycastle.cert.X509CertificateHolder; +import org.bouncycastle.cert.X509v3CertificateBuilder; +import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter; +import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.bouncycastle.openssl.PEMParser; +import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter; +import org.bouncycastle.openssl.jcajce.JceOpenSSLPKCS8DecryptorProviderBuilder; +import org.bouncycastle.operator.ContentSigner; +import org.bouncycastle.operator.InputDecryptorProvider; +import org.bouncycastle.operator.OperatorCreationException; +import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder; +import org.bouncycastle.pkcs.PKCS8EncryptedPrivateKeyInfo; +import org.bouncycastle.pkcs.PKCSException; + +/** + * Utilities around private keys and certificate, mostly wrapping BouncyCastle + * implementations. + */ +class PkiUtils { + private final static CmsLog log = CmsLog.getLog(PkiUtils.class); + + public final static String PKCS12 = "PKCS12"; + public static final String DEFAULT_KEYSTORE_PATH = KernelConstants.DIR_NODE + '/' + CmsConstants.NODE + ".p12"; + + public static final String DEFAULT_PEM_KEY_PATH = KernelConstants.DIR_NODE + '/' + CmsConstants.NODE + ".key"; + + public static final String DEFAULT_PEM_CERT_PATH = KernelConstants.DIR_NODE + '/' + CmsConstants.NODE + ".crt"; + + private final static String SECURITY_PROVIDER; + static { + Security.addProvider(new BouncyCastleProvider()); + SECURITY_PROVIDER = "BC"; + } + + public static X509Certificate generateSelfSignedCertificate(KeyStore keyStore, X500Principal x500Principal, + int keySize, char[] keyPassword) { + try { + KeyPairGenerator kpGen = KeyPairGenerator.getInstance("RSA", SECURITY_PROVIDER); + kpGen.initialize(keySize, new SecureRandom()); + KeyPair pair = kpGen.generateKeyPair(); + Date notBefore = new Date(System.currentTimeMillis() - 10000); + Date notAfter = new Date(System.currentTimeMillis() + 365 * 24L * 3600 * 1000); + BigInteger serial = BigInteger.valueOf(System.currentTimeMillis()); + X509v3CertificateBuilder certGen = new JcaX509v3CertificateBuilder(x500Principal, serial, notBefore, + notAfter, x500Principal, pair.getPublic()); + ContentSigner sigGen = new JcaContentSignerBuilder("SHA256WithRSAEncryption").setProvider(SECURITY_PROVIDER) + .build(pair.getPrivate()); + X509Certificate cert = new JcaX509CertificateConverter().setProvider(SECURITY_PROVIDER) + .getCertificate(certGen.build(sigGen)); + cert.checkValidity(new Date()); + cert.verify(cert.getPublicKey()); + + keyStore.setKeyEntry(x500Principal.getName(), pair.getPrivate(), keyPassword, new Certificate[] { cert }); + return cert; + } catch (GeneralSecurityException | OperatorCreationException e) { + throw new RuntimeException("Cannot generate self-signed certificate", e); + } + } + + public static KeyStore getKeyStore(Path keyStoreFile, char[] keyStorePassword, String keyStoreType) { + try { + KeyStore store = KeyStore.getInstance(keyStoreType, SECURITY_PROVIDER); + if (Files.exists(keyStoreFile)) { + try (InputStream fis = Files.newInputStream(keyStoreFile)) { + store.load(fis, keyStorePassword); + } + } else { + store.load(null); + } + return store; + } catch (GeneralSecurityException | IOException e) { + throw new RuntimeException("Cannot load keystore " + keyStoreFile, e); + } + } + + public static void saveKeyStore(Path keyStoreFile, char[] keyStorePassword, KeyStore keyStore) { + try { + try (OutputStream fis = Files.newOutputStream(keyStoreFile)) { + keyStore.store(fis, keyStorePassword); + } + } catch (GeneralSecurityException | IOException e) { + throw new RuntimeException("Cannot save keystore " + keyStoreFile, e); + } + } + +// public static byte[] pemToPKCS12(final String keyFile, final String cerFile, final String password) +// throws Exception { +// // Get the private key +// FileReader reader = new FileReader(keyFile); +// +// PEMReader pem = new PemReader(reader, new PasswordFinder() { +// @Override +// public char[] getPassword() { +// return password.toCharArray(); +// } +// }); +// +// PrivateKey key = ((KeyPair) pem.readObject()).getPrivate(); +// +// pem.close(); +// reader.close(); +// +// // Get the certificate +// reader = new FileReader(cerFile); +// pem = new PEMReader(reader); +// +// X509Certificate cert = (X509Certificate) pem.readObject(); +// +// pem.close(); +// reader.close(); +// +// // Put them into a PKCS12 keystore and write it to a byte[] +// ByteArrayOutputStream bos = new ByteArrayOutputStream(); +// KeyStore ks = KeyStore.getInstance("PKCS12"); +// ks.load(null); +// ks.setKeyEntry("alias", (Key) key, password.toCharArray(), new java.security.cert.Certificate[] { cert }); +// ks.store(bos, password.toCharArray()); +// bos.close(); +// return bos.toByteArray(); +// } + + public static void loadPem(KeyStore keyStore, Reader key, char[] keyPassword, Reader cert) { + PrivateKey privateKey = loadPemPrivateKey(key, keyPassword); + X509Certificate certificate = loadPemCertificate(cert); + try { + keyStore.setKeyEntry(certificate.getSubjectX500Principal().getName(), privateKey, keyPassword, + new java.security.cert.Certificate[] { certificate }); + } catch (KeyStoreException e) { + throw new RuntimeException("Cannot store PEM certificate", e); + } + } + + public static PrivateKey loadPemPrivateKey(Reader reader, char[] keyPassword) { + try (PEMParser pemParser = new PEMParser(reader)) { + JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider("BC"); + Object object = pemParser.readObject(); + PrivateKeyInfo privateKeyInfo; + if (object instanceof PKCS8EncryptedPrivateKeyInfo) { + if (keyPassword == null) + throw new IllegalArgumentException("A key password is required"); + InputDecryptorProvider decProv = new JceOpenSSLPKCS8DecryptorProviderBuilder().build(keyPassword); + privateKeyInfo = ((PKCS8EncryptedPrivateKeyInfo) object).decryptPrivateKeyInfo(decProv); + } else if (object instanceof PrivateKeyInfo) { + privateKeyInfo = (PrivateKeyInfo) object; + } else { + throw new IllegalArgumentException("Unsupported format for private key"); + } + return converter.getPrivateKey(privateKeyInfo); + } catch (IOException | OperatorCreationException | PKCSException e) { + throw new RuntimeException("Cannot read private key", e); + } + } + + public static X509Certificate loadPemCertificate(Reader reader) { + try (PEMParser pemParser = new PEMParser(reader)) { + X509CertificateHolder certHolder = (X509CertificateHolder) pemParser.readObject(); + X509Certificate cert = new JcaX509CertificateConverter().setProvider(SECURITY_PROVIDER) + .getCertificate(certHolder); + return cert; + } catch (IOException | CertificateException e) { + throw new RuntimeException("Cannot read private key", e); + } + } + + public static void main(String[] args) throws Exception { + final String ALGORITHM = "RSA"; + final String provider = "BC"; + SecureRandom secureRandom = new SecureRandom(); + long begin = System.currentTimeMillis(); + for (int i = 512; i < 1024; i = i + 2) { + try { + KeyPairGenerator keyGen = KeyPairGenerator.getInstance(ALGORITHM, provider); + keyGen.initialize(i, secureRandom); + keyGen.generateKeyPair(); + } catch (Exception e) { + System.err.println(i + " : " + e.getMessage()); + } + } + System.out.println((System.currentTimeMillis() - begin) + " ms"); + + // // String text = "a"; + // String text = + // "testtesttesttesttesttesttesttesttesttesttesttesttesttesttest"; + // try { + // System.out.println(text); + // PrivateKey privateKey; + // PublicKey publicKey; + // char[] password = "changeit".toCharArray(); + // String alias = "CN=test"; + // KeyStore keyStore = KeyStore.getInstance("pkcs12"); + // File p12file = new File("test.p12"); + // p12file.delete(); + // if (!p12file.exists()) { + // keyStore.load(null); + // generateSelfSignedCertificate(keyStore, new X500Principal(alias), + // 513, password); + // try (OutputStream out = new FileOutputStream(p12file)) { + // keyStore.store(out, password); + // } + // } + // try (InputStream in = new FileInputStream(p12file)) { + // keyStore.load(in, password); + // privateKey = (PrivateKey) keyStore.getKey(alias, password); + // publicKey = keyStore.getCertificateChain(alias)[0].getPublicKey(); + // } + // // KeyPair key; + // // final KeyPairGenerator keyGen = + // // KeyPairGenerator.getInstance(ALGORITHM); + // // keyGen.initialize(4096, new SecureRandom()); + // // long begin = System.currentTimeMillis(); + // // key = keyGen.generateKeyPair(); + // // System.out.println((System.currentTimeMillis() - begin) + " ms"); + // // keyStore.load(null); + // // keyStore.setKeyEntry("test", key.getPrivate(), password, null); + // // try(OutputStream out=new FileOutputStream(p12file)) { + // // keyStore.store(out, password); + // // } + // // privateKey = key.getPrivate(); + // // publicKey = key.getPublic(); + // + // Cipher encrypt = Cipher.getInstance(ALGORITHM); + // encrypt.init(Cipher.ENCRYPT_MODE, publicKey); + // byte[] encrypted = encrypt.doFinal(text.getBytes()); + // String encryptedBase64 = + // Base64.getEncoder().encodeToString(encrypted); + // System.out.println(encryptedBase64); + // byte[] encryptedFromBase64 = + // Base64.getDecoder().decode(encryptedBase64); + // + // Cipher decrypt = Cipher.getInstance(ALGORITHM); + // decrypt.init(Cipher.DECRYPT_MODE, privateKey); + // byte[] decrypted = decrypt.doFinal(encryptedFromBase64); + // System.out.println(new String(decrypted)); + // } catch (Exception e) { + // e.printStackTrace(); + // } + + } + + public static void createSelfSignedKeyStore(Path keyStorePath, char[] keyStorePassword, String keyStoreType) { + // for (Provider provider : Security.getProviders()) + // System.out.println(provider.getName()); + // File keyStoreFile = keyStorePath.toFile(); + char[] keyPwd = Arrays.copyOf(keyStorePassword, keyStorePassword.length); + if (!Files.exists(keyStorePath)) { + try { + Files.createDirectories(keyStorePath.getParent()); + KeyStore keyStore = getKeyStore(keyStorePath, keyStorePassword, keyStoreType); + generateSelfSignedCertificate(keyStore, + new X500Principal("CN=" + InetAddress.getLocalHost().getHostName() + ",OU=UNSECURE,O=UNSECURE"), + 1024, keyPwd); + saveKeyStore(keyStorePath, keyStorePassword, keyStore); + if (log.isDebugEnabled()) + log.debug("Created self-signed unsecure keystore " + keyStorePath); + } catch (Exception e) { + try { + if (Files.size(keyStorePath) == 0) + Files.delete(keyStorePath); + } catch (IOException e1) { + // silent + } + log.error("Cannot create keystore " + keyStorePath, e); + } + } else { + throw new IllegalStateException("Keystore " + keyStorePath + " already exists"); + } + } + +} diff --git a/org.argeo.cms/src/org/argeo/cms/security/AbstractKeyring.java b/org.argeo.cms/src/org/argeo/cms/security/AbstractKeyring.java index 08ac54936..10b583fdf 100644 --- a/org.argeo.cms/src/org/argeo/cms/security/AbstractKeyring.java +++ b/org.argeo.cms/src/org/argeo/cms/security/AbstractKeyring.java @@ -9,7 +9,6 @@ import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.Reader; import java.io.Writer; -import java.security.AccessController; import java.security.Provider; import java.security.Security; import java.util.Arrays; @@ -27,7 +26,7 @@ import javax.security.auth.login.LoginException; import org.apache.commons.io.IOUtils; import org.argeo.api.cms.CmsAuth; -import org.argeo.cms.CmsException; +import org.argeo.util.CurrentSubject; /** username / password based keyring. TODO internationalize */ public abstract class AbstractKeyring implements Keyring, CryptoKeyring { @@ -65,23 +64,24 @@ public abstract class AbstractKeyring implements Keyring, CryptoKeyring { /** Triggers lazy initialization */ protected SecretKey getSecretKey(char[] password) { - Subject subject = Subject.getSubject(AccessController.getContext()); + Subject subject = CurrentSubject.current(); + if (subject == null) + throw new IllegalStateException("Current subject cannot be null"); // we assume only one secrete key is available Iterator iterator = subject.getPrivateCredentials(SecretKey.class).iterator(); - if (!iterator.hasNext() || password!=null) {// not initialized + if (!iterator.hasNext() || password != null) {// not initialized CallbackHandler callbackHandler = password == null ? new KeyringCallbackHandler() : new PasswordProvidedCallBackHandler(password); ClassLoader currentContextClassLoader = Thread.currentThread().getContextClassLoader(); Thread.currentThread().setContextClassLoader(getClass().getClassLoader()); try { - LoginContext loginContext = new LoginContext(CmsAuth.LOGIN_CONTEXT_KEYRING, subject, - callbackHandler); + LoginContext loginContext = new LoginContext(CmsAuth.LOGIN_CONTEXT_KEYRING, subject, callbackHandler); loginContext.login(); // FIXME will login even if password is wrong iterator = subject.getPrivateCredentials(SecretKey.class).iterator(); return iterator.next(); } catch (LoginException e) { - throw new CmsException("Keyring login failed", e); + throw new IllegalStateException("Keyring login failed", e); } finally { Thread.currentThread().setContextClassLoader(currentContextClassLoader); } @@ -89,7 +89,7 @@ public abstract class AbstractKeyring implements Keyring, CryptoKeyring { } else { SecretKey secretKey = iterator.next(); if (iterator.hasNext()) - throw new CmsException("More than one secret key in private credentials"); + throw new IllegalStateException("More than one secret key in private credentials"); return secretKey; } } @@ -112,7 +112,7 @@ public abstract class AbstractKeyring implements Keyring, CryptoKeyring { IOUtils.copy(reader, writer); return writer.toCharArray(); } catch (IOException e) { - throw new CmsException("Cannot decrypt to char array", e); + throw new IllegalStateException("Cannot decrypt to char array", e); } finally { // IOUtils.closeQuietly(reader); // IOUtils.closeQuietly(in); @@ -134,7 +134,7 @@ public abstract class AbstractKeyring implements Keyring, CryptoKeyring { set(path, in); } } catch (IOException e) { - throw new CmsException("Cannot encrypt to char array", e); + throw new IllegalStateException("Cannot encrypt to char array", e); } finally { // IOUtils.closeQuietly(writer); // IOUtils.closeQuietly(out); @@ -147,7 +147,7 @@ public abstract class AbstractKeyring implements Keyring, CryptoKeyring { setup(password); SecretKey secretKey = getSecretKey(password); if (secretKey == null) - throw new CmsException("Could not unlock keyring"); + throw new IllegalStateException("Could not unlock keyring"); } protected Provider getSecurityProvider() { @@ -205,7 +205,7 @@ public abstract class AbstractKeyring implements Keyring, CryptoKeyring { char[] password = passwordCb.getPassword(); return password; } catch (Exception e) { - throw new CmsException("Cannot ask for a password", e); + throw new IllegalStateException("Cannot ask for a password", e); } } diff --git a/org.argeo.cms/src/org/argeo/cms/security/ChecksumFactory.java b/org.argeo.cms/src/org/argeo/cms/security/ChecksumFactory.java index 69e8a08fd..7344f01bc 100644 --- a/org.argeo.cms/src/org/argeo/cms/security/ChecksumFactory.java +++ b/org.argeo.cms/src/org/argeo/cms/security/ChecksumFactory.java @@ -11,11 +11,10 @@ import java.nio.file.Paths; import java.nio.file.SimpleFileVisitor; import java.nio.file.attribute.BasicFileAttributes; import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; import java.util.Base64; import java.util.zip.Checksum; -import org.argeo.cms.CmsException; - /** Allows to fine tune how files are read. */ public class ChecksumFactory { private int regionSize = 10 * 1024 * 1024; @@ -81,8 +80,8 @@ public class ChecksumFactory { return digest; } } - } catch (Exception e) { - throw new CmsException("Cannot digest " + path, e); + } catch (NoSuchAlgorithmException | IOException e) { + throw new IllegalStateException("Cannot digest " + path, e); } } @@ -113,8 +112,8 @@ public class ChecksumFactory { cursor = cursor + regionSize; } return crc.getValue(); - } catch (Exception e) { - throw new CmsException("Cannot checksum " + path, e); + } catch (IOException e) { + throw new IllegalStateException("Cannot checksum " + path, e); } finally { long duration = System.currentTimeMillis() - begin; System.out.println(duration / 1000 + "s"); diff --git a/org.argeo.cms/src/org/argeo/cms/security/PkiUtils.java b/org.argeo.cms/src/org/argeo/cms/security/PkiUtils.java deleted file mode 100644 index d6f90acfb..000000000 --- a/org.argeo.cms/src/org/argeo/cms/security/PkiUtils.java +++ /dev/null @@ -1,300 +0,0 @@ -package org.argeo.cms.security; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.Reader; -import java.math.BigInteger; -import java.net.InetAddress; -import java.nio.file.Files; -import java.nio.file.Path; -import java.security.GeneralSecurityException; -import java.security.KeyPair; -import java.security.KeyPairGenerator; -import java.security.KeyStore; -import java.security.KeyStoreException; -import java.security.PrivateKey; -import java.security.SecureRandom; -import java.security.Security; -import java.security.cert.Certificate; -import java.security.cert.CertificateException; -import java.security.cert.X509Certificate; -import java.util.Arrays; -import java.util.Date; - -import javax.security.auth.x500.X500Principal; - -import org.argeo.api.cms.CmsConstants; -import org.argeo.api.cms.CmsLog; -import org.argeo.cms.internal.runtime.KernelConstants; -import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; -import org.bouncycastle.cert.X509CertificateHolder; -import org.bouncycastle.cert.X509v3CertificateBuilder; -import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter; -import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder; -import org.bouncycastle.jce.provider.BouncyCastleProvider; -import org.bouncycastle.openssl.PEMParser; -import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter; -import org.bouncycastle.openssl.jcajce.JceOpenSSLPKCS8DecryptorProviderBuilder; -import org.bouncycastle.operator.ContentSigner; -import org.bouncycastle.operator.InputDecryptorProvider; -import org.bouncycastle.operator.OperatorCreationException; -import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder; -import org.bouncycastle.pkcs.PKCS8EncryptedPrivateKeyInfo; -import org.bouncycastle.pkcs.PKCSException; - -/** - * Utilities around private keys and certificate, mostly wrapping BouncyCastle - * implementations. - */ -public class PkiUtils { - private final static CmsLog log = CmsLog.getLog(PkiUtils.class); - - public final static String PKCS12 = "PKCS12"; - public static final String DEFAULT_KEYSTORE_PATH = KernelConstants.DIR_NODE + '/' + CmsConstants.NODE + ".p12"; - - public static final String DEFAULT_PEM_KEY_PATH = KernelConstants.DIR_NODE + '/' + CmsConstants.NODE + ".key"; - - public static final String DEFAULT_PEM_CERT_PATH = KernelConstants.DIR_NODE + '/' + CmsConstants.NODE + ".crt"; - - private final static String SECURITY_PROVIDER; - static { - Security.addProvider(new BouncyCastleProvider()); - SECURITY_PROVIDER = "BC"; - } - - public static X509Certificate generateSelfSignedCertificate(KeyStore keyStore, X500Principal x500Principal, - int keySize, char[] keyPassword) { - try { - KeyPairGenerator kpGen = KeyPairGenerator.getInstance("RSA", SECURITY_PROVIDER); - kpGen.initialize(keySize, new SecureRandom()); - KeyPair pair = kpGen.generateKeyPair(); - Date notBefore = new Date(System.currentTimeMillis() - 10000); - Date notAfter = new Date(System.currentTimeMillis() + 365 * 24L * 3600 * 1000); - BigInteger serial = BigInteger.valueOf(System.currentTimeMillis()); - X509v3CertificateBuilder certGen = new JcaX509v3CertificateBuilder(x500Principal, serial, notBefore, - notAfter, x500Principal, pair.getPublic()); - ContentSigner sigGen = new JcaContentSignerBuilder("SHA256WithRSAEncryption").setProvider(SECURITY_PROVIDER) - .build(pair.getPrivate()); - X509Certificate cert = new JcaX509CertificateConverter().setProvider(SECURITY_PROVIDER) - .getCertificate(certGen.build(sigGen)); - cert.checkValidity(new Date()); - cert.verify(cert.getPublicKey()); - - keyStore.setKeyEntry(x500Principal.getName(), pair.getPrivate(), keyPassword, new Certificate[] { cert }); - return cert; - } catch (GeneralSecurityException | OperatorCreationException e) { - throw new RuntimeException("Cannot generate self-signed certificate", e); - } - } - - public static KeyStore getKeyStore(Path keyStoreFile, char[] keyStorePassword, String keyStoreType) { - try { - KeyStore store = KeyStore.getInstance(keyStoreType, SECURITY_PROVIDER); - if (Files.exists(keyStoreFile)) { - try (InputStream fis = Files.newInputStream(keyStoreFile)) { - store.load(fis, keyStorePassword); - } - } else { - store.load(null); - } - return store; - } catch (GeneralSecurityException | IOException e) { - throw new RuntimeException("Cannot load keystore " + keyStoreFile, e); - } - } - - public static void saveKeyStore(Path keyStoreFile, char[] keyStorePassword, KeyStore keyStore) { - try { - try (OutputStream fis = Files.newOutputStream(keyStoreFile)) { - keyStore.store(fis, keyStorePassword); - } - } catch (GeneralSecurityException | IOException e) { - throw new RuntimeException("Cannot save keystore " + keyStoreFile, e); - } - } - -// public static byte[] pemToPKCS12(final String keyFile, final String cerFile, final String password) -// throws Exception { -// // Get the private key -// FileReader reader = new FileReader(keyFile); -// -// PEMReader pem = new PemReader(reader, new PasswordFinder() { -// @Override -// public char[] getPassword() { -// return password.toCharArray(); -// } -// }); -// -// PrivateKey key = ((KeyPair) pem.readObject()).getPrivate(); -// -// pem.close(); -// reader.close(); -// -// // Get the certificate -// reader = new FileReader(cerFile); -// pem = new PEMReader(reader); -// -// X509Certificate cert = (X509Certificate) pem.readObject(); -// -// pem.close(); -// reader.close(); -// -// // Put them into a PKCS12 keystore and write it to a byte[] -// ByteArrayOutputStream bos = new ByteArrayOutputStream(); -// KeyStore ks = KeyStore.getInstance("PKCS12"); -// ks.load(null); -// ks.setKeyEntry("alias", (Key) key, password.toCharArray(), new java.security.cert.Certificate[] { cert }); -// ks.store(bos, password.toCharArray()); -// bos.close(); -// return bos.toByteArray(); -// } - - public static void loadPem(KeyStore keyStore, Reader key, char[] keyPassword, Reader cert) { - PrivateKey privateKey = loadPemPrivateKey(key, keyPassword); - X509Certificate certificate = loadPemCertificate(cert); - try { - keyStore.setKeyEntry(certificate.getSubjectX500Principal().getName(), privateKey, keyPassword, - new java.security.cert.Certificate[] { certificate }); - } catch (KeyStoreException e) { - throw new RuntimeException("Cannot store PEM certificate", e); - } - } - - public static PrivateKey loadPemPrivateKey(Reader reader, char[] keyPassword) { - try (PEMParser pemParser = new PEMParser(reader)) { - JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider("BC"); - Object object = pemParser.readObject(); - PrivateKeyInfo privateKeyInfo; - if (object instanceof PKCS8EncryptedPrivateKeyInfo) { - if (keyPassword == null) - throw new IllegalArgumentException("A key password is required"); - InputDecryptorProvider decProv = new JceOpenSSLPKCS8DecryptorProviderBuilder().build(keyPassword); - privateKeyInfo = ((PKCS8EncryptedPrivateKeyInfo) object).decryptPrivateKeyInfo(decProv); - } else if (object instanceof PrivateKeyInfo) { - privateKeyInfo = (PrivateKeyInfo) object; - } else { - throw new IllegalArgumentException("Unsupported format for private key"); - } - return converter.getPrivateKey(privateKeyInfo); - } catch (IOException | OperatorCreationException | PKCSException e) { - throw new RuntimeException("Cannot read private key", e); - } - } - - public static X509Certificate loadPemCertificate(Reader reader) { - try (PEMParser pemParser = new PEMParser(reader)) { - X509CertificateHolder certHolder = (X509CertificateHolder) pemParser.readObject(); - X509Certificate cert = new JcaX509CertificateConverter().setProvider(SECURITY_PROVIDER) - .getCertificate(certHolder); - return cert; - } catch (IOException | CertificateException e) { - throw new RuntimeException("Cannot read private key", e); - } - } - - public static void main(String[] args) throws Exception { - final String ALGORITHM = "RSA"; - final String provider = "BC"; - SecureRandom secureRandom = new SecureRandom(); - long begin = System.currentTimeMillis(); - for (int i = 512; i < 1024; i = i + 2) { - try { - KeyPairGenerator keyGen = KeyPairGenerator.getInstance(ALGORITHM, provider); - keyGen.initialize(i, secureRandom); - keyGen.generateKeyPair(); - } catch (Exception e) { - System.err.println(i + " : " + e.getMessage()); - } - } - System.out.println((System.currentTimeMillis() - begin) + " ms"); - - // // String text = "a"; - // String text = - // "testtesttesttesttesttesttesttesttesttesttesttesttesttesttest"; - // try { - // System.out.println(text); - // PrivateKey privateKey; - // PublicKey publicKey; - // char[] password = "changeit".toCharArray(); - // String alias = "CN=test"; - // KeyStore keyStore = KeyStore.getInstance("pkcs12"); - // File p12file = new File("test.p12"); - // p12file.delete(); - // if (!p12file.exists()) { - // keyStore.load(null); - // generateSelfSignedCertificate(keyStore, new X500Principal(alias), - // 513, password); - // try (OutputStream out = new FileOutputStream(p12file)) { - // keyStore.store(out, password); - // } - // } - // try (InputStream in = new FileInputStream(p12file)) { - // keyStore.load(in, password); - // privateKey = (PrivateKey) keyStore.getKey(alias, password); - // publicKey = keyStore.getCertificateChain(alias)[0].getPublicKey(); - // } - // // KeyPair key; - // // final KeyPairGenerator keyGen = - // // KeyPairGenerator.getInstance(ALGORITHM); - // // keyGen.initialize(4096, new SecureRandom()); - // // long begin = System.currentTimeMillis(); - // // key = keyGen.generateKeyPair(); - // // System.out.println((System.currentTimeMillis() - begin) + " ms"); - // // keyStore.load(null); - // // keyStore.setKeyEntry("test", key.getPrivate(), password, null); - // // try(OutputStream out=new FileOutputStream(p12file)) { - // // keyStore.store(out, password); - // // } - // // privateKey = key.getPrivate(); - // // publicKey = key.getPublic(); - // - // Cipher encrypt = Cipher.getInstance(ALGORITHM); - // encrypt.init(Cipher.ENCRYPT_MODE, publicKey); - // byte[] encrypted = encrypt.doFinal(text.getBytes()); - // String encryptedBase64 = - // Base64.getEncoder().encodeToString(encrypted); - // System.out.println(encryptedBase64); - // byte[] encryptedFromBase64 = - // Base64.getDecoder().decode(encryptedBase64); - // - // Cipher decrypt = Cipher.getInstance(ALGORITHM); - // decrypt.init(Cipher.DECRYPT_MODE, privateKey); - // byte[] decrypted = decrypt.doFinal(encryptedFromBase64); - // System.out.println(new String(decrypted)); - // } catch (Exception e) { - // e.printStackTrace(); - // } - - } - - public static void createSelfSignedKeyStore(Path keyStorePath, char[] keyStorePassword, String keyStoreType) { - // for (Provider provider : Security.getProviders()) - // System.out.println(provider.getName()); - // File keyStoreFile = keyStorePath.toFile(); - char[] keyPwd = Arrays.copyOf(keyStorePassword, keyStorePassword.length); - if (!Files.exists(keyStorePath)) { - try { - Files.createDirectories(keyStorePath.getParent()); - KeyStore keyStore = getKeyStore(keyStorePath, keyStorePassword, keyStoreType); - generateSelfSignedCertificate(keyStore, - new X500Principal("CN=" + InetAddress.getLocalHost().getHostName() + ",OU=UNSECURE,O=UNSECURE"), - 1024, keyPwd); - saveKeyStore(keyStorePath, keyStorePassword, keyStore); - if (log.isDebugEnabled()) - log.debug("Created self-signed unsecure keystore " + keyStorePath); - } catch (Exception e) { - try { - if (Files.size(keyStorePath) == 0) - Files.delete(keyStorePath); - } catch (IOException e1) { - // silent - } - log.error("Cannot create keystore " + keyStorePath, e); - } - } else { - throw new IllegalStateException("Keystore " + keyStorePath + " already exists"); - } - } - -} diff --git a/org.argeo.util/src/org/argeo/osgi/metatype/EnumAD.java b/org.argeo.util/src/org/argeo/osgi/metatype/EnumAD.java deleted file mode 100644 index 0fc4f32aa..000000000 --- a/org.argeo.util/src/org/argeo/osgi/metatype/EnumAD.java +++ /dev/null @@ -1,60 +0,0 @@ -package org.argeo.osgi.metatype; - -import org.argeo.util.naming.SpecifiedName; -import org.osgi.service.metatype.AttributeDefinition; - -public interface EnumAD extends SpecifiedName, AttributeDefinition { - String name(); - - default Object getDefault() { - return null; - } - - @Override - default String getName() { - return name(); - } - - @Override - default String getID() { - return getClass().getName() + "." + name(); - } - - @Override - default String getDescription() { - return null; - } - - @Override - default int getCardinality() { - return 0; - } - - @Override - default int getType() { - return STRING; - } - - @Override - default String[] getOptionValues() { - return null; - } - - @Override - default String[] getOptionLabels() { - return null; - } - - @Override - default String validate(String value) { - return null; - } - - @Override - default String[] getDefaultValue() { - Object value = getDefault(); - if (value == null) - return null; - return new String[] { value.toString() }; - } -} diff --git a/org.argeo.util/src/org/argeo/osgi/metatype/EnumOCD.java b/org.argeo.util/src/org/argeo/osgi/metatype/EnumOCD.java deleted file mode 100644 index 97c7d56e1..000000000 --- a/org.argeo.util/src/org/argeo/osgi/metatype/EnumOCD.java +++ /dev/null @@ -1,54 +0,0 @@ -package org.argeo.osgi.metatype; - -import java.io.IOException; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.EnumSet; -import java.util.List; - -import org.osgi.service.metatype.AttributeDefinition; -import org.osgi.service.metatype.ObjectClassDefinition; - -public class EnumOCD> implements ObjectClassDefinition { - private final Class enumClass; - private String locale; - - public EnumOCD(Class clazz, String locale) { - this.enumClass = clazz; - this.locale = locale; - } - - @Override - public String getName() { - return null; - } - - public String getLocale() { - return locale; - } - - @Override - public String getID() { - return enumClass.getName(); - } - - @Override - public String getDescription() { - return null; - } - - @Override - public AttributeDefinition[] getAttributeDefinitions(int filter) { - EnumSet set = EnumSet.allOf(enumClass); - List attrs = new ArrayList<>(); - for (T key : set) - attrs.add((AttributeDefinition) key); - return attrs.toArray(new AttributeDefinition[attrs.size()]); - } - - @Override - public InputStream getIcon(int size) throws IOException { - return null; - } - -} diff --git a/org.argeo.util/src/org/argeo/osgi/metatype/package-info.java b/org.argeo.util/src/org/argeo/osgi/metatype/package-info.java deleted file mode 100644 index bca5d1fda..000000000 --- a/org.argeo.util/src/org/argeo/osgi/metatype/package-info.java +++ /dev/null @@ -1,2 +0,0 @@ -/** OSGi metatype support. */ -package org.argeo.osgi.metatype; \ No newline at end of file diff --git a/rap/org.argeo.cms.ui.rap/src/org/argeo/cms/ui/script/CmsScriptApp.java b/rap/org.argeo.cms.ui.rap/src/org/argeo/cms/ui/script/CmsScriptApp.java index a2b944064..6b3a670d7 100644 --- a/rap/org.argeo.cms.ui.rap/src/org/argeo/cms/ui/script/CmsScriptApp.java +++ b/rap/org.argeo.cms.ui.rap/src/org/argeo/cms/ui/script/CmsScriptApp.java @@ -22,7 +22,7 @@ import javax.servlet.http.HttpServletResponse; import org.argeo.api.cms.CmsLog; import org.argeo.api.cms.ux.CmsTheme; -import org.argeo.cms.CmsException; +import org.argeo.cms.swt.CmsException; import org.argeo.cms.ui.CmsUiConstants; import org.argeo.cms.ui.CmsUiProvider; import org.argeo.cms.ui.util.CmsUiUtils; diff --git a/rap/org.argeo.cms.ui.rap/src/org/argeo/cms/ui/script/CmsScriptRwtApplication.java b/rap/org.argeo.cms.ui.rap/src/org/argeo/cms/ui/script/CmsScriptRwtApplication.java index 499840a73..9879fb019 100644 --- a/rap/org.argeo.cms.ui.rap/src/org/argeo/cms/ui/script/CmsScriptRwtApplication.java +++ b/rap/org.argeo.cms.ui.rap/src/org/argeo/cms/ui/script/CmsScriptRwtApplication.java @@ -11,7 +11,7 @@ import javax.script.ScriptEngineManager; import javax.script.ScriptException; import org.argeo.api.cms.CmsLog; -import org.argeo.cms.CmsException; +import org.argeo.cms.swt.CmsException; import org.eclipse.rap.rwt.application.Application; import org.eclipse.rap.rwt.application.ApplicationConfiguration; import org.osgi.framework.BundleContext; diff --git a/rap/org.argeo.cms.ui.rap/src/org/argeo/cms/web/AbstractCmsEntryPoint.java b/rap/org.argeo.cms.ui.rap/src/org/argeo/cms/web/AbstractCmsEntryPoint.java index a909dbdd7..f3269f2c4 100644 --- a/rap/org.argeo.cms.ui.rap/src/org/argeo/cms/web/AbstractCmsEntryPoint.java +++ b/rap/org.argeo.cms.ui.rap/src/org/argeo/cms/web/AbstractCmsEntryPoint.java @@ -24,12 +24,12 @@ import javax.servlet.http.HttpServletRequest; import org.argeo.api.cms.CmsLog; import org.argeo.api.cms.ux.CmsView; import org.argeo.api.cms.CmsAuth; -import org.argeo.cms.CmsException; import org.argeo.cms.auth.CurrentUser; import org.argeo.cms.auth.RemoteAuthCallback; import org.argeo.cms.auth.RemoteAuthCallbackHandler; import org.argeo.cms.servlet.ServletHttpRequest; import org.argeo.cms.servlet.ServletHttpResponse; +import org.argeo.cms.swt.CmsException; import org.argeo.cms.swt.CmsStyles; import org.argeo.cms.swt.CmsSwtUtils; import org.argeo.eclipse.ui.specific.UiContext; diff --git a/rap/org.argeo.cms.ui.rap/src/org/argeo/cms/web/SimpleApp.java b/rap/org.argeo.cms.ui.rap/src/org/argeo/cms/web/SimpleApp.java index f063117ae..38a9b4449 100644 --- a/rap/org.argeo.cms.ui.rap/src/org/argeo/cms/web/SimpleApp.java +++ b/rap/org.argeo.cms.ui.rap/src/org/argeo/cms/web/SimpleApp.java @@ -22,8 +22,8 @@ import javax.jcr.version.VersionManager; import org.argeo.api.cms.CmsConstants; import org.argeo.api.cms.CmsLog; -import org.argeo.cms.CmsException; import org.argeo.cms.jcr.CmsJcrUtils; +import org.argeo.cms.swt.CmsException; import org.argeo.cms.ui.CmsUiConstants; import org.argeo.cms.ui.CmsUiProvider; import org.argeo.cms.ui.LifeCycleUiProvider; diff --git a/rap/org.argeo.cms.ui.rap/src/org/argeo/cms/web/SimpleErgonomics.java b/rap/org.argeo.cms.ui.rap/src/org/argeo/cms/web/SimpleErgonomics.java index 1b50c19b7..783f6eb73 100644 --- a/rap/org.argeo.cms.ui.rap/src/org/argeo/cms/web/SimpleErgonomics.java +++ b/rap/org.argeo.cms.ui.rap/src/org/argeo/cms/web/SimpleErgonomics.java @@ -10,7 +10,7 @@ import javax.jcr.RepositoryException; import org.argeo.api.cms.CmsLog; import org.argeo.api.cms.ux.CmsImageManager; import org.argeo.api.cms.ux.UxContext; -import org.argeo.cms.CmsException; +import org.argeo.cms.swt.CmsException; import org.argeo.cms.swt.CmsStyles; import org.argeo.cms.swt.CmsSwtUtils; import org.argeo.cms.swt.SimpleSwtUxContext; diff --git a/rcp/org.argeo.cms.e4.rcp/src/org/argeo/cms/e4/rcp/CmsE4Application.java b/rcp/org.argeo.cms.e4.rcp/src/org/argeo/cms/e4/rcp/CmsE4Application.java index a13c0170f..b37a76587 100644 --- a/rcp/org.argeo.cms.e4.rcp/src/org/argeo/cms/e4/rcp/CmsE4Application.java +++ b/rcp/org.argeo.cms.e4.rcp/src/org/argeo/cms/e4/rcp/CmsE4Application.java @@ -11,8 +11,8 @@ import org.argeo.api.cms.CmsAuth; import org.argeo.api.cms.ux.CmsImageManager; import org.argeo.api.cms.ux.CmsView; import org.argeo.api.cms.ux.UxContext; -import org.argeo.cms.CmsException; import org.argeo.cms.auth.CurrentUser; +import org.argeo.cms.swt.CmsException; import org.argeo.cms.swt.CmsSwtUtils; import org.argeo.cms.swt.SimpleSwtUxContext; import org.argeo.cms.swt.auth.CmsLoginShell; @@ -55,7 +55,7 @@ public class CmsE4Application implements IApplication, CmsView { } } if (CurrentUser.getUsername(getSubject()) == null) - throw new CmsException("Cannot log in"); + throw new IllegalStateException("Cannot log in"); // try { // CallbackHandler callbackHandler = new DefaultLoginDialog(