Example #1
0
/**
 * 全局设定文件
 *
 * @author xiaoleilu
 */
public class ServerSetting {
  private static Logger log = Log.get();

  // -------------------------------------------------------- Default value start
  /** 默认的字符集编码 */
  public static final String DEFAULT_CHARSET = "utf-8";

  public static final String WILD_CARD = "/*";
  // -------------------------------------------------------- Default value end

  /** 字符编码 */
  private static String charset = DEFAULT_CHARSET;
  /** 端口 */
  private static int port = 8090;
  /** 根目录 */
  private static File root;
  /** Filter映射表 */
  private static Map<String, Filter> filterMap;
  /** Action映射表 */
  private static Map<String, Action> actionMap;

  static {
    filterMap = new ConcurrentHashMap<String, Filter>();

    actionMap = new ConcurrentHashMap<String, Action>();
    final DefaultIndexAction defaultIndexAction = new DefaultIndexAction();
    actionMap.put(StrUtil.SLASH, defaultIndexAction);
  }

  /** @return 获取编码 */
  public static String getCharset() {
    return charset;
  }
  /** @return 字符集 */
  public static Charset charset() {
    return Charset.forName(getCharset());
  }

  /**
   * 设置编码
   *
   * @param charset 编码
   */
  public static void setCharset(String charset) {
    ServerSetting.charset = charset;
  }

  /** @return 监听端口 */
  public static int getPort() {
    return port;
  }
  /**
   * 设置监听端口
   *
   * @param port 端口
   */
  public static void setPort(int port) {
    ServerSetting.port = port;
  }

  // -----------------------------------------------------------------------------------------------
  // Root start
  /** @return 根目录 */
  public static File getRoot() {
    return root;
  }
  /** @return 根目录 */
  public static boolean isRootAvailable() {
    if (root != null && root.isDirectory() && root.isHidden() == false && root.canRead()) {
      return true;
    }
    return false;
  }
  /** @return 根目录 */
  public static String getRootPath() {
    return FileUtil.getAbsolutePath(root);
  }
  /**
   * 根目录
   *
   * @param root 根目录绝对路径
   */
  public static void setRoot(String root) {
    ServerSetting.root = FileUtil.mkdir(root);
    log.debug("Set root to [{}]", ServerSetting.root.getAbsolutePath());
  }
  /**
   * 根目录
   *
   * @param root 根目录绝对路径
   */
  public static void setRoot(File root) {
    if (root.exists() == false) {
      root.mkdirs();
    } else if (root.isDirectory() == false) {
      throw new ServerSettingException(StrUtil.format("{} is not a directory!", root.getPath()));
    }
    ServerSetting.root = root;
  }
  // -----------------------------------------------------------------------------------------------
  // Root end

  // -----------------------------------------------------------------------------------------------
  // Filter start
  /** @return 获取FilterMap */
  public static Map<String, Filter> getFilterMap() {
    return filterMap;
  }
  /**
   * 获得路径对应的Filter
   *
   * @param path 路径,为空时将获得 根目录对应的Action
   * @return Filter
   */
  public static Filter getFilter(String path) {
    if (StrUtil.isBlank(path)) {
      path = StrUtil.SLASH;
    }
    return getFilterMap().get(path.trim());
  }
  /**
   * 设置FilterMap
   *
   * @param filterMap FilterMap
   */
  public static void setFilterMap(Map<String, Filter> filterMap) {
    ServerSetting.filterMap = filterMap;
  }

  /**
   * 设置Filter类,已有的Filter类将被覆盖
   *
   * @param path 拦截路径(必须以"/"开头)
   * @param filter Action类
   */
  public static void setFilter(String path, Filter filter) {
    if (StrUtil.isBlank(path)) {
      path = StrUtil.SLASH;
    }

    if (null == filter) {
      log.warn("Added blank action, pass it.");
      return;
    }
    // 所有路径必须以 "/" 开头,如果没有则补全之
    if (false == path.startsWith(StrUtil.SLASH)) {
      path = StrUtil.SLASH + path;
    }

    ServerSetting.filterMap.put(path, filter);
  }

  /**
   * 设置Filter类,已有的Filter类将被覆盖
   *
   * @param path 拦截路径(必须以"/"开头)
   * @param filterClass Filter类
   */
  public static void setFilter(String path, Class<? extends Filter> filterClass) {
    setFilter(path, (Filter) Singleton.get(filterClass));
  }

  /**
   * 设置通配Filter类,已有的Filter类将被覆盖
   *
   * @param filter Action类
   */
  public static void setWildCardFilter(Filter filter) {
    setFilter(WILD_CARD, filter);
  }

  /**
   * 设置通配Filter类,已有的Filter类将被覆盖
   *
   * @param filterClass Filter类
   */
  public static void setWildCardFilter(Class<? extends Filter> filterClass) {
    setWildCardFilter((Filter) Singleton.get(filterClass));
  }

  /** @return 获得通配路径对应的Filter */
  public static Filter getWildCardFilter() {
    return getFilter(WILD_CARD);
  }
  // -----------------------------------------------------------------------------------------------
  // Filter end

  // -----------------------------------------------------------------------------------------------
  // Action start
  /** @return 获取ActionMap */
  public static Map<String, Action> getActionMap() {
    return actionMap;
  }
  /**
   * 获得路径对应的Action
   *
   * @param path 路径,为空时将获得 根目录对应的Action
   * @return Action
   */
  public static Action getAction(String path) {
    if (StrUtil.isBlank(path)) {
      path = StrUtil.SLASH;
    }
    return getActionMap().get(path.trim());
  }
  /**
   * 设置ActionMap
   *
   * @param actionMap ActionMap
   */
  public static void setActionMap(Map<String, Action> actionMap) {
    ServerSetting.actionMap = actionMap;
  }

  /**
   * 设置Action类,已有的Action类将被覆盖
   *
   * @param path 拦截路径(必须以"/"开头)
   * @param action Action类
   */
  public static void setAction(String path, Action action) {
    if (StrUtil.isBlank(path)) {
      path = StrUtil.SLASH;
    }

    if (null == action) {
      log.warn("Added blank action, pass it.");
      return;
    }
    // 所有路径必须以 "/" 开头,如果没有则补全之
    if (false == path.startsWith(StrUtil.SLASH)) {
      path = StrUtil.SLASH + path;
    }

    ServerSetting.actionMap.put(path, action);
  }

  /**
   * 增加Action类,已有的Action类将被覆盖<br>
   * 所有Action都是以单例模式存在的!
   *
   * @param path 拦截路径(必须以"/"开头)
   * @param actionClass Action类
   */
  public static void setAction(String path, Class<? extends Action> actionClass) {
    setAction(path, (Action) Singleton.get(actionClass));
  }

  /**
   * 增加Action类,已有的Action类将被覆盖<br>
   * 自动读取Route的注解来获得Path路径
   *
   * @param action 带注解的Action对象
   */
  public static void setAction(Action action) {
    final Route route = action.getClass().getAnnotation(Route.class);
    if (route != null) {
      final String path = route.value();
      if (StrUtil.isNotBlank(path)) {
        setAction(path, action);
        return;
      }
    }
    throw new ServerSettingException(
        "Can not find Route annotation,please add annotation to Action class!");
  }

  /**
   * 增加Action类,已有的Action类将被覆盖<br>
   * 所有Action都是以单例模式存在的!
   *
   * @param actionClass 带注解的Action类
   */
  public static void setAction(Class<? extends Action> actionClass) {
    setAction((Action) Singleton.get(actionClass));
  }
  // -----------------------------------------------------------------------------------------------
  // Action start

}
Example #2
0
/**
 * 认证器
 *
 * @author Looly
 */
public class Auth implements Cloneable {
  private static final Logger log = Log.get();

  // --------------------------------------------------------------- Static method start
  /**
   * 创建认证器
   *
   * @return 认证器
   */
  public static Auth build() {
    return new Auth();
  }

  /**
   * 创建认证器
   *
   * @param bucket Bucket
   * @param key 文件key
   * @param contentMd5 内容MD5
   * @param date 日期
   * @param config 配置文件
   * @param request Http请求对象
   */
  public static Auth build(
      String bucket,
      String key,
      String contentMd5,
      String date,
      Config config,
      HttpRequest request) {
    return new Auth(bucket, key, contentMd5, date, config, request);
  }

  /**
   * 用于签名的字符串
   *
   * @param bucket Bucket
   * @param key 文件key
   * @param contentMd5 内容的md5值
   * @param date 日期
   * @param request 请求对象
   * @return 用于签名的字符串
   */
  public static String strToSign(
      String bucket, String key, String contentMd5, String date, HttpRequest request) {
    String contentType = request.contentType();
    if (StrUtil.isBlank(contentType)) {
      contentType = "text/plain";
      request.contentType(contentType);
      log.warn("Content-Type header is empty, use default Content-Type: {}", contentType);
    }

    return StrUtil.builder()
        .append(request.method())
        .append("\n")
        .append(StrUtil.nullToEmpty(contentMd5))
        .append("\n")
        .append(contentType)
        .append("\n")
        .append(StrUtil.nullToEmpty(date))
        .append("\n")
        .append(canonicalizedUcloudHeaders(request))
        // canonicalizedUcloudHeaders尾部带一个换行符
        .append(canonicalizedResource(bucket, key))
        .toString();
  }

  /**
   * 签名
   *
   * @param privateKey 私钥
   * @param strToSign 被签名的字符串
   * @return 签名
   */
  public static String sign(String privateKey, String strToSign) {
    return SignatureUtil.macSign(privateKey, strToSign);
  }

  /**
   * 认证字符串
   *
   * @param publicKey 公钥
   * @param signature 签名
   * @return 认证字符串
   */
  public static String authorization(String publicKey, String signature) {
    return StrUtil.builder()
        .append("UCloud ")
        .append(publicKey)
        .append(":")
        .append(signature)
        .toString();
  }

  /**
   * 用于签名的标准Ucloud头信息字符串,尾部带换行符
   *
   * @param request Http请求
   * @return 用于签名的Ucloud头信息字符串
   */
  public static String canonicalizedUcloudHeaders(HttpRequest request) {
    Param param = Param.create();

    Map<String, String[]> headers = request.headers();
    String[] value;
    for (Entry<String, String[]> headerEntry : headers.entrySet()) {
      String name = headerEntry.getKey().toLowerCase();
      if (name.startsWith("x-ucloud-")) {
        value = headerEntry.getValue();
        if (value != null && value.length > 0) {
          param.set(name, value[0]);
        }
      }
    }

    StringBuilder builder = StrUtil.builder();
    for (Entry<String, Object> entry : param.entrySet()) {
      builder.append(entry.getKey()).append(":").append(entry.getValue()).append("\n");
    }

    return builder.toString();
  }

  /**
   * 用于签名的标准资源字符串
   *
   * @param bucket Bucket
   * @param key 文件的key(在Ufile中的文件名)
   * @return 标准资源字符串
   */
  public static String canonicalizedResource(String bucket, String key) {
    return StrUtil.builder().append("/").append(bucket).append("/").append(key).toString();
  }
  // --------------------------------------------------------------- Static method end

  // --------------------------------------------------------------- Field start
  /** Bucket */
  private String bucket;
  /** 文件在Bucket中的唯一名 */
  private String key;
  /** 文件的MD5 */
  private String contentMd5 = StrUtil.EMPTY;
  /** 日期 */
  private String date = StrUtil.EMPTY;
  /** 配置文件 */
  private Config config;
  /** Http请求对象 */
  private HttpRequest request;
  // --------------------------------------------------------------- Field end

  /** 构造 */
  public Auth() {}

  /**
   * 构造
   *
   * @param bucket Bucket
   * @param key 文件key
   * @param contentMd5 内容MD5
   * @param date 日期
   * @param config 配置文件
   * @param request Http请求对象
   */
  public Auth(
      String bucket,
      String key,
      String contentMd5,
      String date,
      Config config,
      HttpRequest request) {
    super();
    this.bucket = bucket;
    this.key = key;
    this.contentMd5 = contentMd5;
    this.date = date;
    this.config = config;
    this.request = request;
  }

  // --------------------------------------------------------------- Getters and Setters start
  /**
   * 获得Bucket
   *
   * @return Bucket
   */
  public String getBucket() {
    return bucket;
  }
  /**
   * 设置Bucket
   *
   * @param bucket Bucket
   */
  public void setBucket(String bucket) {
    this.bucket = bucket;
  }

  /** @return 文件key */
  public String getKey() {
    return key;
  }
  /**
   * 设置文件key
   *
   * @param key 文件key
   */
  public void setKey(String key) {
    this.key = key;
  }

  /** @return 文件内容MD5 */
  public String getContentMd5() {
    return contentMd5;
  }
  /**
   * 设置文件内容MD5
   *
   * @param contentMd5 文件内容MD5
   */
  public void setContentMd5(String contentMd5) {
    this.contentMd5 = contentMd5;
  }

  /** @return 日期 */
  public String getDate() {
    return date;
  }

  /**
   * 设置日期
   *
   * @param date 日期
   */
  public void setDate(String date) {
    this.date = date;
  }

  /** @return 配置文件 */
  public Config getConfig() {
    return config;
  }
  /**
   * 设置配置文件
   *
   * @param config 配置文件
   */
  public void setConfig(Config config) {
    this.config = config;
  }

  /** @return Http请求对象 */
  public HttpRequest getRequest() {
    return request;
  }
  /**
   * 设置Http请求对象
   *
   * @param request Http请求对象
   */
  public void setRequest(HttpRequest request) {
    this.request = request;
  }
  // --------------------------------------------------------------- Getters and Setters end

  /** 生成认证字符串 */
  @Override
  public String toString() {
    final String strToSign = Auth.strToSign(bucket, key, contentMd5, date, request);
    final String signature = Auth.sign(config.getPrivateKey(), strToSign);
    final String authorization = Auth.authorization(config.getPublicKey(), signature);

    return authorization;
  }

  /** 克隆对象 */
  public Auth clone() {
    try {
      return (Auth) super.clone();
    } catch (CloneNotSupportedException e) {
      throw new RuntimeException(e.getMessage(), e);
    }
  }
}