Page History

Home

Seiji Sogabe edited this page 9 days ago

Clone this wiki locally
    /**
     * <p>[概 要] 論理パスを解決します。</p>
     * <p>[詳 細] "file:xxx"形式もしくは"classpath:xxx"形式で指定されたファイルパスを物理パスに変換します。</p>
     * <p>[備 考] </p>
     *
     * @param uri 論理パス
     * @return 物理パス。解決できない場合は<codE>null</codE>。
     */
    public static String resolvePath(String uri) {
        ObjectHelper.notNull(uri, "uri");

        // スキーム部分を取得
        String scheme = ResourceHelper.getScheme(uri);
        if (scheme == null) {
            LOG.trace("### スキームが未設定");
            return null;
        }

        // スキームごとに処理
        String answer;
        switch (scheme) {
            case "file:":
                answer = resolveFilePath(uri);
                break;
            case "classpath:":
                answer = resolveClassPath(uri);
                break;
            default:
                // サポートしないスキームの場合
                LOG.trace("### サポートしないスキーム: {}", scheme);
                answer = null;
        }

        return answer;
    }

    /**
     * <p>[概 要] ファイルパスを解決します。</p>
     * <p>[詳 細] "file:xxx"形式で指定されたファイルパスを物理パスに変換します。</p>
     * <p>以下のケースは対象外となり、<code>null</code>を返します。</code></p>
     * <ul>
     *     <li>形式が異なる</li>
     *     <li>絶対パス</li>
     *     <li>カレントパス以外</li>
     *     <li>ファイルが存在しない</li>
     * </ul>
     * <p>[備 考] </p>
     *
     * @param uri "file:"で始まるパス
     * @return 物理パス。解決できない場合は<codE>null</codE>。
     */
    public static String resolveFilePath(String uri) {
        ObjectHelper.notNull(uri, "uri");
        LOG.trace("### uri: {}", uri);
        // スキーム部分を取得
        String scheme = ResourceHelper.getScheme(uri);
        if (!"file:".equals(scheme)) {
            LOG.trace("スキームが異なります。{}", scheme);
            return null;
        }

        // パス部分を取得し正規化
        String p = ObjectHelper.after(uri, scheme);
        p = tryDecodeUri(p);
        p = FileUtil.compactPath(p);
        String answer = FileUtil.normalizePath(p);
        LOG.trace("### 正規化パス: {}", answer);

        // 絶対パスは対象外
        if (Paths.get(answer).isAbsolute()) {
            LOG.trace("### 絶対パスは対象外: {}", uri);
            return null;
        }
        // カレントパス配下でなけれ対象外
        // 正規化したパスに".."が含まれる場合は、カレントパス配下以外
        if (answer.contains("..")) {
            LOG.trace("### カレントパス配下ではない場合は対象外: {}", uri);
            return null;
        }

        // 存在しているか確認
        File f = new File(answer);
        if (!f.exists()) {
            LOG.trace("### ファイルが存在しない: {}", uri);
            return null;
        }

        LOG.trace("### パス: {}", answer);
        return answer;
    }

    /**
     * <p>[概 要] クラスパスを解決します。</p>
     * <p>[詳 細] "classpath:xxx"形式で指定されたファイルパスを物理パスに変換します。</p>
     * <p>以下のケースは対象外となり、<code>null</code>を返します。</code></p>
     * <ul>
     *     <li>形式が異なる</li>
     *     <li>ファイルが存在しない</li>
     * </ul>
     * <p>[備 考] </p>
     *
     * @param uri "classpath:"で始まるパス
     * @return 物理パス。解決できない場合は<codE>null</codE>。
     */
    public static String resolveClassPath(String uri) {
        ObjectHelper.notNull(uri, "uri");
        LOG.trace("### uri: {}", uri);
        // スキーム部分を取得
        String scheme = ResourceHelper.getScheme(uri);
        if (!"classpath:".equals(scheme)) {
            LOG.trace("スキームが異なります。{}", scheme);
            return null;
        }

        // パス部分を取得し正規化
        String p = ObjectHelper.after(uri, scheme);
        p = FileUtil.compactPath(p, '/');
        p = tryDecodeUri(p);
        LOG.trace("### 正規化パス: {}", p);

        // クラスパスから検索
        ClassResolver resolver = new DefaultClassResolver(new DefaultCamelContext());
        URL u = resolver.loadResourceAsURL(p);
        if (u == null) {
            LOG.trace("### クラスパスに見つかりません。{}", p);
            return null;
        }

        // パスを取得し、先頭の不要なセパレータを削除
        String answer = u.getPath();
        answer = tryDecodeUri(answer);
        answer = FileUtil.normalizePath(answer);
        answer = FileUtil.stripFirstLeadingSeparator(answer);

        LOG.trace("### クラスパスから検索: {}", answer);
        return answer;
    }

    /**
     * URIを表す文字列をデコードします。
     *
     * @param uri URI
     * @return デコードしたURI。
     */
    private static String tryDecodeUri(String uri) {
        try {
            uri = URLDecoder.decode(uri, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            LOG.warn("failed to decode URL:{}", uri);
        }
        return uri;
    }