1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package org.opencastproject.event.handler;
22
23 import static org.opencastproject.util.OsgiUtil.getOptCfg;
24 import static org.opencastproject.util.OsgiUtil.getOptCfgAsBoolean;
25
26 import org.opencastproject.assetmanager.api.AssetManager;
27 import org.opencastproject.assetmanager.api.Snapshot;
28 import org.opencastproject.assetmanager.api.query.AQueryBuilder;
29 import org.opencastproject.assetmanager.api.query.ARecord;
30 import org.opencastproject.assetmanager.api.query.AResult;
31 import org.opencastproject.mediapackage.MediaPackage;
32 import org.opencastproject.mediapackage.MediaPackageElement;
33 import org.opencastproject.mediapackage.selector.SimpleElementSelector;
34 import org.opencastproject.message.broker.api.assetmanager.AssetManagerItem;
35 import org.opencastproject.oaipmh.persistence.OaiPmhDatabase;
36 import org.opencastproject.oaipmh.persistence.QueryBuilder;
37 import org.opencastproject.oaipmh.persistence.SearchResult;
38 import org.opencastproject.oaipmh.persistence.SearchResultItem;
39 import org.opencastproject.publication.api.OaiPmhPublicationService;
40 import org.opencastproject.security.api.Organization;
41 import org.opencastproject.security.api.SecurityService;
42 import org.opencastproject.security.api.User;
43 import org.opencastproject.security.util.SecurityUtil;
44 import org.opencastproject.util.data.Collections;
45 import org.opencastproject.util.data.Option;
46
47 import org.osgi.framework.BundleContext;
48 import org.osgi.service.cm.ConfigurationException;
49 import org.osgi.service.cm.ManagedService;
50 import org.osgi.service.component.annotations.Activate;
51 import org.osgi.service.component.annotations.Component;
52 import org.osgi.service.component.annotations.Reference;
53 import org.slf4j.Logger;
54 import org.slf4j.LoggerFactory;
55
56 import java.util.Collection;
57 import java.util.Dictionary;
58 import java.util.HashSet;
59 import java.util.Optional;
60 import java.util.Set;
61
62 @Component(
63 immediate = true,
64 service = {
65 ManagedService.class,
66 OaiPmhUpdatedEventHandler.class
67 },
68 property = {
69 "service.description=OAI-PMH Updated Event Handler",
70 "service.pid=org.opencastproject.event.handler.OaiPmhUpdatedEventHandler"
71 }
72 )
73 public class OaiPmhUpdatedEventHandler implements ManagedService {
74
75
76 protected static final Logger logger = LoggerFactory.getLogger(OaiPmhUpdatedEventHandler.class);
77
78
79 protected static final String CFG_PROPAGATE_EPISODE = "propagate.episode";
80 protected static final String CFG_FLAVORS = "flavors";
81 protected static final String CFG_TAGS = "tags";
82
83
84 private boolean propagateEpisode = false;
85
86
87 private Set<String> flavors = new HashSet<>();
88
89
90 private Set<String> tags = new HashSet<>();
91
92
93 private SecurityService securityService = null;
94
95
96 private OaiPmhDatabase oaiPmhPersistence = null;
97
98
99 private OaiPmhPublicationService oaiPmhPublicationService = null;
100
101
102 protected String systemAccount = null;
103
104
105 protected AssetManager assetManager = null;
106
107
108
109
110
111
112
113 @Activate
114 protected void activate(BundleContext bundleContext) {
115 this.systemAccount = bundleContext.getProperty("org.opencastproject.security.digest.user");
116 }
117
118 @Override
119 public void updated(Dictionary<String, ?> dictionary) throws ConfigurationException {
120 final Option<Boolean> propagateEpisode = getOptCfgAsBoolean(dictionary, CFG_PROPAGATE_EPISODE);
121 if (propagateEpisode.isSome()) {
122 this.propagateEpisode = propagateEpisode.get();
123 }
124
125 final Option<String> flavorsRaw = getOptCfg(dictionary, CFG_FLAVORS);
126 if (flavorsRaw.isSome()) {
127 final String[] flavorStrings = flavorsRaw.get().split("\\s*,\\s*");
128 this.flavors = Collections.set(flavorStrings);
129 } else {
130 this.flavors = new HashSet<>();
131 }
132
133 final Option<String> tagsRaw = getOptCfg(dictionary, CFG_TAGS);
134 if (tagsRaw.isSome()) {
135 final String[] tags = tagsRaw.get().split("\\s*,\\s*");
136 this.tags = Collections.set(tags);
137 } else {
138 this.tags = new HashSet<>();
139 }
140 }
141
142 public void handleEvent(AssetManagerItem.TakeSnapshot snapshotItem) {
143 if (!propagateEpisode) {
144 logger.trace("Skipping automatic propagation of episode meta data to OAI-PMH since it is turned off.");
145 return;
146 }
147
148
149 logger.debug("Handling update event for media package {}", snapshotItem.getId());
150
151
152 final User prevUser = securityService.getUser();
153 final Organization prevOrg = securityService.getOrganization();
154
155 try {
156 securityService.setUser(SecurityUtil.createSystemUser(systemAccount, prevOrg));
157
158
159
160
161 String versionStr = Long.toString(snapshotItem.getVersion());
162 AQueryBuilder q = assetManager.createQuery();
163 AResult snapshotQueryResult = q.select(q.snapshot())
164 .where(q.organizationId().eq(prevOrg.getId())
165 .and(q.mediaPackageId(snapshotItem.getId())
166 .and(q.version().eq(assetManager.toVersion(versionStr).get())))).run();
167 Optional<ARecord> snapshotRecordOpt = snapshotQueryResult.getRecords().stream().findFirst();
168 if (snapshotRecordOpt.isPresent()) {
169 Snapshot snapshot = snapshotRecordOpt.get().getSnapshot().get();
170 MediaPackage snapshotMp = snapshot.getMediaPackage();
171
172
173 SimpleElementSelector mpeSelector = new SimpleElementSelector();
174 for (String flavor : flavors) {
175 mpeSelector.addFlavor(flavor);
176 }
177 for (String tag : tags) {
178 mpeSelector.addTag(tag);
179 }
180 Collection<MediaPackageElement> elementsToUpdate = mpeSelector.select(snapshotMp, true);
181 if (elementsToUpdate == null || elementsToUpdate.isEmpty()) {
182 logger.debug("The media package {} does not contain any elements matching the given flavors and tags",
183 snapshotMp.getIdentifier().toString());
184 return;
185 }
186
187 SearchResult result = oaiPmhPersistence.search(
188 QueryBuilder.query().mediaPackageId(snapshotMp).isDeleted(false).build());
189 for (SearchResultItem searchResultItem : result.getItems()) {
190 try {
191 oaiPmhPublicationService.updateMetadata(snapshotMp, searchResultItem.getRepository(), flavors, tags, false);
192
193 } catch (Exception e) {
194 logger.error("Unable to update OAI-PMH publication for the media package {} in repository {}",
195 snapshotItem.getId(), searchResultItem.getRepository(), e);
196 }
197 }
198 }
199 } finally {
200 securityService.setOrganization(prevOrg);
201 securityService.setUser(prevUser);
202 }
203 }
204
205 @Reference
206 public void setAssetManager(AssetManager assetManager) {
207 this.assetManager = assetManager;
208 }
209
210 @Reference
211 public void setOaiPmhPersistence(OaiPmhDatabase oaiPmhPersistence) {
212 this.oaiPmhPersistence = oaiPmhPersistence;
213 }
214
215 @Reference
216 public void setOaiPmhPublicationService(OaiPmhPublicationService oaiPmhPublicationService) {
217 this.oaiPmhPublicationService = oaiPmhPublicationService;
218 }
219
220 @Reference
221 public void setSecurityService(SecurityService securityService) {
222 this.securityService = securityService;
223 }
224 }