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