/*
* Copyright 1999-2012 Alibaba Group.
*
* 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 com.alibaba.cobar.manager.dao.xml;
import static com.alibaba.cobar.manager.util.ConstantDefine.ACTIVE;
import static com.alibaba.cobar.manager.util.ConstantDefine.CLUSTER_ID;
import static com.alibaba.cobar.manager.util.ConstantDefine.DELETE;
import static com.alibaba.cobar.manager.util.ConstantDefine.HOST;
import static com.alibaba.cobar.manager.util.ConstantDefine.ID;
import static com.alibaba.cobar.manager.util.ConstantDefine.IN_ACTIVE;
import static com.alibaba.cobar.manager.util.ConstantDefine.NAME;
import static com.alibaba.cobar.manager.util.ConstantDefine.PASSWORD;
import static com.alibaba.cobar.manager.util.ConstantDefine.PORT;
import static com.alibaba.cobar.manager.util.ConstantDefine.SERVER_PORT;
import static com.alibaba.cobar.manager.util.ConstantDefine.STATUS;
import static com.alibaba.cobar.manager.util.ConstantDefine.TIME_DIFF;
import static com.alibaba.cobar.manager.util.ConstantDefine.USER;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.locks.ReentrantLock;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.InitializingBean;
import org.xmlpull.mxp1.MXParser;
import org.xmlpull.mxp1_serializer.MXSerializer;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import com.alibaba.cobar.manager.dao.CobarDAO;
import com.alibaba.cobar.manager.dataobject.xml.CobarDO;
import com.alibaba.cobar.manager.util.EncryptUtil;
/**
* @author haiqing.zhuhq 2011-6-15
*/
public class CobarDAOImple extends AbstractDAOImple implements CobarDAO, InitializingBean {
private static final Logger logger = Logger.getLogger(CobarDAOImple.class);
private Map<Long, CobarDO> map;
private static long maxId;
private static final ReentrantLock lock = new ReentrantLock();
private static final Map<String, Integer> typeMap = new HashMap<String, Integer>();
static {
typeMap.put("id", ID);
typeMap.put("name", NAME);
typeMap.put("status", STATUS);
typeMap.put("clusterId", CLUSTER_ID);
typeMap.put("host", HOST);
typeMap.put("port", PORT);
typeMap.put("password", PASSWORD);
typeMap.put("time_diff", TIME_DIFF);
typeMap.put("user", USER);
typeMap.put("serverPort", SERVER_PORT);
}
public CobarDAOImple() {
map = new HashMap<Long, CobarDO>();
xpp = new MXParser();
xsl = new MXSerializer();
maxId = Long.MIN_VALUE;
}
private boolean read() {
FileInputStream is = null;
lock.lock();
try {
map.clear();
is = new FileInputStream(xmlPath);
xpp.setInput(is, "UTF-8");
while (!(xpp.getEventType() == XmlPullParser.END_TAG && "cobars".equals(xpp.getName()))) {
if (xpp.getEventType() == XmlPullParser.START_TAG && "cobar".equals(xpp.getName())) {
CobarDO cobar = read(xpp);
if (null == cobar) {
throw new XmlPullParserException("Cobar read error");
}
maxId = (maxId < cobar.getId()) ? cobar.getId() : maxId;
map.put(cobar.getId(), cobar);
}
xpp.next();
}
is.close();
return true;
} catch (FileNotFoundException e) {
logger.error(e.getMessage(), e);
} catch (XmlPullParserException e) {
logger.error(e.getMessage(), e);
} catch (IOException e) {
logger.error(e.getMessage(), e);
} finally {
maxId = maxId < 0 ? 0 : maxId;
lock.unlock();
}
if (null != is) {
try {
is.close();
} catch (IOException e) {
logger.error(e.getMessage(), e);
}
}
return false;
}
@SuppressWarnings({ "rawtypes", "unchecked" })
private boolean write() {
FileOutputStream os = null;
lock.lock();
try {
if (!backup(xmlPath)) {
logger.error("cobar backup fail!");
}
os = new FileOutputStream(xmlPath);
xsl.setOutput(os, "UTF-8");
xsl.startDocument("UTF-8", null);
xsl.text("\n");
xsl.startTag(null, "cobars");
xsl.text("\n");
Iterator it = map.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<Long, CobarDO> entry = (Entry<Long, CobarDO>) it.next();
CobarDO cobar = entry.getValue();
if (!write(cobar)) {
throw new IOException("Cobar write error!");
}
}
xsl.endTag(null, "cobars");
xsl.endDocument();
os.close();
return true;
} catch (IOException e) {
logger.error(e.getMessage(), e);
} finally {
lock.unlock();
}
if (null != os) {
try {
os.close();
} catch (IOException e) {
logger.error(e.getMessage(), e);
}
}
return false;
}
private boolean write(CobarDO cobar) {
try {
writePrefix(false);
xsl.startTag(null, "cobar");
xsl.text("\n");
writeProperty("id", String.valueOf(cobar.getId()));
writeProperty("clusterId", String.valueOf(cobar.getClusterId()));
writeProperty("name", cobar.getName());
writeProperty("status", cobar.getStatus());
writeProperty("host", cobar.getHost());
writeProperty("serverPort", String.valueOf(cobar.getServerPort()));
writeProperty("port", String.valueOf(cobar.getPort()));
writeProperty("user", cobar.getUser());
String password = EncryptUtil.encrypt(cobar.getPassword());
writeProperty("password", password);
writeProperty("time_diff", cobar.getTime_diff());
writePrefix(true);
xsl.endTag(null, "cobar");
xsl.text("\n");
return true;
} catch (IOException e) {
logger.error(e.getMessage(), e);
}
return false;
}
private CobarDO read(XmlPullParser xpp) {
CobarDO cobar = new CobarDO();
cobar.setServerPort(8066);
try {
while (!(xpp.getEventType() == XmlPullParser.END_TAG && "cobar".equals(xpp.getName()))) {
if (xpp.getEventType() == XmlPullParser.START_TAG && "property".equals(xpp.getName())) {
int type = typeMap.get(xpp.getAttributeValue(0).trim());
switch (type) {
case ID:
cobar.setId(Long.parseLong(xpp.nextText().trim()));
break;
case NAME:
cobar.setName(xpp.nextText().trim());
break;
case CLUSTER_ID:
cobar.setClusterId(Long.parseLong(xpp.nextText().trim()));
break;
case STATUS:
String value = xpp.nextText().trim();
if (ACTIVE.equals(value)) {
cobar.setStatus(ACTIVE);
} else if (DELETE.equals(value)) {
cobar.setStatus(DELETE);
} else {
cobar.setStatus(IN_ACTIVE);
}
break;
case HOST:
cobar.setHost(xpp.nextText().trim());
break;
case PORT:
cobar.setPort(Integer.parseInt(xpp.nextText().trim()));
break;
case SERVER_PORT:
cobar.setServerPort(Integer.parseInt(xpp.nextText().trim()));
break;
case USER:
cobar.setUser(xpp.nextText().trim());
break;
case PASSWORD:
String password = EncryptUtil.decrypt(xpp.nextText().trim());
cobar.setPassword(password);
break;
case TIME_DIFF:
cobar.setTime_diff(xpp.nextText().trim());
break;
default:
break;
}
}
xpp.next();
}
return cobar;
} catch (NumberFormatException e) {
logger.error(e.getMessage(), e);
} catch (XmlPullParserException e) {
logger.error(e.getMessage(), e);
} catch (IOException e) {
logger.error(e.getMessage(), e);
}
return null;
}
@Override
public CobarDO getCobarById(long id) {
return map.get(id);
}
// @SuppressWarnings({ "unchecked", "rawtypes" })
// @Override
// public int getCobarCountByStatus(long clusterId, String status) {
// int count = 0;
// Iterator it = map.entrySet().iterator();
// while (it.hasNext()) {
// Map.Entry<Long, CobarDO> entry = (Entry<Long, CobarDO>) it.next();
// CobarDO cobar = entry.getValue();
// if (clusterId == cobar.getClusterId() && status.equals(cobar.getStatus())) {
// count++;
// }
// }
// return count;
// }
@Override
public void afterPropertiesSet() throws Exception {
xmlPath = xmlFileLoader.getFilePath();
if (null == xmlPath) {
logger.error("cobar xmlpath doesn't set!");
throw new IllegalArgumentException("cobar xmlpath doesn't set!");
} else {
if (xmlPath.endsWith(System.getProperty("file.separator"))) {
xmlPath = new StringBuilder(xmlPath).append("cobar.xml").toString();
} else {
xmlPath =
new StringBuilder(xmlPath).append(System.getProperty("file.separator"))
.append("cobar.xml")
.toString();
}
read();
}
}
@SuppressWarnings({ "rawtypes", "unchecked" })
@Override
public boolean checkName(String name, long clusterId) {
Iterator it = map.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<Long, CobarDO> entry = (Entry<Long, CobarDO>) it.next();
CobarDO cobar = entry.getValue();
if (clusterId == cobar.getClusterId() && cobar.getName().equals(name)) {
return false;
}
}
return true;
}
@Override
public boolean addCobar(CobarDO cobar) {
lock.lock();
try {
if (!checkName(cobar.getName(), cobar.getClusterId())) {
return false;
}
cobar.setId(++maxId);
map.put(cobar.getId(), cobar);
if (!write()) {
logger.error("Fail to add cobar!");
recovery(xmlPath);
read();
return false;
}
} finally {
lock.unlock();
}
return true;
}
@SuppressWarnings({ "rawtypes", "unchecked" })
@Override
public List<CobarDO> getCobarList(long clusterId) {
List<CobarDO> list = new ArrayList<CobarDO>();
Iterator it = map.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<Long, CobarDO> entry = (Entry<Long, CobarDO>) it.next();
CobarDO cobar = entry.getValue();
if (clusterId == cobar.getClusterId()) {
list.add(cobar);
}
}
return list;
}
@SuppressWarnings({ "rawtypes", "unchecked" })
@Override
public List<CobarDO> getCobarList(long clusterId, String status) {
List<CobarDO> list = new ArrayList<CobarDO>();
Iterator it = map.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<Long, CobarDO> entry = (Entry<Long, CobarDO>) it.next();
CobarDO cobar = entry.getValue();
if (clusterId == cobar.getClusterId() && status.equals(cobar.getStatus())) {
list.add(cobar);
}
}
return list;
}
@Override
public List<CobarDO> listCobarById(long[] cobarIds) {
List<CobarDO> list = new LinkedList<CobarDO>();
for (int i = 0; i < cobarIds.length; i++) {
CobarDO cobar = map.get(cobarIds[i]);
if (cobar != null) {
list.add(cobar);
}
}
return list;
}
@Override
public boolean modifyCobar(CobarDO cobar) {
lock.lock();
try {
if (!checkName(cobar.getName(), cobar.getClusterId(), cobar.getId())) {
return false;
}
map.put(cobar.getId(), cobar);
if (!write()) {
logger.error("Fail to modify cobar!");
recovery(xmlPath);
read();
return false;
}
} finally {
lock.unlock();
}
return true;
}
@SuppressWarnings({ "rawtypes", "unchecked" })
@Override
public boolean checkName(String name, long clusterId, long cobarId) {
Iterator it = map.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<Long, CobarDO> entry = (Entry<Long, CobarDO>) it.next();
CobarDO cobar = entry.getValue();
if (cobar.getId() == cobarId) {
continue;
}
if (clusterId == cobar.getClusterId() && cobar.getName().equals(name)) {
return false;
}
}
return true;
}
@Override
public List<CobarDO> listAllCobar() {
return new ArrayList<CobarDO>(map.values());
}
}