X-Git-Url: https://git.argeo.org/?a=blobdiff_plain;f=org.argeo.cms%2Fsrc%2Forg%2Fargeo%2Fcms%2Finternal%2Fosgi%2FDeployConfig.java;h=e45b9508d19026133631e6af48d6a299118af7f2;hb=eb4324be6ac9cdff15828a21ee7d3f6ca2f19fb9;hp=c31f50ded9c8ad8f98a0b40f45d5e0a3758760fa;hpb=f4da6777015da3fc392138f0c01cea2f2add9ed3;p=lgpl%2Fargeo-commons.git 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 c31f50ded..e45b9508d 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 @@ -6,8 +6,11 @@ import java.io.Writer; import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; +import java.util.Arrays; import java.util.Dictionary; +import java.util.HashSet; import java.util.List; +import java.util.Set; import java.util.SortedMap; import java.util.TreeMap; @@ -27,16 +30,14 @@ import org.argeo.osgi.useradmin.UserAdminConf; import org.argeo.util.naming.AttributesDictionary; import org.argeo.util.naming.LdifParser; import org.argeo.util.naming.LdifWriter; -import org.eclipse.equinox.http.jetty.JettyConfigurator; -import org.osgi.framework.FrameworkUtil; import org.osgi.framework.InvalidSyntaxException; import org.osgi.service.cm.Configuration; import org.osgi.service.cm.ConfigurationAdmin; import org.osgi.service.cm.ConfigurationEvent; -import org.osgi.service.cm.ConfigurationListener; /** Manages the LDIF-based deployment configuration. */ -public class DeployConfig implements ConfigurationListener { +public class DeployConfig { + private final CmsLog log = CmsLog.getLog(getClass()); // private final BundleContext bc = FrameworkUtil.getBundle(getClass()).getBundleContext(); @@ -50,24 +51,6 @@ public class DeployConfig implements ConfigurationListener { private ConfigurationAdmin configurationAdmin; - public DeployConfig() { -// this.dataModels = dataModels; - // ConfigurationAdmin configurationAdmin = -// // bc.getService(bc.getServiceReference(ConfigurationAdmin.class)); -// try { -// if (!isInitialized()) { // first init -// isFirstInit = true; -// firstInit(); -// } -// this.configurationAdmin = configurationAdmin; -//// init(configurationAdmin, isClean, isFirstInit); -// } catch (IOException e) { -// throw new RuntimeException("Could not init deploy configs", e); -// } - // FIXME check race conditions during initialization - // bc.registerService(ConfigurationListener.class, this, null); - } - private void firstInit() throws IOException { log.info("## FIRST INIT ##"); Files.createDirectories(deployConfigPath.getParent()); @@ -120,93 +103,82 @@ public class DeployConfig implements ConfigurationListener { } // http server -// Dictionary webServerConfig = InitUtils -// .getHttpServerConfig(getProps(KernelConstants.JETTY_FACTORY_PID, NodeConstants.DEFAULT)); -// if (!webServerConfig.isEmpty()) { -// // TODO check for other customizers + Dictionary webServerConfig = InitUtils + .getHttpServerConfig(getProps(KernelConstants.JETTY_FACTORY_PID, CmsConstants.DEFAULT)); + if (!webServerConfig.isEmpty()) { + // TODO check for other customizers // webServerConfig.put("customizer.class", "org.argeo.equinox.jetty.CmsJettyCustomizer"); -// putFactoryDeployConfig(KernelConstants.JETTY_FACTORY_PID, webServerConfig); -// } - LdapName defaultHttpServiceDn = serviceDn(KernelConstants.JETTY_FACTORY_PID, CmsConstants.DEFAULT); - if (deployConfigs.containsKey(defaultHttpServiceDn)) { - // remove old default configs since we have now to start Jetty servlet bridge - // indirectly - deployConfigs.remove(defaultHttpServiceDn); + putFactoryDeployConfig(KernelConstants.JETTY_FACTORY_PID, webServerConfig); } +// LdapName defaultHttpServiceDn = serviceDn(KernelConstants.JETTY_FACTORY_PID, CmsConstants.DEFAULT); +// if (deployConfigs.containsKey(defaultHttpServiceDn)) { +// // remove old default configs since we have now to start Jetty servlet bridge +// // indirectly +// deployConfigs.remove(defaultHttpServiceDn); +// } // SAVE save(); // - // Explicitly configures Jetty so that the default server is not started by the - // activator of the Equinox Jetty bundle. - Dictionary webServerConfig = InitUtils - .getHttpServerConfig(getProps(KernelConstants.JETTY_FACTORY_PID, CmsConstants.DEFAULT)); -// if (!webServerConfig.isEmpty()) { -// webServerConfig.put("customizer.class", KernelConstants.CMS_JETTY_CUSTOMIZER_CLASS); -// -// // TODO centralise with Jetty extender -// Object webSocketEnabled = webServerConfig.get(InternalHttpConstants.WEBSOCKET_ENABLED); -// if (webSocketEnabled != null && webSocketEnabled.toString().equals("true")) { -// bc.registerService(ServerEndpointConfig.Configurator.class, new CmsWebSocketConfigurator(), null); -// webServerConfig.put(InternalHttpConstants.WEBSOCKET_ENABLED, "true"); -// } -// } +// Dictionary webServerConfig = InitUtils +// .getHttpServerConfig(getProps(KernelConstants.JETTY_FACTORY_PID, CmsConstants.DEFAULT)); + } - int tryCount = 60; + public void start() { try { - tryGettyJetty: while (tryCount > 0) { + if (!isInitialized()) { // first init + isFirstInit = true; + firstInit(); + } + + boolean isClean = true; + if (configurationAdmin != null) try { - JettyConfigurator.startServer(KernelConstants.DEFAULT_JETTY_SERVER, webServerConfig); - // Explicitly starts Jetty OSGi HTTP bundle, so that it gets triggered if OSGi - // configuration is not cleaned - FrameworkUtil.getBundle(JettyConfigurator.class).start(); - break tryGettyJetty; - } catch (IllegalStateException e) { - // Jetty may not be ready - try { - Thread.sleep(1000); - } catch (Exception e1) { - // silent - } - tryCount--; + Configuration[] confs = configurationAdmin + .listConfigurations("(service.factoryPid=" + CmsConstants.NODE_USER_ADMIN_PID + ")"); + isClean = confs == null || confs.length == 0; + } catch (Exception e) { + throw new IllegalStateException("Cannot analyse clean state", e); } + + try (InputStream in = Files.newInputStream(deployConfigPath)) { + deployConfigs = new LdifParser().read(in); } - } catch (Exception e) { - log.error("Cannot start default Jetty server with config " + webServerConfig, e); + if (isClean) { + if (log.isDebugEnabled()) + log.debug("Clean state, loading from framework properties..."); + setFromFrameworkProperties(isFirstInit); + if (configurationAdmin != null) + loadConfigs(); + } + // TODO check consistency if not clean + } catch (IOException e) { + throw new RuntimeException("Cannot load deploy configuration", e); } - } - public void init() throws IOException { - if (!isInitialized()) { // first init - isFirstInit = true; - firstInit(); - } + public void stop() { - boolean isClean; - try { - Configuration[] confs = configurationAdmin - .listConfigurations("(service.factoryPid=" + CmsConstants.NODE_USER_ADMIN_PID + ")"); - isClean = confs == null || confs.length == 0; - } catch (Exception e) { - throw new IllegalStateException("Cannot analyse clean state", e); - } - - try (InputStream in = Files.newInputStream(deployConfigPath)) { - deployConfigs = new LdifParser().read(in); - } - if (isClean) { - if (log.isDebugEnabled()) - log.debug("Clean state, loading from framework properties..."); - setFromFrameworkProperties(isFirstInit); - loadConfigs(); - } - // TODO check consistency if not clean } - public void destroy() { - + protected void logAllConfigurations() { + if (!log.isDebugEnabled()) + return; + try { + Configuration[] configurations = configurationAdmin.listConfigurations(null); + if (configurations == null) { + log.debug("No configuration available"); + return; + } + Arrays.sort(configurations, (o1, o2) -> o1.getPid().compareTo(o2.getPid())); + for (Configuration configuration : configurations) { + log.debug(configuration.getFactoryPid() + " - " + configuration.getPid() + " - " + + configuration.getProperties()); + } + } catch (IOException | InvalidSyntaxException e) { + throw new IllegalStateException("Cannot log configurations", e); + } } public void loadConfigs() throws IOException { @@ -220,6 +192,7 @@ public class DeployConfig implements ConfigurationListener { throw new IllegalArgumentException(e); } deployConfigs: for (LdapName dn : deployConfigs.keySet()) { + Attributes deployConfig = deployConfigs.get(dn); Rdn lastRdn = dn.getRdn(dn.size() - 1); LdapName prefix = (LdapName) dn.getPrefix(dn.size() - 1); if (prefix.toString().equals(CmsConstants.DEPLOY_BASEDN)) { @@ -227,26 +200,53 @@ public class DeployConfig implements ConfigurationListener { // service String pid = lastRdn.getValue().toString(); Configuration conf = configurationAdmin.getConfiguration(pid); - AttributesDictionary dico = new AttributesDictionary(deployConfigs.get(dn)); + AttributesDictionary dico = new AttributesDictionary(deployConfig); conf.update(dico); } else { // service factory definition } } else { - Attributes config = deployConfigs.get(dn); - Attribute disabled = config.get(UserAdminConf.disabled.name()); + Attribute disabled = deployConfig.get(UserAdminConf.disabled.name()); if (disabled != null) continue deployConfigs; // service factory service + if (!lastRdn.getType().equals(CmsConstants.CN)) + throw new IllegalStateException("Only " + CmsConstants.CN + "= is supported: " + dn); Rdn beforeLastRdn = dn.getRdn(dn.size() - 2); assert beforeLastRdn.getType().equals(CmsConstants.OU); String factoryPid = beforeLastRdn.getValue().toString(); - Configuration conf = configurationAdmin.createFactoryConfiguration(factoryPid.toString(), null); - if (systemRolesDn.equals(dn)) { - systemRolesConf = configurationAdmin.createFactoryConfiguration(factoryPid.toString(), null); + + String cn = lastRdn.getValue().toString(); + Configuration conf = getSingleServiceConfiguration(factoryPid, cn); + if (conf != null) { + if (systemRolesDn.equals(dn)) + systemRolesConf = conf; + // TODO deal with modifications +// boolean modified = false; +// Dictionary currentProperties = conf.getProperties(); +// +// attrs: for (NamingEnumeration it = deployConfig.getAll(); it +// .hasMoreElements();) { +// Attribute attr = (Attribute) it.next(); +// String key = attr.getID(); +// Object currentValue = currentProperties.get(key); +// if (currentValue == null) { +// modified = true; +// break attrs; +// } +// } + +// AttributesDictionary dico = new AttributesDictionary(deployConfig); +// conf.update(dico); } else { - AttributesDictionary dico = new AttributesDictionary(config); - conf.update(dico); + + conf = configurationAdmin.createFactoryConfiguration(factoryPid.toString(), null); + if (systemRolesDn.equals(dn)) { + systemRolesConf = configurationAdmin.createFactoryConfiguration(factoryPid.toString(), null); + } else { + AttributesDictionary dico = new AttributesDictionary(deployConfig); + conf.update(dico); + } } } } @@ -256,9 +256,29 @@ public class DeployConfig implements ConfigurationListener { throw new IllegalStateException("System roles are not configured."); systemRolesConf.update(new AttributesDictionary(deployConfigs.get(systemRolesDn))); +// logAllConfigurations(); + } + + public Set> getUserDirectoryConfigs() { + // not static because class is not supported by Android + final LdapName USER_ADMIN_BASE_DN; + try { + USER_ADMIN_BASE_DN = new LdapName( + CmsConstants.OU + "=" + CmsConstants.NODE_USER_ADMIN_PID + "," + CmsConstants.DEPLOY_BASEDN); + } catch (InvalidNameException e) { + throw new IllegalArgumentException(e); + } + Set> res = new HashSet<>(); + for (LdapName dn : deployConfigs.keySet()) { + if (dn.endsWith(USER_ADMIN_BASE_DN)) { + Attributes attributes = deployConfigs.get(dn); + res.add(new AttributesDictionary(attributes)); + } + } + return res; } - @Override +// @Override public void configurationEvent(ConfigurationEvent event) { try { if (ConfigurationEvent.CM_UPDATED == event.getType()) { @@ -350,13 +370,11 @@ public class DeployConfig implements ConfigurationListener { } public boolean hasDomain() { - Configuration[] configs; - try { - configs = configurationAdmin - .listConfigurations("(service.factoryPid=" + CmsConstants.NODE_USER_ADMIN_PID + ")"); - } catch (IOException | InvalidSyntaxException e) { - throw new IllegalStateException("Cannot list user directories", e); - } + // FIXME lookup deploy configs directly + if (configurationAdmin == null) + return false; + + Configuration[] configs = listConfigurationsByFactory(CmsConstants.NODE_USER_ADMIN_PID); boolean hasDomain = false; for (Configuration config : configs) { @@ -369,6 +387,34 @@ public class DeployConfig implements ConfigurationListener { return hasDomain; } + private Configuration[] listConfigurationsByFactory(String factoryPid) { + try { + Configuration[] configs = configurationAdmin.listConfigurations("(service.factoryPid=" + factoryPid + ")"); + if (configs == null) + configs = new Configuration[0]; + return configs; + } catch (IOException | InvalidSyntaxException e) { + throw new IllegalStateException("Cannot list configurations with factoryPid " + factoryPid, e); + } + + } + + private Configuration getSingleServiceConfiguration(String factoryPid, String cn) { + Configuration[] configs = listConfigurationsByFactory(factoryPid); + List res = new ArrayList<>(); + for (Configuration config : configs) { + Object currentCn = config.getProperties().get(CmsConstants.CN); + if (currentCn != null && cn.equals(currentCn.toString())) + res.add(config); + } + if (res.size() == 0) + return null; + if (res.size() > 1) + throw new IllegalStateException( + "More than one " + factoryPid + " configuration returned for " + CmsConstants.CN + "=" + cn); + return res.get(0); + } + /* * UTILITIES */