You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@karaf.apache.org by gn...@apache.org on 2014/04/10 16:16:03 UTC
[41/59] [abbrv] [KARAF-2852] Merge system/core and system/command
http://git-wip-us.apache.org/repos/asf/karaf/blob/0a100d76/system/src/main/java/org/apache/karaf/system/SystemService.java
----------------------------------------------------------------------
diff --git a/system/src/main/java/org/apache/karaf/system/SystemService.java b/system/src/main/java/org/apache/karaf/system/SystemService.java
new file mode 100644
index 0000000..2f53946
--- /dev/null
+++ b/system/src/main/java/org/apache/karaf/system/SystemService.java
@@ -0,0 +1,130 @@
+ /*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.karaf.system;
+
+/**
+ * Describe a system service
+ */
+public interface SystemService {
+
+ /**
+ * Types defining what to remove on a restart of Karaf
+ */
+ public enum Swipe {
+ /** Delete nothing; simple restart */
+ NONE,
+ /** Delete only the cache; everything else remains */
+ CACHE,
+ /** Forces a clean restart by removing the working directory; this option is compatible to the former clean method. */
+ ALL
+ }
+
+ /**
+ * Halt the Karaf container.
+ */
+ void halt() throws Exception;
+
+ /**
+ * Halt the Karaf container.
+ *
+ * @param time shutdown delay. The time argument can have different formats.
+ * First, it can be an absolute time in the format hh:mm, in which hh is the hour (1 or 2 digits) and mm
+ * is the minute of the hour (in two digits). Second, it can be in the format +m, in which m is the number of minutes
+ * to wait. The word now is an alias for +0.
+ */
+ void halt(String time) throws Exception;
+
+ /**
+ * Reboot the Karaf container.
+ *
+ * @throws Exception
+ */
+ void reboot() throws Exception;
+
+ /**
+ * Reboot the Karaf container.
+ *
+ * @param time reboot delay. The time argument can have different formats.
+ * First, it can be an absolute time in the format hh:mm, in which hh is the hour (1 or 2 digits) and mm
+ * is the minute of the hour (in two digits). Second, it can be in the format +m, in which m is the number of minutes
+ * to wait. The word now is an alias for +0.
+ * @param clean Force a clean restart by deleting the working directory.
+ */
+ void reboot(String time, Swipe clean) throws Exception;
+
+ /**
+ * Set the system start level.
+ *
+ * @param startLevel the new system start level.
+ */
+ void setStartLevel(int startLevel) throws Exception;
+
+ /**
+ * Get the system start level.
+ *
+ * @return the current system start level.
+ */
+ int getStartLevel() throws Exception;
+
+ /**
+ * Get the version of the current Karaf instance
+ *
+ * @return instance version
+ */
+ String getVersion();
+
+ /**
+ * Get the name of the current Karaf instance
+ *
+ * @return instance name
+ */
+ String getName();
+
+ /**
+ * Set the name of the Karaf instance
+ *
+ * @param name new instance name
+ */
+ void setName(String name);
+
+ /**
+ * Get the current OSGi framework in use.
+ *
+ * @return the name of the OSGi framework in use.
+ * @throws Exception
+ */
+ FrameworkType getFramework();
+
+ /**
+ * change OSGi framework
+ *
+ * @param framework to use.
+ */
+ void setFramework(FrameworkType framework);
+
+ /**
+ * Enable or diable debgging
+ * @param debug enable if true
+ */
+ void setFrameworkDebug(boolean debug);
+
+ /**
+ * Set a system property and persist to etc/system.properties
+ * @param key
+ */
+ String setSystemProperty(String key, String value, boolean persist);
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0a100d76/system/src/main/java/org/apache/karaf/system/commands/FrameworkOptions.java
----------------------------------------------------------------------
diff --git a/system/src/main/java/org/apache/karaf/system/commands/FrameworkOptions.java b/system/src/main/java/org/apache/karaf/system/commands/FrameworkOptions.java
new file mode 100644
index 0000000..9e16a7d
--- /dev/null
+++ b/system/src/main/java/org/apache/karaf/system/commands/FrameworkOptions.java
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.karaf.system.commands;
+
+import org.apache.karaf.shell.api.action.Action;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Option;
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.system.FrameworkType;
+import org.apache.karaf.system.SystemService;
+
+/**
+ * Command for enabling/disabling debug logging on the OSGi framework
+ */
+@Command(scope = "system", name = "framework", description = "OSGi Framework options.")
+@Service
+public class FrameworkOptions implements Action {
+
+ @Option(name = "-debug", aliases={"--enable-debug"}, description="Enable debug for the OSGi framework", required = false, multiValued = false)
+ boolean debug;
+
+ @Option(name = "-nodebug", aliases={"--disable-debug"}, description="Disable debug for the OSGi framework", required = false, multiValued = false)
+ boolean nodebug;
+
+ @Argument(name = "framework", required = false, description = "Name of the OSGi framework to use")
+ String framework;
+
+ @Reference
+ SystemService systemService;
+
+ @Override
+ public Object execute() throws Exception {
+
+ if (!debug^nodebug && framework == null) {
+ System.out.printf("Current OSGi framework is %s%n", systemService.getFramework().name());
+ return null;
+ }
+ if (framework != null) {
+ FrameworkType frameworkType = FrameworkType.valueOf(framework);
+ systemService.setFramework(frameworkType);
+ System.out.println("Changed OSGi framework to " + frameworkType.toString().toLowerCase() + ". Karaf needs to be restarted to make the change effective");
+ }
+ if (debug) {
+ FrameworkType frameworkType = systemService.getFramework();
+ System.out.printf("Enabling debug for OSGi framework (%s)%n", frameworkType.name());
+ systemService.setFrameworkDebug(true);
+ }
+ if (nodebug) {
+ FrameworkType frameworkType = systemService.getFramework();
+ System.out.printf("Disabling debug for OSGi framework (%s)%n", frameworkType.name());
+ systemService.setFrameworkDebug(false);
+ }
+
+ return null;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0a100d76/system/src/main/java/org/apache/karaf/system/commands/Name.java
----------------------------------------------------------------------
diff --git a/system/src/main/java/org/apache/karaf/system/commands/Name.java b/system/src/main/java/org/apache/karaf/system/commands/Name.java
new file mode 100644
index 0000000..a716d82
--- /dev/null
+++ b/system/src/main/java/org/apache/karaf/system/commands/Name.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.karaf.system.commands;
+
+
+import org.apache.karaf.shell.api.action.Action;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.system.SystemService;
+
+/**
+ * Command to shut down Karaf container.
+ */
+@Command(scope = "system", name = "name", description = "Show or change Karaf instance name.")
+@Service
+public class Name implements Action {
+
+ @Argument(name = "name", index = 0, description = "New name for the instance", required = false, multiValued = false)
+ String name;
+
+ @Reference
+ SystemService systemService;
+
+ @Override
+ public Object execute() throws Exception {
+ if (name == null) {
+ System.out.println(systemService.getName());
+ } else {
+ systemService.setName(name);
+ System.out.println("Instance name changed to " + name + ". Restart needed for this to take effect.");
+ }
+ return null;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0a100d76/system/src/main/java/org/apache/karaf/system/commands/Shutdown.java
----------------------------------------------------------------------
diff --git a/system/src/main/java/org/apache/karaf/system/commands/Shutdown.java b/system/src/main/java/org/apache/karaf/system/commands/Shutdown.java
new file mode 100644
index 0000000..b8b4b41
--- /dev/null
+++ b/system/src/main/java/org/apache/karaf/system/commands/Shutdown.java
@@ -0,0 +1,104 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.karaf.system.commands;
+
+import org.apache.karaf.shell.api.action.Action;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Option;
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.shell.api.console.Session;
+import org.apache.karaf.system.SystemService;
+
+/**
+ * Command to shut down Karaf container.
+ */
+@Command(scope = "system", name = "shutdown", description = "Shutdown Karaf.")
+@Service
+public class Shutdown implements Action {
+
+ @Option(name = "-f", aliases = "--force", description = "Force the shutdown without confirmation message.", required = false, multiValued = false)
+ boolean force = false;
+
+ @Option(name = "-r", aliases = "--reboot", description = "Reboot the Karaf container.", required = false, multiValued = false)
+ boolean reboot = false;
+
+ @Option(name = "-h", aliases = "--halt", description = "Halt the Karaf container.", required = false, multiValued = false)
+ boolean halt = false;
+
+ @Option(name = "-c", aliases = {"--clean", "--clean-all", "-ca"}, description = "Force a clean restart by deleting the data directory")
+ private boolean cleanAll;
+
+ @Option(name = "-cc", aliases = {"--clean-cache", "-cc"}, description = "Force a clean restart by deleting the cache directory")
+ private boolean cleanCache;
+
+
+ @Argument(name = "time", index = 0, description = "Shutdown after a specified delay. The time argument can have different" +
+ " formats. First, it can be an absolute time in the format hh:mm, in which hh is the hour (1 or 2 digits) and mm" +
+ " is the minute of the hour (in two digits). Second, it can be in the format +m, in which m is the number of minutes" +
+ " to wait. The word now is an alias for +0.", required = false, multiValued = false)
+ String time;
+
+ @Reference
+ SystemService systemService;
+
+ @Reference
+ Session session;
+
+ @Override
+ public Object execute() throws Exception {
+
+ if (force) {
+ if (reboot) {
+ systemService.reboot(time, determineSwipeType());
+ } else {
+ systemService.halt(time);
+ }
+ return null;
+ }
+
+ for (; ; ) {
+ String karafName = System.getProperty("karaf.name");
+ String msg;
+ if (reboot) {
+ msg = String.format("Confirm: reboot instance %s (yes/no): ", karafName);
+ } else {
+ msg = String.format("Confirm: halt instance %s (yes/no): ", karafName);
+ }
+ String str = session.readLine(msg, null);
+ if (str.equalsIgnoreCase("yes")) {
+ if (reboot) {
+ systemService.reboot(time, determineSwipeType());
+ } else {
+ systemService.halt(time);
+ }
+ }
+ return null;
+ }
+ }
+
+ private SystemService.Swipe determineSwipeType() {
+ if (cleanAll) {
+ return SystemService.Swipe.ALL;
+ } else if (cleanCache) {
+ return SystemService.Swipe.CACHE;
+ }
+ return SystemService.Swipe.NONE;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0a100d76/system/src/main/java/org/apache/karaf/system/commands/StartLevel.java
----------------------------------------------------------------------
diff --git a/system/src/main/java/org/apache/karaf/system/commands/StartLevel.java b/system/src/main/java/org/apache/karaf/system/commands/StartLevel.java
new file mode 100644
index 0000000..e91c15a
--- /dev/null
+++ b/system/src/main/java/org/apache/karaf/system/commands/StartLevel.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.karaf.system.commands;
+
+import org.apache.karaf.shell.api.action.Action;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.system.SystemService;
+
+/**
+ * Get/set the system start level.
+ */
+@Command(scope = "system", name = "start-level", description = "Gets or sets the system start level.")
+@Service
+public class StartLevel implements Action {
+
+ @Argument(index = 0, name = "level", description = "The new system start level to set", required = false, multiValued = false)
+ Integer level;
+
+ @Reference
+ SystemService systemService;
+
+ @Override
+ public Object execute() throws Exception {
+ if (level == null) {
+ System.out.println("Level " + systemService.getStartLevel());
+ } else {
+ systemService.setStartLevel(level);
+ }
+ return null;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0a100d76/system/src/main/java/org/apache/karaf/system/commands/SystemProperty.java
----------------------------------------------------------------------
diff --git a/system/src/main/java/org/apache/karaf/system/commands/SystemProperty.java b/system/src/main/java/org/apache/karaf/system/commands/SystemProperty.java
new file mode 100644
index 0000000..37c2a1e
--- /dev/null
+++ b/system/src/main/java/org/apache/karaf/system/commands/SystemProperty.java
@@ -0,0 +1,157 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.karaf.system.commands;
+
+import java.io.File;
+import java.io.PrintStream;
+import java.text.SimpleDateFormat;
+import java.util.Collections;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.Properties;
+import java.util.Set;
+import java.util.Vector;
+
+import org.apache.karaf.shell.api.action.Action;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Option;
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.system.SystemService;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+
+/**
+ * Command that allow access to system properties easily.
+ */
+@Command(scope = "system", name = "property", description = "Get or set a system property.")
+@Service
+public class SystemProperty implements Action {
+
+ @Option(name = "-p", aliases = {"--persistent"}, description = "Persist the new value to the etc/system.properties file")
+ boolean persistent;
+
+ @Option(name = "-f", aliases = {"--file-dump"}, description = "Dump all system properties in a file (in data folder)")
+ boolean dumpToFile;
+
+ @Option(name = "-u", aliases = {"--unset"}, description = "Show unset know properties with value unset")
+ boolean unset;
+
+ @Argument(index = 0, name = "key", required = false, description = "The system property name")
+ String key;
+
+ @Argument(index = 1, name = "value", required = false, description = "New value for the system property")
+ String value;
+
+ @Reference
+ BundleContext bundleContext;
+
+ @Reference
+ SystemService systemService;
+
+ @Override
+ public Object execute() throws Exception {
+ if (key == null && value == null) {
+ Properties props = (Properties) System.getProperties().clone();
+
+ String def = null;
+ if (unset) {
+ def = "unset";
+ }
+
+ setProperty(props, Constants.FRAMEWORK_BEGINNING_STARTLEVEL, def);
+ setProperty(props, Constants.FRAMEWORK_BOOTDELEGATION, def);
+ setProperty(props, Constants.FRAMEWORK_BUNDLE_PARENT, def);
+ setProperty(props, Constants.FRAMEWORK_BUNDLE_PARENT_APP, def);
+ setProperty(props, Constants.FRAMEWORK_BUNDLE_PARENT_BOOT, def);
+ setProperty(props, Constants.FRAMEWORK_BUNDLE_PARENT_EXT, def);
+ setProperty(props, Constants.FRAMEWORK_BUNDLE_PARENT_FRAMEWORK, def);
+ setProperty(props, Constants.FRAMEWORK_EXECPERMISSION, def);
+ setProperty(props, Constants.FRAMEWORK_EXECUTIONENVIRONMENT, def);
+ setProperty(props, Constants.FRAMEWORK_LANGUAGE, def);
+ setProperty(props, Constants.FRAMEWORK_LIBRARY_EXTENSIONS, def);
+ setProperty(props, Constants.FRAMEWORK_OS_NAME, def);
+ setProperty(props, Constants.FRAMEWORK_OS_VERSION, def);
+ setProperty(props, Constants.FRAMEWORK_PROCESSOR, def);
+ setProperty(props, Constants.FRAMEWORK_SECURITY, def);
+ setProperty(props, Constants.FRAMEWORK_SECURITY_OSGI, def);
+ setProperty(props, Constants.FRAMEWORK_STORAGE, def);
+ setProperty(props, Constants.FRAMEWORK_STORAGE_CLEAN_ONFIRSTINIT, def);
+ setProperty(props, Constants.FRAMEWORK_SYSTEMPACKAGES, def);
+ setProperty(props, Constants.FRAMEWORK_SYSTEMPACKAGES_EXTRA, def);
+ setProperty(props, Constants.FRAMEWORK_VENDOR, def);
+ setProperty(props, Constants.FRAMEWORK_VERSION, def);
+ setProperty(props, Constants.FRAMEWORK_WINDOWSYSTEM, def);
+
+ setProperty(props, Constants.SUPPORTS_BOOTCLASSPATH_EXTENSION, def);
+ setProperty(props, Constants.SUPPORTS_FRAMEWORK_EXTENSION, def);
+ setProperty(props, Constants.SUPPORTS_FRAMEWORK_FRAGMENT, def);
+ setProperty(props, Constants.SUPPORTS_FRAMEWORK_REQUIREBUNDLE, def);
+
+ if (dumpToFile) {
+ PrintStream ps = new PrintStream(
+ new File(
+ bundleContext.getProperty("karaf.data"),
+ "dump-properties-" + System.currentTimeMillis() + ".properties"
+ )
+ );
+ ps.println("#Dump of the System and OSGi properties with the command system:property");
+ ps.println("#Dump executed at " + new SimpleDateFormat().format(new Date()));
+ printOrderedProperties(props, ps);
+ ps.flush();
+ ps.close();
+ } else {
+ printOrderedProperties(props, System.out);
+ }
+
+ return null;
+ }
+
+ if (value != null) {
+ systemService.setSystemProperty(key, value, persistent);
+ } else {
+ System.out.println(System.getProperty(key));
+ }
+
+ return null;
+ }
+
+ private void printOrderedProperties(Properties props, PrintStream out) {
+ Set<Object> keys = props.keySet();
+ Vector<String> order = new Vector<String>(keys.size());
+ for (Iterator<Object> i = keys.iterator(); i.hasNext(); ) {
+ Object str = (Object) i.next();
+ order.add((String) str);
+ }
+ Collections.sort(order);
+ for (Iterator<String> i = order.iterator(); i.hasNext(); ) {
+ String key = (String) i.next();
+ out.println(key + "=" + props.getProperty(key));
+ }
+ }
+
+ private void setProperty(Properties props, String key, String def) {
+ String val = bundleContext.getProperty(key);
+ if (val == null && def != null) {
+ props.setProperty(key, def);
+ } else if (val != null) {
+ props.setProperty(key, val);
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0a100d76/system/src/main/java/org/apache/karaf/system/commands/Version.java
----------------------------------------------------------------------
diff --git a/system/src/main/java/org/apache/karaf/system/commands/Version.java b/system/src/main/java/org/apache/karaf/system/commands/Version.java
new file mode 100644
index 0000000..9837aaa
--- /dev/null
+++ b/system/src/main/java/org/apache/karaf/system/commands/Version.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.karaf.system.commands;
+
+import org.apache.karaf.shell.api.action.Action;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.system.SystemService;
+
+@Command(scope = "system", name = "version", description = "Display the instance version")
+@Service
+public class Version implements Action {
+
+ @Reference
+ SystemService systemService;
+
+ @Override
+ public Object execute() throws Exception {
+ System.out.println(systemService.getVersion());
+ return null;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0a100d76/system/src/main/java/org/apache/karaf/system/internal/SystemServiceImpl.java
----------------------------------------------------------------------
diff --git a/system/src/main/java/org/apache/karaf/system/internal/SystemServiceImpl.java b/system/src/main/java/org/apache/karaf/system/internal/SystemServiceImpl.java
new file mode 100644
index 0000000..8fa5a38
--- /dev/null
+++ b/system/src/main/java/org/apache/karaf/system/internal/SystemServiceImpl.java
@@ -0,0 +1,238 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package org.apache.karaf.system.internal;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.Calendar;
+import java.util.GregorianCalendar;
+
+import org.apache.felix.utils.properties.Properties;
+import org.apache.karaf.system.FrameworkType;
+import org.apache.karaf.system.SystemService;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.startlevel.FrameworkStartLevel;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Implementation of the system service.
+ */
+public class SystemServiceImpl implements SystemService {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(SystemServiceImpl.class);
+
+ private BundleContext bundleContext;
+
+ public void setBundleContext(BundleContext bundleContext) {
+ this.bundleContext = bundleContext;
+ }
+
+ public BundleContext getBundleContext() {
+ return this.bundleContext;
+ }
+
+ public void halt() throws Exception {
+ halt(null);
+ }
+
+ public void halt(String time) throws Exception {
+ shutdown(timeToSleep(time));
+ }
+
+ public void reboot() throws Exception {
+ reboot(null, Swipe.NONE);
+ }
+
+ public void reboot(String time, Swipe cleanup) throws Exception {
+ reboot(timeToSleep(time), cleanup);
+ }
+
+ private void shutdown(final long sleep) {
+ new Thread() {
+ public void run() {
+ try {
+ sleepWithMsg(sleep, "Shutdown in " + sleep / 1000 / 60 + " minute(s)");
+ getBundleContext().getBundle(0).stop();
+ } catch (Exception e) {
+ LOGGER.error("Halt error", e);
+ }
+ }
+ }.start();
+ }
+
+ private void reboot(final long sleep, final Swipe clean) {
+ new Thread() {
+ public void run() {
+ try {
+ sleepWithMsg(sleep, "Reboot in " + sleep / 1000 / 60 + " minute(s)");
+ System.setProperty("karaf.restart", "true");
+ if (clean.equals(Swipe.ALL)) {
+ System.setProperty("karaf.clean.all", "true");
+ } else if (clean.equals(Swipe.CACHE)) {
+ System.setProperty("karaf.clean.cache", "true");
+ }
+ bundleContext.getBundle(0).stop();
+ } catch (Exception e) {
+ LOGGER.error("Reboot error", e);
+ }
+ }
+ }.start();
+ }
+
+ private void sleepWithMsg(final long sleep, String msg)
+ throws InterruptedException {
+ if (sleep > 0) {
+ LOGGER.info(msg);
+ System.err.println(msg);
+ }
+ Thread.sleep(sleep);
+ }
+
+ public void setStartLevel(int startLevel) throws Exception {
+ getBundleContext().getBundle(0).adapt(FrameworkStartLevel.class).setStartLevel(startLevel);
+ }
+
+ public int getStartLevel() throws Exception {
+ return getBundleContext().getBundle(0).adapt(FrameworkStartLevel.class).getStartLevel();
+ }
+
+ /**
+ * Convert a time string to sleep period (in millisecond).
+ *
+ * @param time the time string.
+ * @return the corresponding sleep period in millisecond.
+ */
+ private long timeToSleep(String time) throws Exception {
+ long sleep = 0;
+ if (time != null) {
+ if (!time.equals("now")) {
+ if (time.startsWith("+")) {
+ // delay in number of minutes provided
+ time = time.substring(1);
+ try {
+ sleep = Long.parseLong(time) * 60 * 1000;
+ } catch (Exception e) {
+ throw new IllegalArgumentException("Time " + time + " is not valid");
+ }
+ } else {
+ // try to parse the date in hh:mm
+ String[] strings = time.split(":");
+ if (strings.length != 2) {
+ throw new IllegalArgumentException("Time " + time + " is not valid");
+ }
+ GregorianCalendar currentDate = new GregorianCalendar();
+ GregorianCalendar shutdownDate = new GregorianCalendar(currentDate.get(Calendar.YEAR), currentDate.get(Calendar.MONTH), currentDate.get(Calendar.DATE), Integer.parseInt(strings[0]), Integer.parseInt(strings[1]));
+ if (shutdownDate.before(currentDate)) {
+ shutdownDate.set(Calendar.DATE, shutdownDate.get(Calendar.DATE) + 1);
+ }
+ sleep = shutdownDate.getTimeInMillis() - currentDate.getTimeInMillis();
+ }
+ }
+ }
+ return sleep;
+ }
+
+ @Override
+ public String getVersion() {
+ return System.getProperty("karaf.version");
+ }
+
+ @Override
+ public String getName() {
+ return bundleContext.getProperty("karaf.name");
+ }
+
+ @Override
+ public void setName(String name) {
+ try {
+ String karafEtc = bundleContext.getProperty("karaf.etc");
+ File etcDir = new File(karafEtc);
+ File syspropsFile = new File(etcDir, "system.properties");
+ FileInputStream fis = new FileInputStream(syspropsFile);
+ Properties props = new Properties();
+ props.load(fis);
+ fis.close();
+ props.setProperty("karaf.name", name);
+ FileOutputStream fos = new FileOutputStream(syspropsFile);
+ props.store(fos, "");
+ fos.close();
+ } catch (Exception e) {
+ throw new RuntimeException(e.getMessage(), e);
+ }
+ }
+
+ public FrameworkType getFramework() {
+ if (bundleContext.getBundle(0).getSymbolicName().contains("felix")) {
+ return FrameworkType.felix;
+ } else {
+ return FrameworkType.equinox;
+ }
+ }
+
+ private Properties loadProps() throws IOException {
+ return new Properties(new File(System.getProperty("karaf.etc"), "config.properties"));
+ }
+
+ public void setFramework(FrameworkType framework) {
+ if (framework == null) {
+ return;
+ }
+ try {
+ Properties properties = loadProps();
+ properties.put("karaf.framework", framework.name());
+ properties.save();
+ } catch (IOException e) {
+ throw new RuntimeException("Error setting framework: " + e.getMessage(), e);
+ }
+ }
+
+ public void setFrameworkDebug(boolean debug) {
+ try {
+ Properties properties = loadProps();
+ if (debug) {
+ properties.put("felix.log.level", "4");
+ properties.put("osgi.debug", "etc/equinox-debug.properties");
+ } else {
+ properties.remove("felix.log.level");
+ properties.remove("osgi.debug");
+ }
+ // TODO populate the equinox-debug.properties file with the one provided in shell/dev module
+ properties.save();
+ } catch (IOException e) {
+ throw new RuntimeException("Error settting framework debugging: " + e.getMessage(), e);
+ }
+ }
+
+ @Override
+ public String setSystemProperty(String key, String value, boolean persist) {
+ if (persist) {
+ try {
+ String etc = System.getProperty("karaf.etc");
+ Properties props = new Properties(new File(etc, "system.properties"));
+ props.put(key, value);
+ props.save();
+ } catch (IOException e) {
+ throw new RuntimeException("Error persisting system property", e);
+ }
+ }
+ return System.setProperty(key, value);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0a100d76/system/src/main/java/org/apache/karaf/system/internal/osgi/Activator.java
----------------------------------------------------------------------
diff --git a/system/src/main/java/org/apache/karaf/system/internal/osgi/Activator.java b/system/src/main/java/org/apache/karaf/system/internal/osgi/Activator.java
new file mode 100644
index 0000000..b7f8eab
--- /dev/null
+++ b/system/src/main/java/org/apache/karaf/system/internal/osgi/Activator.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.karaf.system.internal.osgi;
+
+import org.apache.karaf.system.SystemService;
+import org.apache.karaf.system.internal.SystemServiceImpl;
+import org.apache.karaf.system.management.internal.SystemMBeanImpl;
+import org.apache.karaf.util.tracker.BaseActivator;
+
+public class Activator extends BaseActivator {
+
+ @Override
+ protected void doStart() throws Exception {
+ SystemServiceImpl systemService = new SystemServiceImpl();
+ systemService.setBundleContext(bundleContext);
+ register(SystemService.class, systemService);
+
+ SystemMBeanImpl mbean = new SystemMBeanImpl();
+ mbean.setBundleContext(bundleContext);
+ mbean.setSystemService(systemService);
+ registerMBean(mbean, "type=system");
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0a100d76/system/src/main/java/org/apache/karaf/system/management/SystemMBean.java
----------------------------------------------------------------------
diff --git a/system/src/main/java/org/apache/karaf/system/management/SystemMBean.java b/system/src/main/java/org/apache/karaf/system/management/SystemMBean.java
new file mode 100644
index 0000000..5d9bdbc
--- /dev/null
+++ b/system/src/main/java/org/apache/karaf/system/management/SystemMBean.java
@@ -0,0 +1,157 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.karaf.system.management;
+
+import javax.management.MBeanException;
+import java.util.Map;
+
+/**
+ * Describe the system MBean.
+ */
+public interface SystemMBean {
+
+ /**
+ * Stop the Karaf instance
+ *
+ * @throws Exception
+ */
+ void halt() throws MBeanException;
+
+ /**
+ * Stop the Karaf instance at a given time.
+ *
+ * @param time the time when to stop the Karaf instance.
+ * @throws Exception
+ */
+ void halt(String time) throws MBeanException;
+
+ /**
+ * Reboot the Karaf instance.
+ *
+ * @throws Exception
+ */
+ void reboot() throws MBeanException;
+
+ /**
+ * Reboot the Karaf instance at a given time.
+ *
+ * @param time the time when to reboot the Karaf instance.
+ * @throws Exception
+ */
+ void reboot(String time) throws MBeanException;
+
+ /**
+ * Reboot the Karaf instance at a given time and clean the cache.
+ *
+ * @param time the time when to reboot the Karaf instance.
+ * @throws Exception
+ */
+ void rebootCleanCache(String time) throws MBeanException;
+
+ /**
+ * Reboot the Karaf instance at a given time and clean all working files.
+ *
+ * @param time the time when to reboot the Karaf instance.
+ * @throws Exception
+ */
+ void rebootCleanAll(String time) throws MBeanException;
+
+ /**
+ * Set the system bundle start level.
+ *
+ * @param startLevel the new system bundle start level.
+ * @throws Exception
+ */
+ void setStartLevel(int startLevel) throws MBeanException;
+
+ /**
+ * Get the current system bundle start level.
+ *
+ * @return the current system bundle start level.
+ * @throws Exception
+ */
+ int getStartLevel() throws MBeanException;
+
+ /**
+ * Get the current OSGi framework in use.
+ *
+ * @return the name of the OSGi framework in use.
+ * @throws Exception
+ */
+ String getFramework();
+
+ /**
+ * change OSGi framework
+ *
+ * @param framework to use.
+ */
+ void setFramework(String framework);
+
+ /**
+ * Enable or diable debgging
+ * @param debug enable if true
+ */
+ void setFrameworkDebug(boolean debug);
+
+ /**
+ * Get the current Karaf instance name.
+ *
+ * @return the current Karaf instance name.
+ */
+ String getName();
+
+ /**
+ * Change Karaf instance name.
+ *
+ * @param name the new Karaf instance name.
+ */
+ void setName(String name);
+
+ /**
+ * Get the version of the current Karaf instance.
+ *
+ * @return the current Karaf instance version.
+ */
+ String getVersion();
+
+ /**
+ * Get all system properties.
+ *
+ * @param unset if true, display the OSGi properties even if they are not defined (with "undef" value).
+ * @param dumpToFile if true, dump the properties into a file in the data folder.
+ * @return the list of system properties.
+ */
+ Map<String, String> getProperties(boolean unset, boolean dumpToFile) throws MBeanException;
+
+ /**
+ * Get the value of a given system property.
+ *
+ * @param key the system property key.
+ * @return the system property value.
+ */
+ String getProperty(String key);
+
+ /**
+ * Set the value of a system property.
+ *
+ * @param key the system property key.
+ * @param value the new system property value.
+ * @param persistent if true, persist the new value to the etc/system.properties file.
+ */
+ void setProperty(String key, String value, boolean persistent);
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0a100d76/system/src/main/java/org/apache/karaf/system/management/internal/SystemMBeanImpl.java
----------------------------------------------------------------------
diff --git a/system/src/main/java/org/apache/karaf/system/management/internal/SystemMBeanImpl.java b/system/src/main/java/org/apache/karaf/system/management/internal/SystemMBeanImpl.java
new file mode 100644
index 0000000..c0f34cd
--- /dev/null
+++ b/system/src/main/java/org/apache/karaf/system/management/internal/SystemMBeanImpl.java
@@ -0,0 +1,259 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.karaf.system.management.internal;
+
+import org.apache.karaf.system.FrameworkType;
+import org.apache.karaf.system.SystemService;
+import org.apache.karaf.system.management.SystemMBean;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+
+import javax.management.MBeanException;
+import javax.management.NotCompliantMBeanException;
+import javax.management.StandardMBean;
+import java.io.File;
+import java.io.PrintStream;
+import java.text.SimpleDateFormat;
+import java.util.*;
+
+/**
+ * System MBean implementation.
+ */
+public class SystemMBeanImpl extends StandardMBean implements SystemMBean {
+
+ private SystemService systemService;
+ private BundleContext bundleContext;
+
+ public void setBundleContext(BundleContext bundleContext) {
+ this.bundleContext = bundleContext;
+ }
+
+ public SystemMBeanImpl() throws NotCompliantMBeanException {
+ super(SystemMBean.class);
+ }
+
+ public void setSystemService(SystemService systemService) {
+ this.systemService = systemService;
+ }
+
+ public SystemService getSystemService() {
+ return this.systemService;
+ }
+
+ public void halt() throws MBeanException {
+ try {
+ systemService.halt();
+ } catch (Exception e) {
+ throw new MBeanException(null, e.getMessage());
+ }
+ }
+
+ public void halt(String time) throws MBeanException {
+ try {
+ systemService.halt(time);
+ } catch (Exception e) {
+ throw new MBeanException(null, e.getMessage());
+ }
+ }
+
+ public void reboot() throws MBeanException {
+ try {
+ systemService.reboot();
+ } catch (Exception e) {
+ throw new MBeanException(null, e.getMessage());
+ }
+ }
+
+ public void reboot(String time) throws MBeanException {
+ try {
+ systemService.reboot(time, SystemService.Swipe.NONE);
+ } catch (Exception e) {
+ throw new MBeanException(null, e.getMessage());
+ }
+ }
+
+ public void rebootCleanCache(String time) throws MBeanException {
+ try {
+ systemService.reboot(time, SystemService.Swipe.CACHE);
+ } catch (Exception e) {
+ throw new MBeanException(null, e.getMessage());
+ }
+ }
+
+ public void rebootCleanAll(String time) throws MBeanException {
+ try {
+ systemService.reboot(time, SystemService.Swipe.ALL);
+ } catch (Exception e) {
+ throw new MBeanException(null, e.getMessage());
+ }
+ }
+
+ public void setStartLevel(int startLevel) throws MBeanException {
+ try {
+ systemService.setStartLevel(startLevel);
+ } catch (Exception e) {
+ throw new MBeanException(null, e.getMessage());
+ }
+ }
+
+ public int getStartLevel() throws MBeanException {
+ try {
+ return systemService.getStartLevel();
+ } catch (Exception e) {
+ throw new MBeanException(null, e.getMessage());
+ }
+ }
+
+ @Override
+ public String getFramework() {
+ return this.systemService.getFramework().toString();
+ }
+
+ @Override
+ public void setFramework(String framework) {
+ this.systemService.setFramework(FrameworkType.valueOf(framework.toLowerCase()));
+ }
+
+ @Override
+ public void setFrameworkDebug(boolean debug) {
+ this.systemService.setFrameworkDebug(debug);
+ }
+
+ @Override
+ public String getName() {
+ return this.systemService.getName();
+ }
+
+ @Override
+ public void setName(String name) {
+ if (name == null || name.trim().isEmpty()) {
+ throw new IllegalArgumentException("Instance name can't be null or empty");
+ }
+ this.systemService.setName(name);
+ }
+
+ @Override
+ public String getVersion() {
+ return this.systemService.getVersion();
+ }
+
+ @Override
+ public Map<String, String> getProperties(boolean unset, boolean dumpToFile) throws MBeanException {
+ try {
+ Map<String, String> result = new HashMap<String, String>();
+
+ Properties props = (Properties) java.lang.System.getProperties().clone();
+
+ String def = null;
+ if (unset) {
+ def = "unset";
+ }
+
+ setProperty(props, Constants.FRAMEWORK_BEGINNING_STARTLEVEL, def);
+ setProperty(props, Constants.FRAMEWORK_BOOTDELEGATION, def);
+ setProperty(props, Constants.FRAMEWORK_BUNDLE_PARENT, def);
+ setProperty(props, Constants.FRAMEWORK_BUNDLE_PARENT_APP, def);
+ setProperty(props, Constants.FRAMEWORK_BUNDLE_PARENT_BOOT, def);
+ setProperty(props, Constants.FRAMEWORK_BUNDLE_PARENT_EXT, def);
+ setProperty(props, Constants.FRAMEWORK_BUNDLE_PARENT_FRAMEWORK, def);
+ setProperty(props, Constants.FRAMEWORK_EXECPERMISSION, def);
+ setProperty(props, Constants.FRAMEWORK_EXECUTIONENVIRONMENT, def);
+ setProperty(props, Constants.FRAMEWORK_LANGUAGE, def);
+ setProperty(props, Constants.FRAMEWORK_LIBRARY_EXTENSIONS, def);
+ setProperty(props, Constants.FRAMEWORK_OS_NAME, def);
+ setProperty(props, Constants.FRAMEWORK_OS_VERSION, def);
+ setProperty(props, Constants.FRAMEWORK_PROCESSOR, def);
+ setProperty(props, Constants.FRAMEWORK_SECURITY, def);
+ setProperty(props, Constants.FRAMEWORK_SECURITY_OSGI, def);
+ setProperty(props, Constants.FRAMEWORK_STORAGE, def);
+ setProperty(props, Constants.FRAMEWORK_STORAGE_CLEAN_ONFIRSTINIT, def);
+ setProperty(props, Constants.FRAMEWORK_SYSTEMPACKAGES, def);
+ setProperty(props, Constants.FRAMEWORK_SYSTEMPACKAGES_EXTRA, def);
+ setProperty(props, Constants.FRAMEWORK_VENDOR, def);
+ setProperty(props, Constants.FRAMEWORK_VERSION, def);
+ setProperty(props, Constants.FRAMEWORK_WINDOWSYSTEM, def);
+
+ setProperty(props, Constants.SUPPORTS_BOOTCLASSPATH_EXTENSION, def);
+ setProperty(props, Constants.SUPPORTS_FRAMEWORK_EXTENSION, def);
+ setProperty(props, Constants.SUPPORTS_FRAMEWORK_FRAGMENT, def);
+ setProperty(props, Constants.SUPPORTS_FRAMEWORK_REQUIREBUNDLE, def);
+
+ if (dumpToFile) {
+ PrintStream ps = new PrintStream(new File(bundleContext.getProperty("karaf.data"), "dump-properties-" + java.lang.System.currentTimeMillis() + ".properties"));
+ ps.println("#Dump of the System and OSGi properties");
+ ps.println("#Dump executed at " + new SimpleDateFormat().format(new Date()));
+ printOrderedProperties(props, ps);
+ ps.flush();
+ ps.close();
+ } else {
+ printOrderedProperties(props, result);
+ }
+
+ return result;
+ } catch (Exception e) {
+ throw new MBeanException(null, e.getMessage());
+ }
+ }
+
+ private void printOrderedProperties(Properties props, PrintStream out) {
+ Set<Object> keys = props.keySet();
+ Vector<String> order = new Vector<String>(keys.size());
+ for (Iterator<Object> i = keys.iterator(); i.hasNext(); ) {
+ Object str = (Object) i.next();
+ order.add((String) str);
+ }
+ Collections.sort(order);
+ for (Iterator<String> i = order.iterator(); i.hasNext(); ) {
+ String key = (String) i.next();
+ out.println(key + "=" + props.getProperty(key));
+ }
+ }
+
+ private void printOrderedProperties(Properties props, Map<String, String> result) {
+ Set<Object> keys = props.keySet();
+ Vector<String> order = new Vector<String>(keys.size());
+ for (Iterator<Object> i = keys.iterator(); i.hasNext(); ) {
+ Object str = (Object) i.next();
+ order.add((String) str);
+ }
+ Collections.sort(order);
+ for (Iterator<String> i = order.iterator(); i.hasNext(); ) {
+ String key = (String) i.next();
+ result.put(key, props.getProperty(key));
+ }
+ }
+
+ private void setProperty(Properties props, String key, String def) {
+ String val = bundleContext.getProperty(key);
+ if (val == null && def != null) {
+ props.setProperty(key, def);
+ } else if (val != null) {
+ props.setProperty(key, val);
+ }
+ }
+
+ @Override
+ public String getProperty(String key) {
+ return java.lang.System.getProperty(key);
+ }
+
+ @Override
+ public void setProperty(String key, String value, boolean persistent) {
+ systemService.setSystemProperty(key, value, persistent);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0a100d76/system/src/main/resources/OSGI-INF/bundle.info
----------------------------------------------------------------------
diff --git a/system/src/main/resources/OSGI-INF/bundle.info b/system/src/main/resources/OSGI-INF/bundle.info
new file mode 100644
index 0000000..acca1c8
--- /dev/null
+++ b/system/src/main/resources/OSGI-INF/bundle.info
@@ -0,0 +1,16 @@
+h1. Synopsis
+
+${project.name}
+
+${project.description}
+
+Maven URL:
+[mvn:${project.groupId}/${project.artifactId}/${project.version}]
+
+h1. Description
+
+This bundle provides support of the system service, which control the Karaf container.
+
+h1. See also
+
+Shutdown - section of the Karaf User Guide
http://git-wip-us.apache.org/repos/asf/karaf/blob/0a100d76/system/src/test/java/org/apache/karaf/system/internal/SystemServiceImplTest.java
----------------------------------------------------------------------
diff --git a/system/src/test/java/org/apache/karaf/system/internal/SystemServiceImplTest.java b/system/src/test/java/org/apache/karaf/system/internal/SystemServiceImplTest.java
new file mode 100644
index 0000000..2de4e1e
--- /dev/null
+++ b/system/src/test/java/org/apache/karaf/system/internal/SystemServiceImplTest.java
@@ -0,0 +1,53 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package org.apache.karaf.system.internal;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.net.URL;
+
+import org.apache.felix.utils.properties.Properties;
+import org.easymock.EasyMock;
+import org.junit.Assert;
+import org.junit.Test;
+import org.osgi.framework.BundleContext;
+
+/**
+ * Implementation of the system service.
+ */
+
+public class SystemServiceImplTest {
+
+ private static final String NEW_NAME = "newName";
+
+ @Test
+ public void testSetName() throws URISyntaxException, IOException {
+ SystemServiceImpl system = new SystemServiceImpl();
+ BundleContext bundleContext = EasyMock.createMock(BundleContext.class);
+ URL propUrl = this.getClass().getClassLoader().getResource("etc/system.properties");
+ File propfile = new File(propUrl.toURI());
+ EasyMock.expect(bundleContext.getProperty("karaf.etc")).andReturn(propfile.getParentFile().getParent() + "/etc");
+ EasyMock.replay(bundleContext);
+ system.setBundleContext(bundleContext);
+ system.setName(NEW_NAME);
+ EasyMock.verify(bundleContext);
+ Properties props = new Properties(propfile);
+ String nameAfter = props.getProperty("karaf.name");
+ Assert.assertEquals(NEW_NAME, nameAfter);
+ }
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0a100d76/system/src/test/resources/etc/system.properties
----------------------------------------------------------------------
diff --git a/system/src/test/resources/etc/system.properties b/system/src/test/resources/etc/system.properties
new file mode 100644
index 0000000..6749fbb
--- /dev/null
+++ b/system/src/test/resources/etc/system.properties
@@ -0,0 +1,22 @@
+################################################################################
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+#Comment
+karaf.name=oldName
+#Comment2