1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package org.opencastproject.event.handler;
23
24 import static org.opencastproject.assetmanager.api.fn.Enrichments.enrich;
25
26 import org.opencastproject.assetmanager.api.AssetManager;
27 import org.opencastproject.assetmanager.api.AssetManagerException;
28 import org.opencastproject.assetmanager.api.Snapshot;
29 import org.opencastproject.assetmanager.api.query.AQueryBuilder;
30 import org.opencastproject.assetmanager.api.query.AResult;
31 import org.opencastproject.mediapackage.Attachment;
32 import org.opencastproject.mediapackage.Catalog;
33 import org.opencastproject.mediapackage.MediaPackage;
34 import org.opencastproject.mediapackage.MediaPackageElementFlavor;
35 import org.opencastproject.mediapackage.MediaPackageElements;
36 import org.opencastproject.mediapackage.MediaPackageException;
37 import org.opencastproject.message.broker.api.series.SeriesItem;
38 import org.opencastproject.metadata.dublincore.DublinCore;
39 import org.opencastproject.metadata.dublincore.DublinCoreCatalog;
40 import org.opencastproject.metadata.dublincore.DublinCoreCatalogService;
41 import org.opencastproject.metadata.dublincore.DublinCoreUtil;
42 import org.opencastproject.security.api.AclScope;
43 import org.opencastproject.security.api.AuthorizationService;
44 import org.opencastproject.security.api.Organization;
45 import org.opencastproject.security.api.OrganizationDirectoryService;
46 import org.opencastproject.security.api.SecurityService;
47 import org.opencastproject.security.api.User;
48 import org.opencastproject.security.util.SecurityUtil;
49 import org.opencastproject.util.NotFoundException;
50 import org.opencastproject.util.data.Tuple;
51 import org.opencastproject.workspace.api.Workspace;
52
53 import org.apache.commons.io.FilenameUtils;
54 import org.osgi.framework.BundleContext;
55 import org.osgi.service.component.annotations.Activate;
56 import org.osgi.service.component.annotations.Component;
57 import org.osgi.service.component.annotations.Reference;
58 import org.slf4j.Logger;
59 import org.slf4j.LoggerFactory;
60
61 import java.io.IOException;
62 import java.net.URI;
63 import java.util.Collections;
64 import java.util.Comparator;
65 import java.util.List;
66
67
68
69
70 @Component(
71 immediate = true,
72 service = {
73 AssetManagerUpdatedEventHandler.class
74 },
75 property = {
76 "service.description=AssetManagerUpdatedEventHandler"
77 }
78 )
79 public class AssetManagerUpdatedEventHandler {
80
81
82 protected static final Logger logger = LoggerFactory.getLogger(AssetManagerUpdatedEventHandler.class);
83
84
85 protected AssetManager assetManager = null;
86
87
88 protected SecurityService securityService = null;
89
90
91 protected AuthorizationService authorizationService = null;
92
93
94 protected OrganizationDirectoryService organizationDirectoryService = null;
95
96
97 protected DublinCoreCatalogService dublinCoreService = null;
98
99
100 protected Workspace workspace = null;
101
102
103 protected String systemAccount = null;
104
105
106
107
108
109
110
111 @Activate
112 protected void activate(BundleContext bundleContext) {
113 this.systemAccount = bundleContext.getProperty("org.opencastproject.security.digest.user");
114 }
115
116
117
118
119
120 @Reference
121 public void setWorkspace(Workspace workspace) {
122 this.workspace = workspace;
123 }
124
125
126
127
128
129 @Reference
130 public void setDublinCoreCatalogService(DublinCoreCatalogService dublinCoreService) {
131 this.dublinCoreService = dublinCoreService;
132 }
133
134
135
136
137
138 @Reference
139 public void setAssetManager(AssetManager assetManager) {
140 this.assetManager = assetManager;
141 }
142
143
144
145
146
147 @Reference
148 public void setSecurityService(SecurityService securityService) {
149 this.securityService = securityService;
150 }
151
152
153
154
155
156 @Reference
157 public void setAuthorizationService(AuthorizationService authorizationService) {
158 this.authorizationService = authorizationService;
159 }
160
161
162
163
164
165 @Reference
166 public void setOrganizationDirectoryService(OrganizationDirectoryService organizationDirectoryService) {
167 this.organizationDirectoryService = organizationDirectoryService;
168 }
169
170 public void handleEvent(final SeriesItem seriesItem) {
171
172 logger.debug("Handling {}", seriesItem);
173 String seriesId = seriesItem.getSeriesId();
174
175
176 final User prevUser = securityService.getUser();
177 final Organization prevOrg = securityService.getOrganization();
178 try {
179 securityService.setUser(SecurityUtil.createSystemUser(systemAccount, prevOrg));
180
181 final AQueryBuilder q = assetManager.createQuery();
182 final AResult result = q.select(q.snapshot()).where(q.seriesId().eq(seriesId).and(q.version().isLatest())).run();
183 List<Snapshot> snapshots = enrich(result).getSnapshots();
184 Collections.sort(
185 enrich(result).getSnapshots(),
186 Comparator.comparing(s->s.getMediaPackage().getIdentifier().toString())
187 );
188
189 for (Snapshot snapshot : snapshots) {
190 final String orgId = snapshot.getOrganizationId();
191 final Organization organization = organizationDirectoryService.getOrganization(orgId);
192 if (organization == null) {
193 logger.warn("Skipping update of episode {} since organization {} is unknown",
194 snapshot.getMediaPackage().getIdentifier().toString(), orgId);
195 continue;
196 }
197 securityService.setOrganization(organization);
198
199 MediaPackage mp = snapshot.getMediaPackage();
200
201
202 Tuple<MediaPackage, Attachment> mpAclAttachmentTuple = null;
203 if (SeriesItem.Type.UpdateAcl.equals(seriesItem.getType())) {
204
205 try {
206 if (seriesItem.getOverrideEpisodeAcl()) {
207 authorizationService.removeAcl(mp, AclScope.Episode);
208 }
209 mpAclAttachmentTuple = authorizationService.setAcl(mp,
210 AclScope.Series, seriesItem.getAcl());
211 } catch (MediaPackageException e) {
212 logger.error("Error setting ACL for media package {}", mp.getIdentifier(), e);
213 }
214 }
215
216
217 if (SeriesItem.Type.UpdateCatalog.equals(seriesItem.getType())
218 || SeriesItem.Type.UpdateElement.equals(seriesItem.getType())) {
219 DublinCoreCatalog seriesDublinCore = null;
220 MediaPackageElementFlavor catalogType = null;
221 if (SeriesItem.Type.UpdateCatalog.equals(seriesItem.getType())) {
222 seriesDublinCore = seriesItem.getMetadata();
223 mp.setSeriesTitle(seriesDublinCore.getFirst(DublinCore.PROPERTY_TITLE));
224 catalogType = MediaPackageElements.SERIES;
225 } else {
226 seriesDublinCore = seriesItem.getExtendedMetadata();
227 catalogType = MediaPackageElementFlavor.flavor(seriesItem.getElementType(), "series");
228 }
229
230
231 Catalog[] seriesCatalogs = mp.getCatalogs(catalogType);
232 if (seriesCatalogs.length == 1) {
233 Catalog c = seriesCatalogs[0];
234 String filename = FilenameUtils.getName(c.getURI().toString());
235 URI uri = workspace.put(mp.getIdentifier().toString(), c.getIdentifier(), filename,
236 dublinCoreService.serialize(seriesDublinCore));
237 c.setURI(uri);
238
239 c.setChecksum(null);
240 }
241 }
242
243
244 if (SeriesItem.Type.Delete.equals(seriesItem.getType())) {
245 mp.setSeries(null);
246 mp.setSeriesTitle(null);
247 for (Catalog seriesCatalog : mp.getCatalogs(MediaPackageElements.SERIES)) {
248 mp.remove(seriesCatalog);
249 }
250 authorizationService.removeAcl(mp, AclScope.Series);
251 for (Catalog episodeCatalog : mp.getCatalogs(MediaPackageElements.EPISODE)) {
252 DublinCoreCatalog episodeDublinCore = DublinCoreUtil.loadDublinCore(workspace, episodeCatalog);
253 episodeDublinCore.remove(DublinCore.PROPERTY_IS_PART_OF);
254 String filename = FilenameUtils.getName(episodeCatalog.getURI().toString());
255 URI uri = workspace.put(mp.getIdentifier().toString(), episodeCatalog.getIdentifier(), filename,
256 dublinCoreService.serialize(episodeDublinCore));
257 episodeCatalog.setURI(uri);
258
259 episodeCatalog.setChecksum(null);
260 }
261
262
263 MediaPackageElementFlavor seriesFlavor = MediaPackageElementFlavor.flavor("*", "series");
264 for (Catalog catalog : mp.getCatalogs()) {
265 if (catalog.getFlavor().matches(seriesFlavor)) {
266 mp.remove(catalog);
267 }
268 }
269 }
270
271 try {
272
273 assetManager.takeSnapshot(snapshot.getOwner(), mp);
274 } catch (AssetManagerException e) {
275 logger.error("Error updating mediapackage {}", mp.getIdentifier().toString(), e);
276 } finally {
277 if (mpAclAttachmentTuple != null) {
278 try {
279 workspace.delete(mpAclAttachmentTuple.getB().getURI());
280 } catch (Exception ex) {
281
282 }
283 }
284 }
285 }
286 } catch (IOException | NotFoundException e) {
287 logger.warn("Unable to handle update event for series {} for user {}: {}",
288 seriesItem, prevUser.getUsername(), e.getMessage());
289 } finally {
290 securityService.setOrganization(prevOrg);
291 securityService.setUser(prevUser);
292 }
293 }
294 }