View Javadoc
1   package de.dlr.shepard.mongoDB;
2   
3   import static com.mongodb.client.model.Filters.eq;
4   
5   import com.mongodb.client.MongoCollection;
6   import com.mongodb.client.MongoDatabase;
7   import com.mongodb.client.gridfs.GridFSBucket;
8   import com.mongodb.client.gridfs.GridFSBuckets;
9   import de.dlr.shepard.util.DateHelper;
10  import de.dlr.shepard.util.UUIDHelper;
11  import io.quarkus.logging.Log;
12  import jakarta.enterprise.context.RequestScoped;
13  import jakarta.inject.Inject;
14  import jakarta.inject.Named;
15  import jakarta.xml.bind.DatatypeConverter;
16  import java.io.InputStream;
17  import java.security.DigestInputStream;
18  import java.security.MessageDigest;
19  import java.security.NoSuchAlgorithmException;
20  import org.bson.Document;
21  import org.bson.types.ObjectId;
22  
23  @RequestScoped
24  public class FileService {
25  
26    private static final int CHUNK_SIZE_BYTES = 1024 * 1024; // 1 MiB
27    private static final String ID_ATTR = "_id";
28    private static final String FILENAME_ATTR = "name";
29    private static final String FILEID_ATTR = "FileMongoId";
30    private static final String CREATEDAT_ATTR = "createdAt";
31    private static final String MD5_ATTR = "md5";
32  
33    @Inject
34    @Named("mongoDatabase")
35    MongoDatabase mongoDatabase;
36  
37    private UUIDHelper uuidHelper;
38    private DateHelper dateHelper;
39  
40    FileService() {}
41  
42    @Inject
43    public FileService(UUIDHelper uuidHelper, DateHelper dateHelper) {
44      this.uuidHelper = uuidHelper;
45      this.dateHelper = dateHelper;
46    }
47  
48    public String createFileContainer() {
49      String oid = "FileContainer" + uuidHelper.getUUID().toString();
50      mongoDatabase.createCollection(oid);
51      return oid;
52    }
53  
54    public ShepardFile createFile(String mongoid, String fileName, InputStream inputStream) {
55      MongoCollection<Document> collection;
56      try {
57        collection = mongoDatabase.getCollection(mongoid);
58      } catch (IllegalArgumentException e) {
59        Log.errorf("Could not find container with mongoid: %s", mongoid);
60        return null;
61      }
62  
63      MessageDigest md;
64      try {
65        md = MessageDigest.getInstance("MD5");
66      } catch (NoSuchAlgorithmException e) {
67        Log.error("No Such Algorithm while uploading file");
68        return null;
69      }
70      DigestInputStream dis = new DigestInputStream(inputStream, md);
71      String fileMongoId = createBucket()
72        .withChunkSizeBytes(CHUNK_SIZE_BYTES)
73        .uploadFromStream(fileName, dis)
74        .toHexString();
75      var file = new ShepardFile(dateHelper.getDate(), fileName, DatatypeConverter.printHexBinary(md.digest()));
76      var doc = toDocument(file).append(FILEID_ATTR, fileMongoId);
77      collection.insertOne(doc);
78      file.setOid(doc.getObjectId(ID_ATTR).toHexString());
79      return file;
80    }
81  
82    public NamedInputStream getPayload(String containerId, String fileoid) {
83      MongoCollection<Document> collection;
84      try {
85        collection = mongoDatabase.getCollection(containerId);
86      } catch (IllegalArgumentException e) {
87        Log.errorf("Could not find container with mongoid: %s", containerId);
88        return null;
89      }
90      var oid = new ObjectId(fileoid);
91      var payloadDocument = collection.find(eq(ID_ATTR, oid)).first();
92      if (payloadDocument == null) {
93        Log.errorf("Could not find document with oid: %s", fileoid);
94        return null;
95      }
96      var fileId = new ObjectId(payloadDocument.getString(FILEID_ATTR));
97      var filename = payloadDocument.getString(FILENAME_ATTR);
98      var gridBucket = createBucket();
99      var gridFsFile = gridBucket.find(eq(ID_ATTR, fileId)).first();
100     var inputStream = gridBucket.openDownloadStream(fileId);
101 
102     return new NamedInputStream(fileoid, inputStream, filename, gridFsFile.getLength());
103   }
104 
105   public ShepardFile getFile(String containerId, String fileoid) {
106     MongoCollection<Document> collection;
107     try {
108       collection = mongoDatabase.getCollection(containerId);
109     } catch (IllegalArgumentException e) {
110       Log.errorf("Could not find container with mongoid: %s", containerId);
111       return null;
112     }
113     var doc = collection.find(eq(ID_ATTR, new ObjectId(fileoid))).first();
114     if (doc == null) {
115       Log.errorf("Could not find file with oid: %s", fileoid);
116       return null;
117     }
118     return toShepardFile(doc);
119   }
120 
121   public boolean deleteFileContainer(String mongoid) {
122     MongoCollection<Document> toDelete;
123     try {
124       toDelete = mongoDatabase.getCollection(mongoid);
125     } catch (IllegalArgumentException e) {
126       Log.errorf("Could not delete container with mongoid: %s", mongoid);
127       return false;
128     }
129     GridFSBucket gridBucket = createBucket();
130     for (Document doc : toDelete.find()) {
131       gridBucket.delete(new ObjectId(doc.getString(FILEID_ATTR)));
132     }
133     toDelete.drop();
134     return true;
135   }
136 
137   public boolean deleteFile(String mongoId, String fileoid) {
138     MongoCollection<Document> collection;
139     try {
140       collection = mongoDatabase.getCollection(mongoId);
141     } catch (IllegalArgumentException e) {
142       Log.errorf("Could not find container with mongoid: %s", mongoId);
143       return false;
144     }
145     var doc = collection.findOneAndDelete(eq(ID_ATTR, new ObjectId(fileoid)));
146     if (doc == null) {
147       Log.warnf("Could not find and delete file with oid: %s", fileoid);
148       return true;
149     }
150     var gridBucket = createBucket();
151     gridBucket.delete(new ObjectId(doc.getString(FILEID_ATTR)));
152     return true;
153   }
154 
155   private static ShepardFile toShepardFile(Document doc) {
156     var file = new ShepardFile(
157       doc.getObjectId(ID_ATTR).toHexString(),
158       doc.getDate(CREATEDAT_ATTR),
159       doc.getString(FILENAME_ATTR),
160       doc.getString(MD5_ATTR)
161     );
162     return file;
163   }
164 
165   private static Document toDocument(ShepardFile file) {
166     var doc = new Document()
167       .append(CREATEDAT_ATTR, file.getCreatedAt())
168       .append(FILENAME_ATTR, file.getFilename())
169       .append(MD5_ATTR, file.getMd5());
170     if (file.getOid() != null) doc.append(ID_ATTR, new ObjectId(file.getOid()));
171     return doc;
172   }
173 
174   private GridFSBucket createBucket() {
175     return GridFSBuckets.create(mongoDatabase);
176   }
177 }