1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package org.opencastproject.assetmanager.impl.persistence;
22
23 import static org.opencastproject.db.Queries.namedQuery;
24
25 import org.opencastproject.assetmanager.api.Availability;
26 import org.opencastproject.assetmanager.api.Property;
27 import org.opencastproject.assetmanager.api.PropertyId;
28 import org.opencastproject.assetmanager.api.Snapshot;
29 import org.opencastproject.assetmanager.impl.HttpAssetProvider;
30 import org.opencastproject.assetmanager.impl.PartialMediaPackage;
31 import org.opencastproject.assetmanager.impl.VersionImpl;
32 import org.opencastproject.db.DBSession;
33 import org.opencastproject.db.Queries;
34 import org.opencastproject.mediapackage.MediaPackage;
35 import org.opencastproject.mediapackage.MediaPackageElement;
36
37 import org.apache.commons.lang3.StringUtils;
38 import org.apache.commons.lang3.tuple.Pair;
39 import org.slf4j.Logger;
40 import org.slf4j.LoggerFactory;
41
42 import java.util.Collection;
43 import java.util.Collections;
44 import java.util.Date;
45 import java.util.List;
46 import java.util.Optional;
47 import java.util.stream.Collectors;
48
49 import javax.annotation.ParametersAreNonnullByDefault;
50 import javax.persistence.NoResultException;
51 import javax.persistence.TypedQuery;
52
53
54
55
56 @ParametersAreNonnullByDefault
57 public class Database {
58 private static final Logger logger = LoggerFactory.getLogger(Database.class);
59
60 private final DBSession db;
61
62 private HttpAssetProvider httpAssetProvider;
63
64 public Database(DBSession db) {
65 this.db = db;
66 }
67
68 public void setHttpAssetProvider(HttpAssetProvider httpAssetProvider) {
69 this.httpAssetProvider = httpAssetProvider;
70 }
71
72
73
74
75 public boolean saveProperty(final Property property) {
76 return db.execTx(em -> {
77 final PropertyId pId = property.getId();
78 final String mpId = pId.getMediaPackageId();
79 final String namespace = pId.getNamespace();
80 final String propertyName = pId.getName();
81
82
83 Long snapshotCount = em.createQuery(
84 "SELECT COUNT(s.id) FROM Snapshot s "
85 + "WHERE s.mediaPackageId = :mediaPackageId", Long.class)
86 .setParameter("mediaPackageId", mpId)
87 .getSingleResult();
88
89 if (snapshotCount == 0) {
90 return false;
91 }
92
93
94 TypedQuery<PropertyDto> query = em.createQuery(
95 "SELECT p FROM Property p "
96 + "WHERE p.mediaPackageId = :mediaPackageId "
97 + "AND p.namespace = :namespace "
98 + "AND p.propertyName = :propertyName",
99 PropertyDto.class);
100 query.setParameter("mediaPackageId", mpId);
101 query.setParameter("namespace", namespace);
102 query.setParameter("propertyName", propertyName);
103
104 PropertyDto existing = null;
105 try {
106 existing = query.getSingleResult();
107 } catch (NoResultException e) {
108
109 }
110
111 PropertyDto updatedOrNew = existing == null
112 ? PropertyDto.mk(property)
113 : existing.update(property.getValue());
114
115 namedQuery.persistOrUpdate(updatedOrNew).apply(em);
116 return true;
117 });
118 }
119
120
121
122
123
124
125 public VersionImpl claimVersion(final String mpId) {
126 return db.execTx(em -> {
127 final Optional<VersionClaimDto> lastOpt = VersionClaimDto.findLastQuery(mpId).apply(em);
128 if (lastOpt.isPresent()) {
129 final VersionImpl claim = VersionImpl.next(lastOpt.get().getLastClaimed());
130 VersionClaimDto.updateQuery(mpId, claim.value()).apply(em);
131 return claim;
132 } else {
133 final VersionImpl first = VersionImpl.FIRST;
134 em.persist(VersionClaimDto.mk(mpId, first.value()));
135 return first;
136 }
137 });
138 }
139
140
141
142
143 public SnapshotDto saveSnapshot(
144 final String orgId,
145 final PartialMediaPackage pmp,
146 final Date archivalDate,
147 final VersionImpl version,
148 final Availability availability,
149 final String storageId,
150 final String owner) {
151 final SnapshotDto snapshotDto = SnapshotDto.mk(
152 pmp.getMediaPackage(),
153 version,
154 orgId,
155 archivalDate,
156 availability,
157 storageId,
158 owner);
159 return db.execTx(em -> {
160
161 em.persist(snapshotDto);
162
163 for (MediaPackageElement e : pmp.getElements()) {
164 final AssetDto a = AssetDto.mk(
165 e.getIdentifier(),
166 snapshotDto,
167 e.getChecksum().toString(),
168 Optional.ofNullable(e.getMimeType()),
169 storageId,
170 e.getSize());
171 em.persist(a);
172 }
173 return snapshotDto;
174 });
175 }
176
177 public void setStorageLocation(Snapshot snapshot, final String storageId) {
178 setStorageLocation(
179 VersionImpl.mk(snapshot.getVersion()),
180 snapshot.getMediaPackage().getIdentifier().toString(),
181 storageId
182 );
183 }
184
185 public void setStorageLocation(final VersionImpl version, final String mpId, final String storageId) {
186 db.execTx(em -> {
187
188 namedQuery.update(
189 "Snapshot.updateStorageIdByVersionAndMpId",
190 Pair.of("storageId", storageId),
191 Pair.of("version", version.value()),
192 Pair.of("mediaPackageId", mpId)
193 ).apply(em);
194
195
196 Optional<SnapshotDtos.Medium> optSnapshot = getSnapshot(version, mpId);
197 if (optSnapshot.isPresent()) {
198
199 namedQuery.update(
200 "Asset.updateStorageIdBySnapshot",
201 Pair.of("storageId", storageId),
202 Pair.of("snapshot", optSnapshot.get().getSnapshotDto())
203 ).apply(em);
204 }
205
206 return null;
207 });
208 }
209
210 public void setAssetStorageLocation(final VersionImpl version, final String mpId, final String mpeId,
211 final String storageId) {
212 db.execTx(em -> {
213 Optional<SnapshotDtos.Medium> optSnapshot = getSnapshot(version, mpId);
214 if (optSnapshot.isPresent()) {
215
216 namedQuery.update(
217 "Asset.updateStorageIdBySnapshotAndMpElementId",
218 Pair.of("storageId", storageId),
219 Pair.of("snapshot", optSnapshot.get().getSnapshotDto()),
220 Pair.of("mediaPackageElementId", mpeId)
221 ).apply(em);
222 }
223
224 return null;
225 });
226 }
227
228 public int setAvailability(final VersionImpl version, final String mpId, final Availability availability) {
229 return db.execTx(em -> {
230 return namedQuery.update(
231 "Snapshot.updateAvailabilityByVersionAndMpId",
232 Pair.of("availability", availability.name()),
233 Pair.of("version", version.value()),
234 Pair.of("mediaPackageId", mpId)
235 ).apply(em);
236 });
237 }
238
239
240
241
242
243
244 public Optional<AssetDto> getAsset(final VersionImpl version, final String mpId, final String mpeId) {
245 return db.execTx(em -> {
246 return Queries.namedQuery
247 .findOpt(
248 "Asset.findAssetByMpIdMpeIdAndVersion",
249 AssetDto.class,
250 Pair.of("mpId", mpId),
251 Pair.of("mpeId", mpeId),
252 Pair.of("version", version.value()))
253 .apply(em);
254 });
255 }
256
257 public Optional<SnapshotDtos.Medium> getSnapshot(final VersionImpl version, final String mpId) {
258 return db.execTx(em -> {
259 return namedQuery.findOpt(
260 "Snapshot.findByMpIdAndVersionOrderByVersionDesc",
261 SnapshotDto.class,
262 Pair.of("mpId", mpId),
263 Pair.of("version", version.value()))
264 .apply(em)
265 .map(result -> new SnapshotDtos.Medium(
266 result,
267 Availability.valueOf(result.getAvailability()),
268 result.getStorageId(),
269 result.getOrganizationId(),
270 result.getOwner()
271 ));
272 });
273 }
274
275
276
277
278
279
280
281
282
283 public int deleteProperties(final String mediaPackageId) {
284 return db.execTx(PropertyDto.deleteQuery(mediaPackageId));
285 }
286
287
288
289
290
291
292
293
294
295
296 public int deleteProperties(final String mediaPackageId, final String namespace) {
297 if (StringUtils.isBlank(namespace)) {
298 return db.execTx(PropertyDto.deleteQuery(mediaPackageId));
299 }
300 return db.execTx(PropertyDto.deleteQuery(mediaPackageId, namespace));
301 }
302
303
304
305
306
307
308
309
310 public boolean snapshotExists(final String mediaPackageId) {
311 return db.execTx(SnapshotDto.existsQuery(mediaPackageId));
312 }
313
314
315
316
317
318
319
320
321
322
323 public boolean snapshotExists(final String mediaPackageId, final String organization) {
324 return db.exec(SnapshotDto.existsQuery(mediaPackageId, organization));
325 }
326
327
328
329
330
331
332
333
334
335
336 public List<Property> selectProperties(final String mediaPackageId, final String namespace) {
337 return db.exec(PropertyDto.selectQuery(mediaPackageId, namespace));
338 }
339
340
341
342
343
344
345
346
347 public long countEvents(final String organization) {
348 return db.exec(SnapshotDto.countEventsQuery(organization));
349 }
350
351
352
353
354
355
356
357
358 public long countSnapshots(final String organization) {
359 return db.exec(SnapshotDto.countSnapshotsQuery(organization));
360 }
361
362 public long countAssets() {
363 return db.exec(AssetDto.countAssetsQuery());
364 }
365
366 public long countProperties() {
367 return db.exec(PropertyDto.countPropertiesQuery());
368 }
369
370 public Optional<AssetDto> findAssetByChecksumAndStoreAndOrg(final String checksum, final String storeId,
371 final String orgId) {
372 return db.execTx(em -> {
373 return namedQuery.findSome(
374 "Asset.findByChecksumStorageIdAndOrganizationId",
375
376 0,
377 1,
378 AssetDto.class,
379 Pair.of("checksum", checksum),
380 Pair.of("storageId", storeId),
381 Pair.of("orgId", orgId))
382 .apply(em)
383 .stream()
384 .findFirst();
385 });
386 }
387
388 public Optional<Snapshot> getLatestSnapshot(String mediaPackageId) {
389 return getLatestSnapshot(mediaPackageId, null);
390 }
391
392 public Optional<Snapshot> getLatestSnapshot(String mediaPackageId, String orgId) {
393 return db.execTx(em -> {
394 Optional<SnapshotDto> snapshotDto = namedQuery.findOpt(
395 "Snapshot.findLatest",
396 SnapshotDto.class,
397 Pair.of("mediaPackageId", mediaPackageId),
398 Pair.of("organizationId", orgId)
399 ).apply(em);
400
401 if (snapshotDto.isEmpty()) {
402 return Optional.empty();
403 }
404
405 Snapshot snapshot = snapshotDto.get().toSnapshot();
406
407 snapshot = httpAssetProvider.prepareForDelivery(snapshot);
408
409 return Optional.of(snapshot);
410 });
411 }
412
413 public Optional<MediaPackage> getMediaPackage(String mediaPackageId) {
414 return getMediaPackage(mediaPackageId, null);
415 }
416 public Optional<MediaPackage> getMediaPackage(String mediaPackageId, String orgId) {
417 return getLatestSnapshot(mediaPackageId, orgId).map(Snapshot::getMediaPackage);
418 }
419
420 public List<Snapshot> getSnapshots(String mediaPackageId) {
421 return getSnapshots(mediaPackageId, null);
422 }
423
424 public List<Snapshot> getSnapshots(String mediaPackageId, String orgId) {
425 return getSnapshots(mediaPackageId, orgId, null);
426 }
427
428 public List<Snapshot> getSnapshots(String mediaPackageId, String orgId, String orderByVersion) {
429 return db.execTx(em -> {
430 String namedQueryName = "ASC".equals(orderByVersion)
431 ? "Snapshot.findOldestVersionFirst" : "Snapshot.findLatestVersionFirst";
432
433 List<SnapshotDto> snapshotDto = namedQuery.findAll(
434 namedQueryName,
435 SnapshotDto.class,
436 Pair.of("mediaPackageId", mediaPackageId),
437 Pair.of("organizationId", orgId)
438 ).apply(em);
439
440 return snapshotDtoToSnapshot(snapshotDto);
441 });
442 }
443
444 public int deleteSnapshots(String mediaPackageId, String orgId) {
445 return db.execTx(em -> {
446 return namedQuery.delete(
447 "Snapshot.delete",
448 Pair.of("mediaPackageId", mediaPackageId),
449 Pair.of("organizationId", orgId)
450 ).apply(em);
451 });
452 }
453
454 public int deleteAllButLatestSnapshot(String mediaPackageId, String orgId) {
455 return db.execTx(em -> {
456 return namedQuery.delete(
457 "Snapshot.deleteAllButLatest",
458 Pair.of("mediaPackageId", mediaPackageId),
459 Pair.of("organizationId", orgId)
460 ).apply(em);
461 });
462 }
463
464 public List<Snapshot> getSnapshotsByMpIdAndVersion(String mediaPackageId, Long version, String orgId) {
465 return db.execTx(em -> {
466 List<SnapshotDto> snapshotDto = namedQuery.findAll(
467 "Snapshot.findByMpIdAndVersion",
468 SnapshotDto.class,
469 Pair.of("mediaPackageId", mediaPackageId),
470 Pair.of("version", version),
471 Pair.of("organizationId", orgId)
472 ).apply(em);
473
474 return snapshotDtoToSnapshot(snapshotDto);
475 });
476 }
477
478 public List<Snapshot> getSnapshotsByDateOrderByMpId(Date start, Date end, String orgId) {
479 return db.execTx(em -> {
480 List<SnapshotDto> snapshotDto = namedQuery.findAll(
481 "Snapshot.findByDateOrderByMpId",
482 SnapshotDto.class,
483 Pair.of("startDate", start),
484 Pair.of("endDate", end),
485 Pair.of("organizationId", orgId)
486 ).apply(em);
487
488 return snapshotDtoToSnapshot(snapshotDto);
489 });
490 }
491
492 public List<Snapshot> getSnapshotsByMpdIdAndDate(String mediaPackageId, Date start, Date end, String orgId) {
493 return getSnapshotsByMpdIdAndDate(mediaPackageId, start, end, orgId, null);
494 }
495
496 public List<Snapshot> getSnapshotsByMpdIdAndDate(String mediaPackageId, Date start, Date end, String orgId,
497 String orderByVersion) {
498 return db.execTx(em -> {
499 String namedQueryName = "Snapshot.findByMpIdAndDate";
500 if ("ASC".equals(orderByVersion)) {
501 namedQueryName = "Snapshot.findByMpIdAndDateOldestVersionFirst";
502 }
503 if ("DESC".equals(orderByVersion)) {
504 namedQueryName = "Snapshot.findByMpIdAndDateLatestVersionFirst";
505 }
506
507 List<SnapshotDto> snapshotDto = namedQuery.findAll(
508 namedQueryName,
509 SnapshotDto.class,
510 Pair.of("mediaPackageId", mediaPackageId),
511 Pair.of("startDate", start),
512 Pair.of("endDate", end),
513 Pair.of("organizationId", orgId)
514 ).apply(em);
515
516 return snapshotDtoToSnapshot(snapshotDto);
517 });
518 }
519
520 public List<Snapshot> getSnapshotsByNotStorageAndDate(String storageId, Date start, Date end, String orgId) {
521 return db.execTx(em -> {
522 List<SnapshotDto> snapshotDto = namedQuery.findAll(
523 "Snapshot.findByNotStorageAndDate",
524 SnapshotDto.class,
525 Pair.of("storageId", storageId),
526 Pair.of("startDate", start),
527 Pair.of("endDate", end),
528 Pair.of("organizationId", orgId)
529 ).apply(em);
530
531 return snapshotDtoToSnapshot(snapshotDto);
532 });
533 }
534
535 public List<Snapshot> getSnapshotsBySeries(String seriesId, String orgId) {
536 return db.execTx(em -> {
537 List<SnapshotDto> snapshotDto = namedQuery.findAll(
538 "Snapshot.findLatestBySeriesId",
539 SnapshotDto.class,
540 Pair.of("seriesId", seriesId),
541 Pair.of("organizationId", orgId)
542 ).apply(em);
543
544 return snapshotDtoToSnapshot(snapshotDto);
545 });
546 }
547
548 public List<Snapshot> getLatestSnapshotsByMediaPackageIds(Collection mediaPackageIds, String orgId) {
549 if (mediaPackageIds.isEmpty()) {
550 return Collections.emptyList();
551 }
552 return db.execTx(em -> {
553 List<SnapshotDto> snapshotDto = namedQuery.findAll(
554 "Snapshot.findLatestByMpIds",
555 SnapshotDto.class,
556 Pair.of("mediaPackageIds", mediaPackageIds),
557 Pair.of("organizationId", orgId)
558 ).apply(em);
559
560 return snapshotDtoToSnapshot(snapshotDto);
561 });
562 }
563
564 public Optional<Snapshot> getSnapshot(String mediaPackageId, String orgId, Long version) {
565 return db.execTx(em -> {
566 Optional<SnapshotDto> snapshotDto = namedQuery.findOpt(
567 "Snapshot.findByMpIdOrgIdAndVersion",
568 SnapshotDto.class,
569 Pair.of("mediaPackageId", mediaPackageId),
570 Pair.of("organizationId", orgId),
571 Pair.of("version", version)
572 ).apply(em);
573
574 if (snapshotDto.isEmpty()) {
575 return Optional.empty();
576 }
577
578 Snapshot snapshot = snapshotDto.get().toSnapshot();
579
580 snapshot = httpAssetProvider.prepareForDelivery(snapshot);
581
582 return Optional.of(snapshot);
583 });
584 }
585
586 public List<Snapshot> getSnapshotsForIndexRebuild(int offset, int limit) {
587 return db.execTx(em -> {
588 List<SnapshotDto> snapshotDto = namedQuery.findSome(
589 "Snapshot.findForIndexRebuild",
590 offset,
591 limit,
592 SnapshotDto.class
593 ).apply(em);
594
595 return snapshotDtoToSnapshot(snapshotDto);
596 });
597 }
598
599 public List<Long> getVersionsByMediaPackage(String mediaPackageId, String orgId) {
600 return db.execTx(em -> {
601 List<Long> versions = namedQuery.findAll(
602 "Snapshot.getSnapshotVersions",
603 Long.class,
604 Pair.of("mediaPackageId", mediaPackageId),
605 Pair.of("organizationId", orgId)
606 ).apply(em);
607
608 return versions;
609 });
610 }
611
612
613
614
615
616 public static <A> A insidePersistenceContextCheck(A a) {
617 if (a != null) {
618 return a;
619 } else {
620 throw new RuntimeException(
621 "Used DTO outside of a persistence context or the DTO has not been assigned an ID yet.");
622 }
623 }
624
625 private List<Snapshot> snapshotDtoToSnapshot(List<SnapshotDto> snapshotDtos) {
626 return snapshotDtos.stream()
627 .map(s -> s.toSnapshot())
628 .map(s -> httpAssetProvider.prepareForDelivery(s))
629 .collect(Collectors.toList());
630 }
631 }