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