/*
* Copyright (c) 2013, OpenCloudDB/MyCAT and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software;Designed and Developed mainly by many Chinese
* opensource volunteers. you can redistribute it and/or modify it under the
* terms of the GNU General Public License version 2 only, as published by the
* Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Any questions about this component can be directed to it's project Web address
* https://code.google.com/p/opencloudb/.
*
*/
package org.opencloudb.handler;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.xml.parsers.ParserConfigurationException;
import org.apache.log4j.Logger;
import org.opencloudb.MycatServer;
import org.opencloudb.config.Fields;
import org.opencloudb.config.model.SystemConfig;
import org.opencloudb.config.util.ConfigUtil;
import org.opencloudb.manager.ManagerConnection;
import org.opencloudb.mysql.PacketUtil;
import org.opencloudb.net.mysql.EOFPacket;
import org.opencloudb.net.mysql.FieldPacket;
import org.opencloudb.net.mysql.ResultSetHeaderPacket;
import org.opencloudb.net.mysql.RowDataPacket;
import org.opencloudb.util.StringUtil;
import org.xml.sax.SAXException;
/**
* Mycat conf file related Handler
*
* @author wuzh
*/
public final class ConfFileHandler {
private static final Logger logger = Logger
.getLogger(ConfFileHandler.class);
private static final int FIELD_COUNT = 1;
private static final ResultSetHeaderPacket header = PacketUtil
.getHeader(FIELD_COUNT);
private static final FieldPacket[] fields = new FieldPacket[FIELD_COUNT];
private static final EOFPacket eof = new EOFPacket();
private static final String UPLOAD_CMD = "FILE @@UPLOAD";
static {
int i = 0;
byte packetId = 0;
header.packetId = ++packetId;
fields[i] = PacketUtil.getField("DATA", Fields.FIELD_TYPE_VAR_STRING);
fields[i++].packetId = ++packetId;
eof.packetId = ++packetId;
}
public static void handle( String stmt,ManagerConnection c) {
ByteBuffer buffer = c.allocate();
// write header
buffer = header.write(buffer, c,true);
// write fields
for (FieldPacket field : fields) {
buffer = field.write(buffer, c,true);
}
// write eof
buffer = eof.write(buffer, c,true);
// write rows
byte packetId = eof.packetId;
String theStmt = stmt.toUpperCase().trim();
PackageBufINf bufInf = null;
if (theStmt.equals("FILE @@LIST")) {
bufInf = listConfigFiles(c, buffer, packetId);
} else if (theStmt.startsWith("FILE @@SHOW")) {
int index = stmt.lastIndexOf(' ');
String fileName = stmt.substring(index + 1);
bufInf = showConfigFile(c, buffer, packetId, fileName);
} else if (theStmt.startsWith(UPLOAD_CMD)) {
int index = stmt.indexOf(' ', UPLOAD_CMD.length());
int index2 = stmt.indexOf(' ', index + 1);
if (index <= 0 || index2 <= 0 || index + 1 > stmt.length()
|| index2 + 1 > stmt.length()) {
bufInf = showInfo(c, buffer, packetId, "Invald param ,usage ");
}
String fileName = stmt.substring(index + 1, index2);
String content = stmt.substring(index2 + 1).trim();
bufInf = upLoadConfigFile(c, buffer, packetId, fileName, content);
} else {
bufInf = showInfo(c, buffer, packetId, "Invald command ");
}
packetId = bufInf.packetId;
buffer = bufInf.buffer;
// write last eof
EOFPacket lastEof = new EOFPacket();
lastEof.packetId = ++packetId;
buffer = lastEof.write(buffer, c,true);
// write buffer
c.write(buffer);
}
private static void checkXMLFile(String xmlFileName, byte[] data)
throws ParserConfigurationException, SAXException, IOException {
InputStream dtdStream = new ByteArrayInputStream(new byte[0]);
File confDir = new File(SystemConfig.getHomePath(), "conf");
if (xmlFileName.equals("schema.xml")) {
dtdStream = MycatServer.class.getResourceAsStream("/schema.dtd");
if (dtdStream == null) {
dtdStream = new ByteArrayInputStream(readFileByBytes(new File(
confDir, "schema.dtd")));
}
} else if (xmlFileName.equals("server.xml")) {
dtdStream = MycatServer.class.getResourceAsStream("/server.dtd");
if (dtdStream == null) {
dtdStream = new ByteArrayInputStream(readFileByBytes(new File(
confDir, "server.dtd")));
}
} else if (xmlFileName.equals("rule.xml")) {
dtdStream = MycatServer.class.getResourceAsStream("/rule.dtd");
if (dtdStream == null) {
dtdStream = new ByteArrayInputStream(readFileByBytes(new File(
confDir, "rule.dtd")));
}
}
ConfigUtil.getDocument(dtdStream, new ByteArrayInputStream(data));
}
/**
* 以字节为单位读取文件,常用于读二进制文件,如图片、声音、影像等文件。
*/
private static byte[] readFileByBytes(File fileName) {
InputStream in = null;
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
try { // 一次读多个字节
byte[] tempbytes = new byte[100];
int byteread = 0;
in = new FileInputStream(fileName);
// 读入多个字节到字节数组中,byteread为一次读入的字节数
while ((byteread = in.read(tempbytes)) != -1) {
outStream.write(tempbytes, 0, byteread);
}
} catch (Exception e1) {
e1.printStackTrace();
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e1) {
}
}
}
return outStream.toByteArray();
}
private static PackageBufINf upLoadConfigFile(ManagerConnection c,
ByteBuffer buffer, byte packetId, String fileName, String content) {
logger.info("Upload Daas Config file " + fileName + " ,content:"
+ content);
String tempFileName = System.currentTimeMillis() + "_" + fileName;
File tempFile = new File(SystemConfig.getHomePath(), "conf"
+ File.separator + tempFileName);
BufferedOutputStream buff = null;
boolean suc = false;
try {
byte[] fileData = content.getBytes("UTF-8");
if (fileName.endsWith(".xml")) {
checkXMLFile(fileName, fileData);
}
buff = new BufferedOutputStream(new FileOutputStream(tempFile));
buff.write(fileData);
buff.flush();
} catch (Exception e) {
logger.warn("write file err " + e);
e.printStackTrace();
return showInfo(c, buffer, packetId, "write file err " + e);
} finally {
if (buff != null) {
try {
buff.close();
suc = true;
} catch (IOException e) {
logger.warn("save config file err " + e);
}
}
}
if (suc) {
// if succcess
File oldFile = new File(SystemConfig.getHomePath(), "conf"
+ File.separator + fileName);
if (oldFile.exists()) {
File backUP = new File(SystemConfig.getHomePath(), "conf"
+ File.separator + fileName + "_"
+ System.currentTimeMillis() + "_auto");
if (!oldFile.renameTo(backUP)) {
String msg = "rename old file failed";
logger.warn(msg + " for upload file "
+ oldFile.getAbsolutePath());
return showInfo(c, buffer, packetId, msg);
}
}
File dest = new File(SystemConfig.getHomePath(), "conf"
+ File.separator + fileName);
if (!tempFile.renameTo(dest)) {
String msg = "rename file failed";
logger.warn(msg + " for upload file "
+ tempFile.getAbsolutePath());
return showInfo(c, buffer, packetId, msg);
}
return showInfo(c, buffer, packetId, "SUCCESS SAVED FILE:"
+ fileName);
} else {
return showInfo(c, buffer, packetId, "UPLOAD ERROR OCCURD:"
+ fileName);
}
}
private static PackageBufINf showInfo(ManagerConnection c,
ByteBuffer buffer, byte packetId, String string) {
PackageBufINf bufINf = new PackageBufINf();
RowDataPacket row = new RowDataPacket(FIELD_COUNT);
row.add(StringUtil.encode(string, c.getCharset()));
row.packetId = ++packetId;
buffer = row.write(buffer, c,true);
bufINf.packetId = packetId;
bufINf.buffer = buffer;
return bufINf;
}
private static PackageBufINf showConfigFile(ManagerConnection c,
ByteBuffer buffer, byte packetId, String fileName) {
File file = new File(SystemConfig.getHomePath(), "conf"
+ File.separator + fileName);
BufferedReader br = null;
PackageBufINf bufINf = new PackageBufINf();
try {
br = new BufferedReader(new FileReader(file));
String line = null;
while ((line = br.readLine()) != null) {
if (line.isEmpty()) {
continue;
}
RowDataPacket row = new RowDataPacket(FIELD_COUNT);
row.add(StringUtil.encode(line, c.getCharset()));
row.packetId = ++packetId;
buffer = row.write(buffer, c,true);
}
bufINf.buffer = buffer;
bufINf.packetId = packetId;
return bufINf;
} catch (Exception e) {
e.printStackTrace();
RowDataPacket row = new RowDataPacket(FIELD_COUNT);
row.add(StringUtil.encode(e.toString(), c.getCharset()));
row.packetId = ++packetId;
buffer = row.write(buffer, c,true);
bufINf.buffer = buffer;
} finally {
if (br != null) {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
bufINf.packetId = packetId;
return bufINf;
}
private static PackageBufINf listConfigFiles(ManagerConnection c,
ByteBuffer buffer, byte packetId) {
PackageBufINf bufINf = new PackageBufINf();
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm");
try {
int i = 1;
File[] file = new File(SystemConfig.getHomePath(), "conf")
.listFiles();
for (File f : file) {
if (f.isFile()) {
RowDataPacket row = new RowDataPacket(FIELD_COUNT);
row.add(StringUtil.encode(
(i++) + " : " + f.getName() + " time:"
+ df.format(new Date(f.lastModified())),
c.getCharset()));
row.packetId = ++packetId;
buffer = row.write(buffer, c,true);
}
}
bufINf.buffer = buffer;
bufINf.packetId = packetId;
return bufINf;
} catch (Exception e) {
e.printStackTrace();
RowDataPacket row = new RowDataPacket(FIELD_COUNT);
row.add(StringUtil.encode(e.toString(), c.getCharset()));
row.packetId = ++packetId;
buffer = row.write(buffer, c,true);
bufINf.buffer = buffer;
}
bufINf.packetId = packetId;
return bufINf;
}
public static void main(String[] args) {
String stmt = "FILE @@UPLOAD test.xml 1234567890";
int index = stmt.indexOf(' ', UPLOAD_CMD.length());
int index2 = stmt.indexOf(' ', index + 1);
if (index <= 0 || index2 <= 0 || index + 1 > stmt.length()
|| index2 + 1 > stmt.length()) {
System.out.println("valid ....");
} else {
String fileName = stmt.substring(index + 1, index2);
String content = stmt.substring(index2 + 1).trim();
System.out.println(fileName + " content:" + content);
}
}
}