@Override
  public Principal getPrincipal(final String ticket) {
    List<String> res =
        redisOperator.execute(
            new JedisAction<List<String>>() {

              @Override
              public List<String> action(Jedis jedis) {
                List<String> res =
                    jedis.hmget(
                        ticket,
                        FIELD_CLASS,
                        FIELD_PRINCIPAL,
                        FIELD_EXPIRES_IN,
                        FIELD_UPDATE_ON_TOUCH);
                if (res == null || res.contains(null)) {
                  return null;
                }
                if (Boolean.valueOf(res.get(3))) {
                  long expire = Longs.tryParse(res.get(2));
                  jedis.expire(ticket, (int) (expire / 1000));
                }
                return res;
              }
            });
    if (res != null) {
      try {
        Class<?> clazz = Class.forName(res.get(0));
        return (Principal) gson.fromJson(res.get(1), clazz);
      } catch (Exception e) {
        logger.error("", e);
      }
    }
    return null;
  }
  @Override
  protected void saveHolder(final String ticket, final PrincipalHolder holder) {
    redisOperator.execute(
        new JedisActionNoResult() {

          @Override
          public void action(Jedis jedis) {
            Map<String, String> map = Maps.newHashMapWithExpectedSize(3);
            map.put(FIELD_CLASS, holder.principal.getClass().getCanonicalName());
            map.put(FIELD_PRINCIPAL, gson.toJson(holder.principal));
            map.put(FIELD_EXPIRES_IN, String.valueOf(holder.expiresIn));
            map.put(FIELD_UPDATE_ON_TOUCH, String.valueOf(holder.updateOnTouch));
            jedis.hmset(ticket, map);
            jedis.expire(ticket, (int) (holder.expiresIn / 1000));
          }
        });
  }