<source>
<location>rpm/usr/sbin</location>
<includes>
- <include>node-service</include>
+ <include>nodectl</include>
</includes>
</source>
</sources>
-#argeo.osgi.baseUrl=http://forge.argeo.org/data/java/argeo-2.1/
-#argeo.osgi.distributionUrl=org/argeo/commons/org.argeo.dep.cms.sdk/2.1.65/org.argeo.dep.cms.sdk-2.1.69.jar
+argeo.node.repo.type=h2
+org.osgi.service.http.port=8080
+osgi.console=2323
+
+# Backend
+#argeo.osgi.start.5.apps=org.argeo.suite.apps
+
+# UI
+#argeo.osgi.start.6.apps=org.argeo.suite.apps.web,org.argeo.suite.workbench.rap
+
+# DO NOT CHANGE BELOW UNLESS YOU KNOW WHAT YOU ARE DOING
+osgi.clean=true
+osgi.bundles=org.argeo.osgi.boot.jar@start
argeo.osgi.bundles=\
/usr/local/share/osgi;in=**/*.jar,\
/usr/share/osgi;in=**/*.jar
-argeo.osgi.boot.debug=true
-
argeo.osgi.start.2.node=\
org.eclipse.equinox.http.servlet,\
org.eclipse.equinox.http.jetty,\
argeo.osgi.start.3.node=\
org.argeo.cms
-argeo.osgi.start.4.apps=\
-org.eclipse.gemini.blueprint.extender
-
-argeo.osgi.start.4.workbench=\
-org.eclipse.equinox.http.registry,\
+argeo.osgi.start.4.node=\
+org.eclipse.gemini.blueprint.extender,\
+org.eclipse.equinox.http.registry
-argeo.node.repo.type=h2
-org.osgi.service.http.port=8080
-
-# DO NOT CHANGE BELOW UNLESS YOU KNOW WHAT YOU ARE DOING
-osgi.bundles=org.argeo.osgi.boot.jar@start
org.osgi.framework.bootdelegation=com.sun.jndi.ldap,\
com.sun.jndi.ldap.sasl,\
com.sun.security.jgss,\
-log4j.rootLogger=WARN, console
+log4j.rootLogger=WARN, console, file
-log4j.logger.org.argeo=DEBUG
+log4j.logger.org.argeo=INFO
## Appenders
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.layout=org.apache.log4j.PatternLayout
-log4j.appender.console.layout.ConversionPattern= %-5p %d{ISO8601} %m - %c - [%t]%n
+log4j.appender.console.layout.ConversionPattern=%-5p %m%n
-log4j.appender.file=org.apache.log4j.RollingFileAppender
-log4j.appender.file.File=/var/log/node/node.log
+log4j.appender.file=org.apache.log4j.DailyRollingFileAppender
+log4j.appender.file.File=/var/log/node/node.csv
log4j.appender.file.layout=org.apache.log4j.PatternLayout
-log4j.appender.file.layout.ConversionPattern= %-5p %d{ISO8601} [%15.15t] %m - %c%n
+log4j.appender.file.layout.ConversionPattern=%d{ISO8601};"%m";%c;%p%n
+log4j.appender.file.bufferedIO=true
+log4j.appender.file.immediateFlush=false
[Service]
Type=simple
PIDFile=/var/run/node/node.pid
-ExecStart=/usr/sbin/node-service start
-#ExecReload=/usr/sbin/node-service reload
-#ExecStop=/usr/sbin/node-service stop
+ExecStart=/usr/sbin/nodectl start
+ExecReload=/usr/sbin/nodectl reload
SuccessExitStatus=143
[Install]
+++ /dev/null
-#!/bin/sh
-APP=node
-
-JVM=java
-
-# Directories and files
-CONF_DIR=/etc/$APP
-
-EXEC_DIR=/var/lib/$APP
-DATA_DIR=$EXEC_DIR/data
-CONF_RW=$EXEC_DIR/state
-LOG_DIR=/var/log/$APP
-LOG_FILE=$LOG_DIR/$APP.log
-
-RUN_DIR=/var/run/$APP
-PID_FILE=$RUN_DIR/$APP.pid
-SHUTDOWN_FILE=$RUN_DIR/$APP.shutdown
-
-OSGI_INSTALL_AREA=/usr/share/osgi/boot
-OSGI_FRAMEWORK=$OSGI_INSTALL_AREA/org.eclipse.osgi.jar
-
-# Overwrite variables
-if [ -f $CONF_DIR/settings.sh ];then
- . $CONF_DIR/settings.sh
-fi
-
-RETVAL=0
-
-start() {
- if [ -f $PID_FILE ];then
- PID=`cat $PID_FILE`
- kill -0 $PID &> /dev/null
- PID_EXISTS=$?
- if [ $PID_EXISTS -eq 0 ]; then
- echo $APP already running with pid $PID
- RETVAL=1
- return $RETVAL
- else
- echo Old $APP process with pid $PID is dead, removing $PID_FILE
- rm -f $PID_FILE
- fi
- fi
-
- if [ ! -f $CONF_RW/config.ini ]; then
- cp --preserve $CONF_DIR/config.ini $CONF_RW/config.ini
- fi
- touch $SHUTDOWN_FILE
- cd $EXEC_DIR
- $JVM \
- -Dargeo.osgi.shutdownFile="$SHUTDOWN_FILE" \
- -Dlog4j.configuration="file:$CONF_DIR/log4j.properties" \
- -Djava.security.manager= \
- -Djava.security.policy="file:$CONF_DIR/node.policy" \
- $JAVA_OPTS -jar $OSGI_FRAMEWORK \
- -configuration "$CONF_RW" \
- -data "$DATA_DIR"
-}
-
-stop() {
- if [ -f $PID_FILE ];then
- PID=`cat $PID_FILE`
- kill -0 $PID &> /dev/null
- PID_EXISTS=$?
- if [ $PID_EXISTS -ne 0 ]; then
- echo Dead $APP process with pid $PID, removing $PID_FILE
- rm -f $PID_FILE
- RETVAL=1
- return $RETVAL
- fi
- else
- echo $APP is not running
- RETVAL=1
- return $RETVAL
- fi
-
- # notifies application by removing the shutdown file
- rm -f $SHUTDOWN_FILE
-
- # wait 5 min for application to shutdown, then kill it
- TIMEOUT=$((5*60))
- BEGIN=$(date +%s)
- while kill -0 $PID &> /dev/null
- do
- sleep 1
- NOW=$(date +%s)
- DURATION=$(($NOW-$BEGIN))
- if [ $DURATION -gt $TIMEOUT ]; then
- kill -9 $PID
- echo Forcibly killed $APP with pid $PID
- RETVAL=1
- fi
- done
-
- # remove pid file
- rm -f $PID_FILE
- return $RETVAL
-
-# timeout is only available in EL6
-# timeout 5m sh << EOF
-#while kill -0 $PID &> /dev/null; do sleep 1; done
-#EOF
-# TIMEOUT_EXIT=$?
-# if [ $TIMEOUT_EXIT -eq 124 ];then
-# kill -9 $PID
-# RETVAL=1
-# echo Killed $APP with pid $PID
-# else
-# echo Stopped $APP with pid $PID
-# fi
-# rm -f $PID_FILE
-# return $RETVAL
-}
-
-status() {
- if [ -f $PID_FILE ];then
- PID=`cat $PID_FILE`
- else
- echo $APP is not running
- return $RETVAL
- fi
- kill -0 $PID &> /dev/null
- PID_EXISTS=$?
- if [ $PID_EXISTS -eq 0 ]; then
- echo $APP is running with pid $PID ...
- else
- echo No $APP process with pid $PID, removing $PID_FILE
- rm -f $PID_FILE
- fi
- return $RETVAL
-}
-
-# main
-case "$1" in
- start)
- start
- ;;
- stop)
- stop
- ;;
- status)
- status
- ;;
- *)
- echo $"Usage: $0 {start|stop|status}"
- exit 1
-esac
\ No newline at end of file
--- /dev/null
+#!/bin/sh
+APP=node
+
+JVM=java
+
+# Directories and files
+CONF_DIR=/etc/$APP
+
+EXEC_DIR=/var/lib/$APP
+DATA_DIR=$EXEC_DIR/data
+CONF_RW=$EXEC_DIR/state
+LOG_DIR=/var/log/$APP
+LOG_FILE=$LOG_DIR/$APP.log
+
+RUN_DIR=/var/run/$APP
+PID_FILE=$RUN_DIR/$APP.pid
+#SHUTDOWN_FILE=$RUN_DIR/$APP.shutdown
+
+OSGI_INSTALL_AREA=/usr/share/osgi/boot
+OSGI_FRAMEWORK=$OSGI_INSTALL_AREA/org.eclipse.osgi.jar
+
+# Overwrite variables
+if [ -f $CONF_DIR/settings.sh ];then
+ . $CONF_DIR/settings.sh
+fi
+
+RETVAL=0
+
+start() {
+ if [ -f $PID_FILE ];then
+ PID=`cat $PID_FILE`
+ kill -0 $PID &> /dev/null
+ PID_EXISTS=$?
+ if [ $PID_EXISTS -eq 0 ]; then
+ echo $APP already running with pid $PID
+ RETVAL=1
+ return $RETVAL
+ else
+ echo Old $APP process with pid $PID is dead, removing $PID_FILE
+ rm -f $PID_FILE
+ fi
+ fi
+
+# if [ ! -f $CONF_RW/config.ini ]; then
+ cp --preserve $CONF_DIR/config.ini $CONF_RW/config.ini
+# fi
+# touch $SHUTDOWN_FILE
+ cd $EXEC_DIR
+ $JVM \
+ -Dlog4j.configuration="file:$CONF_DIR/log4j.properties" \
+ -Djava.security.manager= \
+ -Djava.security.policy="file:$CONF_DIR/node.policy" \
+ $JAVA_OPTS -jar $OSGI_FRAMEWORK \
+ -configuration "$CONF_RW" \
+ -data "$DATA_DIR"
+}
+
+reload() {
+ echo Not yet implemented
+}
+
+stop() {
+ if [ -f $PID_FILE ];then
+ PID=`cat $PID_FILE`
+ kill -0 $PID &> /dev/null
+ PID_EXISTS=$?
+ if [ $PID_EXISTS -ne 0 ]; then
+ echo Dead $APP process with pid $PID, removing $PID_FILE
+ rm -f $PID_FILE
+ RETVAL=1
+ return $RETVAL
+ fi
+ else
+ echo $APP is not running
+ RETVAL=1
+ return $RETVAL
+ fi
+
+ # notifies application by removing the shutdown file
+ rm -f $SHUTDOWN_FILE
+
+ # wait 10 min for application to shutdown, then kill it
+ TIMEOUT=$((10*60))
+ BEGIN=$(date +%s)
+ while kill -0 $PID &> /dev/null
+ do
+ sleep 1
+ NOW=$(date +%s)
+ DURATION=$(($NOW-$BEGIN))
+ if [ $DURATION -gt $TIMEOUT ]; then
+ kill -9 $PID
+ echo Forcibly killed $APP with pid $PID
+ RETVAL=1
+ fi
+ done
+
+ # remove pid file
+ rm -f $PID_FILE
+ return $RETVAL
+
+# timeout is only available in EL6
+# timeout 5m sh << EOF
+#while kill -0 $PID &> /dev/null; do sleep 1; done
+#EOF
+# TIMEOUT_EXIT=$?
+# if [ $TIMEOUT_EXIT -eq 124 ];then
+# kill -9 $PID
+# RETVAL=1
+# echo Killed $APP with pid $PID
+# else
+# echo Stopped $APP with pid $PID
+# fi
+# rm -f $PID_FILE
+# return $RETVAL
+}
+
+status() {
+ if [ -f $PID_FILE ];then
+ PID=`cat $PID_FILE`
+ else
+ echo $APP is not running
+ return $RETVAL
+ fi
+ kill -0 $PID &> /dev/null
+ PID_EXISTS=$?
+ if [ $PID_EXISTS -eq 0 ]; then
+ echo $APP is running with pid $PID ...
+ else
+ echo No $APP process with pid $PID, removing $PID_FILE
+ rm -f $PID_FILE
+ fi
+ return $RETVAL
+}
+
+# main
+case "$1" in
+ start)
+ start
+ ;;
+ reload)
+ reload
+ ;;
+ stop)
+ stop
+ ;;
+ status)
+ status
+ ;;
+ *)
+ echo $"Usage: $0 {start|stop|status}"
+ exit 1
+esac
\ No newline at end of file
@Override
public boolean isMasterData() {
- return false;
+ // TODO make it configurable
+ return true;
}
}
@Override
public void start(BundleContext bundleContext) throws Exception {
+ Runtime.getRuntime().addShutdownHook(new CmsShutdown());
instance = this;
this.bc = bundleContext;
this.logReaderService = getService(LogReaderService.class);
long initDuration = System.currentTimeMillis() - begin;
if (log.isTraceEnabled())
log.trace("Kernel initialization took " + initDuration + "ms");
- directorsCut(initDuration);
+ tributeToFreeSoftware(initDuration);
}
}
- final private void directorsCut(long initDuration) {
- // final long ms = 128l + (long) (Math.random() * 128d);
- long ms = initDuration / 100;
- log.info("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
+ 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)) + " %");
}
- long durationNano = System.nanoTime() - beginNano;
- final double M = 1000d * 1000d;
- double sleepAccuracy = ((double) durationNano) / (ms * M);
- if (log.isDebugEnabled())
- log.debug("Sleep accuracy: " + String.format("%.2f", 100 - (sleepAccuracy * 100 - 100)) + " %");
}
private void prepareNodeRepository(Repository deployedNodeRepository) {
--- /dev/null
+package org.argeo.cms.internal.kernel;
+
+import java.io.IOException;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.FrameworkEvent;
+import org.osgi.framework.FrameworkUtil;
+import org.osgi.framework.launch.Framework;
+
+/** Shutdowns the OSGi framework */
+class CmsShutdown extends Thread {
+ public final int EXIT_OK = 0;
+ public final int EXIT_ERROR = 1;
+ public final int EXIT_TIMEOUT = 2;
+ public final int EXIT_UNKNOWN = 3;
+
+ private final Log log = LogFactory.getLog(CmsShutdown.class);
+ // private final BundleContext bc =
+ // FrameworkUtil.getBundle(CmsShutdown.class).getBundleContext();
+ private final Framework framework;
+
+ /** Shutdown timeout in ms */
+ private long timeout = 10 * 60 * 1000;
+
+ public CmsShutdown() {
+ super("CMS Shutdown Hook");
+ framework = (Framework) FrameworkUtil.getBundle(CmsShutdown.class).getBundleContext().getBundle(0);
+ }
+
+ @Override
+ public void run() {
+ if (framework.getState() != Bundle.ACTIVE) {
+ return;
+ }
+
+ if (log.isDebugEnabled())
+ log.debug("Shutting down OSGi framework...");
+ try {
+ // shutdown framework
+ framework.stop();
+ // wait for shutdown
+ FrameworkEvent shutdownEvent = framework.waitForStop(timeout);
+ int stoppedType = shutdownEvent.getType();
+ Runtime runtime = Runtime.getRuntime();
+ if (stoppedType == FrameworkEvent.STOPPED) {
+ // close VM
+ //System.exit(EXIT_OK);
+ } else if (stoppedType == FrameworkEvent.ERROR) {
+ log.error("The OSGi framework stopped with an error");
+ runtime.halt(EXIT_ERROR);
+ } else if (stoppedType == FrameworkEvent.WAIT_TIMEDOUT) {
+ log.error("The OSGi framework hasn't stopped after " + timeout + "ms."
+ + " Forcibly terminating the JVM...");
+ runtime.halt(EXIT_TIMEOUT);
+ } else {
+ log.error("Unknown state of OSGi framework after " + timeout + "ms."
+ + " Forcibly terminating the JVM... (" + shutdownEvent + ")");
+ runtime.halt(EXIT_UNKNOWN);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ log.error("Unexpected exception " + e + " in shutdown hook. " + " Forcibly terminating the JVM...");
+ Runtime.getRuntime().halt(EXIT_UNKNOWN);
+ }
+ }
+
+}
import static java.util.Locale.ENGLISH;
import java.io.File;
+import java.lang.management.ManagementFactory;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.nio.file.spi.FileSystemProvider;
private ThreadGroup threadGroup = new ThreadGroup("CMS");
private KernelThread kernelThread;
- private List<Runnable> shutdownHooks = new ArrayList<>();
+ private List<Runnable> stopHooks = new ArrayList<>();
private final String stateUuid;
private final boolean cleanState;
availableSince = System.currentTimeMillis();
if (log.isDebugEnabled())
- log.debug("## CMS STARTED " + this.stateUuid + (cleanState ? " (clean state) " : " "));
+ log.debug("## CMS starting... stateUuid=" + this.stateUuid + (cleanState ? " (clean state) " : " "));
initI18n();
initServices();
// JCR
RepositoryServiceFactory repositoryServiceFactory = new RepositoryServiceFactory();
- shutdownHooks.add(() -> repositoryServiceFactory.shutdown());
+ stopHooks.add(() -> repositoryServiceFactory.shutdown());
bc.registerService(ManagedServiceFactory.class, repositoryServiceFactory,
LangUtils.dico(Constants.SERVICE_PID, NodeConstants.NODE_REPOS_FACTORY_PID));
// Security
NodeUserAdmin userAdmin = new NodeUserAdmin(NodeConstants.ROLES_BASEDN);
- shutdownHooks.add(() -> userAdmin.destroy());
+ stopHooks.add(() -> userAdmin.destroy());
bc.registerService(ManagedServiceFactory.class, userAdmin,
LangUtils.dico(Constants.SERVICE_PID, NodeConstants.NODE_USER_ADMIN_PID));
tmConf.setLogPart2Filename(new File(tmDir2, tmDir2.getName() + ".tlog").getAbsolutePath());
}
BitronixTransactionManager transactionManager = getTransactionManager();
- shutdownHooks.add(() -> transactionManager.shutdown());
+ stopHooks.add(() -> transactionManager.shutdown());
BitronixTransactionSynchronizationRegistry transactionSynchronizationRegistry = getTransactionSynchronizationRegistry();
// register
bc.registerService(TransactionManager.class, transactionManager, null);
}
void shutdown() {
+ if (log.isDebugEnabled())
+ log.debug("CMS stopping... stateUuid=" + this.stateUuid + (cleanState ? " (clean state) " : " "));
+
if (kernelThread != null)
kernelThread.destroyAndJoin();
+ applyStopHooks();
- applyShutdownHooks();
-
- if (log.isDebugEnabled())
- log.debug("## CMS STOPPED");
+ long duration = ((System.currentTimeMillis() - availableSince) / 1000) / 60;
+ log.info("## ARGEO CMS STOPPED after " + (duration / 60) + "h " + (duration % 60) + "min uptime ##");
}
/** Apply shutdown hoos in reverse order. */
- private void applyShutdownHooks() {
- for (int i = shutdownHooks.size() - 1; i >= 0; i--) {
+ private void applyStopHooks() {
+ for (int i = stopHooks.size() - 1; i >= 0; i--) {
try {
- shutdownHooks.get(i).run();
+ stopHooks.get(i).run();
} catch (Exception e) {
log.error("Could not run shutdown hook #" + i);
}
public String getHostname() {
return hostname;
}
-
- /** Workaround for blocking Gogo shell by system shutdown. */
- private class GogoShellKiller extends Thread {
-
- public GogoShellKiller() {
- super("Gogo Shell Killer");
- setDaemon(true);
- }
-
- @Override
- public void run() {
- ThreadGroup rootTg = getRootThreadGroup(null);
- Thread gogoShellThread = findGogoShellThread(rootTg);
- if (gogoShellThread == null)
- return;
- while (getNonDaemonCount(rootTg) > 2) {
- try {
- Thread.sleep(100);
- } catch (InterruptedException e) {
- // silent
- }
- }
- gogoShellThread = findGogoShellThread(rootTg);
- if (gogoShellThread == null)
- return;
- System.exit(0);
- }
- }
-
- private static ThreadGroup getRootThreadGroup(ThreadGroup tg) {
- if (tg == null)
- tg = Thread.currentThread().getThreadGroup();
- if (tg.getParent() == null)
- return tg;
- else
- return getRootThreadGroup(tg.getParent());
- }
-
- private static int getNonDaemonCount(ThreadGroup rootThreadGroup) {
- Thread[] threads = new Thread[rootThreadGroup.activeCount()];
- rootThreadGroup.enumerate(threads);
- int nonDameonCount = 0;
- for (Thread t : threads)
- if (t != null && !t.isDaemon())
- nonDameonCount++;
- return nonDameonCount;
- }
-
- private static Thread findGogoShellThread(ThreadGroup rootThreadGroup) {
- Thread[] threads = new Thread[rootThreadGroup.activeCount()];
- rootThreadGroup.enumerate(threads, true);
- for (Thread thread : threads) {
- if (thread.getName().equals("Gogo shell"))
- return thread;
- }
- return null;
- }
-
}
if (keyStorePassword == null)
keyStorePassword = "changeit";
if (!Files.exists(keyStorePath))
- createSelfSignedKeyStore(keyStorePath);
+ createSelfSignedKeyStore(keyStorePath, keyStorePassword);
props.put(JettyConstants.SSL_KEYSTORETYPE, "PKCS12");
props.put(JettyConstants.SSL_KEYSTORE, keyStorePath.toString());
props.put(JettyConstants.SSL_PASSWORD, keyStorePassword);
// Business roles
String userAdminUris = getFrameworkProp(NodeConstants.USERADMIN_URIS);
if (userAdminUris == null) {
- String demoBaseDn = "dc=example,dc=com";
- File businessRolesFile = new File(nodeBaseDir, demoBaseDn + ".ldif");
- if (!businessRolesFile.exists())
- try {
- FileUtils.copyInputStreamToFile(getClass().getResourceAsStream(demoBaseDn + ".ldif"),
- businessRolesFile);
- } catch (IOException e) {
- throw new CmsException("Cannot copy demo resource", e);
- }
- userAdminUris = businessRolesFile.toURI().toString();
- log.warn("## DEV Using dummy base DN " + demoBaseDn);
- // TODO downgrade security level
+ String demoBaseDn = "dc=example,dc=com";
+ File businessRolesFile = new File(nodeBaseDir, demoBaseDn + ".ldif");
+ if (!businessRolesFile.exists())
+ try {
+ FileUtils.copyInputStreamToFile(getClass().getResourceAsStream(demoBaseDn + ".ldif"),
+ businessRolesFile);
+ } catch (IOException e) {
+ throw new CmsException("Cannot copy demo resource", e);
+ }
+ userAdminUris = businessRolesFile.toURI().toString();
+ log.warn("## DEV Using dummy base DN " + demoBaseDn);
+ // TODO downgrade security level
}
for (String userAdminUri : userAdminUris.split(" "))
uris.add(userAdminUri);
return res;
}
-
+
/**
- * Called before node initialisation, in order populate OSGi instance are
- * with some files (typically LDIF, etc).
+ * Called before node initialisation, in order populate OSGi instance are with
+ * some files (typically LDIF, etc).
*/
static void prepareInstanceArea() {
String nodeInit = getFrameworkProp(NodeConstants.NODE_INIT);
}
}
- private void createSelfSignedKeyStore(Path keyStorePath) {
+ private void createSelfSignedKeyStore(Path keyStorePath, String keyStorePassword) {
// for (Provider provider : Security.getProviders())
// System.out.println(provider.getName());
File keyStoreFile = keyStorePath.toFile();
- char[] ksPwd = "changeit".toCharArray();
+ char[] ksPwd = keyStorePassword.toCharArray();
char[] keyPwd = Arrays.copyOf(ksPwd, ksPwd.length);
if (!keyStoreFile.exists()) {
try {
--- /dev/null
+package org.argeo.cms.internal.kernel;
+
+/**
+ * Workaround for killing Gogo shell by system shutdown.
+ *
+ * @see https://issues.apache.org/jira/browse/FELIX-4208
+ */
+class GogoShellKiller extends Thread {
+
+ public GogoShellKiller() {
+ super("Gogo Shell Killer");
+ setDaemon(true);
+ }
+
+ @Override
+ public void run() {
+ ThreadGroup rootTg = getRootThreadGroup(null);
+ Thread gogoShellThread = findGogoShellThread(rootTg);
+ if (gogoShellThread == null)
+ return;
+ while (getNonDaemonCount(rootTg) > 2) {
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException e) {
+ // silent
+ }
+ }
+ gogoShellThread = findGogoShellThread(rootTg);
+ if (gogoShellThread == null)
+ return;
+ // No non-deamon threads left, forcibly halting the VM
+ Runtime.getRuntime().halt(0);
+ }
+
+ private ThreadGroup getRootThreadGroup(ThreadGroup tg) {
+ if (tg == null)
+ tg = Thread.currentThread().getThreadGroup();
+ if (tg.getParent() == null)
+ return tg;
+ else
+ return getRootThreadGroup(tg.getParent());
+ }
+
+ private int getNonDaemonCount(ThreadGroup rootThreadGroup) {
+ Thread[] threads = new Thread[rootThreadGroup.activeCount()];
+ rootThreadGroup.enumerate(threads);
+ int nonDameonCount = 0;
+ for (Thread t : threads)
+ if (t != null && !t.isDaemon())
+ nonDameonCount++;
+ return nonDameonCount;
+ }
+
+ private Thread findGogoShellThread(ThreadGroup rootThreadGroup) {
+ Thread[] threads = new Thread[rootThreadGroup.activeCount()];
+ rootThreadGroup.enumerate(threads, true);
+ for (Thread thread : threads) {
+ if (thread.getName().equals("Gogo shell"))
+ return thread;
+ }
+ return null;
+ }
+
+}
\ No newline at end of file
if (sr != null) {
sb.append(' ');
String[] objectClasses = (String[]) sr.getProperty(Constants.OBJECTCLASS);
- sb.append(arrayToString(objectClasses));
+ if (isSpringApplicationContext(objectClasses)) {
+ sb.append("{org.springframework.context.ApplicationContext}");
+ Object symbolicName = sr.getProperty(Constants.BUNDLE_SYMBOLICNAME);
+ if (symbolicName != null)
+ sb.append(" " + Constants.BUNDLE_SYMBOLICNAME + ": " + symbolicName);
+ } else {
+ sb.append(arrayToString(objectClasses));
+ }
Object cn = sr.getProperty(NodeConstants.CN);
if (cn != null)
sb.append(" " + NodeConstants.CN + ": " + cn);
Object factoryPid = sr.getProperty(ConfigurationAdmin.SERVICE_FACTORYPID);
if (factoryPid != null)
sb.append(" " + ConfigurationAdmin.SERVICE_FACTORYPID + ": " + factoryPid);
-// else {
-// Object servicePid = sr.getProperty(Constants.SERVICE_PID);
-// if (servicePid != null)
-// sb.append(" " + Constants.SERVICE_PID + ": " + servicePid);
-// }
+ // else {
+ // Object servicePid = sr.getProperty(Constants.SERVICE_PID);
+ // if (servicePid != null)
+ // sb.append(" " + Constants.SERVICE_PID + ": " + servicePid);
+ // }
// servlets
Object whiteBoardPattern = sr.getProperty(KernelConstants.WHITEBOARD_PATTERN_PROP);
if (whiteBoardPattern != null)
Object contextName = sr.getProperty(KernelConstants.CONTEXT_NAME_PROP);
if (contextName != null)
sb.append(" " + KernelConstants.CONTEXT_NAME_PROP + ": " + contextName);
-
+
// user directories
Object baseDn = sr.getProperty(UserAdminConf.baseDn.name());
if (baseDn != null)
sb.append(" " + UserAdminConf.baseDn.name() + ": " + baseDn);
+
}
return sb.toString();
}
return sb.toString();
}
+ private boolean isSpringApplicationContext(String[] objectClasses) {
+ for (String clss : objectClasses) {
+ if (clss.equals("org.eclipse.gemini.blueprint.context.DelegatedExecutionOsgiBundleApplicationContext")) {
+ return true;
+ }
+ }
+ return false;
+ }
+
//
// ARGEO LOGGER
//