+ private Long availableSince;
+
+ private final boolean cleanState;
+
+ private NodeHttp nodeHttp;
+
+ // Readiness
+ private boolean nodeAvailable = false;
+ private boolean userAdminAvailable = false;
+ private boolean httpExpected = false;
+ private boolean httpAvailable = false;
+
+ public CmsDeployment() {
+ ServiceReference<NodeState> nodeStateSr = bc.getServiceReference(NodeState.class);
+ if (nodeStateSr == null)
+ throw new CmsException("No node state available");
+
+ NodeState nodeState = bc.getService(nodeStateSr);
+ cleanState = nodeState.isClean();
+
+ nodeHttp = new NodeHttp(cleanState);
+ dataModels = new DataModels(bc);
+ initTrackers();
+ }
+
+ private void initTrackers() {
+ ServiceTracker<?, ?> httpSt = new ServiceTracker<NodeHttp, NodeHttp>(bc, NodeHttp.class, null) {
+
+ @Override
+ public NodeHttp addingService(ServiceReference<NodeHttp> reference) {
+ httpAvailable = true;
+ checkReadiness();
+ return super.addingService(reference);
+ }
+ };
+ // httpSt.open();
+ KernelUtils.asyncOpen(httpSt);
+
+ ServiceTracker<?, ?> repoContextSt = new RepositoryContextStc();
+ // repoContextSt.open();
+ KernelUtils.asyncOpen(repoContextSt);
+
+ ServiceTracker<?, ?> userAdminSt = new ServiceTracker<UserAdmin, UserAdmin>(bc, UserAdmin.class, null) {
+ @Override
+ public UserAdmin addingService(ServiceReference<UserAdmin> reference) {
+ UserAdmin userAdmin = super.addingService(reference);
+ addStandardSystemRoles(userAdmin);
+ userAdminAvailable = true;
+ checkReadiness();
+ return userAdmin;
+ }
+ };
+ // userAdminSt.open();
+ KernelUtils.asyncOpen(userAdminSt);
+
+ ServiceTracker<?, ?> confAdminSt = new ServiceTracker<ConfigurationAdmin, ConfigurationAdmin>(bc,
+ ConfigurationAdmin.class, null) {
+ @Override
+ public ConfigurationAdmin addingService(ServiceReference<ConfigurationAdmin> reference) {
+ ConfigurationAdmin configurationAdmin = bc.getService(reference);
+ deployConfig = new DeployConfig(configurationAdmin, dataModels, cleanState);
+ httpExpected = deployConfig.getProps(KernelConstants.JETTY_FACTORY_PID, "default") != null;
+ try {
+ // Configuration[] configs = configurationAdmin
+ // .listConfigurations("(service.factoryPid=" +
+ // NodeConstants.NODE_REPOS_FACTORY_PID + ")");
+ // for (Configuration config : configs) {
+ // Object cn = config.getProperties().get(NodeConstants.CN);
+ // if (log.isDebugEnabled())
+ // log.debug("Standalone repo cn: " + cn);
+ // }
+ Configuration[] configs = configurationAdmin
+ .listConfigurations("(service.factoryPid=" + NodeConstants.NODE_USER_ADMIN_PID + ")");
+
+ boolean hasDomain = false;
+ for (Configuration config : configs) {
+ Object realm = config.getProperties().get(UserAdminConf.realm.name());
+ if (realm != null) {
+ log.debug("Found realm: " + realm);
+ hasDomain = true;
+ }
+ }
+ if (hasDomain) {
+ loadIpaJaasConfiguration();
+ }
+ } catch (Exception e) {
+ throw new CmsException("Cannot initialize config", e);
+ }
+ return super.addingService(reference);
+ }
+ };
+ // confAdminSt.open();
+ KernelUtils.asyncOpen(confAdminSt);
+ }
+
+ private void addStandardSystemRoles(UserAdmin userAdmin) {
+ // we assume UserTransaction is already available (TODO make it more robust)
+ UserTransaction userTransaction = bc.getService(bc.getServiceReference(UserTransaction.class));
+ try {
+ userTransaction.begin();
+ Role adminRole = userAdmin.getRole(NodeConstants.ROLE_ADMIN);
+ if (adminRole == null) {
+ adminRole = userAdmin.createRole(NodeConstants.ROLE_ADMIN, Role.GROUP);
+ }
+ if (userAdmin.getRole(NodeConstants.ROLE_USER_ADMIN) == null) {
+ Group userAdminRole = (Group) userAdmin.createRole(NodeConstants.ROLE_USER_ADMIN, Role.GROUP);
+ userAdminRole.addMember(adminRole);
+ }
+ userTransaction.commit();
+ } catch (Exception e) {
+ try {
+ userTransaction.rollback();
+ } catch (Exception e1) {
+ // silent
+ }
+ throw new CmsException("Cannot add standard system roles", e);
+ }
+ }
+
+ private void loadIpaJaasConfiguration() {
+ if (System.getProperty(KernelConstants.JAAS_CONFIG_PROP) == null) {
+ String jaasConfig = KernelConstants.JAAS_CONFIG_IPA;
+ URL url = getClass().getClassLoader().getResource(jaasConfig);
+ KernelUtils.setJaasConfiguration(url);
+ log.debug("Set IPA JAAS configuration.");
+ }
+ }
+
+ public void shutdown() {
+ if (nodeHttp != null)
+ nodeHttp.destroy();
+ if (deployConfig != null) {
+ new Thread(() -> deployConfig.save(), "Save Argeo Deploy Config").start();
+ }
+ }
+
+ private void checkReadiness() {
+ if (nodeAvailable && userAdminAvailable && (httpExpected ? httpAvailable : true)) {
+ String data = KernelUtils.getFrameworkProp(KernelUtils.OSGI_INSTANCE_AREA);
+ String state = KernelUtils.getFrameworkProp(KernelUtils.OSGI_CONFIGURATION_AREA);
+ availableSince = System.currentTimeMillis();
+ long jvmUptime = ManagementFactory.getRuntimeMXBean().getUptime();
+ String jvmUptimeStr = " in " + (jvmUptime / 1000) + "." + (jvmUptime % 1000) + "s";
+ log.info("## ARGEO NODE AVAILABLE" + (log.isDebugEnabled() ? jvmUptimeStr : "") + " ##");
+ if (log.isDebugEnabled()) {
+ log.debug("## state: " + state);
+ if (data != null)
+ log.debug("## data: " + data);
+ }
+ long begin = bc.getService(bc.getServiceReference(NodeState.class)).getAvailableSince();
+ long initDuration = System.currentTimeMillis() - begin;
+ if (log.isTraceEnabled())
+ log.trace("Kernel initialization took " + initDuration + "ms");
+ tributeToFreeSoftware(initDuration);
+ }
+ }
+
+ final private void tributeToFreeSoftware(long initDuration) {
+ if (log.isTraceEnabled()) {
+ long ms = initDuration / 100;
+ log.trace("Spend " + ms + "ms" + " reflecting on the progress brought to mankind" + " by Free Software...");
+ long beginNano = System.nanoTime();
+ try {
+ Thread.sleep(ms, 0);
+ } catch (InterruptedException e) {
+ // silent
+ }
+ long durationNano = System.nanoTime() - beginNano;
+ final double M = 1000d * 1000d;
+ double sleepAccuracy = ((double) durationNano) / (ms * M);
+ log.trace("Sleep accuracy: " + String.format("%.2f", 100 - (sleepAccuracy * 100 - 100)) + " %");
+ }
+ }
+
+ private void prepareNodeRepository(Repository deployedNodeRepository) {
+ if (availableSince != null) {
+ throw new CmsException("Deployment is already available");
+ }
+
+ // home
+ prepareDataModel(NodeConstants.NODE, KernelUtils.openAdminSession(deployedNodeRepository));
+ }
+
+ private void prepareHomeRepository(RepositoryImpl deployedRepository) {