001/* 002 * SPDX-License-Identifier: Apache-2.0 003 * 004 * Copyright 2025 The Enola <https://enola.dev> Authors 005 * 006 * Licensed under the Apache License, Version 2.0 (the "License"); 007 * you may not use this file except in compliance with the License. 008 * You may obtain a copy of the License at 009 * 010 * https://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package dev.enola.cas; 019 020import com.google.common.io.ByteSource; 021 022import dev.enola.common.io.resource.*; 023 024import io.ipfs.cid.Cid; 025 026import java.io.IOException; 027import java.net.URI; 028 029/** <a href="https://ipfs.tech/">IPFS</a> Resource, via an IPFS Kubo RPC API. */ 030public class IPFSApiResource extends BaseResource implements ReadableResource { 031 032 // TODO implement WritableResource 033 034 public static class Provider implements ResourceProvider { 035 private final IPFSBlobStore ipfs; 036 037 public Provider(IPFSBlobStore ipfs) { 038 this.ipfs = ipfs; 039 } 040 041 @Override 042 public Resource getResource(URI uri) { 043 if (isIPFS(uri)) 044 return new ReadableButNotWritableDelegatingResource(new IPFSApiResource(ipfs, uri)); 045 else return null; 046 } 047 } 048 049 private static boolean isIPFS(URI uri) { 050 return "ipfs".equals(uri.getScheme()); 051 } 052 053 private static void check(URI uri) { 054 if (!isIPFS(uri)) throw new IllegalArgumentException(uri.toString()); 055 } 056 057 private final IPFSBlobStore ipfs; 058 059 public IPFSApiResource(IPFSBlobStore ipfs, URI uri) { 060 super(uri); 061 check(uri); 062 this.ipfs = ipfs; 063 } 064 065 @Override 066 public ByteSource byteSource() { 067 try { 068 return ipfs.load(Cid.decode(uri().getAuthority()), uri().getPath()); 069 } catch (IOException e) { 070 return new ErrorByteSource(e); 071 } 072 } 073}