Example #1
0
/** @author haiqing.zhuhq 2011-6-15 */
public class CobarAccesser implements InitializingBean {

  private static final Logger logger = LoggerFactory.getLogger(CobarAccesser.class);
  private AdapterDelegate cobarAdapterDelegate;
  private XmlAccesser xmlAccesser;

  public AdapterDelegate getCobarAdapterDelegate() {
    return cobarAdapterDelegate;
  }

  public void setCobarAdapterDelegate(AdapterDelegate cobarAdapterDelegate) {
    this.cobarAdapterDelegate = cobarAdapterDelegate;
  }

  public XmlAccesser getXmlAccesser() {
    return xmlAccesser;
  }

  public void setXmlAccesser(XmlAccesser xmlAccesser) {
    this.xmlAccesser = xmlAccesser;
  }

  @Override
  public void afterPropertiesSet() throws Exception {
    if (cobarAdapterDelegate == null) {
      throw new IllegalArgumentException("property 'cobarAdapterDelegate' is null!");
    }
    if (xmlAccesser == null) {
      throw new IllegalArgumentException("property 'xmlAccesser' is null!");
    }
  }

  public CobarAdapterDAO getAccesser(long cobarId) {
    final CobarDO cobar = xmlAccesser.getCobarDAO().getCobarById(cobarId);
    if (cobar == null) {
      logger.error(
          new StringBuilder("Fail to get cobar information which id = ")
              .append(cobarId)
              .toString());
    }
    CobarAdapterDAO accesser =
        cobarAdapterDelegate.getCobarNodeAccesser(
            cobar.getHost(), cobar.getPort(), cobar.getUser(), cobar.getPassword());
    return accesser;
  }

  public CobarAdapterDAO getAccesser(CobarDO cobar) {
    CobarAdapterDAO accesser =
        cobarAdapterDelegate.getCobarNodeAccesser(
            cobar.getHost(), cobar.getPort(), cobar.getUser(), cobar.getPassword());
    return accesser;
  }
}
Example #2
0
public class TestCobarAdapter {

  public static CobarAdapter cobarAdapter = null;
  public static SimpleCobarNode sCobarNode = null;

  private static final Logger logger = LoggerFactory.getLogger(TestCobarAdapter.class);

  @BeforeClass
  public static void init() {
    try {
      cobarAdapter = CobarFactory.getCobarAdapter("cobar");
      sCobarNode = CobarFactory.getSimpleCobarNode("cobar");
    } catch (Exception e) {
      logger.error(e.getMessage(), e);
      Assert.fail();
    }
  }

  @Before
  public void initData() {
    if (null != cobarAdapter && null != cobarAdapter.getDataSource()) {
      try {
        cobarAdapter.destroy();
      } catch (Exception e) {
        logger.error("destroy adpter error");
        Assert.fail();
      }
    }
  }

  @After
  public void end() {
    try {
      if (null != cobarAdapter && null != cobarAdapter.getDataSource()) {
        cobarAdapter.destroy();
      }

    } catch (Exception e) {
      logger.error("destroy adpter error");
      Assert.fail();
    }
  }
}
Example #3
0
/**
 * 加载一个appname对应的资源,比如用户密码/tddl数据源等
 *
 * @author jianghang 2014-5-28 下午5:09:41
 * @since 5.1.0
 */
public final class AppLoader extends AbstractLifecycle implements Lifecycle {

  private static final Logger logger = LoggerFactory.getLogger(AppLoader.class);
  private static final String DATAID_PREFIX = "com.taobao.corona.";
  private static final String DATAID_SUFFIX = ".passwd";
  private static final String QUARANTINE_SURFIX = ".quarantine";
  private ConfigDataHandlerFactory cdhf = ConfigDataHandlerCity.getFactory(null, null);
  private Cache<String, ConfigDataHandler> cdhs = CacheBuilder.newBuilder().build();
  private String cluster;
  private Map<String /* app */, UserConfig> users;
  private Map<String, SchemaConfig> schemas;
  private QuarantineConfig quarantine;

  public AppLoader(String cluster) {
    this.cluster = cluster;
  }

  @Override
  protected void doInit() throws TddlException {
    this.users = new HashMap<String, UserConfig>();
    this.schemas = new HashMap<String, SchemaConfig>();
    this.quarantine = QuarantineConfig.getInstance();
  }

  /** 装载app */
  public void loadApp(final String app) {
    try {
      logger.info("start loading app:" + app);
      this.loadUser(app);
      this.loadSchema(app);
      this.loadQuarantine(app);
      logger.info("finish loading app:" + app);
    } catch (Throwable e) {
      throw new TddlNestableRuntimeException(e);
    }
  }

  /**
   * Do not add cluster to keep compatible with old tddl
   *
   * @param app
   * @throws ExecutionException
   * @throws TddlException
   */
  private void loadQuarantine(String app) throws ExecutionException, TddlException {
    String dataId = DATAID_PREFIX + app + QUARANTINE_SURFIX;
    ConfigDataHandler cdh = getQuarantineDataHandler(app, dataId);
    String config = cdh.getData();
    this.parseQuarantineConfig(dataId, app, config);
  }

  /** 卸载app */
  public void unLoadApp(final String app) {
    try {
      logger.info("start unLoading app:" + app);
      this.unLoadUser(app);
      this.unLoadSchema(app);
      logger.info("finish unLoading app:" + app);
    } catch (Throwable e) {
      throw new TddlNestableRuntimeException(e);
    }
  }

  private synchronized void loadUser(final String app) throws ExecutionException, TddlException {
    String dataId = DATAID_PREFIX + this.cluster + "." + app + DATAID_SUFFIX;
    ConfigDataHandler cdh = getConfigDataHandler(app, dataId);
    String config = cdh.getData();
    if (StringUtil.isEmpty(config)) {
      cdhs.invalidate(dataId);
      cdh.destroy();

      // 重新拿一下新的dataId
      String newDataId = DATAID_PREFIX + app + DATAID_SUFFIX;
      cdh = getConfigDataHandler(app, newDataId);
      config = cdh.getData();
    }

    this.parseConfig(dataId, app, config);
  }

  private synchronized void unLoadUser(final String app) throws TddlException {
    String dataId = DATAID_PREFIX + this.cluster + "." + app + DATAID_SUFFIX;
    ConfigDataHandler cdh = cdhs.getIfPresent(dataId);
    if (cdh != null) {
      cdh.destroy();
      cdhs.invalidate(dataId);
    }

    String newDataId = DATAID_PREFIX + app + DATAID_SUFFIX;
    cdh = cdhs.getIfPresent(newDataId);
    if (cdh != null) {
      cdh.destroy();
      cdhs.invalidate(dataId);
    }

    users.remove(app);
  }

  private synchronized void loadSchema(final String app) {
    SchemaConfig schema = schemas.get(app);
    if (schema != null) {
      return;
    }

    // MDC.put("app", app);
    TDataSource ds = new TDataSource();
    ds.putConnectionProperties(ConnectionProperties.CHOOSE_STREAMING, true);
    ds.putConnectionProperties(ConnectionProperties.PROCESS_AUTO_INCREMENT_BY_SEQUENCE, true);
    ds.putConnectionProperties(ConnectionProperties.INIT_CONCURRENT_POOL_EVERY_CONNECTION, false);
    // 共享一个链接池
    ds.setGlobalExecutorService(CobarServer.getInstance().getServerExectuor());
    // ds.putConnectionProperties(ConnectionProperties.MERGE_CONCURRENT,
    // true);
    // ds.putConnectionProperties(ConnectionProperties.CONCURRENT_THREAD_SIZE,
    // CobarServer.getInstance()
    // .getConfig()
    // .getSystem()
    // .getServerExecutor());
    ds.setSharding(false); // 允许非sharding启动
    ds.setAppName(app);
    // try {
    // ds.init();
    // } catch (TddlException e) {
    // // 启动时出错不往上抛
    // logger.error(e);
    // } finally {
    // MDC.remove("app");
    // }
    schema = new SchemaConfig(app);
    schema.setDataSource(ds);
    schemas.put(app, schema);
  }

  private synchronized void unLoadSchema(final String app) throws TddlException {
    SchemaConfig schema = schemas.remove(app);
    if (schema != null) {
      TDataSource dataSource = schema.getDataSource();
      if (dataSource != null) {
        dataSource.destroy();
      }
    }
  }

  private ConfigDataHandler getQuarantineDataHandler(final String app, final String dataId)
      throws ExecutionException {
    return cdhs.get(
        dataId,
        new Callable<ConfigDataHandler>() {

          @Override
          public ConfigDataHandler call() throws Exception {
            return cdhf.getConfigDataHandler(
                dataId,
                new ConfigDataListener() {

                  @Override
                  public void onDataRecieved(String dataId, String data) {
                    parseQuarantineConfig(dataId, app, data);
                  }
                });
          }
        });
  }

  private ConfigDataHandler getConfigDataHandler(final String app, final String dataId)
      throws ExecutionException {
    return cdhs.get(
        dataId,
        new Callable<ConfigDataHandler>() {

          @Override
          public ConfigDataHandler call() throws Exception {
            return cdhf.getConfigDataHandler(
                dataId,
                new ConfigDataListener() {

                  @Override
                  public void onDataRecieved(String dataId, String data) {
                    parseConfig(dataId, app, data);
                  }
                });
          }
        });
  }

  private synchronized void parseConfig(String dataId, String app, String config) {
    if (StringUtil.isEmpty(config)) {
      logger.info("password data is empty, so use default passwd, dataId:" + dataId);
      config = app;
    }

    UserConfig user = this.users.get(app);
    if (user == null) {
      user = new UserConfig();
      this.users.put(app, user);
    }
    user.setName(app);
    user.setPassword(config);
    user.setSchemas(this.buildSchema(app));
  }

  private void parseQuarantineConfig(String dataId, String app, String config) {
    /* Must clear existing whitelist first always */
    cleanHostByApp(app);
    if (StringUtil.isEmpty(config)) {
      return;
    }

    parseQuarantine(app, dataId, config);
  }

  private synchronized void parseQuarantine(String app, String dataId, String config) {
    quarantine.resetHosts(app, config);
  }

  private void cleanHostByApp(String app) {
    quarantine.cleanHostByApp(app);
  }

  private Set<String> buildSchema(String app) {
    Set<String> result = new HashSet<String>();
    result.add(app);
    return result;
  }

  public Map<String, SchemaConfig> getSchemas() {
    return schemas;
  }

  public Map<String, UserConfig> getUsers() {
    return users;
  }

  @Override
  protected void doDestroy() throws TddlException {
    for (ConfigDataHandler cdh : cdhs.asMap().values()) {
      try {
        cdh.destroy();
      } catch (Exception e) {
        // ignore
      }
    }

    for (SchemaConfig schema : schemas.values()) {
      TDataSource dataSource = schema.getDataSource();
      try {
        if (dataSource != null) {
          dataSource.destroy();
        }
      } catch (Exception e) {
        // ignore
      }
    }
  }

  public QuarantineConfig getQuarantine() {
    return quarantine;
  }
}
Example #4
0
/**
 * 一组{@linkplain TableRule}的集合
 *
 * @author junyu
 * @author <a href="*****@*****.**">jianghang</a>
 */
public class VirtualTableRoot extends AbstractLifecycle
    implements Lifecycle, ApplicationContextAware {

  private static final Logger logger = LoggerFactory.getLogger(VirtualTableRoot.class);
  protected String dbType = "MYSQL";
  protected Map<String /* 大写key */, TableRule> virtualTableMap;
  protected Map<String /* 大写key */, String> dbIndexMap;

  protected String defaultDbIndex;
  protected boolean needIdInGroup = false;
  protected boolean completeDistinct = false;
  protected boolean lazyInit = false;
  protected ApplicationContext context;

  public void init() throws TddlException {
    if (virtualTableMap == null || virtualTableMap.isEmpty()) {
      // 如果为空,采用自动查找的方式,将bean name做为逻辑表名
      Map<String, TableRule> vts = new HashMap<String, TableRule>();
      String[] tbeanNames = context.getBeanNamesForType(TableRule.class);
      for (String name : tbeanNames) {
        Object obj = context.getBean(name);
        vts.put(name, (TableRule) obj);
      }
      setTableRules(vts);
    }

    for (Map.Entry<String, TableRule> entry : virtualTableMap.entrySet()) {
      if (!lazyInit) {
        initTableRule(entry.getKey(), entry.getValue());
      }
    }
  }

  /**
   * 此处有个问题是Map中key对应的VirtualTableRule为null;
   *
   * @param virtualTableName
   * @return
   */
  public TableRule getVirtualTable(String virtualTableName) {
    RuleUtils.notNull(virtualTableName, "virtual table name is null");
    TableRule tablRule = virtualTableMap.get(virtualTableName.toUpperCase());
    if (tablRule != null && lazyInit && !tablRule.isInited()) {
      try {
        initTableRule(virtualTableName, tablRule);
      } catch (TddlException e) {
        throw new TddlRuleException(e);
      }
    }

    return tablRule;
  }

  public void setTableRules(Map<String, TableRule> virtualTableMap) {
    Map<String, TableRule> logicTableMap = new HashMap<String, TableRule>(virtualTableMap.size());
    for (Entry<String, TableRule> entry : virtualTableMap.entrySet()) {
      logicTableMap.put(entry.getKey().toUpperCase(), entry.getValue()); // 转化大写
    }
    this.virtualTableMap = logicTableMap;
  }

  public void setDbIndexMap(Map<String, String> dbIndexMap) {
    Map<String, String> logicTableMap = new HashMap<String, String>(dbIndexMap.size());
    for (Entry<String, String> entry : dbIndexMap.entrySet()) {
      logicTableMap.put(entry.getKey().toUpperCase(), entry.getValue()); // 转化大写
    }
    this.dbIndexMap = logicTableMap;
  }

  private void initTableRule(String tableNameKey, TableRule tableRule) throws TddlException {
    tableNameKey = tableNameKey.toUpperCase();
    logger.warn("virtual table start to init :" + tableNameKey);
    if (tableRule.getDbType() == null) {
      // 如果虚拟表中dbType为null,那指定全局dbType
      tableRule.setDbType(this.getDbTypeEnumObj());
    }

    if (tableRule.getVirtualTbName() == null) {
      tableRule.setVirtualTbName(tableNameKey);
    }
    tableRule.init();
    logger.warn("virtual table inited :" + tableNameKey);
  }

  public String getDefaultDbIndex() {
    return defaultDbIndex;
  }

  public void setDefaultDbIndex(String defaultDbIndex) {
    this.defaultDbIndex = defaultDbIndex;
  }

  public Map<String, String> getDbIndexMap() {
    return dbIndexMap;
  }

  public DBType getDbTypeEnumObj() {
    return DBType.valueOf(this.dbType);
  }

  public String getDbType() {
    return this.dbType;
  }

  public void setDbType(String dbType) {
    this.dbType = dbType;
  }

  public boolean isNeedIdInGroup() {
    return needIdInGroup;
  }

  public void setNeedIdInGroup(boolean needIdInGroup) {
    this.needIdInGroup = needIdInGroup;
  }

  public boolean isCompleteDistinct() {
    return completeDistinct;
  }

  public void setCompleteDistinct(boolean completeDistinct) {
    this.completeDistinct = completeDistinct;
  }

  public void setLazyInit(boolean lazyInit) {
    this.lazyInit = lazyInit;
  }

  @Override
  public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
    this.context = applicationContext;
  }
}
/**
 * 序列DAO默认实现,JDBC方式
 *
 * @author nianbing
 */
public class DefaultSequenceDao extends AbstractLifecycle implements SequenceDao {

  private static final Logger logger = LoggerFactory.getLogger(DefaultSequenceDao.class);
  private static final int MIN_STEP = 1;
  private static final int MAX_STEP = 100000;
  private static final int DEFAULT_STEP = 1000;
  private static final int DEFAULT_RETRY_TIMES = 150;

  private static final String DEFAULT_TABLE_NAME = "sequence";
  private static final String DEFAULT_NAME_COLUMN_NAME = "name";
  private static final String DEFAULT_VALUE_COLUMN_NAME = "value";
  private static final String DEFAULT_GMT_MODIFIED_COLUMN_NAME = "gmt_modified";

  private static final long DELTA = 100000000L;

  private DataSource dataSource;

  /** 重试次数 */
  private int retryTimes = DEFAULT_RETRY_TIMES;

  /** 步长 */
  private int step = DEFAULT_STEP;

  /** 序列所在的表名 */
  private String tableName = DEFAULT_TABLE_NAME;

  /** 存储序列名称的列名 */
  private String nameColumnName = DEFAULT_NAME_COLUMN_NAME;

  /** 存储序列值的列名 */
  private String valueColumnName = DEFAULT_VALUE_COLUMN_NAME;

  /** 存储序列最后更新时间的列名 */
  private String gmtModifiedColumnName = DEFAULT_GMT_MODIFIED_COLUMN_NAME;

  private volatile String selectSql;
  private volatile String updateSql;

  public SequenceRange nextRange(String name) throws SequenceException {
    if (name == null) {
      throw new IllegalArgumentException("序列名称不能为空");
    }

    long oldValue;
    long newValue;

    Connection conn = null;
    PreparedStatement stmt = null;
    ResultSet rs = null;

    for (int i = 0; i < retryTimes + 1; ++i) {
      try {
        conn = dataSource.getConnection();
        stmt = conn.prepareStatement(getSelectSql());
        stmt.setString(1, name);
        rs = stmt.executeQuery();
        rs.next();
        oldValue = rs.getLong(1);

        if (oldValue < 0) {
          StringBuilder message = new StringBuilder();
          message.append("Sequence value cannot be less than zero, value = ").append(oldValue);
          message.append(", please check table ").append(getTableName());

          throw new SequenceException(message.toString());
        }

        if (oldValue > Long.MAX_VALUE - DELTA) {
          StringBuilder message = new StringBuilder();
          message.append("Sequence value overflow, value = ").append(oldValue);
          message.append(", please check table ").append(getTableName());

          throw new SequenceException(message.toString());
        }

        newValue = oldValue + getStep();
      } catch (SQLException e) {
        throw new SequenceException(e);
      } finally {
        closeResultSet(rs);
        rs = null;
        closeStatement(stmt);
        stmt = null;
        closeConnection(conn);
        conn = null;
      }

      try {
        conn = dataSource.getConnection();
        stmt = conn.prepareStatement(getUpdateSql());
        stmt.setLong(1, newValue);
        stmt.setTimestamp(2, new Timestamp(System.currentTimeMillis()));
        stmt.setString(3, name);
        stmt.setLong(4, oldValue);
        int affectedRows = stmt.executeUpdate();
        if (affectedRows == 0) {
          // retry
          continue;
        }

        return new SequenceRange(oldValue + 1, newValue);
      } catch (SQLException e) {
        throw new SequenceException(e);
      } finally {
        closeStatement(stmt);
        stmt = null;
        closeConnection(conn);
        conn = null;
      }
    }

    throw new SequenceException("Retried too many times, retryTimes = " + retryTimes);
  }

  private String getSelectSql() {
    if (selectSql == null) {
      synchronized (this) {
        if (selectSql == null) {
          StringBuilder buffer = new StringBuilder();
          buffer.append("select ").append(getValueColumnName());
          buffer.append(" from ").append(getTableName());
          buffer.append(" where ").append(getNameColumnName()).append(" = ?");

          selectSql = buffer.toString();
        }
      }
    }

    return selectSql;
  }

  private String getUpdateSql() {
    if (updateSql == null) {
      synchronized (this) {
        if (updateSql == null) {
          StringBuilder buffer = new StringBuilder();
          buffer.append("update ").append(getTableName());
          buffer.append(" set ").append(getValueColumnName()).append(" = ?, ");
          buffer.append(getGmtModifiedColumnName()).append(" = ? where ");
          buffer.append(getNameColumnName()).append(" = ? and ");
          buffer.append(getValueColumnName()).append(" = ?");

          updateSql = buffer.toString();
        }
      }
    }

    return updateSql;
  }

  private static void closeResultSet(ResultSet rs) {
    if (rs != null) {
      try {
        rs.close();
      } catch (SQLException e) {
        logger.debug("Could not close JDBC ResultSet", e);
      } catch (Throwable e) {
        logger.debug("Unexpected exception on closing JDBC ResultSet", e);
      }
    }
  }

  private static void closeStatement(Statement stmt) {
    if (stmt != null) {
      try {
        stmt.close();
      } catch (SQLException e) {
        logger.debug("Could not close JDBC Statement", e);
      } catch (Throwable e) {
        logger.debug("Unexpected exception on closing JDBC Statement", e);
      }
    }
  }

  private static void closeConnection(Connection conn) {
    if (conn != null) {
      try {
        conn.close();
      } catch (SQLException e) {
        logger.debug("Could not close JDBC Connection", e);
      } catch (Throwable e) {
        logger.debug("Unexpected exception on closing JDBC Connection", e);
      }
    }
  }

  public DataSource getDataSource() {
    return dataSource;
  }

  public void setDataSource(DataSource dataSource) {
    this.dataSource = dataSource;
  }

  public int getRetryTimes() {
    return retryTimes;
  }

  public void setRetryTimes(int retryTimes) {
    if (retryTimes < 0) {
      throw new IllegalArgumentException(
          "Property retryTimes cannot be less than zero, retryTimes = " + retryTimes);
    }

    this.retryTimes = retryTimes;
  }

  public int getStep() {
    return step;
  }

  public void setStep(int step) {
    if (step < MIN_STEP || step > MAX_STEP) {
      StringBuilder message = new StringBuilder();
      message.append("Property step out of range [").append(MIN_STEP);
      message.append(",").append(MAX_STEP).append("], step = ").append(step);

      throw new IllegalArgumentException(message.toString());
    }

    this.step = step;
  }

  public String getTableName() {
    return tableName;
  }

  public void setTableName(String tableName) {
    this.tableName = tableName;
  }

  public String getNameColumnName() {
    return nameColumnName;
  }

  public void setNameColumnName(String nameColumnName) {
    this.nameColumnName = nameColumnName;
  }

  public String getValueColumnName() {
    return valueColumnName;
  }

  public void setValueColumnName(String valueColumnName) {
    this.valueColumnName = valueColumnName;
  }

  public String getGmtModifiedColumnName() {
    return gmtModifiedColumnName;
  }

  public void setGmtModifiedColumnName(String gmtModifiedColumnName) {
    this.gmtModifiedColumnName = gmtModifiedColumnName;
  }
}
Example #6
0
/** @author haiqing.zhuhq 2012-2-21 */
public class EncryptUtil {

  private static final Logger logger = LoggerFactory.getLogger(EncryptUtil.class);

  /** 密钥,长度必须大于8 */
  private static final String PASSWORD_CRYPT_KEY = "cobar-manager";

  private static final String DES = "DES";

  /**
   * 加密
   *
   * @param src 数据源
   * @param key 密钥,长度必须大于8
   * @return 返回加密后的数据
   * @throws Exception
   */
  public static byte[] encrypt(byte[] src, byte[] key) throws Exception {
    // DES算法要求有一个可信任的随机数源
    SecureRandom sr = new SecureRandom();
    // 从原始密匙数据创建DESKeySpec对象
    DESKeySpec dks = new DESKeySpec(key);
    // 创建一个密匙工厂,然后用它把DESKeySpec转换成
    // 一个SecretKey对象
    SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(DES);
    SecretKey securekey = keyFactory.generateSecret(dks);
    // Cipher对象实际完成加密操作
    Cipher cipher = Cipher.getInstance(DES);
    // 用密匙初始化Cipher对象
    cipher.init(Cipher.ENCRYPT_MODE, securekey, sr);
    // 现在,获取数据并加密
    // 正式执行加密操作
    return cipher.doFinal(src);
  }

  /**
   * 解密
   *
   * @param src 数据源
   * @param key 密钥,长度必须是8的倍数
   * @return 返回解密后的原始数据
   * @throws Exception
   */
  public static byte[] decrypt(byte[] src, byte[] key) throws Exception {
    // DES算法要求有一个可信任的随机数源
    SecureRandom sr = new SecureRandom();
    // 从原始密匙数据创建一个DESKeySpec对象
    DESKeySpec dks = new DESKeySpec(key);
    // 创建一个密匙工厂,然后用它把DESKeySpec对象转换成
    // 一个SecretKey对象
    SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(DES);
    SecretKey securekey = keyFactory.generateSecret(dks);
    // Cipher对象实际完成解密操作
    Cipher cipher = Cipher.getInstance(DES);
    // 用密匙初始化Cipher对象
    cipher.init(Cipher.DECRYPT_MODE, securekey, sr);
    // 现在,获取数据并解密
    // 正式执行解密操作
    return cipher.doFinal(src);
  }

  /**
   * 密码解密
   *
   * @param data
   * @return
   * @throws Exception
   */
  public static final String decrypt(String data) {
    try {
      return new String(decrypt(hex2byte(data.getBytes()), PASSWORD_CRYPT_KEY.getBytes()));
    } catch (Exception e) {
      logger.error("decrypt error!!");
      logger.error(e.getMessage(), e);
    }
    return null;
  }

  /**
   * 密码加密
   *
   * @param password
   * @return
   * @throws Exception
   */
  public static final String encrypt(String password) {
    try {
      return byte2hex(encrypt(password.getBytes(), PASSWORD_CRYPT_KEY.getBytes()));
    } catch (Exception e) {
      logger.error("encrypt error!!");
      logger.error(e.getMessage(), e);
    }
    return null;
  }

  /**
   * 二行制转字符串
   *
   * @param b
   * @return
   */
  public static String byte2hex(byte[] b) {
    String hs = "";
    String stmp = "";
    for (int n = 0; n < b.length; n++) {
      stmp = (java.lang.Integer.toHexString(b[n] & 0XFF));
      if (stmp.length() == 1) hs = hs + "0" + stmp;
      else hs = hs + stmp;
    }
    return hs.toUpperCase();
  }

  public static byte[] hex2byte(byte[] b) {
    if ((b.length % 2) != 0) throw new IllegalArgumentException("长度不是偶数");
    byte[] b2 = new byte[b.length / 2];
    for (int n = 0; n < b.length; n += 2) {
      String item = new String(b, n, 2);
      b2[n / 2] = (byte) Integer.parseInt(item, 16);
    }
    return b2;
  }
}