openfire二次开发:使用Annotation注解VO转换xml文档

IQElementMapping是一个注解类,用于映射实体类与xml对象


/**
 * openfire_src
 */
package com.kingray.openfire.plugin.packet;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * IQ映射注解,用于注解实体类的字段,帮助转换器转换为xml对象
 * @author KRXiongYingqi
 * @version 2013-6-17 上午10:44:44
 */
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.TYPE})
public @interface IQElementMapping {
	public String value();
}


VO接口,所有实体类的超类

package com.kingray.openfire.plugin.vo;

import java.io.Serializable;
/**
 * VO类,所有实体类的超类
 * @author KRXiongYingqi
 * @version 2013-6-20 下午4:02:49
 */
public interface VO extends Serializable{

}


消息实体,使用IQElementMapping注解

package com.kingray.openfire.plugin.vo;

import java.util.Date;

import com.kingray.openfire.plugin.packet.IQElementMapping;
import com.xiongyingqi.util.DateHelper;

/**
 * 消息实体,用于存储传递时用到的查询条件或返回结果
 * @author KRXiongYingqi
 * @version 2013-6-20 下午2:14:47
 */
@IQElementMapping("message")
public class MessageVO implements VO {
	@IQElementMapping("messageId")
	private long messageId;
	
	@IQElementMapping("sendMessageId")
	private String sendMessageId;
	
	@IQElementMapping("messageFrom")
	private String messageFrom;
	
	@IQElementMapping("messageTo")
	private String messageTo;
	
	@IQElementMapping("messageSubject")
	private String messageSubject;
	
	@IQElementMapping("messageBody")
	private String messageBody;
	
	@IQElementMapping("messageDateTime")
	private Date messageDateTime;
	
	@IQElementMapping("messageDateTimeStr")
	private String messageDateTimeStr;
	
	@IQElementMapping("messageType")
	private String messageType;
	
	public MessageVO(){
	}
	public MessageVO(long messageId, String sendMessageId, String messageFrom, String messageTo, String messageBody){
		this.messageId = messageId;
		this.sendMessageId = sendMessageId;
		this.messageFrom = messageFrom;
		this.messageTo = messageTo;
		this.messageBody = messageBody;
	}
	/**
	 * @return the messageType
	 */
	public String getMessageType() {
		return messageType;
	}
	/**
	 * @param messageType the messageType to set
	 */
	public void setMessageType(String messageType) {
		this.messageType = messageType;
	}
	/**
	 * @return the messageSubject
	 */
	public String getMessageSubject() {
		return messageSubject;
	}
	/**
	 * @param messageSubject the messageSubject to set
	 */
	public void setMessageSubject(String messageSubject) {
		this.messageSubject = messageSubject;
	}
	/**
	 * @return the messageId
	 */
	public long getMessageId() {
		return messageId;
	}
	/**
	 * @param messageId the messageId to set
	 */
	public void setMessageId(long messageId) {
		this.messageId = messageId;
	}
	/**
	 * @return the sendMessageId
	 */
	public String getSendMessageId() {
		return sendMessageId;
	}
	/**
	 * @param sendMessageId the sendMessageId to set
	 */
	public void setSendMessageId(String sendMessageId) {
		this.sendMessageId = sendMessageId;
	}
	/**
	 * @return the messageFrom
	 */
	public String getMessageFrom() {
		return messageFrom;
	}
	/**
	 * @param messageFrom the messageFrom to set
	 */
	public void setMessageFrom(String messageFrom) {
		if(messageFrom == null) messageFrom = "";
		this.messageFrom = messageFrom;
	}
	/**
	 * @return the messageTo
	 */
	public String getMessageTo() {
		return messageTo;
	}
	/**
	 * @param messageTo the messageTo to set
	 */
	public void setMessageTo(String messageTo) {
		if(messageTo == null) messageTo = "";
		this.messageTo = messageTo;
	}
	/**
	 * @return the messageBody
	 */
	public String getMessageBody() {
		return messageBody;
	}
	/**
	 * @param messageBody the messageBody to set
	 */
	public void setMessageBody(String messageBody) {
		this.messageBody = messageBody;
	}
	/**
	 * @return the messageDateTime
	 */
	public Date getMessageDateTime() {
		return messageDateTime;
	}
	/**
	 * @param messageDateTime the messageDateTime to set
	 */
	public void setMessageDateTime(Date messageDateTime) {
		this.messageDateTimeStr = DateHelper.FORMATTER_LONG.format(messageDateTime);
		this.messageDateTime = messageDateTime;
	}
	/**
	 * @return the messageDateTimeStr
	 */
	public String getMessageDateTimeStr() {
		return messageDateTimeStr;
	}
	/**
	 * @param messageDateTimeStr the messageDateTimeStr to set
	 */
	public void setMessageDateTimeStr(String messageDateTimeStr) {
		this.messageDateTime = DateHelper.strToDateLong(messageDateTimeStr);
		this.messageDateTimeStr = messageDateTimeStr;
	}
	@Override
	public String toString() {
		return this.getClass() + "@" + hashCode() + ": messageId: " + messageId + ", sendMessageId: " 
				+ sendMessageId + ", messageFrom: " + messageFrom + ", messageTo: " + messageTo + ", messageBody: " 
				+ messageBody + ", messageDateTime: " + messageDateTime;
	}
}

xml转换工具,使用反射机制

/**
 * openfire_src
 */
package com.xiongyingqi.convert;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Iterator;

import org.dom4j.DocumentHelper;
import org.dom4j.Element;

import com.kingray.openfire.plugin.packet.KingrayNameSpace;
import com.kingray.openfire.plugin.vo.VO;
import com.xiongyingqi.util.StringHelper;

/**
 * Xml转换工具
 * @author KRXiongYingqi
 * @version 2013-6-17 下午4:44:03
 */
public class XmlConvert {
	private Class annotationClass;
	
	public XmlConvert(Class annotationClass){
		this.annotationClass = annotationClass;
	}
	
	/**
	 * 由Collection<? extends VO>转换为xml,被转换的类必须由有注解类注解
	 * <br>2013-6-17 下午4:44:45
	 * @param collection 消息集合
	 * @return org.dom4j.Element
	 */
	public Element convertVOs(Collection<? extends VO> collection){
		Element element = DocumentHelper.createElement(KingrayNameSpace.QUERY_MESSAGE.getKey());
		for (Iterator iterator = collection.iterator(); iterator.hasNext();) { // 遍历集合
			Object instance =  iterator.next();
			Class instanceClass = instance.getClass();
			
			String elementName = null; 
			if(instanceClass.isAnnotationPresent(annotationClass)){ // 判断VO类是否包含了annotationClass的注解
				Annotation annotation = instanceClass.getAnnotation(annotationClass); // 获取annotationClass的注解
				Method[] methods = annotationClass.getMethods(); // 获取annotationClass的所有方法
				if(methods.length > 1){ // 如果有多个注解
					for (int i = 0; i < methods.length; i++) {
						Method method = methods[i];
						String methodName = method.getName(); // 注解方法的方法名
						
						if("value".equals(methodName)){ // 是否为value方法
							try {
								elementName = (String) method.invoke(annotation);
							} catch (IllegalArgumentException e) {
								e.printStackTrace();
							} catch (IllegalAccessException e) {
								e.printStackTrace();
							} catch (InvocationTargetException e) {
								e.printStackTrace();
							}
							break;
						}
					}
				} else if(methods.length == 1){
					Method method = methods[0];
					String methodName = method.getName(); // 注解方法的方法名
					
					if("value".equals(methodName)){ // 是否为value方法
						try {
							elementName = (String) method.invoke(annotation);
						} catch (IllegalArgumentException e) {
							e.printStackTrace();
						} catch (IllegalAccessException e) {
							e.printStackTrace();
						} catch (InvocationTargetException e) {
							e.printStackTrace();
						}
					}
				}
				
			}
			if(StringHelper.nullOrEmpty(elementName)){
				elementName = instance.getClass().getSimpleName();
			}
			Element messageElement = DocumentHelper.createElement(elementName); // 创建节点
			
//			Class clazz = IQElementMapping.class;
			Field[] fields = instance.getClass().getDeclaredFields();
			for (int i = 0; i < fields.length; i++) { // 遍历每个字段
				Field field = fields[i];
				if(field.isAnnotationPresent(annotationClass)){ // 检测是否为IQElementMapping的注解类型
					Annotation annotation = field.getAnnotation(annotationClass);
					Method[] methods = annotationClass.getDeclaredMethods(); // 获取注解类的所有方法
					for (int j = 0; j < methods.length; j++) {
						Method annoutationMethod = methods[j];
						String fieldName = null;
						try {
							fieldName = annoutationMethod.invoke(annotation) + ""; // 获取注解方法的返回值
						} catch (IllegalArgumentException e1) {
							e1.printStackTrace();
						} catch (IllegalAccessException e1) {
							e1.printStackTrace();
						} catch (InvocationTargetException e1) {
							e1.printStackTrace();
						}
//						annotation.value();
						String fieldValue = null; // 被注解的字段的值
						try {
							String methodName = "get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1); // 使用bean的方法
							Method method = instance.getClass().getDeclaredMethod(methodName);
							Object returnObject = method.invoke(instance);
							if(returnObject != null){
								fieldValue = returnObject + "";
							}
//						fieldValue = (String) field.get(messageVO);
						} catch (IllegalArgumentException e) {
							e.printStackTrace();
						} catch (IllegalAccessException e) {
							e.printStackTrace();
						} catch (SecurityException e) {
							e.printStackTrace();
						} catch (NoSuchMethodException e) {
							e.printStackTrace();
						} catch (InvocationTargetException e) {
							e.printStackTrace();
						}
						if(StringHelper.notNullAndNotEmpty(fieldValue)){
							messageElement.addAttribute(fieldName, fieldValue);  // 为每个字段设置属性
						}
					}
				}
			}
			element.add(messageElement);
		}
		return element;
	}
}


IQ处理器,用于处理客户端发送的查询IQ

package com.kingray.openfire.plugin.handler;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;

import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.jivesoftware.openfire.IQHandlerInfo;
import org.jivesoftware.openfire.IQRouter;
import org.jivesoftware.openfire.XMPPServer;
import org.jivesoftware.openfire.auth.UnauthorizedException;
import org.jivesoftware.openfire.disco.ServerFeaturesProvider;
import org.jivesoftware.openfire.handler.IQHandler;
import org.jivesoftware.openfire.session.ClientSession;
import org.xmpp.packet.IQ;
import org.xmpp.packet.JID;
import org.xmpp.packet.PacketError;

import com.kingray.openfire.plugin.dao.MessageDAO;
import com.kingray.openfire.plugin.dao.impl.MessageDAOImpl;
import com.kingray.openfire.plugin.packet.IQElementMapping;
import com.kingray.openfire.plugin.packet.KingrayNameSpace;
import com.kingray.openfire.plugin.packet.MessageHistoryIQ;
import com.kingray.openfire.plugin.vo.MessageVO;
import com.xiongyingqi.convert.XmlConvert;
import com.xiongyingqi.util.CalendarHelper;
import com.xiongyingqi.util.DateHelper;
import com.xiongyingqi.util.StringHelper;

/**
 * 服务类,用于处理客户端的数据查询等请求
 * @author XiongYingqi
 * 
 */
public class KingrayMessageHistoryIQHandler extends IQHandler implements ServerFeaturesProvider {
	private static final KingrayNameSpace QUERY_MESSAGE = KingrayNameSpace.QUERY_MESSAGE; // 命名空间
	private MessageDAO messageDAO;
	private XmlConvert convert;
	
	private IQHandlerInfo info;
	
	private String serverString;
	
	public KingrayMessageHistoryIQHandler() {
		super(QUERY_MESSAGE.getKey()); // 取一个处理器名
		messageDAO = new MessageDAOImpl();
		convert = new XmlConvert(IQElementMapping.class);
		info = new IQHandlerInfo(QUERY_MESSAGE.getKey(), QUERY_MESSAGE.getValue());
		
		XMPPServer server = XMPPServer.getInstance();
		serverString = server.getServerInfo().getXMPPDomain();
		
		// 注册IQ处理服务
		IQRouter iqRouter = server.getIQRouter();
		iqRouter.addHandler(this);
		
//		server.getServerFeaturesProviders().add(this);
//		server.getIQDiscoInfoHandler().addServerFeature(QUERY_MESSAGE.getValue());
		
	}

	@Override
	public IQ handleIQ(IQ packet) throws UnauthorizedException {
		System.out.println("packet.toXML() =========== " + packet.toXML());
		IQ response = handleMessageHistory(packet);
		
		response.setType(IQ.Type.result);
		response.setFrom(serverString);
		JID fromJid = packet.getFrom();
		ClientSession session = XMPPServer.getInstance().getSessionManager().getSession(fromJid);
		if(session == null){ // 
			response.setChildElement(packet.getChildElement().createCopy());
			response.setError(PacketError.Condition.not_authorized);
		}
//		session.process(response);
//		deliverer.deliver(response);
		
		System.out.println(this.getClass() + " handleIQ ====== " + response.toXML());
//		response = null;
		return response;
	}
	
	/**
	 * 处理消息记录
	 * <br>2013-6-18 上午9:49:27
	 * @param packet
	 * @return
	 */
	public IQ handleMessageHistory(IQ packet){
		IQ response = IQ.createResultIQ(packet);
		
		String userName = packet.getFrom().getNode();
		
		// 读取根节点数据
		Element element = packet.getChildElement();
		String relationUserName = element.attributeValue("relationUserName");
		String actionType = element.attributeValue("actionType");
		String messageDateTimeStr = element.attributeValue("messageDateTime");
		
		Date messageDateTime = null;
		if(StringHelper.notNullAndNotEmpty(messageDateTimeStr)){
			try {
				messageDateTime = DateHelper.strToDate(messageDateTimeStr);
			} catch (Exception e) {
			}
		}
		
		//读取<message节点数据>
		Collection<Long> messageIds = new HashSet<Long>();
		Collection<String> sendMessageIds = new HashSet<String>();
		
		List messageElements = element.elements();
		for (Iterator iterator = messageElements.iterator(); iterator.hasNext();) {
			Element messageElement = (Element) iterator.next();
			String messageIdStr = messageElement.attributeValue("messageId"); // 优先读取messageId
			if(StringHelper.notNullAndNotEmpty(messageIdStr)){
				Long messageId = Long.parseLong(messageIdStr);
				messageIds.add(messageId);
			} else { // 如果不存在messageId属性,则读取sendMessageId
				String sendMessageId = messageElement.attributeValue("sendMessageId");
				if(StringHelper.notNullAndNotEmpty(sendMessageId)){
					sendMessageIds.add(sendMessageId);
				}
			}
		}
		
		if(!StringHelper.notNullAndNotEmpty(actionType)){ // 判断是否指定actionType,如果没有指定,则默认使用QUERY_COUNT
			actionType = MessageHistoryIQ.MessageHistoryActionType.QUERY_COUNT.toString();
		} 
		Element resultElement = null;
		
		if(actionType.equals(MessageHistoryIQ.MessageHistoryActionType.QUERY_COUNT.toString())){ // 查询条数
			int messageHistoryCount = messageDAO.getMessageHistoryCountByUserName(userName, relationUserName, messageDateTime);
			resultElement = handleMessageHistoryCountResponseIQ(response, messageHistoryCount, relationUserName, messageDateTime);
		} else if(actionType.equals(MessageHistoryIQ.MessageHistoryActionType.QUERY_SUMMARY.toString())){ // 查询预览
			Collection<MessageVO> messageVOs = messageDAO.getMessageHistorySummaryByUserName(userName, relationUserName, messageDateTime);
			resultElement = convert.convertVOs(messageVOs); // 将获取的数据转换为xml
		} else if(actionType.equals(MessageHistoryIQ.MessageHistoryActionType.QUERY_DETAIL.toString())){ // 查询详细消息
			Collection<MessageVO> messageVOs = null;
			// 检查查询条件,如果查询条件不足,那么就返回错误
			if(messageIds != null && messageIds.size() > 0){
				messageVOs = messageDAO.getMessageHistoryDetailByMessageIds(messageIds);
			} else if(sendMessageIds != null && sendMessageIds.size() > 0){
				messageVOs = messageDAO.getMessageHistoryDetailBySendMessageIds(sendMessageIds);
			} else if(StringHelper.notNullAndNotEmpty(userName)){
				messageVOs = messageDAO.getMessageHistoryDetailByUserName(userName, relationUserName, messageDateTime);
			} else { // 查询条件不足,返回错误
				response.setChildElement(packet.getChildElement().createCopy());
				response.setError(PacketError.Condition.bad_request);
				return response;
			}
			
			if(messageVOs != null){
				resultElement = convert.convertVOs(messageVOs); // 将获取的数据转换为xml
			}
		}
		System.out.println("resultElement ======== " + resultElement);
		resultElement.addAttribute("actionType", actionType); // 加入actionType
		resultElement.addNamespace("", QUERY_MESSAGE.getValue()); // 加入命名空间
		response.setChildElement(resultElement);
		
		return response;
	}
	/**
	 * 返回总消息数的IQ
	 * <br>2013-6-17 下午3:26:22
	 * @param packet
	 * @param messageCount
	 * @param relationUserName
	 * @param messageDateTime
	 * @return
	 */
	public Element handleMessageHistoryCountResponseIQ(IQ packet, int messageHistoryCount, String relationUserName, Date messageDateTime){
		Element element = DocumentHelper.createElement(QUERY_MESSAGE.getKey());
//		Element messageHistoryCountElement = DocumentHelper.createElement("messageHistoryCount");
//		messageHistoryCountElement.setData(messageHistoryCount);
//		element.add(messageHistoryCountElement);
		element.addAttribute("messageHistoryCount", messageHistoryCount + "");
		if(StringHelper.notNullAndNotEmpty(relationUserName)){
			element.addAttribute("relationUserName", relationUserName);
		}
		if(messageDateTime != null){
			element.addAttribute("messageDateTime", DateHelper.dateToStr(messageDateTime));
		}
		element.addNamespace("", QUERY_MESSAGE.getValue()); // 加入命名空间
//		packet.setChildElement(element);
		return element;
	}
	
	/**
	 * 必须实现该方法,否则openfire将无法实例化本处理器
	 */
	@Override
	public IQHandlerInfo getInfo() {
		return info;
	}


	/**
	 * <br>2013-6-19 下午5:56:05
	 * @see org.jivesoftware.openfire.disco.ServerFeaturesProvider#getFeatures()
	 */
	@Override
	public Iterator<String> getFeatures() {
		ArrayList<String> features = new ArrayList<String>();
        features.add(QUERY_MESSAGE.getValue());
        return features.iterator();
	}

}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值