Split karaf module, separate support for admin and features

Signed-off-by: Lukasz Dywicki <luke@code-house.org>

git-svn-id: https://svn.apache.org/repos/asf/karaf/webconsole/trunk@1225493 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/karaf/admin/pom.xml b/karaf/admin/pom.xml
new file mode 100644
index 0000000..8861242
--- /dev/null
+++ b/karaf/admin/pom.xml
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!--
+   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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.apache.karaf.webconsole</groupId>
+        <artifactId>karaf</artifactId>
+        <version>0.3.0-SNAPSHOT</version>
+    </parent>
+
+    <groupId>org.apache.karaf.webconsole.karaf</groupId>
+    <artifactId>org.apache.karaf.webconsole.karaf.admin</artifactId>
+    <name>Apache Karaf :: WebConsole :: Karaf :: Admin</name>
+    <packaging>bundle</packaging>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.karaf.webconsole</groupId>
+            <artifactId>org.apache.karaf.webconsole.core</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.karaf.admin</groupId>
+            <artifactId>org.apache.karaf.admin.core</artifactId>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <version>2.3.5</version>
+                <extensions>true</extensions>
+                <configuration>
+                    <instructions>
+                        <Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
+                        <Import-Package>
+                            !org.apache.karaf.webconsole.karaf.admin*,
+                            *,
+                            <!-- transient dependencies -->
+                            org.ops4j.pax.wicket.api,
+                            org.ops4j.pax.wicket.util,
+                            org.ops4j.pax.wicket.util.proxy,
+                            <!-- karaf -->
+                            org.apache.karaf.admin
+                        </Import-Package>
+                    </instructions>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/karaf/admin/src/main/java/org/apache/karaf/webconsole/karaf/admin/AdminPage.java b/karaf/admin/src/main/java/org/apache/karaf/webconsole/karaf/admin/AdminPage.java
new file mode 100644
index 0000000..d699b75
--- /dev/null
+++ b/karaf/admin/src/main/java/org/apache/karaf/webconsole/karaf/admin/AdminPage.java
@@ -0,0 +1,16 @@
+package org.apache.karaf.webconsole.karaf.admin;
+
+import org.apache.karaf.admin.AdminService;
+import org.apache.karaf.webconsole.core.page.SidebarPage;
+import org.ops4j.pax.wicket.api.PaxWicketBean;
+
+public class AdminPage extends SidebarPage {
+
+    @PaxWicketBean(name = "adminService")
+    protected AdminService admin;
+
+    public AdminPage() {
+        setSidebarProvider(new AdminSidebarProvider());
+    }
+
+}
diff --git a/karaf/admin/src/main/java/org/apache/karaf/webconsole/karaf/admin/AdminSidebarProvider.java b/karaf/admin/src/main/java/org/apache/karaf/webconsole/karaf/admin/AdminSidebarProvider.java
new file mode 100644
index 0000000..4077324
--- /dev/null
+++ b/karaf/admin/src/main/java/org/apache/karaf/webconsole/karaf/admin/AdminSidebarProvider.java
@@ -0,0 +1,33 @@
+package org.apache.karaf.webconsole.karaf.admin;
+
+import static org.apache.karaf.webconsole.core.util.LinkUtils.createPageLink;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.karaf.webconsole.core.navigation.SidebarProvider;
+import org.apache.karaf.webconsole.core.widget.WidgetProvider;
+import org.apache.karaf.webconsole.karaf.admin.create.CreateInstancePage;
+import org.apache.karaf.webconsole.karaf.admin.list.InstancesPage;
+import org.apache.wicket.Page;
+import org.apache.wicket.markup.html.link.Link;
+
+public class AdminSidebarProvider implements SidebarProvider {
+
+    @SuppressWarnings("unchecked")
+    public List<Link<Page>> getItems(String componentId, String labelId) {
+        return Arrays.asList(
+            createPageLink(componentId, labelId, "Create instance", CreateInstancePage.class)
+        );
+    }
+
+    public Link<Page> getMasterPageLink(String linkId, String labelId) {
+        return createPageLink(linkId, labelId, "Instances", InstancesPage.class);
+    }
+
+    public List<WidgetProvider> getWidgetProviders() {
+        return Collections.emptyList();
+    }
+
+}
diff --git a/karaf/admin/src/main/java/org/apache/karaf/webconsole/karaf/admin/create/CreateInstancePage.java b/karaf/admin/src/main/java/org/apache/karaf/webconsole/karaf/admin/create/CreateInstancePage.java
new file mode 100644
index 0000000..e02005f
--- /dev/null
+++ b/karaf/admin/src/main/java/org/apache/karaf/webconsole/karaf/admin/create/CreateInstancePage.java
@@ -0,0 +1,46 @@
+package org.apache.karaf.webconsole.karaf.admin.create;
+
+import static org.apache.wicket.model.Model.of;
+
+import org.apache.karaf.webconsole.karaf.admin.AdminPage;
+import org.apache.karaf.webconsole.karaf.admin.model.InstanceSettingsExt;
+import org.apache.karaf.webconsole.karaf.admin.model.KarafInstance;
+import org.apache.karaf.webconsole.karaf.admin.settings.InstanceSettingsPanel;
+import org.apache.wicket.Session;
+import org.apache.wicket.markup.html.form.Button;
+import org.apache.wicket.markup.html.form.Form;
+import org.apache.wicket.markup.html.form.TextField;
+import org.apache.wicket.model.CompoundPropertyModel;
+import org.ops4j.pax.wicket.api.PaxWicketMountPoint;
+
+@PaxWicketMountPoint(mountPoint = "/karaf/admin/create")
+public class CreateInstancePage extends AdminPage {
+
+    public CreateInstancePage() {
+        KarafInstance instance = new KarafInstance();
+        instance.setSettings(new InstanceSettingsExt());
+
+        CompoundPropertyModel<KarafInstance> model = new CompoundPropertyModel<KarafInstance>(instance);
+
+        Form<KarafInstance> form = new Form<KarafInstance>("instance", model);
+        form.add(new TextField<String>("name"));
+        form.add(new InstanceSettingsPanel("settings", of(new InstanceSettingsExt())));
+
+        form.add(new Button("submit") {
+            @Override
+            public void onSubmit() {
+                try {
+                    KarafInstance instance = (KarafInstance) getForm().getModelObject();
+                    admin.createInstance(instance.getName(), instance.getSettings());
+                } catch (Exception e) {
+                    e.printStackTrace();
+
+                    Session.get().error("Cannot create instance");
+                }
+            }
+        });
+
+        add(form);
+    }
+
+}
diff --git a/karaf/admin/src/main/java/org/apache/karaf/webconsole/karaf/admin/list/InstanceActionsPanel.java b/karaf/admin/src/main/java/org/apache/karaf/webconsole/karaf/admin/list/InstanceActionsPanel.java
new file mode 100644
index 0000000..d466b0e
--- /dev/null
+++ b/karaf/admin/src/main/java/org/apache/karaf/webconsole/karaf/admin/list/InstanceActionsPanel.java
@@ -0,0 +1,79 @@
+package org.apache.karaf.webconsole.karaf.admin.list;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.karaf.admin.Instance;
+import org.apache.karaf.webconsole.core.table.ActionsPanel;
+import org.apache.wicket.Session;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.link.Link;
+import org.apache.wicket.model.IModel;
+
+public class InstanceActionsPanel extends ActionsPanel<Instance> {
+
+    public InstanceActionsPanel(String id, IModel<Instance> model) {
+        super(id, model);
+    }
+
+    @Override
+    protected List<Link> getLinks(Instance object, String id) {
+        List<Link> links = new ArrayList<Link>();
+
+        try {
+            if (Instance.STOPPED.equals(object.getState())) {
+                links.add(new Link(id) {
+                    {
+                        add(new Label("label", "Start"));
+                    }
+                    @Override
+                    public void onClick() {
+                        Instance instance = (Instance) InstanceActionsPanel.this.getDefaultModelObject();
+   
+                        try {
+                            instance.start("");
+                        } catch (Exception e) {
+                            Session.get().error("Cannot start instance " + instance.getName());
+                        }
+                    }
+                });
+            } else {
+                links.add(new Link(id) {
+                    {
+                        add(new Label("label", "Stop"));
+                    }
+                    @Override
+                    public void onClick() {
+                        Instance instance = (Instance) InstanceActionsPanel.this.getDefaultModelObject();
+   
+                        try {
+                            instance.stop();
+                        } catch (Exception e) {
+                            Session.get().error("Cannot stop instance " + instance.getName());
+                        }
+                    }
+                });
+            }
+        } catch (Exception e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+        }
+        links.add(new Link(id) {
+            {
+                add(new Label("label", "Destroy"));
+            }
+            @Override
+            public void onClick() {
+                Instance instance = (Instance) InstanceActionsPanel.this.getDefaultModelObject();
+
+                try {
+                    instance.destroy();
+                } catch (Exception e) {
+                    Session.get().error("Cannot destroy instance " + instance.getName());
+                }
+            }
+        });
+
+        return links;
+    }
+}
diff --git a/karaf/admin/src/main/java/org/apache/karaf/webconsole/karaf/admin/list/InstancesPage.java b/karaf/admin/src/main/java/org/apache/karaf/webconsole/karaf/admin/list/InstancesPage.java
new file mode 100644
index 0000000..ac36785
--- /dev/null
+++ b/karaf/admin/src/main/java/org/apache/karaf/webconsole/karaf/admin/list/InstancesPage.java
@@ -0,0 +1,39 @@
+package org.apache.karaf.webconsole.karaf.admin.list;
+
+import static org.apache.wicket.model.Model.of;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.karaf.admin.Instance;
+import org.apache.karaf.webconsole.core.table.OrdinalColumn;
+import org.apache.karaf.webconsole.core.table.PropertyColumnExt;
+import org.apache.karaf.webconsole.karaf.admin.AdminPage;
+import org.apache.karaf.webconsole.karaf.admin.model.InstancesDataProvider;
+import org.apache.wicket.extensions.markup.html.repeater.data.grid.ICellPopulator;
+import org.apache.wicket.extensions.markup.html.repeater.data.table.AbstractColumn;
+import org.apache.wicket.extensions.markup.html.repeater.data.table.DefaultDataTable;
+import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn;
+import org.apache.wicket.markup.repeater.Item;
+import org.apache.wicket.model.IModel;
+
+public class InstancesPage extends AdminPage {
+
+    public InstancesPage() {
+        List<IColumn<Instance>> columns = new ArrayList<IColumn<Instance>>();
+        columns.add(new OrdinalColumn<Instance>());
+        columns.add(new PropertyColumnExt<Instance>("PID", "pid"));
+        columns.add(new PropertyColumnExt<Instance>("Name", "name"));
+        columns.add(new PropertyColumnExt<Instance>("Root", "root"));
+        columns.add(new PropertyColumnExt<Instance>("State", "state"));
+        columns.add(new PropertyColumnExt<Instance>("Location", "location"));
+        columns.add(new AbstractColumn<Instance>(of("Actions")) {
+            public void populateItem(Item<ICellPopulator<Instance>> cellItem, String componentId, IModel<Instance> rowModel) {
+                cellItem.add(new InstanceActionsPanel(componentId, rowModel));
+            }
+        });
+
+        add(new DefaultDataTable<Instance>("instances", columns, new InstancesDataProvider(admin), 20));
+    }
+
+}
diff --git a/karaf/admin/src/main/java/org/apache/karaf/webconsole/karaf/admin/model/InstanceModel.java b/karaf/admin/src/main/java/org/apache/karaf/webconsole/karaf/admin/model/InstanceModel.java
new file mode 100644
index 0000000..2e776fa
--- /dev/null
+++ b/karaf/admin/src/main/java/org/apache/karaf/webconsole/karaf/admin/model/InstanceModel.java
@@ -0,0 +1,23 @@
+package org.apache.karaf.webconsole.karaf.admin.model;
+
+import org.apache.karaf.admin.AdminService;
+import org.apache.karaf.admin.Instance;
+import org.apache.wicket.model.LoadableDetachableModel;
+
+public class InstanceModel extends LoadableDetachableModel<Instance> {
+
+    private AdminService admin;
+    private String name;
+
+    public InstanceModel(AdminService admin, Instance object) {
+        super(object);
+        this.admin = admin;
+        this.name = object.getName();
+    }
+
+    @Override
+    protected Instance load() {
+        return admin.getInstance(name);
+    }
+
+}
diff --git a/karaf/admin/src/main/java/org/apache/karaf/webconsole/karaf/admin/model/InstanceSettingsExt.java b/karaf/admin/src/main/java/org/apache/karaf/webconsole/karaf/admin/model/InstanceSettingsExt.java
new file mode 100644
index 0000000..9398988
--- /dev/null
+++ b/karaf/admin/src/main/java/org/apache/karaf/webconsole/karaf/admin/model/InstanceSettingsExt.java
@@ -0,0 +1,13 @@
+package org.apache.karaf.webconsole.karaf.admin.model;
+
+import java.io.Serializable;
+
+import org.apache.karaf.admin.InstanceSettings;
+
+public class InstanceSettingsExt extends InstanceSettings implements Serializable {
+
+    public InstanceSettingsExt() {
+        super(0, 0, 0, "", "", null, null);
+    }
+
+}
diff --git a/karaf/admin/src/main/java/org/apache/karaf/webconsole/karaf/admin/model/InstancesDataProvider.java b/karaf/admin/src/main/java/org/apache/karaf/webconsole/karaf/admin/model/InstancesDataProvider.java
new file mode 100644
index 0000000..0d9b92f
--- /dev/null
+++ b/karaf/admin/src/main/java/org/apache/karaf/webconsole/karaf/admin/model/InstancesDataProvider.java
@@ -0,0 +1,35 @@
+package org.apache.karaf.webconsole.karaf.admin.model;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.karaf.admin.AdminService;
+import org.apache.karaf.admin.Instance;
+import org.apache.wicket.extensions.markup.html.repeater.util.SortableDataProvider;
+import org.apache.wicket.model.IModel;
+
+public class InstancesDataProvider extends SortableDataProvider<Instance> {
+
+    private AdminService admin;
+
+    public InstancesDataProvider(AdminService admin) {
+        this.admin = admin;
+    }
+
+    public Iterator<? extends Instance> iterator(int first, int count) {
+        List<Instance> list = new ArrayList<Instance>();
+        Collections.addAll(list, admin.getInstances());
+        return list.subList(first, count).iterator();
+    }
+
+    public int size() {
+        return admin.getInstances().length;
+    }
+
+    public IModel<Instance> model(Instance object) {
+        return new InstanceModel(admin, object);
+    }
+
+}
diff --git a/karaf/admin/src/main/java/org/apache/karaf/webconsole/karaf/admin/model/KarafInstance.java b/karaf/admin/src/main/java/org/apache/karaf/webconsole/karaf/admin/model/KarafInstance.java
new file mode 100644
index 0000000..db9ff47
--- /dev/null
+++ b/karaf/admin/src/main/java/org/apache/karaf/webconsole/karaf/admin/model/KarafInstance.java
@@ -0,0 +1,27 @@
+package org.apache.karaf.webconsole.karaf.admin.model;
+
+import java.io.Serializable;
+
+public class KarafInstance implements Serializable {
+
+    private String name;
+
+    private InstanceSettingsExt settings;
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public InstanceSettingsExt getSettings() {
+        return settings;
+    }
+
+    public void setSettings(InstanceSettingsExt settings) {
+        this.settings = settings;
+    }
+
+}
diff --git a/karaf/admin/src/main/java/org/apache/karaf/webconsole/karaf/admin/navigation/AdminNavigationProvider.java b/karaf/admin/src/main/java/org/apache/karaf/webconsole/karaf/admin/navigation/AdminNavigationProvider.java
new file mode 100644
index 0000000..79094c3
--- /dev/null
+++ b/karaf/admin/src/main/java/org/apache/karaf/webconsole/karaf/admin/navigation/AdminNavigationProvider.java
@@ -0,0 +1,21 @@
+package org.apache.karaf.webconsole.karaf.admin.navigation;
+
+import static org.apache.karaf.webconsole.core.util.LinkUtils.createPageLink;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.karaf.webconsole.core.navigation.NavigationProvider;
+import org.apache.karaf.webconsole.karaf.admin.list.InstancesPage;
+import org.apache.wicket.Page;
+import org.apache.wicket.markup.html.link.Link;
+
+public class AdminNavigationProvider implements NavigationProvider {
+
+    public List<Link<Page>> getItems(String componentId, String labelId) {
+        List<Link<Page>> links = new ArrayList<Link<Page>>();
+        links.add(createPageLink(componentId, labelId, "Instances", InstancesPage.class));
+        return links;
+    }
+
+}
diff --git a/karaf/admin/src/main/java/org/apache/karaf/webconsole/karaf/admin/settings/InstanceSettingsForm.java b/karaf/admin/src/main/java/org/apache/karaf/webconsole/karaf/admin/settings/InstanceSettingsForm.java
new file mode 100644
index 0000000..95b48cd
--- /dev/null
+++ b/karaf/admin/src/main/java/org/apache/karaf/webconsole/karaf/admin/settings/InstanceSettingsForm.java
@@ -0,0 +1,27 @@
+package org.apache.karaf.webconsole.karaf.admin.settings;
+
+import org.apache.karaf.webconsole.karaf.admin.model.InstanceSettingsExt;
+import org.apache.wicket.markup.html.form.Form;
+import org.apache.wicket.markup.html.form.TextArea;
+import org.apache.wicket.markup.html.form.TextField;
+import org.apache.wicket.model.CompoundPropertyModel;
+import org.apache.wicket.model.IModel;
+
+public class InstanceSettingsForm extends Form<InstanceSettingsExt> {
+
+    public InstanceSettingsForm(String id, IModel<InstanceSettingsExt> model) {
+        super(id, new CompoundPropertyModel<InstanceSettingsExt>(model));
+
+        add(new TextField<Integer>("sshPort"));
+        add(new TextField<Integer>("rmiRegistryPort"));
+        add(new TextField<Integer>("rmiServerPort"));
+
+        add(new TextArea<String>("javaOpts"));
+        add(new TextField<String>("location"));
+
+        // we need additional checks here
+        //add(new TextArea<String>("features"));
+        //add(new TextArea<String>("featureURLs"));
+    }
+
+}
diff --git a/karaf/admin/src/main/java/org/apache/karaf/webconsole/karaf/admin/settings/InstanceSettingsPanel.java b/karaf/admin/src/main/java/org/apache/karaf/webconsole/karaf/admin/settings/InstanceSettingsPanel.java
new file mode 100644
index 0000000..4fb73de
--- /dev/null
+++ b/karaf/admin/src/main/java/org/apache/karaf/webconsole/karaf/admin/settings/InstanceSettingsPanel.java
@@ -0,0 +1,15 @@
+package org.apache.karaf.webconsole.karaf.admin.settings;
+
+import org.apache.karaf.webconsole.karaf.admin.model.InstanceSettingsExt;
+import org.apache.wicket.markup.html.panel.Panel;
+import org.apache.wicket.model.IModel;
+
+public class InstanceSettingsPanel extends Panel {
+
+    public InstanceSettingsPanel(String id, IModel<InstanceSettingsExt> model) {
+        super(id, model);
+
+        add(new InstanceSettingsForm("settings", model));
+    }
+
+}
diff --git a/karaf/src/main/resources/OSGI-INF/blueprint/karaf.xml b/karaf/admin/src/main/resources/OSGI-INF/blueprint/admin.xml
similarity index 60%
copy from karaf/src/main/resources/OSGI-INF/blueprint/karaf.xml
copy to karaf/admin/src/main/resources/OSGI-INF/blueprint/admin.xml
index 614ffd6..80f9b58 100644
--- a/karaf/src/main/resources/OSGI-INF/blueprint/karaf.xml
+++ b/karaf/admin/src/main/resources/OSGI-INF/blueprint/admin.xml
@@ -17,22 +17,13 @@
 -->
 <blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
 
-    <service interface="org.apache.karaf.webconsole.core.navigation.ConsoleTabProvider">
-        <bean class="org.apache.karaf.webconsole.karaf.internal.navigation.KarafConsoleTabProvider" />
-    </service>
-
-    <reference id="featuresService" interface="org.apache.karaf.features.FeaturesService"/>
-
-    <service ref="widgetProvider" interface="org.apache.karaf.webconsole.core.widget.WidgetProvider">
+    <service interface="org.apache.karaf.webconsole.core.navigation.NavigationProvider">
         <service-properties>
-            <entry key="intention" value="dashboard" />
+            <entry key="extends" value="karaf" />
         </service-properties>
+        <bean class="org.apache.karaf.webconsole.karaf.admin.navigation.AdminNavigationProvider" />
     </service>
 
-    <bean id="widgetProvider" class="org.apache.karaf.webconsole.karaf.internal.widget.KarafFeaturesWidgetProvider">
-        <argument ref="featuresService" />
-    </bean>
-
-    <bean id="featuresSidebar" class="org.apache.karaf.webconsole.karaf.internal.sidebar.KarafFeaturesSidebar" />
+    <reference id="adminService" interface="org.apache.karaf.admin.AdminService"/>
 
 </blueprint>
diff --git a/karaf/admin/src/main/resources/org/apache/karaf/webconsole/karaf/admin/create/CreateInstancePage.html b/karaf/admin/src/main/resources/org/apache/karaf/webconsole/karaf/admin/create/CreateInstancePage.html
new file mode 100644
index 0000000..9dd9b38
--- /dev/null
+++ b/karaf/admin/src/main/resources/org/apache/karaf/webconsole/karaf/admin/create/CreateInstancePage.html
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+   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.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd" >
+    <wicket:head>
+        <title>Karaf WebConsole</title>
+    </wicket:head>
+
+    <body>
+        <wicket:extend>
+            <h1>Create new instance</h1>
+
+            <form wicket:id="instance">
+                Name<br />
+                <input type="text" wicket:id="name" />
+
+                <div wicket:id="settings"></div>
+
+                <input wicket:id="submit" type="submit" />
+            </form>
+        </wicket:extend>
+    </body>
+</html>
diff --git a/karaf/admin/src/main/resources/org/apache/karaf/webconsole/karaf/admin/list/InstancesPage.html b/karaf/admin/src/main/resources/org/apache/karaf/webconsole/karaf/admin/list/InstancesPage.html
new file mode 100644
index 0000000..00e8cf8
--- /dev/null
+++ b/karaf/admin/src/main/resources/org/apache/karaf/webconsole/karaf/admin/list/InstancesPage.html
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+   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.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd" >
+    <wicket:head>
+        <title>Karaf WebConsole</title>
+    </wicket:head>
+
+    <body>
+        <wicket:extend>
+            <h1>Instances</h1>
+
+            <table wicket:id="instances" class="dataview" />
+
+        </wicket:extend>
+    </body>
+</html>
diff --git a/karaf/admin/src/main/resources/org/apache/karaf/webconsole/karaf/admin/settings/InstanceSettingsPanel.html b/karaf/admin/src/main/resources/org/apache/karaf/webconsole/karaf/admin/settings/InstanceSettingsPanel.html
new file mode 100644
index 0000000..44d71a9
--- /dev/null
+++ b/karaf/admin/src/main/resources/org/apache/karaf/webconsole/karaf/admin/settings/InstanceSettingsPanel.html
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+   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.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd" >
+    <wicket:head>
+        <title>Karaf WebConsole</title>
+    </wicket:head>
+
+    <wicket:panel>
+        <form wicket:id="settings">
+            SSH port<br />
+            <input type="text" wicket:id="sshPort" />
+
+            <h2>RMI Connector</h2>
+            Registry port<br />
+            <input type="text" wicket:id="rmiRegistryPort" />
+            Server port<br />
+            <input type="text" wicket:id="rmiServerPort" />
+
+            <h2>Runtime</h2>
+            Java process options<br />
+            <textarea wicket:id="javaOpts"></textarea>
+
+            <h2>Read only properties</h2>
+            Instance location<br />
+            <input type="text" wicket:id="location" />
+        </form>
+    </wicket:panel>
+</html>
diff --git a/karaf/core/pom.xml b/karaf/core/pom.xml
new file mode 100644
index 0000000..cf4580f
--- /dev/null
+++ b/karaf/core/pom.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!--
+   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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.apache.karaf.webconsole</groupId>
+        <artifactId>karaf</artifactId>
+        <version>0.3.0-SNAPSHOT</version>
+    </parent>
+
+    <groupId>org.apache.karaf.webconsole.karaf</groupId>
+    <artifactId>org.apache.karaf.webconsole.karaf.core</artifactId>
+    <name>Apache Karaf :: WebConsole :: Karaf :: Core</name>
+    <packaging>bundle</packaging>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.karaf.webconsole</groupId>
+            <artifactId>org.apache.karaf.webconsole.core</artifactId>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <version>2.3.5</version>
+                <extensions>true</extensions>
+                <configuration>
+                    <instructions>
+                        <Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
+                        <Import-Package>
+                            !org.apache.karaf.webconsole.karaf.features*,
+                            *,
+                            <!-- transient dependencies -->
+                            org.ops4j.pax.wicket.api,
+                            org.ops4j.pax.wicket.util,
+                            org.ops4j.pax.wicket.util.proxy,
+                            <!-- karaf -->
+                            org.apache.karaf.features
+                        </Import-Package>
+                    </instructions>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/karaf/core/src/main/java/org/apache/karaf/webconsole/karaf/core/KarafOverviewPage.java b/karaf/core/src/main/java/org/apache/karaf/webconsole/karaf/core/KarafOverviewPage.java
new file mode 100644
index 0000000..1e81495
--- /dev/null
+++ b/karaf/core/src/main/java/org/apache/karaf/webconsole/karaf/core/KarafOverviewPage.java
@@ -0,0 +1,26 @@
+package org.apache.karaf.webconsole.karaf.core;
+
+import org.apache.karaf.webconsole.core.page.SecuredPage;
+import org.apache.karaf.webconsole.karaf.core.model.Karaf;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.model.CompoundPropertyModel;
+import org.ops4j.pax.wicket.api.PaxWicketMountPoint;
+
+@PaxWicketMountPoint(mountPoint = "/karaf")
+public class KarafOverviewPage extends SecuredPage {
+
+    public KarafOverviewPage() {
+        setDefaultModel(new CompoundPropertyModel<Karaf>(new Karaf()));
+
+        add(new Label("version"));
+
+        add(new Label("home"));
+        add(new Label("base"));
+        add(new Label("data"));
+        add(new Label("instances"));
+
+        add(new Label("localConsole"));
+        add(new Label("remoteShell"));
+    }
+
+}
diff --git a/karaf/core/src/main/java/org/apache/karaf/webconsole/karaf/core/model/Karaf.java b/karaf/core/src/main/java/org/apache/karaf/webconsole/karaf/core/model/Karaf.java
new file mode 100644
index 0000000..f01a280
--- /dev/null
+++ b/karaf/core/src/main/java/org/apache/karaf/webconsole/karaf/core/model/Karaf.java
@@ -0,0 +1,35 @@
+package org.apache.karaf.webconsole.karaf.core.model;
+
+import java.io.Serializable;
+
+public class Karaf implements Serializable {
+
+    public String getVersion() {
+        return System.getProperty("karaf.version");
+    }
+
+    public String getHome() {
+        return System.getProperty("karaf.home");
+    }
+
+    public String getBase() {
+        return System.getProperty("karaf.base");
+    }
+
+    public String getData() {
+        return System.getProperty("karaf.data");
+    }
+
+    public String getInstances() {
+        return System.getProperty("karaf.instances");
+    }
+
+    public Boolean isLocalConsole() {
+        return Boolean.getBoolean("karaf.startLocalConsole");
+    }
+
+    public Boolean isRemoteShell() {
+        return Boolean.getBoolean("karaf.startRemoteShell");
+    }
+
+}
diff --git a/karaf/core/src/main/java/org/apache/karaf/webconsole/karaf/core/navigation/KarafConsoleTabProvider.java b/karaf/core/src/main/java/org/apache/karaf/webconsole/karaf/core/navigation/KarafConsoleTabProvider.java
new file mode 100644
index 0000000..4e2f241
--- /dev/null
+++ b/karaf/core/src/main/java/org/apache/karaf/webconsole/karaf/core/navigation/KarafConsoleTabProvider.java
@@ -0,0 +1,23 @@
+package org.apache.karaf.webconsole.karaf.core.navigation;
+
+import static org.apache.karaf.webconsole.core.util.LinkUtils.createPageLink;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.karaf.webconsole.core.navigation.ConsoleTabProvider;
+import org.apache.karaf.webconsole.karaf.core.KarafOverviewPage;
+import org.apache.wicket.Page;
+import org.apache.wicket.markup.html.link.Link;
+
+public class KarafConsoleTabProvider implements ConsoleTabProvider {
+
+    public List<Link<Page>> getItems(String componentId, String labelId) {
+        return Collections.emptyList();
+    }
+
+    public Link<Page> getModuleLink(String componentId, String labelId) {
+        return createPageLink(componentId, labelId, "Karaf", KarafOverviewPage.class);
+    }
+
+}
diff --git a/karaf/core/src/main/resources/OSGI-INF/blueprint/core.xml b/karaf/core/src/main/resources/OSGI-INF/blueprint/core.xml
new file mode 100644
index 0000000..bc8d037
--- /dev/null
+++ b/karaf/core/src/main/resources/OSGI-INF/blueprint/core.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!--
+   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.
+-->
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="
+        http://www.osgi.org/xmlns/blueprint/v1.0.0
+        http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd
+    ">
+
+    <service interface="org.apache.karaf.webconsole.core.navigation.ConsoleTabProvider">
+        <bean class="org.apache.karaf.webconsole.core.navigation.ExtendableConsoleTabProvider">
+            <argument>
+                <bean class="org.apache.karaf.webconsole.karaf.core.navigation.KarafConsoleTabProvider" />
+            </argument>
+            <property name="extensions">
+                <reference-list interface="org.apache.karaf.webconsole.core.navigation.NavigationProvider"
+                    availability="optional" filter="(extends=karaf)" />
+            </property>
+        </bean>
+    </service>
+
+</blueprint>
diff --git a/karaf/core/src/main/resources/org/apache/karaf/webconsole/karaf/core/KarafOverviewPage.html b/karaf/core/src/main/resources/org/apache/karaf/webconsole/karaf/core/KarafOverviewPage.html
new file mode 100644
index 0000000..107736a
--- /dev/null
+++ b/karaf/core/src/main/resources/org/apache/karaf/webconsole/karaf/core/KarafOverviewPage.html
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+   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.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd" >
+    <wicket:head>
+        <title>Karaf WebConsole</title>
+    </wicket:head>
+
+    <body>
+        <wicket:extend>
+            <h1>Karaf overview</h1>
+            <p>
+                You run Karaf in version <span wicket:id="version">2.2.3</span>
+            </p>
+
+            <h2>Directories</h2>
+            <ul>
+                <li>
+                    Karaf home <span wicket:id="home">/opt/karaf/2.2.3</span>
+                </li>
+                <li>
+                    Karaf base <span wicket:id="base">/opt/karaf/2.2.3</span>
+                </li>
+                <li>
+                    Karaf data directory <span wicket:id="data">/opt/karaf/2.2.3/data</span>
+                </li>
+                <li>
+                    Karaf instances directory <span wicket:id="instances">/opt/karaf/2.2.3/instances</span>
+                </li>
+            </ul>
+
+            <h2>Consoles</h2>
+            <ul>
+                <li>
+                    Local console is enabled: <span wicket:id="localConsole" />
+                </li>
+                <li>
+                    Remote shell is enabled: <span wicket:id="remoteShell" />
+                </li>
+            </ul>
+        </wicket:extend>
+    </body>
+</html>
\ No newline at end of file
diff --git a/karaf/features/pom.xml b/karaf/features/pom.xml
new file mode 100644
index 0000000..ce757d1
--- /dev/null
+++ b/karaf/features/pom.xml
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!--
+   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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.apache.karaf.webconsole</groupId>
+        <artifactId>karaf</artifactId>
+        <version>0.3.0-SNAPSHOT</version>
+    </parent>
+
+    <groupId>org.apache.karaf.webconsole.karaf</groupId>
+    <artifactId>org.apache.karaf.webconsole.karaf.features</artifactId>
+    <name>Apache Karaf :: WebConsole :: Karaf :: Features</name>
+    <packaging>bundle</packaging>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.karaf.webconsole</groupId>
+            <artifactId>org.apache.karaf.webconsole.core</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.karaf.features</groupId>
+            <artifactId>org.apache.karaf.features.core</artifactId>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <version>2.3.5</version>
+                <extensions>true</extensions>
+                <configuration>
+                    <instructions>
+                        <Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
+                        <Import-Package>
+                            !org.apache.karaf.webconsole.karaf.features*,
+                            *,
+                            <!-- transient dependencies -->
+                            org.ops4j.pax.wicket.api,
+                            org.ops4j.pax.wicket.util,
+                            org.ops4j.pax.wicket.util.proxy,
+                            <!-- karaf -->
+                            org.apache.karaf.features
+                        </Import-Package>
+                    </instructions>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/karaf/src/main/java/org/apache/karaf/webconsole/karaf/internal/FeatureModel.java b/karaf/features/src/main/java/org/apache/karaf/webconsole/karaf/features/FeatureModel.java
similarity index 96%
rename from karaf/src/main/java/org/apache/karaf/webconsole/karaf/internal/FeatureModel.java
rename to karaf/features/src/main/java/org/apache/karaf/webconsole/karaf/features/FeatureModel.java
index ea51ad3..f0202fa 100644
--- a/karaf/src/main/java/org/apache/karaf/webconsole/karaf/internal/FeatureModel.java
+++ b/karaf/features/src/main/java/org/apache/karaf/webconsole/karaf/features/FeatureModel.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.karaf.webconsole.karaf.internal;
+package org.apache.karaf.webconsole.karaf.features;
 
 import org.apache.karaf.features.Feature;
 import org.apache.karaf.features.FeaturesService;
diff --git a/karaf/src/main/java/org/apache/karaf/webconsole/karaf/internal/FeaturesProvider.java b/karaf/features/src/main/java/org/apache/karaf/webconsole/karaf/features/FeaturesProvider.java
similarity index 97%
rename from karaf/src/main/java/org/apache/karaf/webconsole/karaf/internal/FeaturesProvider.java
rename to karaf/features/src/main/java/org/apache/karaf/webconsole/karaf/features/FeaturesProvider.java
index 8b50302..a864ef7 100644
--- a/karaf/src/main/java/org/apache/karaf/webconsole/karaf/internal/FeaturesProvider.java
+++ b/karaf/features/src/main/java/org/apache/karaf/webconsole/karaf/features/FeaturesProvider.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.karaf.webconsole.karaf.internal;
+package org.apache.karaf.webconsole.karaf.features;
 
 import java.util.ArrayList;
 import java.util.Arrays;
diff --git a/karaf/src/main/java/org/apache/karaf/webconsole/karaf/internal/KarafFeaturesPage.java b/karaf/features/src/main/java/org/apache/karaf/webconsole/karaf/features/KarafFeaturesPage.java
similarity index 90%
rename from karaf/src/main/java/org/apache/karaf/webconsole/karaf/internal/KarafFeaturesPage.java
rename to karaf/features/src/main/java/org/apache/karaf/webconsole/karaf/features/KarafFeaturesPage.java
index ce474a5..f330639 100644
--- a/karaf/src/main/java/org/apache/karaf/webconsole/karaf/internal/KarafFeaturesPage.java
+++ b/karaf/features/src/main/java/org/apache/karaf/webconsole/karaf/features/KarafFeaturesPage.java
@@ -1,4 +1,4 @@
-package org.apache.karaf.webconsole.karaf.internal;
+package org.apache.karaf.webconsole.karaf.features;
 
 import org.apache.karaf.features.FeaturesService;
 import org.apache.karaf.webconsole.core.navigation.SidebarProvider;
diff --git a/karaf/src/main/java/org/apache/karaf/webconsole/karaf/internal/MissingFeatureException.java b/karaf/features/src/main/java/org/apache/karaf/webconsole/karaf/features/MissingFeatureException.java
similarity index 94%
rename from karaf/src/main/java/org/apache/karaf/webconsole/karaf/internal/MissingFeatureException.java
rename to karaf/features/src/main/java/org/apache/karaf/webconsole/karaf/features/MissingFeatureException.java
index 73d85d6..464b478 100644
--- a/karaf/src/main/java/org/apache/karaf/webconsole/karaf/internal/MissingFeatureException.java
+++ b/karaf/features/src/main/java/org/apache/karaf/webconsole/karaf/features/MissingFeatureException.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.karaf.webconsole.karaf.internal;
+package org.apache.karaf.webconsole.karaf.features;
 
 public class MissingFeatureException extends RuntimeException {
 
diff --git a/karaf/src/main/java/org/apache/karaf/webconsole/karaf/internal/RepositoriesProvider.java b/karaf/features/src/main/java/org/apache/karaf/webconsole/karaf/features/RepositoriesProvider.java
similarity index 93%
rename from karaf/src/main/java/org/apache/karaf/webconsole/karaf/internal/RepositoriesProvider.java
rename to karaf/features/src/main/java/org/apache/karaf/webconsole/karaf/features/RepositoriesProvider.java
index 3b685d2..86f640f 100644
--- a/karaf/src/main/java/org/apache/karaf/webconsole/karaf/internal/RepositoriesProvider.java
+++ b/karaf/features/src/main/java/org/apache/karaf/webconsole/karaf/features/RepositoriesProvider.java
@@ -14,14 +14,14 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.karaf.webconsole.karaf.internal;
+package org.apache.karaf.webconsole.karaf.features;
 
 import java.util.Arrays;
 import java.util.Iterator;
 
 import org.apache.karaf.features.FeaturesService;
 import org.apache.karaf.features.Repository;
-import org.apache.karaf.webconsole.karaf.internal.model.RepositoryModel;
+import org.apache.karaf.webconsole.karaf.features.model.RepositoryModel;
 import org.apache.wicket.extensions.markup.html.repeater.util.SortableDataProvider;
 import org.apache.wicket.model.IModel;
 
diff --git a/karaf/src/main/java/org/apache/karaf/webconsole/karaf/internal/feature/FeaturesActionsPanel.java b/karaf/features/src/main/java/org/apache/karaf/webconsole/karaf/features/feature/FeaturesActionsPanel.java
similarity index 97%
rename from karaf/src/main/java/org/apache/karaf/webconsole/karaf/internal/feature/FeaturesActionsPanel.java
rename to karaf/features/src/main/java/org/apache/karaf/webconsole/karaf/features/feature/FeaturesActionsPanel.java
index 8d8f660..e5fa414 100644
--- a/karaf/src/main/java/org/apache/karaf/webconsole/karaf/internal/feature/FeaturesActionsPanel.java
+++ b/karaf/features/src/main/java/org/apache/karaf/webconsole/karaf/features/feature/FeaturesActionsPanel.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.karaf.webconsole.karaf.internal.feature;
+package org.apache.karaf.webconsole.karaf.features.feature;
 
 import java.util.Arrays;
 import java.util.List;
diff --git a/karaf/src/main/java/org/apache/karaf/webconsole/karaf/internal/feature/FeaturesPage.java b/karaf/features/src/main/java/org/apache/karaf/webconsole/karaf/features/feature/FeaturesPage.java
similarity index 95%
rename from karaf/src/main/java/org/apache/karaf/webconsole/karaf/internal/feature/FeaturesPage.java
rename to karaf/features/src/main/java/org/apache/karaf/webconsole/karaf/features/feature/FeaturesPage.java
index cb21c00..0f24ae4 100644
--- a/karaf/src/main/java/org/apache/karaf/webconsole/karaf/internal/feature/FeaturesPage.java
+++ b/karaf/features/src/main/java/org/apache/karaf/webconsole/karaf/features/feature/FeaturesPage.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.karaf.webconsole.karaf.internal.feature;
+package org.apache.karaf.webconsole.karaf.features.feature;
 
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -23,8 +23,8 @@
 
 import org.apache.karaf.features.Feature;
 import org.apache.karaf.features.Repository;
-import org.apache.karaf.webconsole.karaf.internal.FeaturesProvider;
-import org.apache.karaf.webconsole.karaf.internal.KarafFeaturesPage;
+import org.apache.karaf.webconsole.karaf.features.FeaturesProvider;
+import org.apache.karaf.webconsole.karaf.features.KarafFeaturesPage;
 import org.apache.wicket.extensions.markup.html.repeater.data.grid.ICellPopulator;
 import org.apache.wicket.extensions.markup.html.repeater.data.table.AbstractColumn;
 import org.apache.wicket.extensions.markup.html.repeater.data.table.DefaultDataTable;
diff --git a/karaf/src/main/java/org/apache/karaf/webconsole/karaf/internal/model/RepositoryModel.java b/karaf/features/src/main/java/org/apache/karaf/webconsole/karaf/features/model/RepositoryModel.java
similarity index 96%
rename from karaf/src/main/java/org/apache/karaf/webconsole/karaf/internal/model/RepositoryModel.java
rename to karaf/features/src/main/java/org/apache/karaf/webconsole/karaf/features/model/RepositoryModel.java
index 17d8762..f1741fb 100644
--- a/karaf/src/main/java/org/apache/karaf/webconsole/karaf/internal/model/RepositoryModel.java
+++ b/karaf/features/src/main/java/org/apache/karaf/webconsole/karaf/features/model/RepositoryModel.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.karaf.webconsole.karaf.internal.model;
+package org.apache.karaf.webconsole.karaf.features.model;
 
 import java.net.URI;
 
diff --git a/karaf/src/main/java/org/apache/karaf/webconsole/karaf/internal/model/RepositoryNotFoundException.java b/karaf/features/src/main/java/org/apache/karaf/webconsole/karaf/features/model/RepositoryNotFoundException.java
similarity index 94%
rename from karaf/src/main/java/org/apache/karaf/webconsole/karaf/internal/model/RepositoryNotFoundException.java
rename to karaf/features/src/main/java/org/apache/karaf/webconsole/karaf/features/model/RepositoryNotFoundException.java
index 6548f08..7f5b7bd 100644
--- a/karaf/src/main/java/org/apache/karaf/webconsole/karaf/internal/model/RepositoryNotFoundException.java
+++ b/karaf/features/src/main/java/org/apache/karaf/webconsole/karaf/features/model/RepositoryNotFoundException.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.karaf.webconsole.karaf.internal.model;
+package org.apache.karaf.webconsole.karaf.features.model;
 
 import java.net.URI;
 
diff --git a/karaf/src/main/java/org/apache/karaf/webconsole/karaf/internal/navigation/KarafConsoleTabProvider.java b/karaf/features/src/main/java/org/apache/karaf/webconsole/karaf/features/navigation/FeaturesNavigationProvider.java
similarity index 71%
rename from karaf/src/main/java/org/apache/karaf/webconsole/karaf/internal/navigation/KarafConsoleTabProvider.java
rename to karaf/features/src/main/java/org/apache/karaf/webconsole/karaf/features/navigation/FeaturesNavigationProvider.java
index cda7601..bb36469 100644
--- a/karaf/src/main/java/org/apache/karaf/webconsole/karaf/internal/navigation/KarafConsoleTabProvider.java
+++ b/karaf/features/src/main/java/org/apache/karaf/webconsole/karaf/features/navigation/FeaturesNavigationProvider.java
@@ -14,30 +14,28 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.karaf.webconsole.karaf.internal.navigation;
+package org.apache.karaf.webconsole.karaf.features.navigation;
 
 import java.util.ArrayList;
 import java.util.List;
 
-import org.apache.karaf.webconsole.core.navigation.ConsoleTabProvider;
-import org.apache.karaf.webconsole.karaf.internal.feature.FeaturesPage;
-import org.apache.karaf.webconsole.karaf.internal.repository.RepositoriesPage;
+import org.apache.karaf.webconsole.core.navigation.NavigationProvider;
+import org.apache.karaf.webconsole.karaf.features.feature.FeaturesPage;
+import org.apache.karaf.webconsole.karaf.features.repository.RepositoriesPage;
 import org.apache.wicket.Page;
 import org.apache.wicket.markup.html.basic.Label;
 import org.apache.wicket.markup.html.link.BookmarkablePageLink;
 import org.apache.wicket.markup.html.link.Link;
 import org.apache.wicket.model.ResourceModel;
 
-public class KarafConsoleTabProvider implements ConsoleTabProvider {
-
-    public Link<Page> getModuleLink(String componentId, String labelId) {
-        return createFeaturesLink(componentId, labelId);
-    }
+public class FeaturesNavigationProvider implements NavigationProvider {
 
     public List<Link<Page>> getItems(String componentId, String labelId) {
         List<Link<Page>> items = new ArrayList<Link<Page>>();
 
-        Link<Page> link = createFeaturesLink(componentId, labelId);
+        Link<Page> link = new BookmarkablePageLink<Page>(componentId, FeaturesPage.class);
+        link.add(new Label(labelId, new ResourceModel("features", "Features")));
+        items.add(link);
 
         link = new BookmarkablePageLink<Page>(componentId, RepositoriesPage.class);
         link.add(new Label(labelId, new ResourceModel("repositories", "Repositories")));
@@ -46,11 +44,5 @@
         return items;
     }
 
-    private Link<Page> createFeaturesLink(String componentId, String labelId) {
-        Link<Page> link = new BookmarkablePageLink<Page>(componentId, FeaturesPage.class);
-        link.add(new Label(labelId, new ResourceModel("features", "Features")));
-
-        return link;
-    }
 
 }
diff --git a/karaf/src/main/java/org/apache/karaf/webconsole/karaf/internal/repository/AddRepositoryForm.java b/karaf/features/src/main/java/org/apache/karaf/webconsole/karaf/features/repository/AddRepositoryForm.java
similarity index 97%
rename from karaf/src/main/java/org/apache/karaf/webconsole/karaf/internal/repository/AddRepositoryForm.java
rename to karaf/features/src/main/java/org/apache/karaf/webconsole/karaf/features/repository/AddRepositoryForm.java
index 5f1a89f..2653ccc 100644
--- a/karaf/src/main/java/org/apache/karaf/webconsole/karaf/internal/repository/AddRepositoryForm.java
+++ b/karaf/features/src/main/java/org/apache/karaf/webconsole/karaf/features/repository/AddRepositoryForm.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.karaf.webconsole.karaf.internal.repository;
+package org.apache.karaf.webconsole.karaf.features.repository;
 
 import java.net.URI;
 import java.net.URISyntaxException;
diff --git a/karaf/src/main/java/org/apache/karaf/webconsole/karaf/internal/repository/AddRepositoryPage.java b/karaf/features/src/main/java/org/apache/karaf/webconsole/karaf/features/repository/AddRepositoryPage.java
similarity index 89%
rename from karaf/src/main/java/org/apache/karaf/webconsole/karaf/internal/repository/AddRepositoryPage.java
rename to karaf/features/src/main/java/org/apache/karaf/webconsole/karaf/features/repository/AddRepositoryPage.java
index 31c5a5e..9b1c77b 100644
--- a/karaf/src/main/java/org/apache/karaf/webconsole/karaf/internal/repository/AddRepositoryPage.java
+++ b/karaf/features/src/main/java/org/apache/karaf/webconsole/karaf/features/repository/AddRepositoryPage.java
@@ -14,9 +14,9 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.karaf.webconsole.karaf.internal.repository;
+package org.apache.karaf.webconsole.karaf.features.repository;
 
-import org.apache.karaf.webconsole.karaf.internal.KarafFeaturesPage;
+import org.apache.karaf.webconsole.karaf.features.KarafFeaturesPage;
 import org.ops4j.pax.wicket.api.PaxWicketMountPoint;
 
 @PaxWicketMountPoint(mountPoint = "/karaf/repositories/add")
diff --git a/karaf/src/main/java/org/apache/karaf/webconsole/karaf/internal/repository/RepositoriesActionPanel.java b/karaf/features/src/main/java/org/apache/karaf/webconsole/karaf/features/repository/RepositoriesActionPanel.java
similarity index 96%
rename from karaf/src/main/java/org/apache/karaf/webconsole/karaf/internal/repository/RepositoriesActionPanel.java
rename to karaf/features/src/main/java/org/apache/karaf/webconsole/karaf/features/repository/RepositoriesActionPanel.java
index 888f141..ccbd00f 100644
--- a/karaf/src/main/java/org/apache/karaf/webconsole/karaf/internal/repository/RepositoriesActionPanel.java
+++ b/karaf/features/src/main/java/org/apache/karaf/webconsole/karaf/features/repository/RepositoriesActionPanel.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.karaf.webconsole.karaf.internal.repository;
+package org.apache.karaf.webconsole.karaf.features.repository;
 
 import java.util.ArrayList;
 import java.util.List;
diff --git a/karaf/src/main/java/org/apache/karaf/webconsole/karaf/internal/repository/RepositoriesPage.java b/karaf/features/src/main/java/org/apache/karaf/webconsole/karaf/features/repository/RepositoriesPage.java
similarity index 92%
rename from karaf/src/main/java/org/apache/karaf/webconsole/karaf/internal/repository/RepositoriesPage.java
rename to karaf/features/src/main/java/org/apache/karaf/webconsole/karaf/features/repository/RepositoriesPage.java
index 7b84008..970d836 100644
--- a/karaf/src/main/java/org/apache/karaf/webconsole/karaf/internal/repository/RepositoriesPage.java
+++ b/karaf/features/src/main/java/org/apache/karaf/webconsole/karaf/features/repository/RepositoriesPage.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.karaf.webconsole.karaf.internal.repository;
+package org.apache.karaf.webconsole.karaf.features.repository;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -23,8 +23,8 @@
 import org.apache.karaf.features.Repository;
 import org.apache.karaf.webconsole.core.page.SidebarPage;
 import org.apache.karaf.webconsole.core.table.OrdinalColumn;
-import org.apache.karaf.webconsole.karaf.internal.KarafFeaturesPage;
-import org.apache.karaf.webconsole.karaf.internal.RepositoriesProvider;
+import org.apache.karaf.webconsole.karaf.features.KarafFeaturesPage;
+import org.apache.karaf.webconsole.karaf.features.RepositoriesProvider;
 import org.apache.wicket.Page;
 import org.apache.wicket.extensions.markup.html.repeater.data.grid.ICellPopulator;
 import org.apache.wicket.extensions.markup.html.repeater.data.table.AbstractColumn;
diff --git a/karaf/src/main/java/org/apache/karaf/webconsole/karaf/internal/sidebar/KarafFeaturesSidebar.java b/karaf/features/src/main/java/org/apache/karaf/webconsole/karaf/features/sidebar/KarafFeaturesSidebar.java
similarity index 88%
rename from karaf/src/main/java/org/apache/karaf/webconsole/karaf/internal/sidebar/KarafFeaturesSidebar.java
rename to karaf/features/src/main/java/org/apache/karaf/webconsole/karaf/features/sidebar/KarafFeaturesSidebar.java
index 7fad1e5..f21f32c 100644
--- a/karaf/src/main/java/org/apache/karaf/webconsole/karaf/internal/sidebar/KarafFeaturesSidebar.java
+++ b/karaf/features/src/main/java/org/apache/karaf/webconsole/karaf/features/sidebar/KarafFeaturesSidebar.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.karaf.webconsole.karaf.internal.sidebar;
+package org.apache.karaf.webconsole.karaf.features.sidebar;
 
 import static org.apache.karaf.webconsole.core.util.LinkUtils.createPageLink;
 
@@ -24,9 +24,9 @@
 
 import org.apache.karaf.webconsole.core.navigation.SidebarProvider;
 import org.apache.karaf.webconsole.core.widget.WidgetProvider;
-import org.apache.karaf.webconsole.karaf.internal.feature.FeaturesPage;
-import org.apache.karaf.webconsole.karaf.internal.repository.AddRepositoryPage;
-import org.apache.karaf.webconsole.karaf.internal.repository.RepositoriesPage;
+import org.apache.karaf.webconsole.karaf.features.feature.FeaturesPage;
+import org.apache.karaf.webconsole.karaf.features.repository.AddRepositoryPage;
+import org.apache.karaf.webconsole.karaf.features.repository.RepositoriesPage;
 import org.apache.wicket.Page;
 import org.apache.wicket.markup.html.link.Link;
 
diff --git a/karaf/src/main/java/org/apache/karaf/webconsole/karaf/internal/widget/FeaturesWidgetPanel.java b/karaf/features/src/main/java/org/apache/karaf/webconsole/karaf/features/widget/FeaturesWidgetPanel.java
similarity index 90%
rename from karaf/src/main/java/org/apache/karaf/webconsole/karaf/internal/widget/FeaturesWidgetPanel.java
rename to karaf/features/src/main/java/org/apache/karaf/webconsole/karaf/features/widget/FeaturesWidgetPanel.java
index ba9aae1..f196cf3 100644
--- a/karaf/src/main/java/org/apache/karaf/webconsole/karaf/internal/widget/FeaturesWidgetPanel.java
+++ b/karaf/features/src/main/java/org/apache/karaf/webconsole/karaf/features/widget/FeaturesWidgetPanel.java
@@ -14,12 +14,12 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.karaf.webconsole.karaf.internal.widget;
+package org.apache.karaf.webconsole.karaf.features.widget;
 
 import org.apache.karaf.features.Feature;
 import org.apache.karaf.features.FeaturesService;
-import org.apache.karaf.webconsole.karaf.internal.feature.FeaturesPage;
-import org.apache.karaf.webconsole.karaf.internal.repository.RepositoriesPage;
+import org.apache.karaf.webconsole.karaf.features.feature.FeaturesPage;
+import org.apache.karaf.webconsole.karaf.features.repository.RepositoriesPage;
 import org.apache.wicket.markup.html.basic.Label;
 import org.apache.wicket.markup.html.link.BookmarkablePageLink;
 import org.apache.wicket.markup.html.panel.Panel;
diff --git a/karaf/src/main/java/org/apache/karaf/webconsole/karaf/internal/widget/KarafFeaturesWidgetProvider.java b/karaf/features/src/main/java/org/apache/karaf/webconsole/karaf/features/widget/KarafFeaturesWidgetProvider.java
similarity index 95%
rename from karaf/src/main/java/org/apache/karaf/webconsole/karaf/internal/widget/KarafFeaturesWidgetProvider.java
rename to karaf/features/src/main/java/org/apache/karaf/webconsole/karaf/features/widget/KarafFeaturesWidgetProvider.java
index 756e0ea..4fc4cb0 100644
--- a/karaf/src/main/java/org/apache/karaf/webconsole/karaf/internal/widget/KarafFeaturesWidgetProvider.java
+++ b/karaf/features/src/main/java/org/apache/karaf/webconsole/karaf/features/widget/KarafFeaturesWidgetProvider.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.karaf.webconsole.karaf.internal.widget;
+package org.apache.karaf.webconsole.karaf.features.widget;
 
 import org.apache.karaf.features.FeaturesService;
 import org.apache.karaf.webconsole.core.widget.WidgetProvider;
diff --git a/karaf/src/main/resources/OSGI-INF/blueprint/karaf.xml b/karaf/features/src/main/resources/OSGI-INF/blueprint/features.xml
similarity index 80%
rename from karaf/src/main/resources/OSGI-INF/blueprint/karaf.xml
rename to karaf/features/src/main/resources/OSGI-INF/blueprint/features.xml
index 614ffd6..781c5f4 100644
--- a/karaf/src/main/resources/OSGI-INF/blueprint/karaf.xml
+++ b/karaf/features/src/main/resources/OSGI-INF/blueprint/features.xml
@@ -17,8 +17,11 @@
 -->
 <blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
 
-    <service interface="org.apache.karaf.webconsole.core.navigation.ConsoleTabProvider">
-        <bean class="org.apache.karaf.webconsole.karaf.internal.navigation.KarafConsoleTabProvider" />
+    <service interface="org.apache.karaf.webconsole.core.navigation.NavigationProvider">
+        <service-properties>
+            <entry key="extends" value="karaf" />
+        </service-properties>
+        <bean class="org.apache.karaf.webconsole.karaf.features.navigation.FeaturesNavigationProvider" />
     </service>
 
     <reference id="featuresService" interface="org.apache.karaf.features.FeaturesService"/>
@@ -29,10 +32,10 @@
         </service-properties>
     </service>
 
-    <bean id="widgetProvider" class="org.apache.karaf.webconsole.karaf.internal.widget.KarafFeaturesWidgetProvider">
+    <bean id="widgetProvider" class="org.apache.karaf.webconsole.karaf.features.widget.KarafFeaturesWidgetProvider">
         <argument ref="featuresService" />
     </bean>
 
-    <bean id="featuresSidebar" class="org.apache.karaf.webconsole.karaf.internal.sidebar.KarafFeaturesSidebar" />
+    <bean id="featuresSidebar" class="org.apache.karaf.webconsole.karaf.features.sidebar.KarafFeaturesSidebar" />
 
 </blueprint>
diff --git a/karaf/src/main/resources/org/apache/karaf/webconsole/karaf/internal/feature/FeaturesPage.html b/karaf/features/src/main/resources/org/apache/karaf/webconsole/karaf/features/feature/FeaturesPage.html
similarity index 100%
rename from karaf/src/main/resources/org/apache/karaf/webconsole/karaf/internal/feature/FeaturesPage.html
rename to karaf/features/src/main/resources/org/apache/karaf/webconsole/karaf/features/feature/FeaturesPage.html
diff --git a/karaf/src/main/resources/org/apache/karaf/webconsole/karaf/internal/feature/FeaturesPage.properties b/karaf/features/src/main/resources/org/apache/karaf/webconsole/karaf/features/feature/FeaturesPage.properties
similarity index 100%
rename from karaf/src/main/resources/org/apache/karaf/webconsole/karaf/internal/feature/FeaturesPage.properties
rename to karaf/features/src/main/resources/org/apache/karaf/webconsole/karaf/features/feature/FeaturesPage.properties
diff --git a/karaf/src/main/resources/org/apache/karaf/webconsole/karaf/internal/feature/FeaturesPage_de.properties b/karaf/features/src/main/resources/org/apache/karaf/webconsole/karaf/features/feature/FeaturesPage_de.properties
similarity index 100%
rename from karaf/src/main/resources/org/apache/karaf/webconsole/karaf/internal/feature/FeaturesPage_de.properties
rename to karaf/features/src/main/resources/org/apache/karaf/webconsole/karaf/features/feature/FeaturesPage_de.properties
diff --git a/karaf/src/main/resources/org/apache/karaf/webconsole/karaf/internal/feature/FeaturesPage_fr.properties b/karaf/features/src/main/resources/org/apache/karaf/webconsole/karaf/features/feature/FeaturesPage_fr.properties
similarity index 100%
rename from karaf/src/main/resources/org/apache/karaf/webconsole/karaf/internal/feature/FeaturesPage_fr.properties
rename to karaf/features/src/main/resources/org/apache/karaf/webconsole/karaf/features/feature/FeaturesPage_fr.properties
diff --git a/karaf/src/main/resources/org/apache/karaf/webconsole/karaf/internal/feature/features.css b/karaf/features/src/main/resources/org/apache/karaf/webconsole/karaf/features/feature/features.css
similarity index 100%
rename from karaf/src/main/resources/org/apache/karaf/webconsole/karaf/internal/feature/features.css
rename to karaf/features/src/main/resources/org/apache/karaf/webconsole/karaf/features/feature/features.css
diff --git a/karaf/src/main/resources/org/apache/karaf/webconsole/karaf/internal/feature/images/feature_install.png b/karaf/features/src/main/resources/org/apache/karaf/webconsole/karaf/features/feature/images/feature_install.png
similarity index 100%
rename from karaf/src/main/resources/org/apache/karaf/webconsole/karaf/internal/feature/images/feature_install.png
rename to karaf/features/src/main/resources/org/apache/karaf/webconsole/karaf/features/feature/images/feature_install.png
Binary files differ
diff --git a/karaf/src/main/resources/org/apache/karaf/webconsole/karaf/internal/feature/images/feature_uninstall.png b/karaf/features/src/main/resources/org/apache/karaf/webconsole/karaf/features/feature/images/feature_uninstall.png
similarity index 100%
rename from karaf/src/main/resources/org/apache/karaf/webconsole/karaf/internal/feature/images/feature_uninstall.png
rename to karaf/features/src/main/resources/org/apache/karaf/webconsole/karaf/features/feature/images/feature_uninstall.png
Binary files differ
diff --git a/karaf/src/main/resources/org/apache/karaf/webconsole/karaf/internal/navigation/package_fr.properties b/karaf/features/src/main/resources/org/apache/karaf/webconsole/karaf/features/navigation/package_fr.properties
similarity index 100%
rename from karaf/src/main/resources/org/apache/karaf/webconsole/karaf/internal/navigation/package_fr.properties
rename to karaf/features/src/main/resources/org/apache/karaf/webconsole/karaf/features/navigation/package_fr.properties
diff --git a/karaf/src/main/resources/org/apache/karaf/webconsole/karaf/internal/repository/AddRepositoryPage.html b/karaf/features/src/main/resources/org/apache/karaf/webconsole/karaf/features/repository/AddRepositoryPage.html
similarity index 100%
rename from karaf/src/main/resources/org/apache/karaf/webconsole/karaf/internal/repository/AddRepositoryPage.html
rename to karaf/features/src/main/resources/org/apache/karaf/webconsole/karaf/features/repository/AddRepositoryPage.html
diff --git a/karaf/src/main/resources/org/apache/karaf/webconsole/karaf/internal/repository/RepositoriesPage.html b/karaf/features/src/main/resources/org/apache/karaf/webconsole/karaf/features/repository/RepositoriesPage.html
similarity index 100%
rename from karaf/src/main/resources/org/apache/karaf/webconsole/karaf/internal/repository/RepositoriesPage.html
rename to karaf/features/src/main/resources/org/apache/karaf/webconsole/karaf/features/repository/RepositoriesPage.html
diff --git a/karaf/src/main/resources/org/apache/karaf/webconsole/karaf/internal/widget/FeaturesWidgetPanel.html b/karaf/features/src/main/resources/org/apache/karaf/webconsole/karaf/features/widget/FeaturesWidgetPanel.html
similarity index 100%
rename from karaf/src/main/resources/org/apache/karaf/webconsole/karaf/internal/widget/FeaturesWidgetPanel.html
rename to karaf/features/src/main/resources/org/apache/karaf/webconsole/karaf/features/widget/FeaturesWidgetPanel.html
diff --git a/karaf/pom.xml b/karaf/pom.xml
index 4f130da..05c5020 100644
--- a/karaf/pom.xml
+++ b/karaf/pom.xml
@@ -26,47 +26,34 @@
     </parent>
 
     <groupId>org.apache.karaf.webconsole</groupId>
-    <artifactId>org.apache.karaf.webconsole.karaf</artifactId>
-    <name>Apache Karaf :: WebConsole :: Karaf extension</name>
-    <packaging>bundle</packaging>
+    <artifactId>karaf</artifactId>
+    <name>Apache Karaf :: WebConsole :: Karaf</name>
+    <packaging>pom</packaging>
 
-    <dependencies>
-        <dependency>
-            <groupId>org.apache.karaf.webconsole</groupId>
-            <artifactId>org.apache.karaf.webconsole.core</artifactId>
-            <version>${project.version}</version>
-        </dependency>
+    <modules>
+        <module>core</module>
+        <module>admin</module>
+        <module>features</module>
+    </modules>
 
-        <dependency>
-            <groupId>org.apache.karaf.features</groupId>
-            <artifactId>org.apache.karaf.features.core</artifactId>
-            <version>${karaf.version}</version>
-        </dependency>
-    </dependencies>
+    <dependencyManagement>
+        <dependencies>
+            <dependency>
+                <groupId>org.apache.karaf.webconsole</groupId>
+                <artifactId>org.apache.karaf.webconsole.core</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.apache.karaf.features</groupId>
+                <artifactId>org.apache.karaf.features.core</artifactId>
+                <version>${karaf.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.apache.karaf.admin</groupId>
+                <artifactId>org.apache.karaf.admin.core</artifactId>
+                <version>${karaf.version}</version>
+            </dependency>
+        </dependencies>
+    </dependencyManagement>
 
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.felix</groupId>
-                <artifactId>maven-bundle-plugin</artifactId>
-                <version>2.3.5</version>
-                <extensions>true</extensions>
-                <configuration>
-                    <instructions>
-                        <Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
-                        <Import-Package>
-                            !org.apache.karaf.webconsole.karaf*,
-                            *,
-                            <!-- transient dependencies -->
-                            org.ops4j.pax.wicket.api,
-                            org.ops4j.pax.wicket.util,
-                            org.ops4j.pax.wicket.util.proxy,
-                            <!-- karaf -->
-                            org.apache.karaf.features
-                        </Import-Package>
-                    </instructions>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-</project>
+</project>
\ No newline at end of file