FELIX-1914: Add a command to enable debug logging for the OSGi framework

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@887538 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/karaf/shell/dev/src/main/java/org/apache/felix/karaf/shell/dev/FrameworkDebug.java b/karaf/shell/dev/src/main/java/org/apache/felix/karaf/shell/dev/FrameworkDebug.java
new file mode 100644
index 0000000..7413c91
--- /dev/null
+++ b/karaf/shell/dev/src/main/java/org/apache/felix/karaf/shell/dev/FrameworkDebug.java
@@ -0,0 +1,71 @@
+/*
+ * 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.felix.karaf.shell.dev;
+
+import java.io.File;
+
+import org.apache.felix.gogo.commands.Command;
+import org.apache.felix.gogo.commands.Option;
+import org.apache.felix.karaf.shell.console.OsgiCommandSupport;
+import org.apache.felix.karaf.shell.dev.framework.Equinox;
+import org.apache.felix.karaf.shell.dev.framework.Felix;
+import org.apache.felix.karaf.shell.dev.framework.Framework;
+
+/**
+ * Command for enabling/disabling debug logging on the OSGi framework
+ */
+@Command(scope = "dev", name = "framework",
+         description = "Enable/disable debugging for the OSGi Framework")
+public class FrameworkDebug extends OsgiCommandSupport {
+
+    private static final String KARAF_BASE = System.getProperty("karaf.base");
+
+    @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;
+
+    @Override
+    protected Object doExecute() throws Exception {
+        Framework framework = getFramework();
+
+        if (!debug^nodebug) {
+            System.err.printf("Required option missing: use -debug or -nodebug%n");
+            return null;
+        }
+        if (debug) {
+            System.out.printf("Enabling debug for OSGi framework (%s)%n", framework.getName());
+            framework.enableDebug(new File(KARAF_BASE));
+        }
+        if (nodebug) {
+            System.out.printf("Disabling debug for OSGi framework (%s)%n", framework.getName());
+            framework.disableDebug(new File(KARAF_BASE));
+        }
+
+        return null;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+
+    public Framework getFramework() {
+        if (bundleContext.getBundle(0).getSymbolicName().contains("felix")) {
+            return new Felix(new File(KARAF_BASE));
+        } else {
+            return new Equinox(new File(KARAF_BASE));
+        }
+    }
+}
diff --git a/karaf/shell/dev/src/main/java/org/apache/felix/karaf/shell/dev/framework/Equinox.java b/karaf/shell/dev/src/main/java/org/apache/felix/karaf/shell/dev/framework/Equinox.java
new file mode 100644
index 0000000..288697b
--- /dev/null
+++ b/karaf/shell/dev/src/main/java/org/apache/felix/karaf/shell/dev/framework/Equinox.java
@@ -0,0 +1,69 @@
+/*
+ * 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.felix.karaf.shell.dev.framework;
+
+import java.io.File;
+import java.io.IOException;
+
+import org.apache.felix.karaf.shell.dev.util.IO;
+
+/**
+ * Represents Eclipse's Equinox as the underlying OSGi framework
+ */
+public class Equinox extends Framework {
+
+    /**
+     * Create a new instance
+     *
+     * @param base 
+     */
+    public Equinox(File base) {
+        super(base);
+    }
+
+    public String getName() {
+        return "Equinox";
+    }
+
+    public void enableDebug(File directory) throws IOException {
+        setConfigProperty("osgi.debug", "etc/equinox-debug.properties");
+        saveConfigProperties();
+
+        System.out.printf("- set osgi.debug=etc/equinox-debug.properties in etc/config.properties%n");
+
+        File debug = new File(directory, "etc/equinox-debug.properties");
+        if (!debug.exists()) {
+            IO.copyTextToFile(
+                    Equinox.class.getResourceAsStream("equinox-debug.properties"),
+                    debug);
+            System.out.printf("- created etc/equinox-debug.properties to configure Equinox debugging options%n");
+        }
+
+        System.out.printf("%nEnable specific debug options in etc/equinox-debug.properties%n");
+        System.out.printf("and restart Karaf now to enable Equinox debug logging%n");
+    }
+
+    @Override
+    public void disableDebug(File directory) throws IOException {
+        removeConfigProperty("osgi.debug");
+        saveConfigProperties();
+        
+        System.out.printf("- removed osgi.debug from etc/config.properties%n%n");
+        System.out.printf("Restart Karaf now to disable Equinox debug logging%n");
+
+    }
+}
diff --git a/karaf/shell/dev/src/main/java/org/apache/felix/karaf/shell/dev/framework/Felix.java b/karaf/shell/dev/src/main/java/org/apache/felix/karaf/shell/dev/framework/Felix.java
new file mode 100644
index 0000000..ff5c6a9
--- /dev/null
+++ b/karaf/shell/dev/src/main/java/org/apache/felix/karaf/shell/dev/framework/Felix.java
@@ -0,0 +1,55 @@
+/*
+ * 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.felix.karaf.shell.dev.framework;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * Represents Apache Felix as the underlying OSGi platform
+ */
+public class Felix extends Framework {
+
+    /**
+     * Create a instance of Karaf running with Felix in the given base directory
+     *
+     * @param base the base directory
+     */
+    public Felix(File base) {
+        super(base);
+    }
+
+    public String getName() {
+        return "Felix";
+    }
+
+    public void enableDebug(File directory) throws IOException {
+        setConfigProperty("felix.log.level", "4");
+        saveConfigProperties();
+        
+        System.out.printf("- set felix.log.level=4 in etc/config.properties%n%n");
+        System.out.printf("Restart Karaf now to enable Felix debug logging%n");
+    }
+
+    public void disableDebug(File directory) throws IOException {
+        removeConfigProperty("felix.log.level");
+        saveConfigProperties();
+
+        System.out.printf("- removed felix.log.level from etc/config.properties%n%n");
+        System.out.printf("Restart Karaf now to disable Felix debug logging%n");
+    }
+}
diff --git a/karaf/shell/dev/src/main/java/org/apache/felix/karaf/shell/dev/framework/Framework.java b/karaf/shell/dev/src/main/java/org/apache/felix/karaf/shell/dev/framework/Framework.java
new file mode 100644
index 0000000..e930549
--- /dev/null
+++ b/karaf/shell/dev/src/main/java/org/apache/felix/karaf/shell/dev/framework/Framework.java
@@ -0,0 +1,154 @@
+/*
+ * 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.felix.karaf.shell.dev.framework;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.Date;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * Class to represent the underlying OSGi framework
+ */
+public abstract class Framework {
+
+    /*
+     * The Karaf base directory
+     */
+    private File base;
+
+    /*
+     * The contents of the etc/config.properties file
+     */
+    private List<String> config;
+
+    /**
+     * Create a instance of this framework in the given base directory
+     *
+     * @param base the base directory
+     */
+    public Framework(File base) {
+        super();
+        this.base = base;
+    }
+
+    /**
+     * Get the underlying OSGi framework name
+     */
+    public abstract String getName();
+
+    /**
+     * Enable the OSGi framework's debug logging
+     *
+     * @param directory the directory containing the Karaf installation
+     * @throws IOException when a problem occurs configuring debug settings
+     */
+    public abstract void enableDebug(File directory) throws IOException;
+
+    /**
+     * Disable the OSGI framework's debug logging
+     *
+     * @param directory the Karaf base installation directory
+     * @throws IOException when a problem occurs removing debug configuration settings
+     */
+    public abstract void disableDebug(File directory) throws IOException;
+
+    /*
+     * Save the etc/config.properties file
+     */
+    protected void saveConfigProperties() throws IOException {
+        PrintWriter writer = null;
+        try {
+            writer = new PrintWriter(new File(base, "etc/config.properties"));
+            for (String line : getConfig()) {
+                writer.printf("%s%n", line);
+            }
+            writer.flush();
+            writer.close();
+        } finally {
+            if (writer != null) {
+                writer.close();
+            }
+        }
+    }
+
+    protected List<String> readPropertyFile(File config) throws IOException {
+        List<String> result = new LinkedList<String>();
+        BufferedReader reader = new BufferedReader(new FileReader(config));
+        String line = reader.readLine();
+        while (line != null) {
+            result.add(line);
+            line = reader.readLine();
+        }
+        return result;
+    }
+
+    /**
+     * Set a new key and value in the etc/config.properties - if the given key
+     * already exists, the existing value will be overwritten
+     *
+     * @param key property key
+     * @param value property value
+     * @throws IOException if the etc/config.properties file can not be read
+     */
+    protected void setConfigProperty(String key, String value) throws IOException {
+        boolean done = false;
+
+        for (int i = 0 ; i < getConfig().size() ; i++) {
+            if (getConfig().get(i).startsWith(key)) {
+                getConfig().set(i, java.lang.String.format("%s=%s", key, value));
+                done = true;
+            }
+        }
+
+        if (!done) {
+            getConfig().add("");
+            getConfig().add(java.lang.String.format("%s=%s", key, value, new Date()));
+        }
+    }
+
+    /**
+     * Remove an existing key from the etc/config.properties file
+     *
+     * @param key the key
+     * @throws IOException if the etc/config.properties file can not be read
+     */
+    protected void removeConfigProperty(String key) throws IOException {
+        for (int i = 0 ; i < getConfig().size() ; i++) {
+            if (getConfig().get(i).startsWith(key)) {
+                getConfig().remove(i);
+            }
+        }
+    }
+
+    /**
+     * Access the contents of the etc/config.properties file
+     *
+     * @return the contents of the file
+     * @throws IOException if the etc/config.properties file can not be read
+     */
+    public List<String> getConfig() throws IOException {
+        if (config == null) {
+            config = readPropertyFile(new File(base, "etc/config.properties"));
+        }
+        return config;
+    }
+}
diff --git a/karaf/shell/dev/src/main/java/org/apache/felix/karaf/shell/dev/util/IO.java b/karaf/shell/dev/src/main/java/org/apache/felix/karaf/shell/dev/util/IO.java
new file mode 100644
index 0000000..15f5f45
--- /dev/null
+++ b/karaf/shell/dev/src/main/java/org/apache/felix/karaf/shell/dev/util/IO.java
@@ -0,0 +1,58 @@
+/*
+ * 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.felix.karaf.shell.dev.util;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.PrintWriter;
+import java.util.Scanner;
+
+/**
+ * Helper class for I/O operations
+ */
+public class IO {
+
+    /**
+     * Write text from an InputStream to a file
+     */
+    public static void copyTextToFile(InputStream stream, File file) throws IOException {
+        PrintWriter writer = null;
+        Scanner scanner = null;
+
+        try {
+            scanner = new Scanner(stream);
+            writer = new PrintWriter(file);
+
+            while (scanner.hasNextLine()) {
+                writer.printf("%s%n", scanner.nextLine());
+            }
+
+            writer.flush();
+        } finally {
+            if (scanner != null) {
+                scanner.close();
+            }
+            if (writer != null) {
+                writer.close();
+            }
+        }
+    }
+}
diff --git a/karaf/shell/dev/src/main/resources/OSGI-INF/blueprint/shell-dev.xml b/karaf/shell/dev/src/main/resources/OSGI-INF/blueprint/shell-dev.xml
index a695b7a..2dd7d28 100644
--- a/karaf/shell/dev/src/main/resources/OSGI-INF/blueprint/shell-dev.xml
+++ b/karaf/shell/dev/src/main/resources/OSGI-INF/blueprint/shell-dev.xml
@@ -23,6 +23,9 @@
         <command name="dev/show-tree">
             <action class="org.apache.felix.karaf.shell.dev.ShowBundleTree"/>
         </command>
+        <command name="dev/framework">
+            <action class="org.apache.felix.karaf.shell.dev.FrameworkDebug" />
+        </command>
     </command-bundle>
 
 </blueprint>
diff --git a/karaf/shell/dev/src/main/resources/org/apache/felix/karaf/shell/dev/framework/equinox-debug.properties b/karaf/shell/dev/src/main/resources/org/apache/felix/karaf/shell/dev/framework/equinox-debug.properties
new file mode 100644
index 0000000..b842875
--- /dev/null
+++ b/karaf/shell/dev/src/main/resources/org/apache/felix/karaf/shell/dev/framework/equinox-debug.properties
@@ -0,0 +1,111 @@
+# 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.
+
+
+#### Debugging options for org.eclipse.osgi
+
+# Turn on general debugging for org.eclipse.osgi
+org.eclipse.osgi/debug=false
+# Prints out class loading debug information
+org.eclipse.osgi/debug/loader=false
+# Prints out event (FrameworkEvent/BundleEvent/ServiceEvent) and listener debug information
+org.eclipse.osgi/debug/events=false
+# Prints out OSGi service debug information (registration/getting/ungetting etc.)
+org.eclipse.osgi/debug/services=false
+# Prints out bundle manifest parsing debug information
+org.eclipse.osgi/debug/manifest=false
+# Prints out LDAP filter debug information
+org.eclipse.osgi/debug/filter=false
+# Prints out security (PermissionAdmin service) debug information
+org.eclipse.osgi/debug/security=false
+# Prints out start level service debug information
+org.eclipse.osgi/debug/startlevel=false
+# Prints out package admin service debug information
+org.eclipse.osgi/debug/packageadmin=false
+# Prints out timing information for bundle activation
+org.eclipse.osgi/debug/bundleTime=false
+# Debug the loading of message bundles
+org.eclipse.osgi/debug/messageBundles=false
+
+# Eclipse adaptor options
+org.eclipse.osgi/eclipseadaptor/debug = false
+org.eclipse.osgi/eclipseadaptor/debug/location = false
+org.eclipse.osgi/eclipseadaptor/debug/platformadmin=false
+org.eclipse.osgi/eclipseadaptor/debug/platformadmin/resolver=false
+org.eclipse.osgi/eclipseadaptor/converter/debug = false
+
+### OSGi resolver options
+# Turns on debugging for the resolver
+org.eclipse.osgi/resolver/debug = false
+# Prints out wiring information after the resolver has completed the resolve process
+org.eclipse.osgi/resolver/wiring = false
+# Prints out Import-Package information
+org.eclipse.osgi/resolver/imports = false
+# Prints out Require-Bundle information
+org.eclipse.osgi/resolver/requires = false
+# Prints out package grouping information form the "uses" clause
+org.eclipse.osgi/resolver/grouping = false
+# Prints out cycle information
+org.eclipse.osgi/resolver/cycles = false
+# Prints out Eclipse-GenericRequire information
+org.eclipse.osgi/resolver/generics = false
+
+#### Profile settings
+org.eclipse.osgi/profile/startup = false
+org.eclipse.osgi/profile/benchmark = false
+org.eclipse.osgi/profile/debug = false
+
+# Override the default implemenation 
+org.eclipse.osgi/profile/impl = org.eclipse.osgi.internal.profile.DefaultProfileLogger
+
+# Append all profile messages to the filename specified
+org.eclipse.osgi/defaultprofile/logfilename =  
+
+# Output all profile log messages synchronously to the jvm console.
+# By default, all log messages are cached until the log buffer is
+# requested.
+org.eclipse.osgi/defaultprofile/logsynchronously = false
+
+# Specify the size of the default profile implementation log buffer.
+org.eclipse.osgi/defaultprofile/buffersize = 256
+
+#### Monitoring settings
+# monitor class loading
+org.eclipse.osgi/monitor/classes=false
+
+# monitor bundle activation
+org.eclipse.osgi/monitor/activation=false
+
+# monitor resource bundle (*.properties) loading
+org.eclipse.osgi/monitor/resources=false
+
+
+#### Trace settings
+# trace class loading - snapshot the execution stack when a class is loaded
+org.eclipse.osgi/trace/classLoading=false
+
+# trace location - file in which execution traces are written
+org.eclipse.osgi/trace/filename=runtime.traces
+
+# trace filters - Java properties file defining which classes should 
+# be traced (if trace/classLoading is true)
+# File format:
+# plugins=<comma separated list of plugins whose classes to trace>
+# packages=<comma separated list of package prefixes of classes to trace>
+# Note that there may be many 'plugins' and 'packages' lines in one file.
+org.eclipse.osgi/trace/filters=trace.properties
+
+# trace bundle activation - snapshot the execution stack when a bundle is activated
+org.eclipse.osgi/trace/activation=false
diff --git a/karaf/shell/dev/src/test/java/org/apache/felix/karaf/shell/dev/framework/EquinoxTest.java b/karaf/shell/dev/src/test/java/org/apache/felix/karaf/shell/dev/framework/EquinoxTest.java
new file mode 100644
index 0000000..85ea42c
--- /dev/null
+++ b/karaf/shell/dev/src/test/java/org/apache/felix/karaf/shell/dev/framework/EquinoxTest.java
@@ -0,0 +1,82 @@
+/*
+ * 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.felix.karaf.shell.dev.framework;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.Properties;
+
+import org.apache.felix.karaf.shell.dev.util.IO;
+import static org.junit.Assert.*;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Test cases for {@link org.apache.felix.karaf.shell.dev.framework.Equinox}
+ */
+public class EquinoxTest {
+
+    private File base;
+    private File etc;
+
+    private Equinox equinox;
+
+    @Before
+    public void setUp() {
+        // creating a dummy karaf instance folder
+        base = new File("target/instances/" + System.currentTimeMillis());
+        base.mkdirs();
+
+        // make sure the etc directory exists
+        etc = new File(base, "etc");
+        etc.mkdirs();
+
+        equinox = new Equinox(base);
+    }
+
+    @Test
+    public void enableDebug() throws IOException {
+        IO.copyTextToFile(
+                EquinoxTest.class.getResourceAsStream("config.properties"),
+                new File(etc, "config.properties"));
+
+        equinox.enableDebug(base);
+
+        Properties properties = new Properties();
+        properties.load(new FileInputStream(new File(base, "etc/config.properties")));
+        assertNotNull(properties.get("osgi.debug"));
+        assertEquals("etc/equinox-debug.properties", properties.get("osgi.debug"));
+
+        assertTrue("Should have created the default Equinox debug config file",
+                   new File(etc, "equinox-debug.properties").exists());
+    }
+
+    @Test
+    public void testDisableDebug() throws IOException {
+        IO.copyTextToFile(
+                EquinoxTest.class.getResourceAsStream("enabled-config.properties"),
+                new File(etc, "config.properties"));
+
+        equinox.disableDebug(base);
+
+        Properties properties = new Properties();
+        properties.load(new FileInputStream(new File(etc, "config.properties")));
+        assertFalse("osgi.debug property should have been removed from the file",
+                    properties.containsKey("osgi.debug"));
+    }
+}
diff --git a/karaf/shell/dev/src/test/java/org/apache/felix/karaf/shell/dev/framework/FelixTest.java b/karaf/shell/dev/src/test/java/org/apache/felix/karaf/shell/dev/framework/FelixTest.java
new file mode 100644
index 0000000..399777b
--- /dev/null
+++ b/karaf/shell/dev/src/test/java/org/apache/felix/karaf/shell/dev/framework/FelixTest.java
@@ -0,0 +1,78 @@
+/*
+ * 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.felix.karaf.shell.dev.framework;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.Properties;
+
+import org.apache.felix.karaf.shell.dev.util.IO;
+import static org.junit.Assert.*;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Test cases for {@link org.apache.felix.karaf.shell.dev.framework.Felix}
+ */
+public class FelixTest {
+
+    private File base;
+    private File etc;
+    
+    private Felix felix;
+
+    @Before
+    public void setUp() {
+        // creating a dummy karaf instance folder
+        base = new File("target/instances/" + System.currentTimeMillis());
+        base.mkdirs();
+
+        // make sure the etc directory exists
+        etc = new File(base, "etc");
+        etc.mkdirs();
+
+        felix = new Felix(base);
+    }
+
+    @Test
+    public void enableDebug() throws IOException {
+        IO.copyTextToFile(
+                FelixTest.class.getResourceAsStream("config.properties"),
+                new File(etc, "config.properties"));
+
+        felix.enableDebug(base);
+
+        Properties properties = new Properties();
+        properties.load(new FileInputStream(new File(etc, "config.properties")));
+        assertNotNull(properties.get("felix.log.level"));
+        assertEquals("4", properties.get("felix.log.level"));
+    }
+
+    @Test
+    public void testDisableDebug() throws IOException {
+        IO.copyTextToFile(
+                FelixTest.class.getResourceAsStream("enabled-config.properties"),
+                new File(etc, "config.properties"));
+
+        felix.disableDebug(base);
+
+        Properties properties = new Properties();
+        properties.load(new FileInputStream(new File(etc, "config.properties")));
+        assertFalse(properties.containsKey("felix.log.level"));
+    }
+}
diff --git a/karaf/shell/dev/src/test/resources/org/apache/felix/karaf/shell/dev/framework/config.properties b/karaf/shell/dev/src/test/resources/org/apache/felix/karaf/shell/dev/framework/config.properties
new file mode 100644
index 0000000..5cc8009
--- /dev/null
+++ b/karaf/shell/dev/src/test/resources/org/apache/felix/karaf/shell/dev/framework/config.properties
@@ -0,0 +1,351 @@
+################################################################################
+#
+#    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.
+#
+################################################################################
+
+#
+# Framework selection properties
+#
+karaf.framework=felix
+
+karaf.framework.equinox=${karaf.default.repository}/org/eclipse/osgi/${equinox.version}/osgi-${equinox.version}.jar
+karaf.framework.felix=${karaf.default.repository}/org/apache/felix/org.apache.felix.framework/${felix.framework.version}/org.apache.felix.framework-${felix.framework.version}.jar
+
+#
+# Framework config properties.
+#
+org.osgi.framework.system.packages=org.osgi.framework; version=1.5.0, \
+ org.osgi.framework.launch; version=1.0.0, \
+ org.osgi.framework.hooks.service; version=1.0.0, \
+ org.osgi.service.packageadmin; version=1.2.0, \
+ org.osgi.service.startlevel; version=1.1.0, \
+ org.osgi.service.url; version=1.0.0, \
+ org.osgi.util.tracker; version=1.4.0 \
+ ${jre-${java.specification.version}}
+
+org.osgi.framework.system.packages.extra=\
+ org.apache.felix.karaf.jaas.boot; version=${karaf.osgi.version}, \
+ org.apache.felix.karaf.version; version=${karaf.osgi.version}
+
+# javax.transaction is needed to avoid class loader constraint violation when using javax.sql  
+org.osgi.framework.bootdelegation=sun.*,com.sun.*,javax.transaction,javax.transaction.*
+
+# To enable the use of the startup.properties file to control the start level:
+karaf.auto.start=startup.properties
+#felix.auto.start=all
+
+org.osgi.framework.startlevel.beginning=100
+karaf.startlevel.bundle=60
+
+#
+# FileMonitor properties
+#
+felix.fileinstall.dir    = ${karaf.base}/etc
+felix.fileinstall.filter = .*\\.cfg
+felix.fileinstall.poll   = 1000
+felix.fileinstall.noInitialDelay = true
+
+#
+# Java platform package export properties.
+#
+
+# Standard package set.  Note that:
+#   - javax.transaction* is exported with a mandatory attribute 
+jre-1.5=, \
+ javax.accessibility, \
+ javax.activity, \
+ javax.crypto, \
+ javax.crypto.interfaces, \
+ javax.crypto.spec, \
+ javax.imageio, \
+ javax.imageio.event, \
+ javax.imageio.metadata, \
+ javax.imageio.plugins.bmp, \
+ javax.imageio.plugins.jpeg, \
+ javax.imageio.spi, \
+ javax.imageio.stream, \
+ javax.management, \
+ javax.management.loading, \
+ javax.management.modelmbean, \
+ javax.management.monitor, \
+ javax.management.openmbean, \
+ javax.management.relation, \
+ javax.management.remote, \
+ javax.management.remote.rmi, \
+ javax.management.timer, \
+ javax.naming, \
+ javax.naming.directory, \
+ javax.naming.event, \
+ javax.naming.ldap, \
+ javax.naming.spi, \
+ javax.net, \
+ javax.net.ssl, \
+ javax.print, \
+ javax.print.attribute, \
+ javax.print.attribute.standard, \
+ javax.print.event, \
+ javax.rmi, \
+ javax.rmi.CORBA, \
+ javax.rmi.ssl, \
+ javax.security.auth, \
+ javax.security.auth.callback, \
+ javax.security.auth.kerberos, \
+ javax.security.auth.login, \
+ javax.security.auth.spi, \
+ javax.security.auth.x500, \
+ javax.security.cert, \
+ javax.security.sasl, \
+ javax.sound.midi, \
+ javax.sound.midi.spi, \
+ javax.sound.sampled, \
+ javax.sound.sampled.spi, \
+ javax.sql, \
+ javax.sql.rowset, \
+ javax.sql.rowset.serial, \
+ javax.sql.rowset.spi, \
+ javax.swing, \
+ javax.swing.border, \
+ javax.swing.colorchooser, \
+ javax.swing.event, \
+ javax.swing.filechooser, \
+ javax.swing.plaf, \
+ javax.swing.plaf.basic, \
+ javax.swing.plaf.metal, \
+ javax.swing.plaf.multi, \
+ javax.swing.plaf.synth, \
+ javax.swing.table, \
+ javax.swing.text, \
+ javax.swing.text.html, \
+ javax.swing.text.html.parser, \
+ javax.swing.text.rtf, \
+ javax.swing.tree, \
+ javax.swing.undo, \
+ javax.transaction; javax.transaction.xa; partial=true; mandatory:=partial, \
+ javax.xml, \
+ javax.xml.datatype, \
+ javax.xml.namespace, \
+ javax.xml.parsers, \
+ javax.xml.transform, \
+ javax.xml.transform.dom, \
+ javax.xml.transform.sax, \
+ javax.xml.transform.stream, \
+ javax.xml.validation, \
+ javax.xml.xpath, \
+ org.ietf.jgss, \
+ org.omg.CORBA, \
+ org.omg.CORBA_2_3, \
+ org.omg.CORBA_2_3.portable, \
+ org.omg.CORBA.DynAnyPackage, \
+ org.omg.CORBA.ORBPackage, \
+ org.omg.CORBA.portable, \
+ org.omg.CORBA.TypeCodePackage, \
+ org.omg.CosNaming, \
+ org.omg.CosNaming.NamingContextExtPackage, \
+ org.omg.CosNaming.NamingContextPackage, \
+ org.omg.Dynamic, \
+ org.omg.DynamicAny, \
+ org.omg.DynamicAny.DynAnyFactoryPackage, \
+ org.omg.DynamicAny.DynAnyPackage, \
+ org.omg.IOP, \
+ org.omg.IOP.CodecFactoryPackage, \
+ org.omg.IOP.CodecPackage, \
+ org.omg.Messaging, \
+ org.omg.PortableInterceptor, \
+ org.omg.PortableInterceptor.ORBInitInfoPackage, \
+ org.omg.PortableServer, \
+ org.omg.PortableServer.CurrentPackage, \
+ org.omg.PortableServer.POAManagerPackage, \
+ org.omg.PortableServer.POAPackage, \
+ org.omg.PortableServer.portable, \
+ org.omg.PortableServer.ServantLocatorPackage, \
+ org.omg.SendingContext, \
+ org.omg.stub.java.rmi, \
+ org.omg.stub.javax.management.remote.rmi, \
+ org.w3c.dom, \
+ org.w3c.dom.bootstrap, \
+ org.w3c.dom.css, \
+ org.w3c.dom.events, \
+ org.w3c.dom.html, \
+ org.w3c.dom.ls, \
+ org.w3c.dom.ranges, \
+ org.w3c.dom.stylesheets, \
+ org.w3c.dom.traversal, \
+ org.w3c.dom.views, \
+ org.xml.sax, \
+ org.xml.sax.ext, \
+ org.xml.sax.helpers
+
+# Standard package set.  Note that:
+#   - javax.transaction* is exported with a mandatory attribute 
+jre-1.6=, \
+ javax.accessibility, \
+ javax.activation, \
+ javax.activity, \
+ javax.annotation, \
+ javax.annotation.processing, \
+ javax.crypto, \
+ javax.crypto.interfaces, \
+ javax.crypto.spec, \
+ javax.imageio, \
+ javax.imageio.event, \
+ javax.imageio.metadata, \
+ javax.imageio.plugins.bmp, \
+ javax.imageio.plugins.jpeg, \
+ javax.imageio.spi, \
+ javax.imageio.stream, \
+ javax.jws, \
+ javax.jws.soap, \
+ javax.lang.model, \
+ javax.lang.model.element, \
+ javax.lang.model.type, \
+ javax.lang.model.util, \
+ javax.management, \
+ javax.management.loading, \
+ javax.management.modelmbean, \
+ javax.management.monitor, \
+ javax.management.openmbean, \
+ javax.management.relation, \
+ javax.management.remote, \
+ javax.management.remote.rmi, \
+ javax.management.timer, \
+ javax.naming, \
+ javax.naming.directory, \
+ javax.naming.event, \
+ javax.naming.ldap, \
+ javax.naming.spi, \
+ javax.net, \
+ javax.net.ssl, \
+ javax.print, \
+ javax.print.attribute, \
+ javax.print.attribute.standard, \
+ javax.print.event, \
+ javax.rmi, \
+ javax.rmi.CORBA, \
+ javax.rmi.ssl, \
+ javax.script, \
+ javax.security.auth, \
+ javax.security.auth.callback, \
+ javax.security.auth.kerberos, \
+ javax.security.auth.login, \
+ javax.security.auth.spi, \
+ javax.security.auth.x500, \
+ javax.security.cert, \
+ javax.security.sasl, \
+ javax.sound.midi, \
+ javax.sound.midi.spi, \
+ javax.sound.sampled, \
+ javax.sound.sampled.spi, \
+ javax.sql, \
+ javax.sql.rowset, \
+ javax.sql.rowset.serial, \
+ javax.sql.rowset.spi, \
+ javax.swing, \
+ javax.swing.border, \
+ javax.swing.colorchooser, \
+ javax.swing.event, \
+ javax.swing.filechooser, \
+ javax.swing.plaf, \
+ javax.swing.plaf.basic, \
+ javax.swing.plaf.metal, \
+ javax.swing.plaf.multi, \
+ javax.swing.plaf.synth, \
+ javax.swing.table, \
+ javax.swing.text, \
+ javax.swing.text.html, \
+ javax.swing.text.html.parser, \
+ javax.swing.text.rtf, \
+ javax.swing.tree, \
+ javax.swing.undo, \
+ javax.tools, \
+ javax.transaction; javax.transaction.xa; partial=true; mandatory:=partial, \
+ javax.xml, \
+ javax.xml.bind, \
+ javax.xml.bind.annotation, \
+ javax.xml.bind.annotation.adapters, \
+ javax.xml.bind.attachment, \
+ javax.xml.bind.helpers, \
+ javax.xml.bind.util, \
+ javax.xml.crypto, \
+ javax.xml.crypto.dom, \
+ javax.xml.crypto.dsig, \
+ javax.xml.crypto.dsig.dom, \
+ javax.xml.crypto.dsig.keyinfo, \
+ javax.xml.crypto.dsig.spec, \
+ javax.xml.datatype, \
+ javax.xml.namespace, \
+ javax.xml.parsers, \
+ javax.xml.soap, \
+ javax.xml.stream, \
+ javax.xml.stream.events, \
+ javax.xml.stream.util, \
+ javax.xml.transform, \
+ javax.xml.transform.dom, \
+ javax.xml.transform.sax, \
+ javax.xml.transform.stax, \
+ javax.xml.transform.stream, \
+ javax.xml.validation, \
+ javax.xml.ws, \
+ javax.xml.ws.handler, \
+ javax.xml.ws.handler.soap, \
+ javax.xml.ws.http, \
+ javax.xml.ws.soap, \
+ javax.xml.ws.spi, \
+ javax.xml.xpath, \
+ org.ietf.jgss, \
+ org.omg.CORBA, \
+ org.omg.CORBA_2_3, \
+ org.omg.CORBA_2_3.portable, \
+ org.omg.CORBA.DynAnyPackage, \
+ org.omg.CORBA.ORBPackage, \
+ org.omg.CORBA.portable, \
+ org.omg.CORBA.TypeCodePackage, \
+ org.omg.CosNaming, \
+ org.omg.CosNaming.NamingContextExtPackage, \
+ org.omg.CosNaming.NamingContextPackage, \
+ org.omg.Dynamic, \
+ org.omg.DynamicAny, \
+ org.omg.DynamicAny.DynAnyFactoryPackage, \
+ org.omg.DynamicAny.DynAnyPackage, \
+ org.omg.IOP, \
+ org.omg.IOP.CodecFactoryPackage, \
+ org.omg.IOP.CodecPackage, \
+ org.omg.Messaging, \
+ org.omg.PortableInterceptor, \
+ org.omg.PortableInterceptor.ORBInitInfoPackage, \
+ org.omg.PortableServer, \
+ org.omg.PortableServer.CurrentPackage, \
+ org.omg.PortableServer.POAManagerPackage, \
+ org.omg.PortableServer.POAPackage, \
+ org.omg.PortableServer.portable, \
+ org.omg.PortableServer.ServantLocatorPackage, \
+ org.omg.SendingContext, \
+ org.omg.stub.java.rmi, \
+ org.omg.stub.javax.management.remote.rmi, \
+ org.w3c.dom, \
+ org.w3c.dom.bootstrap, \
+ org.w3c.dom.css, \
+ org.w3c.dom.events, \
+ org.w3c.dom.html, \
+ org.w3c.dom.ls, \
+ org.w3c.dom.ranges, \
+ org.w3c.dom.stylesheets, \
+ org.w3c.dom.traversal, \
+ org.w3c.dom.views, \
+ org.w3c.dom.xpath, \
+ org.xml.sax, \
+ org.xml.sax.ext, \
+ org.xml.sax.helpers
diff --git a/karaf/shell/dev/src/test/resources/org/apache/felix/karaf/shell/dev/framework/enabled-config.properties b/karaf/shell/dev/src/test/resources/org/apache/felix/karaf/shell/dev/framework/enabled-config.properties
new file mode 100644
index 0000000..53c4eca
--- /dev/null
+++ b/karaf/shell/dev/src/test/resources/org/apache/felix/karaf/shell/dev/framework/enabled-config.properties
@@ -0,0 +1,355 @@
+################################################################################
+#
+#    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.
+#
+################################################################################
+
+#
+# Framework selection properties
+#
+karaf.framework=felix
+
+karaf.framework.equinox=${karaf.default.repository}/org/eclipse/osgi/${equinox.version}/osgi-${equinox.version}.jar
+karaf.framework.felix=${karaf.default.repository}/org/apache/felix/org.apache.felix.framework/${felix.framework.version}/org.apache.felix.framework-${felix.framework.version}.jar
+
+# Here are the properties to enable debugging
+felix.log.level=4
+osgi.debug=etc/equinox-debug.properties
+
+#
+# Framework config properties.
+#
+org.osgi.framework.system.packages=org.osgi.framework; version=1.5.0, \
+ org.osgi.framework.launch; version=1.0.0, \
+ org.osgi.framework.hooks.service; version=1.0.0, \
+ org.osgi.service.packageadmin; version=1.2.0, \
+ org.osgi.service.startlevel; version=1.1.0, \
+ org.osgi.service.url; version=1.0.0, \
+ org.osgi.util.tracker; version=1.4.0 \
+ ${jre-${java.specification.version}}
+
+org.osgi.framework.system.packages.extra=\
+ org.apache.felix.karaf.jaas.boot; version=${karaf.osgi.version}, \
+ org.apache.felix.karaf.version; version=${karaf.osgi.version}
+
+# javax.transaction is needed to avoid class loader constraint violation when using javax.sql  
+org.osgi.framework.bootdelegation=sun.*,com.sun.*,javax.transaction,javax.transaction.*
+
+# To enable the use of the startup.properties file to control the start level:
+karaf.auto.start=startup.properties
+#felix.auto.start=all
+
+org.osgi.framework.startlevel.beginning=100
+karaf.startlevel.bundle=60
+
+#
+# FileMonitor properties
+#
+felix.fileinstall.dir    = ${karaf.base}/etc
+felix.fileinstall.filter = .*\\.cfg
+felix.fileinstall.poll   = 1000
+felix.fileinstall.noInitialDelay = true
+
+#
+# Java platform package export properties.
+#
+
+# Standard package set.  Note that:
+#   - javax.transaction* is exported with a mandatory attribute 
+jre-1.5=, \
+ javax.accessibility, \
+ javax.activity, \
+ javax.crypto, \
+ javax.crypto.interfaces, \
+ javax.crypto.spec, \
+ javax.imageio, \
+ javax.imageio.event, \
+ javax.imageio.metadata, \
+ javax.imageio.plugins.bmp, \
+ javax.imageio.plugins.jpeg, \
+ javax.imageio.spi, \
+ javax.imageio.stream, \
+ javax.management, \
+ javax.management.loading, \
+ javax.management.modelmbean, \
+ javax.management.monitor, \
+ javax.management.openmbean, \
+ javax.management.relation, \
+ javax.management.remote, \
+ javax.management.remote.rmi, \
+ javax.management.timer, \
+ javax.naming, \
+ javax.naming.directory, \
+ javax.naming.event, \
+ javax.naming.ldap, \
+ javax.naming.spi, \
+ javax.net, \
+ javax.net.ssl, \
+ javax.print, \
+ javax.print.attribute, \
+ javax.print.attribute.standard, \
+ javax.print.event, \
+ javax.rmi, \
+ javax.rmi.CORBA, \
+ javax.rmi.ssl, \
+ javax.security.auth, \
+ javax.security.auth.callback, \
+ javax.security.auth.kerberos, \
+ javax.security.auth.login, \
+ javax.security.auth.spi, \
+ javax.security.auth.x500, \
+ javax.security.cert, \
+ javax.security.sasl, \
+ javax.sound.midi, \
+ javax.sound.midi.spi, \
+ javax.sound.sampled, \
+ javax.sound.sampled.spi, \
+ javax.sql, \
+ javax.sql.rowset, \
+ javax.sql.rowset.serial, \
+ javax.sql.rowset.spi, \
+ javax.swing, \
+ javax.swing.border, \
+ javax.swing.colorchooser, \
+ javax.swing.event, \
+ javax.swing.filechooser, \
+ javax.swing.plaf, \
+ javax.swing.plaf.basic, \
+ javax.swing.plaf.metal, \
+ javax.swing.plaf.multi, \
+ javax.swing.plaf.synth, \
+ javax.swing.table, \
+ javax.swing.text, \
+ javax.swing.text.html, \
+ javax.swing.text.html.parser, \
+ javax.swing.text.rtf, \
+ javax.swing.tree, \
+ javax.swing.undo, \
+ javax.transaction; javax.transaction.xa; partial=true; mandatory:=partial, \
+ javax.xml, \
+ javax.xml.datatype, \
+ javax.xml.namespace, \
+ javax.xml.parsers, \
+ javax.xml.transform, \
+ javax.xml.transform.dom, \
+ javax.xml.transform.sax, \
+ javax.xml.transform.stream, \
+ javax.xml.validation, \
+ javax.xml.xpath, \
+ org.ietf.jgss, \
+ org.omg.CORBA, \
+ org.omg.CORBA_2_3, \
+ org.omg.CORBA_2_3.portable, \
+ org.omg.CORBA.DynAnyPackage, \
+ org.omg.CORBA.ORBPackage, \
+ org.omg.CORBA.portable, \
+ org.omg.CORBA.TypeCodePackage, \
+ org.omg.CosNaming, \
+ org.omg.CosNaming.NamingContextExtPackage, \
+ org.omg.CosNaming.NamingContextPackage, \
+ org.omg.Dynamic, \
+ org.omg.DynamicAny, \
+ org.omg.DynamicAny.DynAnyFactoryPackage, \
+ org.omg.DynamicAny.DynAnyPackage, \
+ org.omg.IOP, \
+ org.omg.IOP.CodecFactoryPackage, \
+ org.omg.IOP.CodecPackage, \
+ org.omg.Messaging, \
+ org.omg.PortableInterceptor, \
+ org.omg.PortableInterceptor.ORBInitInfoPackage, \
+ org.omg.PortableServer, \
+ org.omg.PortableServer.CurrentPackage, \
+ org.omg.PortableServer.POAManagerPackage, \
+ org.omg.PortableServer.POAPackage, \
+ org.omg.PortableServer.portable, \
+ org.omg.PortableServer.ServantLocatorPackage, \
+ org.omg.SendingContext, \
+ org.omg.stub.java.rmi, \
+ org.omg.stub.javax.management.remote.rmi, \
+ org.w3c.dom, \
+ org.w3c.dom.bootstrap, \
+ org.w3c.dom.css, \
+ org.w3c.dom.events, \
+ org.w3c.dom.html, \
+ org.w3c.dom.ls, \
+ org.w3c.dom.ranges, \
+ org.w3c.dom.stylesheets, \
+ org.w3c.dom.traversal, \
+ org.w3c.dom.views, \
+ org.xml.sax, \
+ org.xml.sax.ext, \
+ org.xml.sax.helpers
+
+# Standard package set.  Note that:
+#   - javax.transaction* is exported with a mandatory attribute 
+jre-1.6=, \
+ javax.accessibility, \
+ javax.activation, \
+ javax.activity, \
+ javax.annotation, \
+ javax.annotation.processing, \
+ javax.crypto, \
+ javax.crypto.interfaces, \
+ javax.crypto.spec, \
+ javax.imageio, \
+ javax.imageio.event, \
+ javax.imageio.metadata, \
+ javax.imageio.plugins.bmp, \
+ javax.imageio.plugins.jpeg, \
+ javax.imageio.spi, \
+ javax.imageio.stream, \
+ javax.jws, \
+ javax.jws.soap, \
+ javax.lang.model, \
+ javax.lang.model.element, \
+ javax.lang.model.type, \
+ javax.lang.model.util, \
+ javax.management, \
+ javax.management.loading, \
+ javax.management.modelmbean, \
+ javax.management.monitor, \
+ javax.management.openmbean, \
+ javax.management.relation, \
+ javax.management.remote, \
+ javax.management.remote.rmi, \
+ javax.management.timer, \
+ javax.naming, \
+ javax.naming.directory, \
+ javax.naming.event, \
+ javax.naming.ldap, \
+ javax.naming.spi, \
+ javax.net, \
+ javax.net.ssl, \
+ javax.print, \
+ javax.print.attribute, \
+ javax.print.attribute.standard, \
+ javax.print.event, \
+ javax.rmi, \
+ javax.rmi.CORBA, \
+ javax.rmi.ssl, \
+ javax.script, \
+ javax.security.auth, \
+ javax.security.auth.callback, \
+ javax.security.auth.kerberos, \
+ javax.security.auth.login, \
+ javax.security.auth.spi, \
+ javax.security.auth.x500, \
+ javax.security.cert, \
+ javax.security.sasl, \
+ javax.sound.midi, \
+ javax.sound.midi.spi, \
+ javax.sound.sampled, \
+ javax.sound.sampled.spi, \
+ javax.sql, \
+ javax.sql.rowset, \
+ javax.sql.rowset.serial, \
+ javax.sql.rowset.spi, \
+ javax.swing, \
+ javax.swing.border, \
+ javax.swing.colorchooser, \
+ javax.swing.event, \
+ javax.swing.filechooser, \
+ javax.swing.plaf, \
+ javax.swing.plaf.basic, \
+ javax.swing.plaf.metal, \
+ javax.swing.plaf.multi, \
+ javax.swing.plaf.synth, \
+ javax.swing.table, \
+ javax.swing.text, \
+ javax.swing.text.html, \
+ javax.swing.text.html.parser, \
+ javax.swing.text.rtf, \
+ javax.swing.tree, \
+ javax.swing.undo, \
+ javax.tools, \
+ javax.transaction; javax.transaction.xa; partial=true; mandatory:=partial, \
+ javax.xml, \
+ javax.xml.bind, \
+ javax.xml.bind.annotation, \
+ javax.xml.bind.annotation.adapters, \
+ javax.xml.bind.attachment, \
+ javax.xml.bind.helpers, \
+ javax.xml.bind.util, \
+ javax.xml.crypto, \
+ javax.xml.crypto.dom, \
+ javax.xml.crypto.dsig, \
+ javax.xml.crypto.dsig.dom, \
+ javax.xml.crypto.dsig.keyinfo, \
+ javax.xml.crypto.dsig.spec, \
+ javax.xml.datatype, \
+ javax.xml.namespace, \
+ javax.xml.parsers, \
+ javax.xml.soap, \
+ javax.xml.stream, \
+ javax.xml.stream.events, \
+ javax.xml.stream.util, \
+ javax.xml.transform, \
+ javax.xml.transform.dom, \
+ javax.xml.transform.sax, \
+ javax.xml.transform.stax, \
+ javax.xml.transform.stream, \
+ javax.xml.validation, \
+ javax.xml.ws, \
+ javax.xml.ws.handler, \
+ javax.xml.ws.handler.soap, \
+ javax.xml.ws.http, \
+ javax.xml.ws.soap, \
+ javax.xml.ws.spi, \
+ javax.xml.xpath, \
+ org.ietf.jgss, \
+ org.omg.CORBA, \
+ org.omg.CORBA_2_3, \
+ org.omg.CORBA_2_3.portable, \
+ org.omg.CORBA.DynAnyPackage, \
+ org.omg.CORBA.ORBPackage, \
+ org.omg.CORBA.portable, \
+ org.omg.CORBA.TypeCodePackage, \
+ org.omg.CosNaming, \
+ org.omg.CosNaming.NamingContextExtPackage, \
+ org.omg.CosNaming.NamingContextPackage, \
+ org.omg.Dynamic, \
+ org.omg.DynamicAny, \
+ org.omg.DynamicAny.DynAnyFactoryPackage, \
+ org.omg.DynamicAny.DynAnyPackage, \
+ org.omg.IOP, \
+ org.omg.IOP.CodecFactoryPackage, \
+ org.omg.IOP.CodecPackage, \
+ org.omg.Messaging, \
+ org.omg.PortableInterceptor, \
+ org.omg.PortableInterceptor.ORBInitInfoPackage, \
+ org.omg.PortableServer, \
+ org.omg.PortableServer.CurrentPackage, \
+ org.omg.PortableServer.POAManagerPackage, \
+ org.omg.PortableServer.POAPackage, \
+ org.omg.PortableServer.portable, \
+ org.omg.PortableServer.ServantLocatorPackage, \
+ org.omg.SendingContext, \
+ org.omg.stub.java.rmi, \
+ org.omg.stub.javax.management.remote.rmi, \
+ org.w3c.dom, \
+ org.w3c.dom.bootstrap, \
+ org.w3c.dom.css, \
+ org.w3c.dom.events, \
+ org.w3c.dom.html, \
+ org.w3c.dom.ls, \
+ org.w3c.dom.ranges, \
+ org.w3c.dom.stylesheets, \
+ org.w3c.dom.traversal, \
+ org.w3c.dom.views, \
+ org.w3c.dom.xpath, \
+ org.xml.sax, \
+ org.xml.sax.ext, \
+ org.xml.sax.helpers