CXF extension. Requires 2.4.3-SNAPSHOT or 2.5.0-SNAPSHOT version to discover cxf bus instances. Tracing is not possible right now, details page shows only some basic informations from bus/ServerRegistry instances.

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

git-svn-id: https://svn.apache.org/repos/asf/karaf/webconsole/trunk@1166605 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/cxf/pom.xml b/cxf/pom.xml
new file mode 100644
index 0000000..e0f8974
--- /dev/null
+++ b/cxf/pom.xml
@@ -0,0 +1,77 @@
+<?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</groupId>
+        <artifactId>webconsole</artifactId>
+        <version>1.0.0-SNAPSHOT</version>
+    </parent>
+
+    <groupId>org.apache.karaf.webconsole</groupId>
+    <artifactId>org.apache.karaf.webconsole.cxf</artifactId>
+    <packaging>bundle</packaging>
+    <name>Apache Karaf :: Karaf Webconsole Prototype :: CXF extension</name>
+    <version>1.0.0-SNAPSHOT</version>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.karaf.webconsole</groupId>
+            <artifactId>org.apache.karaf.webconsole.core</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.cxf</groupId>
+            <artifactId>cxf-rt-core</artifactId>
+            <version>${cxf.version}</version>
+        </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.cxf*,
+                            *,
+                            <!-- transient dependencies -->
+                            org.ops4j.pax.wicket.api,
+                            org.ops4j.pax.wicket.util,
+                            org.ops4j.pax.wicket.util.proxy,
+                            <!-- camel dependencies -->
+                            org.apache.cxf;version="[2.3,3)",
+                            <!-- cglib (transient) -->
+                            net.sf.cglib.proxy;version="[2,3)",
+                            net.sf.cglib.core;version="[2,3)",
+                            net.sf.cglib.reflect;version="[2,3)",
+                        </Import-Package>
+                    </instructions>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/cxf/src/main/java/org/apache/karaf/webconsole/cxf/internal/BusFinder.java b/cxf/src/main/java/org/apache/karaf/webconsole/cxf/internal/BusFinder.java
new file mode 100644
index 0000000..20c38e8
--- /dev/null
+++ b/cxf/src/main/java/org/apache/karaf/webconsole/cxf/internal/BusFinder.java
@@ -0,0 +1,11 @@
+package org.apache.karaf.webconsole.cxf.internal;
+
+import java.util.List;
+
+import org.apache.cxf.Bus;
+
+public interface BusFinder {
+
+    List<Bus> getBuses();
+
+}
diff --git a/cxf/src/main/java/org/apache/karaf/webconsole/cxf/internal/DefaultBusFinder.java b/cxf/src/main/java/org/apache/karaf/webconsole/cxf/internal/DefaultBusFinder.java
new file mode 100644
index 0000000..ee22525
--- /dev/null
+++ b/cxf/src/main/java/org/apache/karaf/webconsole/cxf/internal/DefaultBusFinder.java
@@ -0,0 +1,70 @@
+package org.apache.karaf.webconsole.cxf.internal;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.cxf.Bus;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceEvent;
+import org.osgi.framework.ServiceListener;
+import org.osgi.framework.ServiceReference;
+import org.springframework.context.ApplicationContext;
+
+public class DefaultBusFinder implements BusFinder, ServiceListener {
+
+    private BundleContext context;
+    private List<Bus> buses = Collections.synchronizedList(new LinkedList<Bus>());
+
+    public DefaultBusFinder(BundleContext context) throws InvalidSyntaxException {
+        this.context = context;
+
+        ServiceReference[] references = context.getServiceReferences(ApplicationContext.class.getName(), null);
+        for (ServiceReference reference : references) {
+            String[] classes = (String[]) reference.getProperty(Constants.OBJECTCLASS);
+            for (String clazz : classes) {
+                if (ApplicationContext.class.getName().equals(clazz)) {
+                    buses.addAll(findSpringBus(reference));
+                }
+            }
+        }
+    }
+
+    public List<Bus> getBuses() {
+        return buses;
+    }
+
+    public void serviceChanged(ServiceEvent event) {
+        ServiceReference reference = event.getServiceReference();
+        String[] classes = (String[]) reference.getProperty(Constants.OBJECTCLASS);
+
+        if (event.getType() == ServiceEvent.REGISTERED) {
+            for (String clazz : classes) {
+                if (ApplicationContext.class.getName().equals(clazz)) {
+                    buses.addAll(findSpringBus(reference));
+                }
+            }
+        } else if (event.getType() == ServiceEvent.UNREGISTERING) {
+            for (String clazz : classes) {
+                if (ApplicationContext.class.getName().equals(clazz)) {
+                    buses.removeAll(findSpringBus(reference));
+                }
+            }
+            
+        }
+    }
+
+    private Collection<Bus> findSpringBus(ServiceReference reference) {
+        ApplicationContext appContext = (ApplicationContext) context.getService(reference);
+
+        Map<String, Bus> contextBuses = appContext.getBeansOfType(Bus.class);
+
+        context.ungetService(reference);
+        return contextBuses.values();
+    }
+
+}
diff --git a/cxf/src/main/java/org/apache/karaf/webconsole/cxf/internal/navigation/CxfConsoleTabProvider.java b/cxf/src/main/java/org/apache/karaf/webconsole/cxf/internal/navigation/CxfConsoleTabProvider.java
new file mode 100644
index 0000000..5bf3540
--- /dev/null
+++ b/cxf/src/main/java/org/apache/karaf/webconsole/cxf/internal/navigation/CxfConsoleTabProvider.java
@@ -0,0 +1,23 @@
+package org.apache.karaf.webconsole.cxf.internal.navigation;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.karaf.webconsole.core.navigation.ConsoleTabProvider;
+import org.apache.karaf.webconsole.core.util.LinkUtils;
+import org.apache.karaf.webconsole.cxf.internal.services.CxfServicesPage;
+import org.apache.wicket.Page;
+import org.apache.wicket.markup.html.link.Link;
+
+public class CxfConsoleTabProvider implements ConsoleTabProvider {
+
+    public List<Link<Page>> getItems(String componentId, String labelId) {
+        return Collections.emptyList();
+    }
+
+    public Link<Page> getModuleLink(String componentId, String labelId) {
+        return LinkUtils.createPageLink(componentId, labelId, "CXF", CxfServicesPage.class);
+    }
+
+
+}
diff --git a/cxf/src/main/java/org/apache/karaf/webconsole/cxf/internal/services/BusModel.java b/cxf/src/main/java/org/apache/karaf/webconsole/cxf/internal/services/BusModel.java
new file mode 100644
index 0000000..4f08888
--- /dev/null
+++ b/cxf/src/main/java/org/apache/karaf/webconsole/cxf/internal/services/BusModel.java
@@ -0,0 +1,35 @@
+package org.apache.karaf.webconsole.cxf.internal.services;
+
+import java.util.List;
+
+import org.apache.cxf.Bus;
+import org.apache.wicket.model.LoadableDetachableModel;
+
+public class BusModel extends LoadableDetachableModel<Bus> {
+
+    private List<Bus> buses;
+    private String id;
+
+    public BusModel(List<Bus> buses, Bus object) {
+        super(object);
+        this.buses = buses;
+        this.id = object.getId();
+    }
+
+    public BusModel(List<Bus> buses, String id) {
+        this.buses = buses;
+        this.id = id;
+    }
+
+    @Override
+    protected Bus load() {
+        for (Bus bus : buses) {
+            if (id.equals(bus.getId())) {
+                return bus;
+            }
+        }
+
+        throw new IllegalArgumentException("Bus " + id + " not found");
+    }
+
+}
diff --git a/cxf/src/main/java/org/apache/karaf/webconsole/cxf/internal/services/CxfBusesActionPanel.java b/cxf/src/main/java/org/apache/karaf/webconsole/cxf/internal/services/CxfBusesActionPanel.java
new file mode 100644
index 0000000..c77c7f3
--- /dev/null
+++ b/cxf/src/main/java/org/apache/karaf/webconsole/cxf/internal/services/CxfBusesActionPanel.java
@@ -0,0 +1,33 @@
+package org.apache.karaf.webconsole.cxf.internal.services;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.cxf.Bus;
+import org.apache.karaf.webconsole.core.table.ActionsPanel;
+import org.apache.wicket.PageParameters;
+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.IModel;
+
+public class CxfBusesActionPanel extends ActionsPanel<Bus> {
+
+    public CxfBusesActionPanel(String componentId, IModel<Bus> model) {
+        super(componentId, model);
+    }
+
+    @Override
+    protected List<Link> getLinks(Bus object, String id) {
+        List<Link> links = new ArrayList<Link>();
+
+        PageParameters params = new PageParameters();
+        params.put("busId", object.getId());
+
+        Link link = new BookmarkablePageLink<DetailsPage>(id, DetailsPage.class, params);
+        link.add(new Label("label", "Details"));
+        links.add(link);
+
+        return links;
+    }
+}
diff --git a/cxf/src/main/java/org/apache/karaf/webconsole/cxf/internal/services/CxfServicesPage.java b/cxf/src/main/java/org/apache/karaf/webconsole/cxf/internal/services/CxfServicesPage.java
new file mode 100644
index 0000000..5e489d2
--- /dev/null
+++ b/cxf/src/main/java/org/apache/karaf/webconsole/cxf/internal/services/CxfServicesPage.java
@@ -0,0 +1,56 @@
+package org.apache.karaf.webconsole.cxf.internal.services;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.cxf.Bus;
+import org.apache.karaf.webconsole.core.page.SinglePage;
+import org.apache.karaf.webconsole.core.table.OrdinalColumn;
+import org.apache.karaf.webconsole.core.table.PropertyColumnExt;
+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.extensions.markup.html.repeater.data.table.ISortableDataProvider;
+import org.apache.wicket.extensions.markup.html.repeater.util.SortableDataProvider;
+import org.apache.wicket.markup.repeater.Item;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.Model;
+import org.ops4j.pax.wicket.api.PaxWicketBean;
+
+public class CxfServicesPage extends SinglePage {
+
+    @PaxWicketBean(name = "busList")
+    private List<Bus> buses;
+
+    public CxfServicesPage() {
+        @SuppressWarnings("unchecked")
+        IColumn<Bus>[] columns = new IColumn[] {
+            new OrdinalColumn<Bus>(),
+            new PropertyColumnExt<Bus>("Bus id", "id"),
+            new AbstractColumn<Bus>(Model.of("Actions")) {
+                public void populateItem(Item<ICellPopulator<Bus>> cellItem, String componentId, IModel<Bus> rowModel) {
+                    cellItem.add(new CxfBusesActionPanel(componentId, rowModel));
+                }
+            }
+        };
+
+        ISortableDataProvider<Bus> provider = new SortableDataProvider<Bus>() {
+            public Iterator<? extends Bus> iterator(int first, int count) {
+                return new ArrayList<Bus>(buses).subList(first, first + count).iterator();
+            }
+
+            public int size() {
+                return buses.size();
+            }
+
+            public IModel<Bus> model(Bus object) {
+                return new BusModel(buses, object);
+            }
+        };
+
+        add(new DefaultDataTable<Bus>("buses", columns, provider, 20));
+    }
+
+}
diff --git a/cxf/src/main/java/org/apache/karaf/webconsole/cxf/internal/services/DetailsPage.java b/cxf/src/main/java/org/apache/karaf/webconsole/cxf/internal/services/DetailsPage.java
new file mode 100644
index 0000000..bca3956
--- /dev/null
+++ b/cxf/src/main/java/org/apache/karaf/webconsole/cxf/internal/services/DetailsPage.java
@@ -0,0 +1,127 @@
+package org.apache.karaf.webconsole.cxf.internal.services;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.cxf.Bus;
+import org.apache.cxf.endpoint.Endpoint;
+import org.apache.cxf.endpoint.Server;
+import org.apache.cxf.endpoint.ServerRegistry;
+import org.apache.cxf.interceptor.Interceptor;
+import org.apache.cxf.phase.Phase;
+import org.apache.cxf.service.model.EndpointInfo;
+import org.apache.cxf.service.model.OperationInfo;
+import org.apache.cxf.service.model.ServiceInfo;
+import org.apache.karaf.webconsole.core.page.SinglePage;
+import org.apache.karaf.webconsole.cxf.internal.trace.TraceInterceptor;
+import org.apache.wicket.PageParameters;
+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.markup.html.list.ListItem;
+import org.apache.wicket.markup.html.list.ListView;
+import org.apache.wicket.model.LoadableDetachableModel;
+import org.ops4j.pax.wicket.api.PaxWicketBean;
+
+public class DetailsPage extends SinglePage {
+
+    @PaxWicketBean(name = "busList")
+    private List<Bus> buses;
+
+    private TraceInterceptor traceIn = new TraceInterceptor(Phase.RECEIVE, "in");
+    private TraceInterceptor traceOut = new TraceInterceptor(Phase.PRE_STREAM, "out");
+
+    public DetailsPage(PageParameters params) {
+        String busId = params.getString("busId");
+
+        final BusModel model = new BusModel(buses, busId);
+
+        Bus object = model.getObject();
+
+        add(new Link("traceOn") {
+            @Override
+            public void onClick() {
+                Bus bus = model.getObject();
+
+                Session.get().info("Trace enabled");
+                bus.getInInterceptors().add(traceIn);
+                bus.getOutInterceptors().add(traceOut);
+            }
+        });
+
+        add(new Link("traceOff") {
+            @Override
+            public void onClick() {
+                Bus bus = model.getObject();
+
+                Session.get().info("Trace disabled");
+                bus.getInInterceptors().remove(traceIn);
+                bus.getOutInterceptors().remove(traceOut);
+            }
+        });
+
+        ServerRegistry extension = object.getExtension(ServerRegistry.class);
+        LoadableDetachableModel<List<Server>> serverModel = new LoadableDetachableModel<List<Server>>(extension.getServers()) {
+            @Override
+            protected List<Server> load() {
+                return model.getObject().getExtension(ServerRegistry.class).getServers();
+            }
+        };
+
+        add(new ListView<Server>("servers", serverModel) {
+            @Override
+            protected void populateItem(ListItem<Server> item) {
+                Server server = item.getModelObject();
+
+                item.add(new Label("class", server.getClass().getName()));
+
+                item.add(new Link("stop") {
+                    @Override
+                    public void onClick() {
+                        //server.stop();
+                    }
+                });
+                item.add(new Link("start") {
+                    @Override
+                    public void onClick() {
+                        //server.start();
+                    }
+                });
+
+                ServiceInfo service = server.getEndpoint().getEndpointInfo().getService();
+                item.add(new ListView<EndpointInfo>("endpoints", new ArrayList<EndpointInfo>(service.getEndpoints())) {
+                    @Override
+                    protected void populateItem(ListItem<EndpointInfo> item) {
+                        EndpointInfo endpointInfo = item.getModelObject();
+
+                        item.add(new Label("namespace", endpointInfo.getName().getNamespaceURI()));
+                        item.add(new Label("element", endpointInfo.getName().getLocalPart()));
+                        item.add(new Label("transport", endpointInfo.getTransportId()));
+
+                        item.add(new ListView<OperationInfo>("operations", new ArrayList<OperationInfo>(endpointInfo.getInterface().getOperations())) {
+
+                            @Override
+                            protected void populateItem(ListItem<OperationInfo> item) {
+                                OperationInfo operation = item.getModelObject();
+
+                                item.add(new Label("input", "" + operation.getInput().getName()));
+                                item.add(new Label("output", "" + operation.getOutput().getName()));
+                                item.add(new Label("faults", "" + operation.getFaults()));
+                            }
+                            
+                        });
+                    }
+                });
+
+                Endpoint endpoint = server.getEndpoint();
+                List<Interceptor> inInterceptors = (List) endpoint.getInInterceptors();
+                List<Interceptor> outInterceptors = (List) endpoint.getOutInterceptors();
+                List<Interceptor> faultInterceptors = (List) endpoint.getInFaultInterceptors();
+
+                item.add(new InterceptorView("in-interceptors", inInterceptors));
+                item.add(new InterceptorView("out-interceptors", outInterceptors));
+                item.add(new InterceptorView("fault-interceptors", faultInterceptors));
+            }
+        });
+    }
+}
diff --git a/cxf/src/main/java/org/apache/karaf/webconsole/cxf/internal/services/InterceptorView.java b/cxf/src/main/java/org/apache/karaf/webconsole/cxf/internal/services/InterceptorView.java
new file mode 100644
index 0000000..b530b84
--- /dev/null
+++ b/cxf/src/main/java/org/apache/karaf/webconsole/cxf/internal/services/InterceptorView.java
@@ -0,0 +1,34 @@
+package org.apache.karaf.webconsole.cxf.internal.services;
+
+import java.util.List;
+
+import org.apache.cxf.interceptor.Interceptor;
+import org.apache.cxf.message.Message;
+import org.apache.cxf.phase.PhaseInterceptor;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.list.ListItem;
+import org.apache.wicket.markup.html.list.ListView;
+
+public class InterceptorView extends ListView<Interceptor> {
+
+    public InterceptorView(String id, List<Interceptor> interceptors) {
+        super(id, interceptors);
+    }
+
+    @Override
+    protected void populateItem(ListItem<Interceptor> item) {
+        Interceptor<? extends Message> interceptor = item.getModelObject();
+
+        item.add(new Label("class", interceptor.getClass().getName()));
+
+        if (interceptor instanceof PhaseInterceptor) {
+            PhaseInterceptor phaseInterceptor = (PhaseInterceptor) interceptor;
+            item.add(new Label("phase", phaseInterceptor.getPhase()));
+            item.add(new Label("id", phaseInterceptor.getId()));
+        } else {
+            item.add(new Label("phase", "no phase interceptor"));
+            item.add(new Label("id", "unknown"));
+        }
+    }
+
+}
diff --git a/cxf/src/main/java/org/apache/karaf/webconsole/cxf/internal/trace/TraceInterceptor.java b/cxf/src/main/java/org/apache/karaf/webconsole/cxf/internal/trace/TraceInterceptor.java
new file mode 100644
index 0000000..ae921e5
--- /dev/null
+++ b/cxf/src/main/java/org/apache/karaf/webconsole/cxf/internal/trace/TraceInterceptor.java
@@ -0,0 +1,22 @@
+package org.apache.karaf.webconsole.cxf.internal.trace;
+
+import java.io.Serializable;
+
+import org.apache.cxf.interceptor.Fault;
+import org.apache.cxf.message.Message;
+import org.apache.cxf.phase.AbstractPhaseInterceptor;
+
+public class TraceInterceptor extends AbstractPhaseInterceptor<Message> implements Serializable {
+
+    private String direction;
+
+    public TraceInterceptor(String phase, String direction) {
+        super(phase);
+        this.direction = direction;
+    }
+
+    public void handleMessage(Message message) throws Fault {
+        System.out.println("--> " + direction + " > " + message);
+    }
+
+}
diff --git a/cxf/src/main/resources/OSGI-INF/blueprint/cxf.xml b/cxf/src/main/resources/OSGI-INF/blueprint/cxf.xml
new file mode 100644
index 0000000..fbea428
--- /dev/null
+++ b/cxf/src/main/resources/OSGI-INF/blueprint/cxf.xml
@@ -0,0 +1,32 @@
+<?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">
+
+    <service interface="org.apache.karaf.webconsole.core.navigation.ConsoleTabProvider">
+        <bean class="org.apache.karaf.webconsole.cxf.internal.navigation.CxfConsoleTabProvider" />
+    </service>
+
+    <bean id="busFinder" class="org.apache.karaf.webconsole.cxf.internal.DefaultBusFinder">
+        <argument ref="blueprintBundleContext" />
+    </bean>
+
+    <service ref="busFinder" auto-export="interfaces" />
+
+    <reference-list id="busList" interface="org.apache.cxf.Bus" availability="optional" />
+
+</blueprint>
diff --git a/cxf/src/main/resources/org/apache/karaf/webconsole/cxf/internal/services/CxfServicesPage.html b/cxf/src/main/resources/org/apache/karaf/webconsole/cxf/internal/services/CxfServicesPage.html
new file mode 100644
index 0000000..8ddf724
--- /dev/null
+++ b/cxf/src/main/resources/org/apache/karaf/webconsole/cxf/internal/services/CxfServicesPage.html
@@ -0,0 +1,33 @@
+<?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">
+<head>
+    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+    <title>Karaf WebConsole</title>
+</head>
+<body>
+
+    <wicket:extend>
+        <h1>Deployed CXF services</h1>
+
+        <table wicket:id="buses" class="dataview" />
+
+    </wicket:extend>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/cxf/src/main/resources/org/apache/karaf/webconsole/cxf/internal/services/DetailsPage.html b/cxf/src/main/resources/org/apache/karaf/webconsole/cxf/internal/services/DetailsPage.html
new file mode 100644
index 0000000..2c4af46
--- /dev/null
+++ b/cxf/src/main/resources/org/apache/karaf/webconsole/cxf/internal/services/DetailsPage.html
@@ -0,0 +1,181 @@
+<?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">
+<head>
+    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+    <title>Karaf WebConsole</title>
+</head>
+<body>
+
+    <wicket:extend>
+        <h1>Bus details</h1>
+
+        <a wicket:id="traceOn">Enable tracing</a>
+        <a wicket:id="traceOff">Disable tracing</a>
+
+        <table class="dataview">
+            <tr>
+                <th colspan="2">Server</th>
+                <th>Operations</th>
+            </tr>
+            <wicket:container wicket:id="servers">
+                <tr>
+                    <td colspan="2">
+                        <span wicket:id="class">org.apache.cxf.rt.SomeClass</span>
+                    </td>
+                    <td>
+                        <a wicket:id="stop">stop</a>
+                        <a wicket:id="start">start</a>
+                    </td>
+                </tr>
+                <tr>
+                    <td colspan="3"><hr /></td>
+                </tr>
+
+                <tr>
+                    <th colspan="3">
+                        <h2>Endpoints</h2>
+                    </th>
+                </tr>
+                <tr>
+                    <th>Namespace</th>
+                    <th>Element</th>
+                    <th>Transport Id</th>
+                </tr>
+                <wicket:container wicket:id="endpoints">
+                    <tr>
+                        <td>
+                            <span wicket:id="namespace">http://someuri</span>
+                        </td>
+                        <td>
+                            <span wicket:id="element">someelem</span>
+                        </td>
+                        <td>
+                            <span wicket:id="transport">soap</span>
+                        </td>
+                    </tr>
+                    <tr>
+                        <th colspan="3">Operations</th>
+                    </tr>
+                    <tr>
+                        <th>Name</th>
+                        <th>Input</th>
+                        <th>Output</th>
+                    </tr>
+                    <wicket:container wicket:id="operations">
+                        <tr>
+                            <td>
+                                <span wicket:id="input">aaa</span>
+                            </td>
+                            <td>
+                                <span wicket:id="output">aaa</span>
+                            </td>
+                            <td>
+                                <span wicket:id="faults">aaa</span>
+                            </td>
+                        </tr>
+                    </wicket:container>
+                </wicket:container>
+                <tr>
+                    <td colspan="3"><hr /></td>
+                </tr>
+
+                <tr>
+                    <th colspan="3">
+                        <h3>In interceptors</h3>
+                    </th>
+                </tr>
+                <tr>
+                    <th width="150px">Id</th>
+                    <th>Class</th>
+                    <th>Phase</th>
+                </tr>
+                <wicket:container wicket:id="in-interceptors">
+                    <tr>
+                        <td>
+                            <span wicket:id="id">some-class</span>
+                        </td>
+                        <td>
+                            <span wicket:id="class">some-class</span>
+                        </td>
+                        <td>
+                            <span wicket:id="phase">some-class</span>
+                        </td>
+                    </tr>
+                </wicket:container>
+                <tr>
+                    <td colspan="3"><hr /></td>
+                </tr>
+
+                <tr>
+                    <th colspan="3">
+                        <h3>Out interceptors</h3>
+                    </th>
+                </tr>
+                <tr>
+                    <th width="150px">Id</th>
+                    <th>Class</th>
+                    <th>Phase</th>
+                </tr>
+                <wicket:container wicket:id="out-interceptors">
+                    <tr>
+                        <td>
+                            <span wicket:id="id">some-class</span>
+                        </td>
+                        <td>
+                            <span wicket:id="class">some-class</span>
+                        </td>
+                        <td>
+                            <span wicket:id="phase">some-class</span>
+                        </td>
+                    </tr>
+                </wicket:container>
+                <tr>
+                    <td colspan="3"><hr /></td>
+                </tr>
+
+                <tr>
+                    <th colspan="3">
+                        <h3>Fault interceptors</h3>
+                    </th>
+                </tr>
+                <tr>
+                    <th width="150px">Id</th>
+                    <th>Class</th>
+                    <th>Phase</th>
+                </tr>
+                <wicket:container wicket:id="fault-interceptors">
+                    <tr>
+                        <td>
+                            <span wicket:id="id">some-class</span>
+                        </td>
+                        <td>
+                            <span wicket:id="class">some-class</span>
+                        </td>
+                        <td>
+                            <span wicket:id="phase">some-class</span>
+                        </td>
+                    </tr>
+                </wicket:container>
+            </wicket:container>
+        </table>
+
+    </wicket:extend>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index a03fe43..054b81f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -34,7 +34,8 @@
         <ops4j.paxwicket.version>0.8.0-SNAPSHOT</ops4j.paxwicket.version>
         <karaf.version>2.2.2</karaf.version>
         <nmr.version>1.4.0</nmr.version>
-        <camel.version>[2.6.0,3)</camel.version>
+        <camel.version>2.6.0</camel.version>
+        <cxf.version>2.5.0-SNAPSHOT</cxf.version>
     </properties>
 
     <modules>
@@ -45,6 +46,7 @@
         <module>features</module>
         <module>servicemix</module>
         <module>camel</module>
+        <module>cxf</module>
 
         <module>examples</module>
         <module>manual</module>
@@ -72,6 +74,17 @@
             <url>http://wiquery.googlecode.com/svn/repo/</url>
         </repository>
         <repository>
+            <id>apache-snapshot</id>
+            <name>Apache Snapshots</name>
+            <url>http://repository.apache.org/content/groups/snapshots-group/</url>
+            <snapshots>
+                <enabled>true</enabled>
+            </snapshots>
+            <releases>
+                <enabled>false</enabled>
+            </releases>
+        </repository>
+        <repository>
             <id>sonatype</id>
             <name>sonatype repo</name>
             <url>http://oss.sonatype.org/content/repositories/ops4j-snapshots/</url>