package com.meidusa.amoeba.aladdin.handler; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; import java.util.StringTokenizer; import com.meidusa.amoeba.aladdin.io.MysqlResultSetPacket; import com.meidusa.amoeba.aladdin.io.ResultPacket; import com.meidusa.amoeba.mysql.jdbc.MysqlDefs; import com.meidusa.amoeba.mysql.net.packet.EOFPacket; import com.meidusa.amoeba.mysql.net.packet.FieldPacket; import com.meidusa.amoeba.mysql.net.packet.ResultSetHeaderPacket; import com.meidusa.amoeba.mysql.net.packet.RowDataPacket; import com.meidusa.amoeba.net.MessageHandler; import com.meidusa.amoeba.net.packet.AbstractPacketBuffer; import com.meidusa.amoeba.net.packet.PacketBuffer; import com.meidusa.amoeba.util.Initialisable; import com.meidusa.amoeba.util.InitialisationException; import com.meidusa.amoeba.xmltable.Condition; import com.meidusa.amoeba.xmltable.XmlColumn; import com.meidusa.amoeba.xmltable.XmlRow; import com.meidusa.amoeba.xmltable.XmlTable; import com.meidusa.amoeba.xmltable.XmlTableLoader; /** * �������mysql ���е�һЩ select query ��Ӧ��,����ֻ�Ǽ򵥵Ľ�һЩ����sql���д�xmltable �ļ��н��ж�λ�� * Ȼ�������ͻ���һЩ���� * * @author struct */ public class MysqlMessageHandlerRunner implements MessageHandlerRunner, Initialisable { private ResultPacket packet = null; private String query; private String xmlTable; private static Map<String, XmlTable> xmlTableMap; private static Map<String, byte[]> resultContent = new HashMap<String, byte[]>(); public String getXmlTable() { return xmlTable; } public void setXmlTable(String collationFile) { this.xmlTable = collationFile; } public MysqlMessageHandlerRunner(){ } public void init(MessageHandler handler) { CommandMessageHandler chandler = (CommandMessageHandler) handler; this.packet = chandler.packet; this.query = chandler.query; } public void reset() { this.packet = null; this.query = null; } public void run() { query = query.toLowerCase(); byte[] content = resultContent.get(query); if (content != null) { MysqlResultSetPacket resultPacket = (MysqlResultSetPacket) packet; resultPacket.setContent(content); return; } StringTokenizer tokenizer = new StringTokenizer(query, " %'"); String[] tokens = new String[tokenizer.countTokens()]; int index = 0; while (tokenizer.hasMoreTokens()) { tokens[index++] = tokenizer.nextToken(); } if (tokens.length > 1) { boolean isSelect = tokens[0].equalsIgnoreCase("select") || tokens[0].equalsIgnoreCase("show"); if (isSelect) { String tableName = tokens[1]; Condition condition = null; for (int i = 2; i < tokens.length; i++) { if (tokens[i].equals("where")) { condition = new Condition(); condition.name = tokens[i + 1]; if (tokens[i + 2].equals("=")) { condition.type = Condition.TYPE.match; } else if (tokens[i + 2].equals("like")) { condition.type = Condition.TYPE.match; } condition.value = tokens[i + 3]; break; } else if (tokens[i].equals("like")) { condition = new Condition(); condition.name = tokens[i + 1]; condition.type = Condition.TYPE.exist; } else if (tokens[i].equals("from")) { tableName = tokens[i + 1]; } } XmlTable xmlTable = xmlTableMap.get(tableName); if (xmlTable != null) { if (tableName.equals("variables") && condition != null) { if (condition.value == null) { condition.value = condition.name; condition.type = Condition.TYPE.match; condition.name = "variable_name"; } } synchronized (resultContent) { content = resultContent.get(query); if (content == null) { content = xmlTableToBytes(xmlTable.query(condition)); resultContent.put(query, content); } } MysqlResultSetPacket resultPacket = (MysqlResultSetPacket) packet; resultPacket.setContent(content); return; } MysqlResultSetPacket resultPacket = (MysqlResultSetPacket) packet; ResultSetHeaderPacket resultHeader = new ResultSetHeaderPacket(); resultHeader.packetId = 1; resultHeader.columns = 1; resultPacket.resulthead = resultHeader; FieldPacket field = new FieldPacket(); field.name = "test"; field.type = (byte) MysqlDefs.FIELD_TYPE_VAR_STRING; field.length = 8; resultPacket.fieldPackets = new FieldPacket[] { field }; } } } private byte[] xmlTableToBytes(XmlTable table) { PacketBuffer buffer = new AbstractPacketBuffer(4086); byte paketId = 1; ResultSetHeaderPacket resultHeader = new ResultSetHeaderPacket(); resultHeader.packetId = paketId++; resultHeader.columns = table.getColumns().size(); buffer.writeBytes(resultHeader.toByteBuffer(null).array()); for (int i = 0; i < resultHeader.columns; i++) { FieldPacket field = new FieldPacket(); field.name = table.getColumns().get(i); field.length = 8; field.packetId = paketId++; field.type = (byte) MysqlDefs.FIELD_TYPE_VAR_STRING; buffer.writeBytes(field.toByteBuffer(null).array()); } EOFPacket fieldEof = new EOFPacket(); fieldEof.serverStatus = 2; fieldEof.warningCount = 0; fieldEof.packetId = paketId++; buffer.writeBytes(fieldEof.toByteBuffer(null).array()); for (XmlRow xmlRow : table.getRows()) { RowDataPacket row = new RowDataPacket(false); row.columns = new ArrayList<Object>(); for (int i = 0; i < resultHeader.columns; i++) { XmlColumn column = xmlRow.getColumMap().get(table.getColumns().get(i)); if (column == null) { row.columns.add(null); } else { row.columns.add(column.getValue()); } } row.packetId = paketId++; buffer.writeBytes(row.toByteBuffer(null).array()); } EOFPacket rowEof = new EOFPacket(); rowEof.serverStatus = 2; rowEof.warningCount = 0; rowEof.packetId = paketId++; buffer.writeBytes(rowEof.toByteBuffer(null).array()); return buffer.toByteBuffer().array(); } public void init() throws InitialisationException { if (xmlTableMap == null) { if (xmlTable != null) { synchronized (this) { if (xmlTableMap != null) return; XmlTableLoader loader = new XmlTableLoader(); loader.setDTD("/com/meidusa/amoeba/xml/table.dtd"); loader.setDTDSystemID("table.dtd"); xmlTableMap = loader.loadXmlTable(xmlTable); } } else { xmlTableMap = new HashMap<String, XmlTable>(); } } } }