diff --git a/components/camel-web/src/main/java/org/apache/camel/web/connectors/CamelConnection.java b/components/camel-web/src/main/java/org/apache/camel/web/connectors/CamelConnection.java new file mode 100644 index 0000000000000..d134379de6722 --- /dev/null +++ b/components/camel-web/src/main/java/org/apache/camel/web/connectors/CamelConnection.java @@ -0,0 +1,32 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.web.connectors; + +import java.util.List; + +/** + * + */ +public interface CamelConnection { + + public CamelDataBean getCamelBean(String type, String name); + + public List getCamelBeans(String type); + + public Object invokeOperation(String type, String name, String operationName, Object[] params, String[] signature); + +} diff --git a/components/camel-web/src/main/java/org/apache/camel/web/connectors/CamelConnectionFactory.java b/components/camel-web/src/main/java/org/apache/camel/web/connectors/CamelConnectionFactory.java new file mode 100644 index 0000000000000..e46de8378fe34 --- /dev/null +++ b/components/camel-web/src/main/java/org/apache/camel/web/connectors/CamelConnectionFactory.java @@ -0,0 +1,54 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.web.connectors; + +import java.io.IOException; + +import org.apache.camel.web.connectors.jmx.CamelJmxConnection; + +/** + * + */ +public class CamelConnectionFactory { + + private static final String JMX_SERVICE_URL_PREFIX = "service:jmx:rmi:///jndi/rmi://"; + + private String jmxHost = "localhost"; + + private String jmxPort = "1099"; + + private String jmxPath = "jmxrmi/camel"; + + private static CamelConnectionFactory instance = new CamelConnectionFactory(); + + private CamelConnectionFactory() {} + + public static CamelConnectionFactory getInstance() { + return instance; + } + + public CamelConnection getJmxConnection() throws IOException { + String jmxServiceUrl = JMX_SERVICE_URL_PREFIX + jmxHost + ":" + jmxPort + "/" + jmxPath; + return new CamelJmxConnection(jmxServiceUrl); + } + + public CamelConnection getJmxConnection(String jmxHost, String jmxPort, String jmxPath) throws IOException { + String jmxServiceUrl = JMX_SERVICE_URL_PREFIX + jmxHost + ":" + jmxPort + "/" + jmxPath; + return new CamelJmxConnection(jmxServiceUrl); + } + +} \ No newline at end of file diff --git a/components/camel-web/src/main/java/org/apache/camel/web/connectors/CamelDataBean.java b/components/camel-web/src/main/java/org/apache/camel/web/connectors/CamelDataBean.java new file mode 100644 index 0000000000000..82d622d8320b0 --- /dev/null +++ b/components/camel-web/src/main/java/org/apache/camel/web/connectors/CamelDataBean.java @@ -0,0 +1,56 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.web.connectors; + +import java.util.HashMap; +import java.util.Map; + +/** + * Camel Managed Bean representation + */ +public class CamelDataBean { + + private final Map properties = new HashMap(); + + private String name; + + private String description; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public Object getProperty(String propertyName) { + return properties.get(propertyName); + } + + public Map getProperties() { + return properties; + } +} diff --git a/components/camel-web/src/main/java/org/apache/camel/web/connectors/jmx/CamelJmxConnection.java b/components/camel-web/src/main/java/org/apache/camel/web/connectors/jmx/CamelJmxConnection.java new file mode 100644 index 0000000000000..c3b20158ca0e0 --- /dev/null +++ b/components/camel-web/src/main/java/org/apache/camel/web/connectors/jmx/CamelJmxConnection.java @@ -0,0 +1,136 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.web.connectors.jmx; + +import javax.management.*; +import javax.management.remote.JMXConnector; +import javax.management.remote.JMXConnectorFactory; +import javax.management.remote.JMXServiceURL; + +import org.apache.camel.web.connectors.CamelConnection; +import org.apache.camel.web.connectors.CamelDataBean; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +/** + * + */ +public class CamelJmxConnection implements CamelConnection { + + private final MBeanServerConnection connection; + + public CamelJmxConnection(String jmxServiceUrl) throws IOException { + JMXServiceURL url = new JMXServiceURL(jmxServiceUrl); + //TODO Handle credentials + JMXConnector connector = JMXConnectorFactory.connect(url); + connection = connector.getMBeanServerConnection(); + } + + protected MBeanInfo getMBeanInfo(ObjectInstance objInstance) throws IntrospectionException, InstanceNotFoundException, IOException, ReflectionException { + //TODO Caching MBeanInfo + MBeanInfo mBeanInfo = connection.getMBeanInfo(objInstance.getObjectName()); + return mBeanInfo; + } + + protected Set getObjectInstances(String type) throws IOException, MalformedObjectNameException { + Set beans = connection.queryMBeans(new ObjectName("org.apache.camel:type=" + type + ",*"), null); + return beans; + } + + ObjectInstance getObjectInstance(String type, String name) throws MalformedObjectNameException, + NullPointerException, IOException { + Set beans = connection.queryMBeans(new ObjectName("org.apache.camel:type=" + type + ",name=" + + name + ",*"), null); + return beans.isEmpty() ? null : beans.iterator().next(); + } + + public CamelDataBean getCamelBean(String type, String name) { + CamelDataBean bean; + try { + ObjectInstance instance = getObjectInstance(type, name); + MBeanInfo info = getMBeanInfo(instance); + bean = new CamelBeanFactory().build(instance, connection, info); + } catch (Exception e) { + throw new RuntimeException(e); + } + + return bean; + } + + public List getCamelBeans(String type) { + List endpoints = new ArrayList(); + try { + Set beans = getObjectInstances(type); + for (ObjectInstance instance : beans) { + MBeanInfo info = getMBeanInfo(instance); + CamelDataBean endpoint = new CamelBeanFactory().build(instance, connection, info); + endpoints.add(endpoint); + } + } catch (Exception e) { + throw new RuntimeException(e); + } + + return endpoints; + } + + public Object invokeOperation(String type, String name, String operationName, Object[] params, String[] signature) { + Object result; + try { + ObjectInstance instance = getObjectInstance(type, name); + result = connection.invoke(instance.getObjectName(), operationName, params, signature); + } catch (Exception e) { + throw new RuntimeException(e); + } + + return result; + } + + private class CamelBeanFactory { + + public CamelDataBean build(ObjectInstance instance, MBeanServerConnection connection, MBeanInfo info) + throws InstanceNotFoundException, IOException, ReflectionException { + + CamelDataBean c = new CamelDataBean(); + String name = instance.getObjectName().getKeyProperty("name"); + if (name.endsWith("\"")) + name = name.substring(0, name.length() - 1); + if (name.startsWith("\"")) + name = name.substring(1); + + c.setName(name); + c.setDescription(info.getDescription()); + + MBeanAttributeInfo[] attributes = info.getAttributes(); + List attributeNames = new ArrayList(); + for (MBeanAttributeInfo attribute : attributes) { + attributeNames.add(attribute.getName()); + } + + List attributeList = connection.getAttributes(instance.getObjectName(), attributeNames.toArray(new String[0])); + List list = attributeList; + for (Attribute attribute : list) { + c.getProperties().put(attribute.getName(), attribute.getValue()); + } + + return c; + } + + } +} \ No newline at end of file diff --git a/components/camel-web/src/main/java/org/apache/camel/web/model/Consumer.java b/components/camel-web/src/main/java/org/apache/camel/web/model/Consumer.java new file mode 100644 index 0000000000000..0fa86ae2d4293 --- /dev/null +++ b/components/camel-web/src/main/java/org/apache/camel/web/model/Consumer.java @@ -0,0 +1,107 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.web.model; + +import org.apache.camel.web.connectors.CamelDataBean; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlRootElement; + +/** + * Consumer + */ +@XmlRootElement +@XmlAccessorType(XmlAccessType.FIELD) +public class Consumer { + + public static final String PROPERTY_STATUS = "State"; + public static final String PROPERTY_ENDPOINT_URI = "EndpointUri"; + public static final String PROPERTY_ROUTE_ID = "RouteId"; + + @XmlAttribute + private String name; + + private String description; + + private String status; + + private String endpointUri; + + private String routeId; + + public void load(CamelDataBean bean) { + name = bean.getName(); + description = bean.getDescription(); + status = (String) bean.getProperty(PROPERTY_STATUS); + endpointUri = (String) bean.getProperty(PROPERTY_ENDPOINT_URI); + routeId = (String) bean.getProperty(PROPERTY_ROUTE_ID); + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public String getEndpointUri() { + return endpointUri; + } + + public void setEndpointUri(String endpointUri) { + this.endpointUri = endpointUri; + } + + public String getRouteId() { + return routeId; + } + + public void setRouteId(String routeId) { + this.routeId = routeId; + } + + public boolean isStartable() { + if(!status.equals("Started")) + return true; + return false; + } + + public boolean isStoppable() { + if(!status.equals("Stopped")) + return true; + return false; + } +} diff --git a/components/camel-web/src/main/java/org/apache/camel/web/model/Consumers.java b/components/camel-web/src/main/java/org/apache/camel/web/model/Consumers.java new file mode 100644 index 0000000000000..0453f4ffaddc9 --- /dev/null +++ b/components/camel-web/src/main/java/org/apache/camel/web/model/Consumers.java @@ -0,0 +1,67 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.web.model; + +import org.apache.camel.web.connectors.CamelDataBean; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import java.util.ArrayList; +import java.util.List; + +/** + * + */ +@XmlRootElement +@XmlAccessorType(XmlAccessType.FIELD) +public class Consumers { + + @XmlElement(name = "consumer") + private List consumers = new ArrayList(); + + @Override + public String toString() { + return "Consumers " + consumers; + } + + public List getConsumers() { + return consumers; + } + + public void setConsumers(List consumers) { + this.consumers = consumers; + } + + public void load(List managedBeans) { + for(CamelDataBean managedBean : managedBeans) { + addConsumer(createConsumer(managedBean)); + } + } + + protected Consumer createConsumer(CamelDataBean bean) { + Consumer consumer = new Consumer(); + consumer.load(bean); + return consumer; + } + + public void addConsumer(Consumer consumer) { + getConsumers().add(consumer); + } + +} \ No newline at end of file diff --git a/components/camel-web/src/main/java/org/apache/camel/web/model/ThreadPool.java b/components/camel-web/src/main/java/org/apache/camel/web/model/ThreadPool.java new file mode 100644 index 0000000000000..63d2109c7a1ca --- /dev/null +++ b/components/camel-web/src/main/java/org/apache/camel/web/model/ThreadPool.java @@ -0,0 +1,132 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.web.model; + +import org.apache.camel.web.connectors.CamelDataBean; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlRootElement; + +/** + * Thread Pool + */ +@XmlRootElement +@XmlAccessorType(XmlAccessType.FIELD) +public class ThreadPool { + + public static final String PROPERTY_ACTIVE_COUNT = "ActiveCount"; + public static final String PROPERTY_CORE_POOL_SIZE = "CorePoolSize"; + public static final String PROPERTY_POOL_SIZE = "PoolSize"; + public static final String PROPERTY_MAXIMUM_POOL_SIZE = "MaximumPoolSize"; + public static final String PROPERTY_TASK_COUNT = "TaskCount"; + public static final String PROPERTY_KEEP_ALIVE_TIME = "KeepAliveTime"; + + @XmlAttribute + private String name; + + private String description; + + private Integer activeCount; + + private Integer corePoolSize; + + private Integer poolSize; + + private Integer maximumPoolSize; + + private Long taskCount; + + private Long keepAliveTime; + + public void load(CamelDataBean bean) { + name = bean.getName(); + description = bean.getDescription(); + activeCount = (Integer) bean.getProperty(PROPERTY_ACTIVE_COUNT); + corePoolSize = (Integer) bean.getProperty(PROPERTY_CORE_POOL_SIZE); + poolSize = (Integer) bean.getProperty(PROPERTY_POOL_SIZE); + maximumPoolSize = (Integer) bean.getProperty(PROPERTY_MAXIMUM_POOL_SIZE); + taskCount = (Long) bean.getProperty(PROPERTY_TASK_COUNT); + keepAliveTime = (Long) bean.getProperty(PROPERTY_KEEP_ALIVE_TIME); + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public Integer getActiveCount() { + return activeCount; + } + + public void setActiveCount(Integer activeCount) { + this.activeCount = activeCount; + } + + public Integer getCorePoolSize() { + return corePoolSize; + } + + public void setCorePoolSize(Integer corePoolSize) { + this.corePoolSize = corePoolSize; + } + + public Integer getPoolSize() { + return poolSize; + } + + public void setPoolSize(Integer poolSize) { + this.poolSize = poolSize; + } + + public Integer getMaximumPoolSize() { + return maximumPoolSize; + } + + public void setMaximumPoolSize(Integer maximumPoolSize) { + this.maximumPoolSize = maximumPoolSize; + } + + public Long getTaskCount() { + return taskCount; + } + + public void setTaskCount(Long taskCount) { + this.taskCount = taskCount; + } + + public Long getKeepAliveTime() { + return keepAliveTime; + } + + public void setKeepAliveTime(Long keepAliveTime) { + this.keepAliveTime = keepAliveTime; + } + +} diff --git a/components/camel-web/src/main/java/org/apache/camel/web/model/ThreadPools.java b/components/camel-web/src/main/java/org/apache/camel/web/model/ThreadPools.java new file mode 100644 index 0000000000000..ed0ce893e03c2 --- /dev/null +++ b/components/camel-web/src/main/java/org/apache/camel/web/model/ThreadPools.java @@ -0,0 +1,67 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.web.model; + +import org.apache.camel.web.connectors.CamelDataBean; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import java.util.ArrayList; +import java.util.List; + +/** + * + */ +@XmlRootElement +@XmlAccessorType(XmlAccessType.FIELD) +public class ThreadPools { + + @XmlElement(name = "threadPool") + private List threadPools = new ArrayList(); + + @Override + public String toString() { + return "Thread pools " + threadPools; + } + + public List getThreadPools() { + return threadPools; + } + + public void setThreadPools(List threadPools) { + this.threadPools = threadPools; + } + + public void load(List managedBeans) { + for(CamelDataBean managedBean : managedBeans) { + addThreadPool(createThreadPool(managedBean)); + } + } + + protected ThreadPool createThreadPool(CamelDataBean bean) { + ThreadPool threadPool = new ThreadPool(); + threadPool.load(bean); + return threadPool; + } + + public void addThreadPool(ThreadPool threadPool) { + getThreadPools().add(threadPool); + } + +} \ No newline at end of file diff --git a/components/camel-web/src/main/java/org/apache/camel/web/resources/CamelContextResource.java b/components/camel-web/src/main/java/org/apache/camel/web/resources/CamelContextResource.java index 6442a816cc3aa..d4af3f35d0afc 100644 --- a/components/camel-web/src/main/java/org/apache/camel/web/resources/CamelContextResource.java +++ b/components/camel-web/src/main/java/org/apache/camel/web/resources/CamelContextResource.java @@ -16,6 +16,7 @@ */ package org.apache.camel.web.resources; +import java.io.IOException; import java.util.Map; import java.util.TreeMap; import javax.annotation.PreDestroy; @@ -30,6 +31,8 @@ import org.apache.camel.CamelContext; import org.apache.camel.ProducerTemplate; import org.apache.camel.support.ServiceSupport; +import org.apache.camel.web.connectors.CamelConnection; +import org.apache.camel.web.connectors.CamelConnectionFactory; import org.apache.camel.web.model.Camel; /** @@ -122,6 +125,34 @@ public EndpointsResource getEndpointsResource() { return new EndpointsResource(this); } + /** + * Returns the active consumers + */ + @Path("consumers") + public ConsumersResource geConsumersResource() { + CamelConnection camelConnection = null; + try { + camelConnection = CamelConnectionFactory.getInstance().getJmxConnection(); + } catch (IOException e) { + throw new RuntimeException(e); + } + return new ConsumersResource(camelConnection); + } + + /** + * Returns the active thread pools + */ + @Path("threadpools") + public ThreadPoolsResource geThreadPoolsResource() { + CamelConnection camelConnection = null; + try { + camelConnection = CamelConnectionFactory.getInstance().getJmxConnection(); + } catch (IOException e) { + throw new RuntimeException(e); + } + return new ThreadPoolsResource(camelConnection); + } + /** * Returns the active languages */ diff --git a/components/camel-web/src/main/java/org/apache/camel/web/resources/ConsumerResource.java b/components/camel-web/src/main/java/org/apache/camel/web/resources/ConsumerResource.java new file mode 100644 index 0000000000000..cf4ee6e9cc865 --- /dev/null +++ b/components/camel-web/src/main/java/org/apache/camel/web/resources/ConsumerResource.java @@ -0,0 +1,92 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.web.resources; + +import com.sun.jersey.api.representation.Form; +import org.apache.camel.web.connectors.CamelConnection; +import org.apache.camel.web.model.Consumer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.ws.rs.*; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import java.net.URI; + +/** + * A single Camel Consumer. + */ +public class ConsumerResource { + + private static final transient Logger LOG = LoggerFactory.getLogger(ConsumerResource.class); + + private Consumer consumer; + + private CamelConnection connection; + + public ConsumerResource(Consumer consumer, CamelConnection connection) { + this.consumer = consumer; + this.connection = connection; + } + + /** + * Returns the XML or JSON representation of this consumer + */ + @GET + @Produces({MediaType.TEXT_XML, MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) + public Consumer getConsumer() { + return consumer; + } + + @GET + @Produces(MediaType.TEXT_PLAIN) + public String getStatusText() { + return consumer.getStatus(); + } + + @POST + @Consumes(MediaType.TEXT_PLAIN) + public Response setStatus(String status) throws Exception { + if (status != null) { + if (status.equalsIgnoreCase("start")) { + connection.invokeOperation("consumers", consumer.getName(), "start", new Object[0], new String[0]); + return Response.ok().build(); + } else if (status.equalsIgnoreCase("stop")) { + connection.invokeOperation("consumers", consumer.getName(), "stop", new Object[0], new String[0]); + return Response.ok().build(); + } + } + return Response.noContent().build(); + } + + + /** + * Sets the status of this route to either "start" or "stop" + * + * @param formData is the form data POSTed typically from a HTML form with the status field + * set to either "start" or "stop" + */ + @POST + @Consumes("application/x-www-form-urlencoded") + public Response setStatus(Form formData) throws Exception { + // TODO replace the Form class with an injected bean? + String status = formData.getFirst("status", String.class); + setStatus(status); + return Response.seeOther(new URI("/consumers")).build(); + } + +} diff --git a/components/camel-web/src/main/java/org/apache/camel/web/resources/ConsumersResource.java b/components/camel-web/src/main/java/org/apache/camel/web/resources/ConsumersResource.java new file mode 100644 index 0000000000000..2f3f8992edc06 --- /dev/null +++ b/components/camel-web/src/main/java/org/apache/camel/web/resources/ConsumersResource.java @@ -0,0 +1,83 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.web.resources; + +import com.sun.jersey.api.view.ImplicitProduces; + +import org.apache.camel.web.connectors.CamelConnection; +import org.apache.camel.web.connectors.CamelDataBean; +import org.apache.camel.web.model.Consumer; +import org.apache.camel.web.model.Consumers; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; +import java.util.List; + +/** + * + */ +@ImplicitProduces(Constants.HTML_MIME_TYPES) +public class ConsumersResource { + + private static final transient Logger LOG = LoggerFactory.getLogger(ConsumersResource.class); + + private CamelConnection camelConnection; + + public ConsumersResource(CamelConnection camelConnection) { + this.camelConnection = camelConnection; + } + + /** + * Returns a list of consumers available in this context + */ + @GET + @Produces({MediaType.TEXT_XML, MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) + public Consumers getDTO() { + if(LOG.isDebugEnabled()) { + LOG.debug("Retrieving consumers."); + } + + List consumersCamelBeans = camelConnection.getCamelBeans("consumers"); + Consumers consumers = new Consumers(); + consumers.load(consumersCamelBeans); + return consumers; + } + + public List getConsumers() { + return getDTO().getConsumers(); + } + + @Path("{name}/status") + public ConsumerResource getConsumerStatus(@PathParam("name") String name) { + CamelDataBean consumerBean = camelConnection.getCamelBean("consumers", name); + + if (consumerBean != null) { + Consumer consumer = new Consumer(); + consumer.load(consumerBean); + return new ConsumerResource(consumer, camelConnection); + } else { + LOG.warn("No consumer found for name: " + name); + return null; + } + } + +} diff --git a/components/camel-web/src/main/java/org/apache/camel/web/resources/ThreadPoolResource.java b/components/camel-web/src/main/java/org/apache/camel/web/resources/ThreadPoolResource.java new file mode 100644 index 0000000000000..5a1d2d21f6fe8 --- /dev/null +++ b/components/camel-web/src/main/java/org/apache/camel/web/resources/ThreadPoolResource.java @@ -0,0 +1,147 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.web.resources; + +import java.net.URI; + +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +import org.apache.camel.web.connectors.CamelConnection; +import org.apache.camel.web.model.ThreadPool; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.sun.jersey.api.representation.Form; + +/** + * A single Thread Pool + */ +public class ThreadPoolResource { + + private static final transient Logger LOG = LoggerFactory.getLogger(ThreadPoolResource.class); + + private ThreadPool threadPool; + + private CamelConnection connection; + + public ThreadPoolResource(ThreadPool threadPool, CamelConnection connection) { + this.threadPool = threadPool; + this.connection = connection; + } + + public ThreadPool getThreadPool() { + return threadPool; + } + + @POST + @Consumes(MediaType.TEXT_PLAIN) + @Path("/corePoolSize") + public Response setCorePoolSize(Integer corePoolSize) throws Exception { + connection.invokeOperation("threadpools", "\"" + threadPool.getName() + "\"", "setCorePoolSize", new Integer[] {corePoolSize}, new String[] {"int"}); + return Response.ok().build(); + } + + + /** + * Sets the core pool size of this thread pool + * + * @param formData is the form data POSTed typically from a HTML form with the corePoolSize field + */ + @POST + @Consumes("application/x-www-form-urlencoded") + @Path("/corePoolSize") + public Response setCorePoolSize(Form formData) throws Exception { + Integer corePoolSize = formData.getFirst("corePoolSize", Integer.class); + setCorePoolSize(corePoolSize); + return Response.seeOther(new URI("/threadpools/" + threadPool.getName())).build(); + } + + @POST + @Consumes(MediaType.TEXT_PLAIN) + @Path("/maximumPoolSize") + public Response setMaximumPoolSize(Integer maximumPoolSize) throws Exception { + connection.invokeOperation("threadpools", "\"" + threadPool.getName() + "\"", "setMaximumPoolSize", new Integer[] {maximumPoolSize}, new String[] {"int"}); + return Response.ok().build(); + } + + + /** + * Sets the maximum pool size of this thread pool + * + * @param formData is the form data POSTed typically from a HTML form with the maximumPoolSize field + */ + @POST + @Consumes("application/x-www-form-urlencoded") + @Path("/maximumPoolSize") + public Response setMaximumPoolSize(Form formData) throws Exception { + Integer maximumPoolSize = formData.getFirst("maximumPoolSize", Integer.class); + setMaximumPoolSize(maximumPoolSize); + return Response.seeOther(new URI("/threadpools/" + threadPool.getName())).build(); + } + + @POST + @Consumes(MediaType.TEXT_PLAIN) + @Path("/keepAliveTime") + public Response setKeepAliveTime(Integer keepAliveTime) throws Exception { + connection.invokeOperation("threadpools", "\"" + threadPool.getName() + "\"", "setKeepAliveTime", new Integer[] {keepAliveTime}, new String[] {"long"}); + return Response.ok().build(); + } + + + /** + * Sets the keep alive time of this thread pool + * + * @param formData is the form data POSTed typically from a HTML form with the keepAliveTime field + */ + @POST + @Consumes("application/x-www-form-urlencoded") + @Path("/keepAliveTime") + public Response setKeepAliveTime(Form formData) throws Exception { + Integer keepAliveTime = formData.getFirst("keepAliveTime", Integer.class); + setKeepAliveTime(keepAliveTime); + return Response.seeOther(new URI("/threadpools/" + threadPool.getName())).build(); + } + + /** + * Purge this thread pool + * + */ + @GET + @Path("/purge") + public Response purge() throws Exception { + connection.invokeOperation("threadpools", "\"" + threadPool.getName() + "\"", "purge", new Object[0], new String[0]); + return Response.seeOther(new URI("/threadpools/" + threadPool.getName())).build(); + } + + /** + * Gets pool size of this thread + */ + @GET + @Path("/poolSize") + @Produces(MediaType.TEXT_PLAIN) + public String getThreadPoolSize() throws Exception { + Integer poolSize = (Integer) connection.invokeOperation("threadpools", "\"" + threadPool.getName() + "\"", "getPoolSize", new Object[0], new String[0]); + return poolSize.toString(); + } + +} diff --git a/components/camel-web/src/main/java/org/apache/camel/web/resources/ThreadPoolsResource.java b/components/camel-web/src/main/java/org/apache/camel/web/resources/ThreadPoolsResource.java new file mode 100644 index 0000000000000..b51c4271efa25 --- /dev/null +++ b/components/camel-web/src/main/java/org/apache/camel/web/resources/ThreadPoolsResource.java @@ -0,0 +1,89 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.web.resources; + +import com.sun.jersey.api.view.ImplicitProduces; + +import org.apache.camel.web.connectors.CamelConnection; +import org.apache.camel.web.connectors.CamelDataBean; +import org.apache.camel.web.model.ThreadPool; +import org.apache.camel.web.model.ThreadPools; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; +import java.util.List; + +/** + * + */ +@ImplicitProduces(Constants.HTML_MIME_TYPES) +public class ThreadPoolsResource { + + private static final transient Logger LOG = LoggerFactory.getLogger(ThreadPoolsResource.class); + + private CamelConnection camelConnection; + + public ThreadPoolsResource(CamelConnection camelConnection) { + this.camelConnection = camelConnection; + } + + /** + * Returns the resource of an individual Camel thread pool + * + * @param name the Thread pool unique name + */ + @Path("{name}") + public ThreadPoolResource getThreadPool(@PathParam("name") String name) { + LOG.info("Retrieving thread pool " + name); + CamelDataBean threadPoolBean = camelConnection.getCamelBean("threadpools", "\"" + name + "\""); + + if (threadPoolBean != null) { + ThreadPool threadPool = new ThreadPool(); + threadPool.load(threadPoolBean); + return new ThreadPoolResource(threadPool, camelConnection); + } else { + LOG.warn("No thread pool found for name: " + name); + return null; + } + } + + /** + * Returns a list of consumers available in this context + */ + @GET + @Produces({MediaType.TEXT_XML, MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) + public ThreadPools getDTO() { + if(LOG.isDebugEnabled()) { + LOG.debug("Retrieving thread pools."); + } + + List threadPoolsCamelBeans = camelConnection.getCamelBeans("threadpools"); + ThreadPools threadPools = new ThreadPools(); + threadPools.load(threadPoolsCamelBeans); + return threadPools; + } + + public List getThreadPools() { + return getDTO().getThreadPools(); + } + +} diff --git a/components/camel-web/src/main/resources/org/apache/camel/web/model/jaxb.index b/components/camel-web/src/main/resources/org/apache/camel/web/model/jaxb.index index 07486a582efa7..454abdffce85f 100644 --- a/components/camel-web/src/main/resources/org/apache/camel/web/model/jaxb.index +++ b/components/camel-web/src/main/resources/org/apache/camel/web/model/jaxb.index @@ -17,3 +17,7 @@ Camel EndpointLink Endpoints +Consumers +Consumer +ThreadPool +ThreadPools \ No newline at end of file diff --git a/components/camel-web/src/main/webapp/WEB-INF/applicationContext.xml b/components/camel-web/src/main/webapp/WEB-INF/applicationContext.xml index 004e3027e6a9a..e150764b8ca69 100644 --- a/components/camel-web/src/main/webapp/WEB-INF/applicationContext.xml +++ b/components/camel-web/src/main/webapp/WEB-INF/applicationContext.xml @@ -22,6 +22,8 @@ http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd"> + + This is an example route which you can start, stop and modify diff --git a/components/camel-web/src/main/webapp/WEB-INF/org/apache/camel/web/resources/ConsumersResource.index.ssp b/components/camel-web/src/main/webapp/WEB-INF/org/apache/camel/web/resources/ConsumersResource.index.ssp new file mode 100644 index 0000000000000..7f1baba065294 --- /dev/null +++ b/components/camel-web/src/main/webapp/WEB-INF/org/apache/camel/web/resources/ConsumersResource.index.ssp @@ -0,0 +1,60 @@ +<%-- + 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. +--%> +<%@ import val it: ConsumersResource %> + +#{ attributes("title") = "Consumers"}# + +

Consumers

+ + + + + + + + +
    + #for(i <- it.getConsumers) +
+ + + + + + + #end + +
ConsumerStatusEndpoint URIRoute ID
+ ${i.getName} + + ${i.getStatus} + +
+ #if(i.isStartable) + + + #end + #if(i.isStoppable) + + + #end +
+
+ ${i.getEndpointUri} + + ${i.getRouteId} +
\ No newline at end of file diff --git a/components/camel-web/src/main/webapp/WEB-INF/org/apache/camel/web/resources/ThreadPoolResource.index.ssp b/components/camel-web/src/main/webapp/WEB-INF/org/apache/camel/web/resources/ThreadPoolResource.index.ssp new file mode 100644 index 0000000000000..a24414a5182c8 --- /dev/null +++ b/components/camel-web/src/main/webapp/WEB-INF/org/apache/camel/web/resources/ThreadPoolResource.index.ssp @@ -0,0 +1,81 @@ +<%-- + 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. +--%> +<%@ import val it: ThreadPoolResource %> + +#{ attributes("title") = "Thread Pool " + it.getThreadPool.getName}# + + + + + + + +

Thread Pool: ${it.getThreadPool.getName}

+ + + + + + + + + + +
    +
+ + + + + + + + +
Core pool sizePool sizeMaximum pool sizeTask countKeep alive timeActions
+
+ + +
+
+ ${it.getThreadPool.getPoolSize} + +
+ + +
+
+ ${it.getThreadPool.getTaskCount} + +
+ + +
+
+
+ +
+
+ +
\ No newline at end of file diff --git a/components/camel-web/src/main/webapp/WEB-INF/org/apache/camel/web/resources/ThreadPoolsResource.index.ssp b/components/camel-web/src/main/webapp/WEB-INF/org/apache/camel/web/resources/ThreadPoolsResource.index.ssp new file mode 100644 index 0000000000000..f6da70e8c741d --- /dev/null +++ b/components/camel-web/src/main/webapp/WEB-INF/org/apache/camel/web/resources/ThreadPoolsResource.index.ssp @@ -0,0 +1,52 @@ +<%-- + 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. +--%> +<%@ import val it: ThreadPoolsResource %> + +#{ attributes("title") = "Thread Pools"}# + +

Thread Pools

+ + + + + + + + + +
    + #for(i <- it.getThreadPools) +
+ + + + + + + #end + +
Thread PoolCore pool sizePool sizeMaximum pool sizeTask count
+ ${i.getName} + + ${i.getCorePoolSize} + + ${i.getPoolSize} + + ${i.getMaximumPoolSize} + + ${i.getTaskCount} +
\ No newline at end of file diff --git a/components/camel-web/src/main/webapp/WEB-INF/scalate/layouts/default.scaml b/components/camel-web/src/main/webapp/WEB-INF/scalate/layouts/default.scaml index 19606cf08594b..68354f889fc4a 100644 --- a/components/camel-web/src/main/webapp/WEB-INF/scalate/layouts/default.scaml +++ b/components/camel-web/src/main/webapp/WEB-INF/scalate/layouts/default.scaml @@ -72,6 +72,10 @@ %a{:href => {uri("/endpoints")}, :title => "View current endpoints or create new ones"} Endpoints | %a{:href => {uri("/routes")}, :title => "View current routes"} Routes + | + %a{:href => {uri("/consumers")}, :title => "View current consumers"} Consumers + | + %a{:href => {uri("/threadpools")}, :title => "View current thread pools"} Thread Pools #site-quicklinks %P %a{:href => "http://camel.apache.org/support.html", :title => "Get help and support using Apache Camel"} Support diff --git a/components/camel-web/src/main/webapp/js/threadPool.js b/components/camel-web/src/main/webapp/js/threadPool.js new file mode 100644 index 0000000000000..a798bfd34a927 --- /dev/null +++ b/components/camel-web/src/main/webapp/js/threadPool.js @@ -0,0 +1,41 @@ +dojo.require("dojox.charting.Theme"); +dojo.require("dojox.charting.scaler.linear"); +dojo.require("dojox.charting.Chart2D"); +dojo.require("dojox.lang.functional"); +dojo.require("dojox.charting.themes.PlotKit.orange"); + +var chart; +var threadPoolSeries = []; + +var xhrArgs = { + url: "/threadpools/" + threadPoolName + "/poolSize", + handleAs: "text", + load: function(data){ + if(threadPoolSeries.length == 100) { + threadPoolSeries.splice(0, 1); + } + threadPoolSeries.push(parseInt(data)); + + chart.updateSeries("ThreadPoolSize", threadPoolSeries); + chart.render(); + setTimeout("update()", 1000); + } +} + +var update = function() { + dojo.xhrGet(xhrArgs); +}; + +var createChart = function() { + chart = new dojox.charting.Chart2D("threadPoolSize"); + chart.setTheme(dojox.charting.themes.PlotKit.orange); + chart.addAxis("x", {fixLower: "minor", natural: true, min: 1, max: 100}); + chart.addAxis("y", {vertical: true, min: 0, max: limit, majorTickStep: 5, minorTickStep: 1}); + chart.addPlot("default", {type: "Areas"}); + chart.addSeries("ThreadPoolSize", threadPoolSeries); + chart.addPlot("grid", {type: "Grid", hMinorLines: true}); + chart.render(); + setTimeout("update()", 1000); +}; + +dojo.addOnLoad(createChart); \ No newline at end of file