renamed modules org.springframework.integration.* -> spring-integration-*
@Ignore'd SimpleTcpNetOutboundGatewayTests#testOutboundClose() to avoid failure; this failure is correlated to the module name change, but hard to understand how it would be caused by it
This commit is contained in:
@@ -0,0 +1,249 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.integration.control;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.management.MBeanServer;
|
||||
import javax.management.MalformedObjectNameException;
|
||||
import javax.management.ObjectName;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.BeanFactoryUtils;
|
||||
import org.springframework.beans.factory.BeanInitializationException;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.ListableBeanFactory;
|
||||
import org.springframework.context.Lifecycle;
|
||||
import org.springframework.integration.channel.DirectChannel;
|
||||
import org.springframework.integration.channel.PollableChannel;
|
||||
import org.springframework.integration.channel.QueueChannel;
|
||||
import org.springframework.integration.channel.SubscribableChannel;
|
||||
import org.springframework.integration.core.Message;
|
||||
import org.springframework.integration.core.MessageChannel;
|
||||
import org.springframework.integration.core.MessageHeaders;
|
||||
import org.springframework.integration.endpoint.AbstractEndpoint;
|
||||
import org.springframework.integration.jmx.JmxHeaders;
|
||||
import org.springframework.integration.jmx.OperationInvokingMessageHandler;
|
||||
import org.springframework.integration.message.MessageBuilder;
|
||||
import org.springframework.jmx.export.MBeanExporter;
|
||||
import org.springframework.jmx.export.assembler.AbstractConfigurableMBeanInfoAssembler;
|
||||
import org.springframework.jmx.export.assembler.MBeanInfoAssembler;
|
||||
import org.springframework.jmx.support.ObjectNameManager;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* JMX-based Control Bus implementation. Exports all channel and endpoint
|
||||
* beans from a given BeanFactory as MBeans.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
* @since 2.0
|
||||
*/
|
||||
public class ControlBus implements BeanFactoryAware, InitializingBean {
|
||||
|
||||
public static final String DEFAULT_DOMAIN = "org.springframework.integration";
|
||||
|
||||
public static final String TARGET_BEAN_NAME = JmxHeaders.PREFIX + "_controlBus_targetBeanName";
|
||||
|
||||
|
||||
private volatile SubscribableChannel operationChannel;
|
||||
|
||||
private final MBeanExporter exporter;
|
||||
|
||||
private final String domain;
|
||||
|
||||
private final Map<String, ObjectName> exportedBeanObjectNameMap = new HashMap<String, ObjectName>();
|
||||
|
||||
private volatile ListableBeanFactory beanFactory;
|
||||
|
||||
private final Set<Class<?>> managedTypes = new HashSet<Class<?>>(
|
||||
Arrays.asList(new Class<?>[] { MessageChannel.class, AbstractEndpoint.class }));
|
||||
|
||||
|
||||
/**
|
||||
* Create a {@link ControlBus} that will register channels and endpoints
|
||||
* as MBeans with the given MBeanServer using the default domain name.
|
||||
* @see #DEFAULT_DOMAIN
|
||||
*/
|
||||
public ControlBus(MBeanServer server) {
|
||||
this(server, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a {@link ControlBus} that will register channels and endpoints
|
||||
* as MBeans with the given MBeanServer using the specified domain name.
|
||||
*/
|
||||
public ControlBus(MBeanServer server, String domain) {
|
||||
Assert.notNull(server, "MBeanServer must not be null.");
|
||||
this.domain = (domain != null) ? domain : DEFAULT_DOMAIN;
|
||||
Assert.isTrue(!ObjectUtils.containsElement(server.getDomains(), this.domain),
|
||||
"Domain [" + this.domain + "] is already in use within this MBeanServer.");
|
||||
MBeanExporter exporter = new MBeanExporter();
|
||||
exporter.setServer(server);
|
||||
exporter.setAutodetect(false);
|
||||
exporter.setAssembler(new ControlBusMBeanInfoAssembler());
|
||||
this.exporter = exporter;
|
||||
}
|
||||
|
||||
|
||||
public void setOperationChannel(SubscribableChannel operationChannel) {
|
||||
this.operationChannel = operationChannel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the channel to which operation-invoking Messages may be sent. Any messages
|
||||
* sent to this channel must contain {@link ControlBus#TARGET_BEAN_NAME} and
|
||||
* {@link JmxHeaders#OPERATION_NAME} header values, and the target bean name must
|
||||
* match one that has been exported by this Control Bus. If the operation returns a
|
||||
* result, the {@link MessageHeaders#REPLY_CHANNEL} header is also required.
|
||||
*/
|
||||
public SubscribableChannel getOperationChannel() {
|
||||
return this.operationChannel;
|
||||
}
|
||||
|
||||
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
|
||||
Assert.isTrue(beanFactory instanceof ListableBeanFactory,
|
||||
"A ListableBeanFactory is required.");
|
||||
this.beanFactory = (ListableBeanFactory) beanFactory;
|
||||
}
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
this.exporter.afterPropertiesSet();
|
||||
for (Class<?> type : this.managedTypes) {
|
||||
Map<String, ?> beans = BeanFactoryUtils.beansOfTypeIncludingAncestors(this.beanFactory, type);
|
||||
for (Map.Entry<String, ?> entry : beans.entrySet()) {
|
||||
Object bean = entry.getValue();
|
||||
String beanName = entry.getKey();
|
||||
Class<?> beanType = bean.getClass();
|
||||
try {
|
||||
ObjectName objectName = this.generateObjectName(beanName, beanType);
|
||||
this.exporter.registerManagedResource(bean, objectName);
|
||||
this.exportedBeanObjectNameMap.put(beanName, objectName);
|
||||
}
|
||||
catch (MalformedObjectNameException e) {
|
||||
throw new BeanInitializationException("Failed to generate JMX ObjectName.", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
OperationInvokingMessageHandler handler = new ControlBusOperationInvokingMessageHandler();
|
||||
handler.setBeanFactory(this.beanFactory);
|
||||
handler.setServer(this.exporter.getServer());
|
||||
handler.afterPropertiesSet();
|
||||
if (this.operationChannel == null) {
|
||||
this.operationChannel = new DirectChannel();
|
||||
}
|
||||
this.operationChannel.subscribe(handler);
|
||||
}
|
||||
|
||||
private ObjectName generateObjectName(String beanName, Class<?> beanType) throws MalformedObjectNameException {
|
||||
StringBuilder sb = new StringBuilder(this.domain + ":name=" + beanName + ",");
|
||||
if (MessageChannel.class.isAssignableFrom(beanType)) {
|
||||
sb.append("type=channel");
|
||||
}
|
||||
else if (AbstractEndpoint.class.isAssignableFrom(beanType)) {
|
||||
sb.append("type=endpoint");
|
||||
}
|
||||
else {
|
||||
sb.append("type=" + ClassUtils.getShortNameAsProperty(beanType));
|
||||
}
|
||||
return ObjectNameManager.getInstance(sb.toString());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* An {@link MBeanInfoAssembler} implementation for channels and endpoints.
|
||||
*/
|
||||
private static class ControlBusMBeanInfoAssembler extends AbstractConfigurableMBeanInfoAssembler {
|
||||
|
||||
@Override
|
||||
protected boolean includeOperation(Method method, String beanKey) {
|
||||
Class<?> declaringClass = method.getDeclaringClass();
|
||||
return this.shouldInclude(method, declaringClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean includeReadAttribute(Method method, String beanKey) {
|
||||
Class<?> declaringClass = method.getDeclaringClass();
|
||||
return this.shouldInclude(method, declaringClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean includeWriteAttribute(Method method, String beanKey) {
|
||||
Class<?> declaringClass = method.getDeclaringClass();
|
||||
return this.shouldInclude(method, declaringClass);
|
||||
}
|
||||
|
||||
private boolean shouldInclude(Method method, Class<?> declaringClass) {
|
||||
if (MessageChannel.class.isAssignableFrom(declaringClass) ||
|
||||
AbstractEndpoint.class.isAssignableFrom(declaringClass)) {
|
||||
Class<?> managementInterface = this.getManagementInterface(declaringClass);
|
||||
if (managementInterface != null) {
|
||||
for (Method interfaceMethod : managementInterface.getMethods()) {
|
||||
if (interfaceMethod.getName().equals(method.getName()) &&
|
||||
Arrays.equals(interfaceMethod.getParameterTypes(), method.getParameterTypes())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private Class<?> getManagementInterface(Class<?> type) {
|
||||
if (AbstractEndpoint.class.isAssignableFrom(type)) {
|
||||
return Lifecycle.class;
|
||||
}
|
||||
if (QueueChannel.class.isAssignableFrom(type)) {
|
||||
return QueueChannelInfo.class;
|
||||
}
|
||||
if (PollableChannel.class.isAssignableFrom(type)) {
|
||||
return PollableChannelInfo.class;
|
||||
}
|
||||
if (MessageChannel.class.isAssignableFrom(type)) {
|
||||
return MessageChannelInfo.class;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private class ControlBusOperationInvokingMessageHandler extends OperationInvokingMessageHandler {
|
||||
|
||||
@Override
|
||||
protected Object handleRequestMessage(Message<?> requestMessage) {
|
||||
String beanName = requestMessage.getHeaders().get(TARGET_BEAN_NAME, String.class);
|
||||
Assert.notNull(beanName, "The ControlBus.TARGET_BEAN_NAME is required.");
|
||||
ObjectName objectName = exportedBeanObjectNameMap.get(beanName);
|
||||
Assert.notNull(objectName,
|
||||
"ControlBus has not exported an MBean for '" + beanName + "'");
|
||||
requestMessage = MessageBuilder.fromMessage(requestMessage)
|
||||
.setHeader(JmxHeaders.OBJECT_NAME, objectName)
|
||||
.setHeader(TARGET_BEAN_NAME, null)
|
||||
.build();
|
||||
return super.handleRequestMessage(requestMessage);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.integration.control;
|
||||
|
||||
/**
|
||||
* This interface defines the MBean attributes and operations
|
||||
* to be exposed for any MessageChannel instance.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
* @since 2.0
|
||||
*/
|
||||
interface MessageChannelInfo {
|
||||
|
||||
/**
|
||||
* Returns the name of the channel.
|
||||
*/
|
||||
String getName();
|
||||
|
||||
/**
|
||||
* Number of Messages that have been sent successfully.
|
||||
*/
|
||||
long getSendSuccessCount();
|
||||
|
||||
/**
|
||||
* Number of Messages that have caused Exceptions on send.
|
||||
* @return
|
||||
*/
|
||||
long getSendErrorCount();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.integration.control;
|
||||
|
||||
/**
|
||||
* This interface defines the MBean attributes and operations
|
||||
* to be exposed for any PollableChannel instance.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
* @since 2.0
|
||||
*/
|
||||
interface PollableChannelInfo extends MessageChannelInfo {
|
||||
|
||||
/**
|
||||
* Clears all Messages currently held by the channel.
|
||||
*/
|
||||
void clear();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.integration.control;
|
||||
|
||||
/**
|
||||
* This interface defines the MBean attributes and operations
|
||||
* to be exposed for any QueueChannel instance.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
* @since 2.0
|
||||
*/
|
||||
interface QueueChannelInfo extends PollableChannelInfo {
|
||||
|
||||
/**
|
||||
* Returns the number of Messages contained within the queue at the time of invocation.
|
||||
*/
|
||||
int getQueueSize();
|
||||
|
||||
/**
|
||||
* Returns the remaining capacity of the queue at the time of invocation.
|
||||
*/
|
||||
int getRemainingCapacity();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.integration.jmx;
|
||||
|
||||
import javax.management.MBeanServer;
|
||||
import javax.management.MalformedObjectNameException;
|
||||
import javax.management.ObjectName;
|
||||
|
||||
import org.springframework.integration.core.Message;
|
||||
import org.springframework.integration.core.MessagingException;
|
||||
import org.springframework.integration.gateway.SimpleMessageMapper;
|
||||
import org.springframework.integration.message.InboundMessageMapper;
|
||||
import org.springframework.integration.message.MessageSource;
|
||||
import org.springframework.jmx.support.ObjectNameManager;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* A {@link MessageSource} implementation that retrieves the current
|
||||
* value of a JMX attribute each time {@link #receive()} is invoked.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
* @since 2.0
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public class AttributePollingMessageSource implements MessageSource {
|
||||
|
||||
private volatile ObjectName objectName;
|
||||
|
||||
private volatile String attributeName;
|
||||
|
||||
private volatile MBeanServer server;
|
||||
|
||||
private volatile InboundMessageMapper<Object> mapper = new SimpleMessageMapper();
|
||||
|
||||
|
||||
/**
|
||||
* Provide the MBeanServer where the JMX MBean has been registered.
|
||||
*/
|
||||
public void setServer(MBeanServer server) {
|
||||
this.server = server;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the String value of the JMX MBean's {@link ObjectName}.
|
||||
*/
|
||||
public void setObjectName(String objectName) {
|
||||
try {
|
||||
this.objectName = ObjectNameManager.getInstance(objectName);
|
||||
}
|
||||
catch (MalformedObjectNameException e) {
|
||||
throw new IllegalArgumentException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the name of the attribute to be retrieved.
|
||||
*/
|
||||
public void setAttributeName(String attributeName) {
|
||||
this.attributeName = attributeName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the attribute value and returns it in the
|
||||
* payload of a Message.
|
||||
*/
|
||||
public Message<?> receive() {
|
||||
Assert.notNull(this.server, "MBeanServer is required");
|
||||
Assert.notNull(this.objectName, "object name is required");
|
||||
Assert.notNull(this.attributeName, "attribute name is required");
|
||||
try {
|
||||
Object value = this.server.getAttribute(this.objectName, this.attributeName);
|
||||
return this.mapper.toMessage(value);
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new MessagingException("failed to retrieve JMX attribute '"
|
||||
+ this.attributeName + "' on MBean [" + this.objectName + "]", e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.integration.jmx;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
import javax.management.Notification;
|
||||
import javax.management.ObjectName;
|
||||
|
||||
import org.springframework.integration.core.Message;
|
||||
import org.springframework.integration.message.OutboundMessageMapper;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Default Messaging Mapper implementation for the {@link NotificationPublishingMessageHandler}.
|
||||
* If the Message has a String-typed payload, that will be passed as the 'message' of
|
||||
* the Notification instance. Otherwise, the payload object will be passed as the
|
||||
* 'userData' of the Notification instance.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
* @since 2.0
|
||||
*/
|
||||
class DefaultNotificationMapper implements OutboundMessageMapper<Notification> {
|
||||
|
||||
private final ObjectName sourceObjectName;
|
||||
|
||||
private final String defaultNotificationType;
|
||||
|
||||
private final AtomicLong sequence = new AtomicLong();
|
||||
|
||||
|
||||
DefaultNotificationMapper(ObjectName sourceObjectName, String defaultNotificationType) {
|
||||
this.sourceObjectName = sourceObjectName;
|
||||
this.defaultNotificationType = defaultNotificationType;
|
||||
}
|
||||
|
||||
|
||||
public Notification fromMessage(Message<?> message) throws Exception {
|
||||
String type = this.resolveNotificationType(message);
|
||||
Assert.hasText(type,
|
||||
"No notification type header is available, and no default has been provided.");
|
||||
Object payload = (message != null) ? message.getPayload() : null;
|
||||
String notificationMessage = (payload instanceof String) ? (String) payload : null;
|
||||
Notification notification = new Notification(type, this.sourceObjectName,
|
||||
this.sequence.incrementAndGet(), System.currentTimeMillis(), notificationMessage);
|
||||
if (payload != null && !(payload instanceof String)) {
|
||||
notification.setUserData(payload);
|
||||
}
|
||||
return notification;
|
||||
}
|
||||
|
||||
private String resolveNotificationType(Message<?> message) {
|
||||
String type = message.getHeaders().get(JmxHeaders.NOTIFICATION_TYPE, String.class);
|
||||
return (type != null) ? type : this.defaultNotificationType;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.integration.jmx;
|
||||
|
||||
import org.springframework.integration.core.MessageHeaders;
|
||||
|
||||
/**
|
||||
* Constants for JMX related Message Header keys.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
* @since 2.0
|
||||
*/
|
||||
public abstract class JmxHeaders {
|
||||
|
||||
public static final String PREFIX = MessageHeaders.PREFIX + "jmx_";
|
||||
|
||||
public static final String OBJECT_NAME = PREFIX + "objectName";
|
||||
|
||||
public static final String OPERATION_NAME = PREFIX + "operationName";
|
||||
|
||||
public static final String NOTIFICATION_TYPE = PREFIX + "notificationType";
|
||||
|
||||
public static final String NOTIFICATION_HANDBACK = PREFIX + "notificationHandback";
|
||||
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.integration.jmx;
|
||||
|
||||
import javax.management.InstanceNotFoundException;
|
||||
import javax.management.ListenerNotFoundException;
|
||||
import javax.management.MBeanServer;
|
||||
import javax.management.Notification;
|
||||
import javax.management.NotificationFilter;
|
||||
import javax.management.NotificationListener;
|
||||
import javax.management.ObjectName;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.integration.core.Message;
|
||||
import org.springframework.integration.endpoint.MessageProducerSupport;
|
||||
import org.springframework.integration.message.MessageBuilder;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* A JMX {@link NotificationListener} implementation that will send Messages
|
||||
* containing the JMX {@link Notification} instances as their payloads.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
* @since 2.0
|
||||
*/
|
||||
public class NotificationListeningMessageProducer extends MessageProducerSupport implements NotificationListener {
|
||||
|
||||
private final Log logger = LogFactory.getLog(this.getClass());
|
||||
|
||||
private volatile MBeanServer server;
|
||||
|
||||
private volatile ObjectName objectName;
|
||||
|
||||
private volatile NotificationFilter filter;
|
||||
|
||||
private volatile Object handback;
|
||||
|
||||
|
||||
/**
|
||||
* Provide a reference to the MBeanServer where the notification
|
||||
* publishing MBeans are registered.
|
||||
*/
|
||||
public void setServer(MBeanServer server) {
|
||||
this.server = server;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the JMX ObjectName of the notification publisher
|
||||
* to which this notification listener should be subscribed.
|
||||
*/
|
||||
public void setObjectName(ObjectName objectName) {
|
||||
this.objectName = objectName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify a {@link NotificationFilter} to be passed to the server
|
||||
* when registering this listener. The filter may be null.
|
||||
*/
|
||||
public void setFilter(NotificationFilter filter) {
|
||||
this.filter = filter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify a handback object to provide context to the listener
|
||||
* upon notification. This object may be null.
|
||||
*/
|
||||
public void setHandback(Object handback) {
|
||||
this.handback = handback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Notification handling method implementation. Creates a Message with the
|
||||
* JMX {@link Notification} as its payload, and if the handback object is
|
||||
* not null, it sets that as a Message header value. The Message is then
|
||||
* sent to this producer's output channel.
|
||||
*/
|
||||
public void handleNotification(Notification notification, Object handback) {
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("received notification: " + notification + ", and handback: " + handback);
|
||||
}
|
||||
MessageBuilder<?> builder = MessageBuilder.withPayload(notification);
|
||||
if (handback != null) {
|
||||
builder.setHeader(JmxHeaders.NOTIFICATION_HANDBACK, handback);
|
||||
}
|
||||
Message<?> message = builder.build();
|
||||
this.sendMessage(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getComponentType() {
|
||||
// TODO: provide header: ("transport", "jmx");
|
||||
return "notification-listener";
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the notification listener with the specified ObjectNames.
|
||||
*/
|
||||
@Override
|
||||
protected void doStart() {
|
||||
try {
|
||||
Assert.notNull(this.server, "MBeanServer is required.");
|
||||
Assert.notNull(this.objectName, "An ObjectName is required.");
|
||||
this.server.addNotificationListener(this.objectName, this, this.filter, this.handback);
|
||||
}
|
||||
catch (InstanceNotFoundException e) {
|
||||
throw new IllegalStateException("Failed to find MBean instance.", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters the notification listener.
|
||||
*/
|
||||
@Override
|
||||
protected void doStop() {
|
||||
if (this.server != null && this.objectName != null) {
|
||||
try {
|
||||
this.server.removeNotificationListener(this.objectName, this, this.filter, this.handback);
|
||||
}
|
||||
catch (InstanceNotFoundException e) {
|
||||
throw new IllegalStateException("Failed to find MBean instance.", e);
|
||||
}
|
||||
catch (ListenerNotFoundException e) {
|
||||
throw new IllegalStateException("Failed to find NotificationListener.", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.integration.jmx;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import javax.management.MalformedObjectNameException;
|
||||
import javax.management.Notification;
|
||||
import javax.management.ObjectName;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.BeanFactoryUtils;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.ListableBeanFactory;
|
||||
import org.springframework.integration.core.Message;
|
||||
import org.springframework.integration.handler.AbstractMessageHandler;
|
||||
import org.springframework.integration.message.OutboundMessageMapper;
|
||||
import org.springframework.jmx.export.MBeanExporter;
|
||||
import org.springframework.jmx.export.annotation.ManagedResource;
|
||||
import org.springframework.jmx.export.notification.NotificationPublisher;
|
||||
import org.springframework.jmx.export.notification.NotificationPublisherAware;
|
||||
import org.springframework.jmx.support.ObjectNameManager;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* @author Mark Fisher
|
||||
* @since 2.0
|
||||
*/
|
||||
public class NotificationPublishingMessageHandler extends AbstractMessageHandler implements BeanFactoryAware, InitializingBean {
|
||||
|
||||
private final PublisherDelegate delegate = new PublisherDelegate();
|
||||
|
||||
private volatile OutboundMessageMapper<Notification> notificationMapper;
|
||||
|
||||
private final ObjectName objectName;
|
||||
|
||||
private volatile String defaultNotificationType;
|
||||
|
||||
|
||||
public NotificationPublishingMessageHandler(ObjectName objectName) {
|
||||
Assert.notNull(objectName, "JMX ObjectName is required");
|
||||
this.objectName = objectName;
|
||||
}
|
||||
|
||||
public NotificationPublishingMessageHandler(String objectName) {
|
||||
Assert.notNull(objectName, "JMX ObjectName is required");
|
||||
try {
|
||||
this.objectName = ObjectNameManager.getInstance(objectName);
|
||||
}
|
||||
catch (MalformedObjectNameException e) {
|
||||
throw new IllegalArgumentException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set a mapper for creating Notifications from a Message. If not provided,
|
||||
* a default implementation will be used such that String-typed payloads will be
|
||||
* passed as the 'message' of the Notification and all other payload types
|
||||
* will be passed as the 'userData' of the Notification.
|
||||
*/
|
||||
public void setNotificationMapper(OutboundMessageMapper<Notification> notificationMapper) {
|
||||
this.notificationMapper = notificationMapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify a dot-delimited String representing the Notification type to
|
||||
* use by default when <emphasis>no</emphasis> explicit Notification mapper
|
||||
* has been configured. If not provided, then a notification type header will
|
||||
* be required for each message being mapped into a Notification.
|
||||
*/
|
||||
public void setDefaultNotificationType(String defaultNotificationType) {
|
||||
this.defaultNotificationType = defaultNotificationType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void onInit() throws Exception {
|
||||
Assert.isTrue(this.getBeanFactory() instanceof ListableBeanFactory, "A ListableBeanFactory is required.");
|
||||
Map<String, MBeanExporter> exporters = BeanFactoryUtils.beansOfTypeIncludingAncestors(
|
||||
(ListableBeanFactory) this.getBeanFactory(), MBeanExporter.class);
|
||||
Assert.isTrue(exporters.size() == 1,
|
||||
"No unique MBeanExporter is available in the current context (found " +
|
||||
exporters.size() + ").");
|
||||
MBeanExporter exporter = exporters.values().iterator().next();
|
||||
if (this.notificationMapper == null) {
|
||||
this.notificationMapper = new DefaultNotificationMapper(this.objectName, this.defaultNotificationType);
|
||||
}
|
||||
exporter.registerManagedResource(this.delegate, this.objectName);
|
||||
if (this.logger.isInfoEnabled()) {
|
||||
this.logger.info("Registered JMX notification publisher as MBean with ObjectName: " + this.objectName);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleMessageInternal(Message<?> message) throws Exception {
|
||||
this.delegate.publish(this.notificationMapper.fromMessage(message));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Simple class used for the actual MBean instances to be registered.
|
||||
*/
|
||||
@ManagedResource
|
||||
private static class PublisherDelegate implements NotificationPublisherAware {
|
||||
|
||||
private volatile NotificationPublisher notificationPublisher;
|
||||
|
||||
public void setNotificationPublisher(NotificationPublisher notificationPublisher) {
|
||||
this.notificationPublisher = notificationPublisher;
|
||||
}
|
||||
|
||||
private void publish(Notification notification) {
|
||||
Assert.state(this.notificationPublisher != null, "NotificationPublisher must not be null.");
|
||||
this.notificationPublisher.sendNotification(notification);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,223 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.integration.jmx;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.management.JMException;
|
||||
import javax.management.MBeanInfo;
|
||||
import javax.management.MBeanOperationInfo;
|
||||
import javax.management.MBeanParameterInfo;
|
||||
import javax.management.MBeanServer;
|
||||
import javax.management.MalformedObjectNameException;
|
||||
import javax.management.ObjectName;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.integration.core.Message;
|
||||
import org.springframework.integration.core.MessagingException;
|
||||
import org.springframework.integration.handler.AbstractReplyProducingMessageHandler;
|
||||
import org.springframework.integration.message.MessageHandler;
|
||||
import org.springframework.integration.message.MessageHandlingException;
|
||||
import org.springframework.jmx.support.ObjectNameManager;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* A {@link MessageHandler} implementation for invoking JMX operations based on
|
||||
* the Message sent to its {@link #handleMessage(Message)} method. Message headers
|
||||
* will be checked first when resolving the 'objectName' and 'operationName' to be
|
||||
* invoked on an MBean. These values would be supplied with the Message headers
|
||||
* defined as {@link JmxHeaders#OBJECT_NAME} and {@link JmxHeaders#OPERATION_NAME},
|
||||
* respectively. In either case, if no header is present, the value resolution
|
||||
* will fallback to the defaults, if any have been configured on this instance via
|
||||
* {@link #setDefaultObjectName(String)} and {@link #setDefaultOperationName(String)},
|
||||
* respectively.
|
||||
*
|
||||
* <p>The operation parameter(s), if any, must be available within the payload of the
|
||||
* Message being handled. If the target operation expects multiple parameters, they
|
||||
* can be provided in either a List or Map typed payload.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
* @author Oleg Zhurakousky
|
||||
* @since 2.0
|
||||
*/
|
||||
public class OperationInvokingMessageHandler extends AbstractReplyProducingMessageHandler implements InitializingBean {
|
||||
|
||||
private volatile MBeanServer server;
|
||||
|
||||
private volatile ObjectName defaultObjectName;
|
||||
|
||||
private volatile String defaultOperationName;
|
||||
|
||||
|
||||
/**
|
||||
* Provide a reference to the MBeanServer within which the MBean
|
||||
* target for operation invocation has been registered.
|
||||
*/
|
||||
public void setServer(MBeanServer server) {
|
||||
this.server = server;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify a default ObjectName to use when no such header is
|
||||
* available on the Message being handled.
|
||||
*/
|
||||
public void setDefaultObjectName(String defaultObjectName) {
|
||||
try {
|
||||
if (defaultObjectName != null) {
|
||||
this.defaultObjectName = ObjectNameManager.getInstance(defaultObjectName);
|
||||
}
|
||||
}
|
||||
catch (MalformedObjectNameException e) {
|
||||
throw new IllegalArgumentException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify a default operation name to be invoked when no such
|
||||
* header is available on the Message being handled.
|
||||
*/
|
||||
public void setDefaultOperationName(String defaultOperationName) {
|
||||
this.defaultOperationName = defaultOperationName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void onInit() {
|
||||
Assert.notNull(this.server, "MBeanServer is required.");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object handleRequestMessage(Message<?> requestMessage) {
|
||||
ObjectName objectName = this.resolveObjectName(requestMessage);
|
||||
String operationName = this.resolveOperationName(requestMessage);
|
||||
Map<String, Object> paramsFromMessage = this.resolveParameters(requestMessage);
|
||||
try {
|
||||
MBeanInfo mbeanInfo = this.server.getMBeanInfo(objectName);
|
||||
MBeanOperationInfo[] opInfoArray = mbeanInfo.getOperations();
|
||||
boolean hasNoArgOption = false;
|
||||
for (MBeanOperationInfo opInfo : opInfoArray) {
|
||||
if (operationName.equals(opInfo.getName())) {
|
||||
MBeanParameterInfo[] paramInfoArray = opInfo.getSignature();
|
||||
if (paramInfoArray.length == 0) {
|
||||
hasNoArgOption = true;
|
||||
}
|
||||
if (paramInfoArray.length == paramsFromMessage.size()) {
|
||||
int index = 0;
|
||||
Object values[] = new Object[paramInfoArray.length];
|
||||
String signature[] = new String[paramInfoArray.length];
|
||||
for (MBeanParameterInfo paramInfo : paramInfoArray) {
|
||||
Object value = paramsFromMessage.get(paramInfo.getName());
|
||||
if (value != null && value.getClass().getName().equals(paramInfo.getType())) {
|
||||
values[index] = value;
|
||||
signature[index] = paramInfo.getType();
|
||||
index++;
|
||||
}
|
||||
}
|
||||
if (index == paramInfoArray.length) {
|
||||
return this.server.invoke(objectName, operationName, values, signature);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (hasNoArgOption) {
|
||||
return this.server.invoke(objectName, operationName, null, null);
|
||||
}
|
||||
throw new MessagingException(requestMessage, "failed to find JMX operation '"
|
||||
+ operationName + "' on MBean [" + objectName + "] of type [" + mbeanInfo.getClassName()
|
||||
+ "] with " + paramsFromMessage.size() + " parameters: " + paramsFromMessage.keySet());
|
||||
}
|
||||
catch (JMException e) {
|
||||
throw new MessageHandlingException(requestMessage, "failed to invoke JMX operation '" +
|
||||
operationName + "' on MBean [" + objectName + "]" + " with " +
|
||||
paramsFromMessage.size() + " parameters: " + paramsFromMessage.keySet(), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* First checks for the presence of a {@link JmxHeaders#OBJECT_NAME} header,
|
||||
* then falls back to this handler's {@link #defaultObjectName} if available.
|
||||
*/
|
||||
private ObjectName resolveObjectName(Message<?> message) {
|
||||
ObjectName objectName = null;
|
||||
Object objectNameHeader = message.getHeaders().get(JmxHeaders.OBJECT_NAME);
|
||||
if (objectNameHeader instanceof ObjectName) {
|
||||
objectName = (ObjectName) objectNameHeader;
|
||||
}
|
||||
else if (objectNameHeader instanceof String) {
|
||||
try {
|
||||
objectName = ObjectNameManager.getInstance(objectNameHeader);
|
||||
}
|
||||
catch (MalformedObjectNameException e) {
|
||||
throw new IllegalArgumentException(e);
|
||||
}
|
||||
}
|
||||
else {
|
||||
objectName = this.defaultObjectName;
|
||||
}
|
||||
Assert.notNull(objectName, "Failed to resolve ObjectName.");
|
||||
return objectName;
|
||||
}
|
||||
|
||||
/**
|
||||
* First checks for the presence of a {@link JmxHeaders#OPERATION_NAME} header,
|
||||
* then falls back to this handler's {@link #defaultOperationName} if available.
|
||||
*/
|
||||
private String resolveOperationName(Message<?> message) {
|
||||
String operationName = message.getHeaders().get(JmxHeaders.OPERATION_NAME, String.class);
|
||||
if (operationName == null) {
|
||||
operationName = this.defaultOperationName;
|
||||
}
|
||||
Assert.notNull(operationName, "Failed to resolve operation name.");
|
||||
return operationName;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Map<String, Object> resolveParameters(Message<?> message) {
|
||||
Map<String, Object> map = null;
|
||||
if (message.getPayload() instanceof Map) {
|
||||
map = (Map<String, Object>) message.getPayload();
|
||||
}
|
||||
else if (message.getPayload() instanceof List) {
|
||||
map = this.createParameterMapFromList((List) message.getPayload());
|
||||
}
|
||||
else if (message.getPayload() != null && message.getPayload().getClass().isArray()) {
|
||||
map = this.createParameterMapFromList(
|
||||
Arrays.asList(ObjectUtils.toObjectArray(message.getPayload())));
|
||||
}
|
||||
else if (message.getPayload() != null) {
|
||||
map = this.createParameterMapFromList(Collections.singletonList(message.getPayload()));
|
||||
}
|
||||
else {
|
||||
map = Collections.EMPTY_MAP;
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Map<String, Object> createParameterMapFromList(List parameters) {
|
||||
Map<String, Object> map = new HashMap<String, Object>();
|
||||
for (int i = 0; i < parameters.size(); i++) {
|
||||
map.put("p" + (i + 1), parameters.get(i));
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.integration.jmx.config;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.integration.config.xml.AbstractPollingInboundChannelAdapterParser;
|
||||
import org.springframework.integration.config.xml.IntegrationNamespaceUtils;
|
||||
|
||||
/**
|
||||
* @author Mark Fisher
|
||||
* @since 2.0
|
||||
*/
|
||||
public class AttributePollingChannelAdapterParser extends AbstractPollingInboundChannelAdapterParser {
|
||||
|
||||
@Override
|
||||
protected String parseSource(Element element, ParserContext parserContext) {
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(
|
||||
"org.springframework.integration.jmx.AttributePollingMessageSource");
|
||||
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "mbean-server", "server");
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "object-name");
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "attribute-name");
|
||||
return BeanDefinitionReaderUtils.registerWithGeneratedName(
|
||||
builder.getBeanDefinition(), parserContext.getRegistry());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.integration.jmx.config;
|
||||
|
||||
import javax.management.MBeanServerFactory;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.xml.AbstractSimpleBeanDefinitionParser;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.integration.config.xml.IntegrationNamespaceUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* @author Mark Fisher
|
||||
* @since 2.0
|
||||
*/
|
||||
public class ControlBusParser extends AbstractSimpleBeanDefinitionParser {
|
||||
|
||||
@Override
|
||||
protected String getBeanClassName(Element element) {
|
||||
return "org.springframework.integration.control.ControlBus";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
|
||||
Object source = parserContext.extractSource(element);
|
||||
builder.getRawBeanDefinition().setSource(source);
|
||||
String mbeanServer = element.getAttribute("mbean-server");
|
||||
if (StringUtils.hasText(mbeanServer)) {
|
||||
builder.addConstructorArgReference(mbeanServer);
|
||||
}
|
||||
else {
|
||||
builder.addConstructorArgValue(MBeanServerFactory.createMBeanServer());
|
||||
}
|
||||
String domain = element.getAttribute("domain");
|
||||
if (StringUtils.hasText(domain)) {
|
||||
builder.addConstructorArgValue(domain);
|
||||
}
|
||||
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "operation-channel");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.integration.jmx.config;
|
||||
|
||||
import org.springframework.integration.config.xml.AbstractIntegrationNamespaceHandler;
|
||||
|
||||
/**
|
||||
* Namespace handler for Spring Integration's <em>jmx</em> namespace.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
* @since 2.0
|
||||
*/
|
||||
public class JmxNamespaceHandler extends AbstractIntegrationNamespaceHandler {
|
||||
|
||||
public void init() {
|
||||
this.registerBeanDefinitionParser("operation-invoking-channel-adapter", new OperationInvokingChannelAdapterParser());
|
||||
this.registerBeanDefinitionParser("attribute-polling-channel-adapter", new AttributePollingChannelAdapterParser());
|
||||
this.registerBeanDefinitionParser("notification-listening-channel-adapter", new NotificationListeningChannelAdapterParser());
|
||||
this.registerBeanDefinitionParser("notification-publishing-channel-adapter", new NotificationPublishingChannelAdapterParser());
|
||||
this.registerBeanDefinitionParser("control-bus", new ControlBusParser());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.integration.jmx.config;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.xml.AbstractSimpleBeanDefinitionParser;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.integration.config.xml.IntegrationNamespaceUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* @author Mark Fisher
|
||||
* @since 2.0
|
||||
*/
|
||||
public class NotificationListeningChannelAdapterParser extends AbstractSimpleBeanDefinitionParser {
|
||||
|
||||
@Override
|
||||
protected String getBeanClassName(Element element) {
|
||||
return "org.springframework.integration.jmx.NotificationListeningMessageProducer";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
|
||||
Object source = parserContext.extractSource(element);
|
||||
String channel = element.getAttribute("channel");
|
||||
if (!StringUtils.hasText(channel)) {
|
||||
parserContext.getReaderContext().error("The 'channel' attribute is required.", source);
|
||||
}
|
||||
builder.addPropertyReference("outputChannel", channel);
|
||||
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "mbean-server", "server");
|
||||
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "notification-filter", "filter");
|
||||
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "handback");
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "send-timeout");
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "object-name");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.integration.jmx.config;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.integration.config.xml.AbstractOutboundChannelAdapterParser;
|
||||
import org.springframework.integration.config.xml.IntegrationNamespaceUtils;
|
||||
|
||||
/**
|
||||
* @author Mark Fisher
|
||||
* @since 2.0
|
||||
*/
|
||||
public class NotificationPublishingChannelAdapterParser extends AbstractOutboundChannelAdapterParser {
|
||||
|
||||
@Override
|
||||
protected AbstractBeanDefinition parseConsumer(Element element, ParserContext parserContext) {
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(
|
||||
"org.springframework.integration.jmx.NotificationPublishingMessageHandler");
|
||||
builder.addConstructorArgValue(element.getAttribute("object-name"));
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "default-notification-type");
|
||||
return builder.getBeanDefinition();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.integration.jmx.config;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.integration.config.xml.AbstractOutboundChannelAdapterParser;
|
||||
import org.springframework.integration.config.xml.IntegrationNamespaceUtils;
|
||||
|
||||
/**
|
||||
* @author Mark Fisher
|
||||
* @since 2.0
|
||||
*/
|
||||
public class OperationInvokingChannelAdapterParser extends AbstractOutboundChannelAdapterParser {
|
||||
|
||||
@Override
|
||||
protected AbstractBeanDefinition parseConsumer(Element element, ParserContext parserContext) {
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(
|
||||
"org.springframework.integration.jmx.OperationInvokingMessageHandler");
|
||||
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "mbean-server", "server");
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "default-object-name");
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "default-operation-name");
|
||||
return builder.getBeanDefinition();
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user