View Javadoc
1   /*
2    * Licensed to The Apereo Foundation under one or more contributor license
3    * agreements. See the NOTICE file distributed with this work for additional
4    * information regarding copyright ownership.
5    *
6    *
7    * The Apereo Foundation licenses this file to you under the Educational
8    * Community License, Version 2.0 (the "License"); you may not use this file
9    * except in compliance with the License. You may obtain a copy of the License
10   * at:
11   *
12   *   http://opensource.org/licenses/ecl2.txt
13   *
14   * Unless required by applicable law or agreed to in writing, software
15   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
16   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
17   * License for the specific language governing permissions and limitations under
18   * the License.
19   *
20   */
21  
22  package org.opencastproject.message.broker.api.scheduler;
23  
24  import org.opencastproject.metadata.dublincore.DublinCoreCatalog;
25  import org.opencastproject.metadata.dublincore.DublinCoreXmlFormat;
26  import org.opencastproject.security.api.AccessControlList;
27  import org.opencastproject.security.api.AccessControlParser;
28  
29  import com.google.gson.Gson;
30  
31  import org.apache.commons.lang3.StringUtils;
32  
33  import java.io.IOException;
34  import java.io.Serializable;
35  import java.io.StringReader;
36  import java.util.Date;
37  import java.util.HashMap;
38  import java.util.Map;
39  import java.util.Properties;
40  import java.util.Set;
41  
42  /**
43   * {@link Serializable} class that represents all of the possible messages sent through a SchedulerService queue.
44   */
45  public class SchedulerItem implements Serializable {
46    private static final long serialVersionUID = 6061069989788904237L;
47  
48    private static final Gson gson = new Gson();
49  
50    private final String event;
51    private final String properties;
52    private final String acl;
53    private final String agentId;
54    private final long end;
55    private final String presenters;
56    private final String recordingState;
57    private final long start;
58  
59    private final Type type;
60  
61    public enum Type {
62      UpdateCatalog, UpdateProperties, UpdateAcl, UpdateAgentId, UpdateEnd, UpdatePresenters, UpdateRecordingStatus,
63      UpdateStart, DeleteRecordingStatus, Delete
64    };
65  
66    /**
67     * @param event
68     *          The event details to update to.
69     * @return Builds {@link SchedulerItem} for updating a scheduled event.
70     */
71    public static SchedulerItem updateCatalog(DublinCoreCatalog event) {
72      return new SchedulerItem(event);
73    }
74  
75    /**
76     * @param properties
77     *          The new properties to update to.
78     * @return Builds {@link SchedulerItem} for updating the properties of an event.
79     */
80    public static SchedulerItem updateProperties(Map<String, String> properties) {
81      return new SchedulerItem(properties);
82    }
83  
84    /**
85     * @return Builds {@link SchedulerItem} for deleting an event.
86     */
87    public static SchedulerItem delete() {
88      return new SchedulerItem(Type.Delete);
89    }
90  
91    /**
92     * @param accessControlList
93     *          the access control list
94     * @return Builds {@link SchedulerItem} for updating the access control list of an event.
95     */
96    public static SchedulerItem updateAcl(AccessControlList accessControlList) {
97      return new SchedulerItem(accessControlList);
98    }
99  
100   /**
101    * @param state
102    *          The recording state
103    * @param lastHeardFrom
104    *          The recording last heard from date
105    * @return Builds {@link SchedulerItem} for updating a recording.
106    */
107   public static SchedulerItem updateRecordingStatus(String state, Long lastHeardFrom) {
108     return new SchedulerItem(state, lastHeardFrom);
109   }
110 
111   /**
112    * @param start
113    *        The new start time for the event.
114    * @return Builds {@link SchedulerItem} for updating the start of an event.
115    */
116   public static SchedulerItem updateStart(Date start) {
117     return new SchedulerItem(start, null, Type.UpdateStart);
118   }
119 
120   /**
121    * @param end
122    *        The new end time for the event.
123    * @return Builds {@link SchedulerItem} for updating the end of an event.
124    */
125   public static SchedulerItem updateEnd(Date end) {
126     return new SchedulerItem(null, end, Type.UpdateEnd);
127   }
128 
129   /**
130    * @param presenters
131    *        The new set of presenters for the event.
132    * @return Builds {@link SchedulerItem} for updating the presenters of an event.
133    */
134   public static SchedulerItem updatePresenters(Set<String> presenters) {
135     return new SchedulerItem(presenters);
136   }
137 
138   /**
139    * @param agentId
140    *        The new agent id for the event.
141    * @return Builds {@link SchedulerItem} for updating the agent id of an event.
142    */
143   public static SchedulerItem updateAgent(String agentId) {
144     return new SchedulerItem(agentId);
145   }
146 
147   /**
148    * @return Builds {@link SchedulerItem} for deleting a recording.
149    */
150   public static SchedulerItem deleteRecordingState() {
151     return new SchedulerItem(Type.DeleteRecordingStatus);
152   }
153 
154   /**
155    * Constructor to build an update event {@link SchedulerItem}.
156    *
157    * @param event
158    *          The event details to update.
159    */
160   public SchedulerItem(DublinCoreCatalog event) {
161     try {
162       this.event = event.toXmlString();
163     } catch (IOException e) {
164       throw new IllegalStateException();
165     }
166     this.properties = null;
167     this.acl = null;
168     this.agentId = null;
169     this.end = -1;
170     this.presenters = null;
171     this.recordingState = null;
172     this.start = -1;
173     this.type = Type.UpdateCatalog;
174   }
175 
176   /**
177    * Constructor to build an update properties for an event {@link SchedulerItem}.
178    *
179    * @param properties
180    *          The properties to update.
181    */
182   public SchedulerItem(Map<String, String> properties) {
183     this.event = null;
184     this.properties = serializeProperties(properties);
185     this.acl = null;
186     this.agentId = null;
187     this.end = -1;
188     this.presenters = null;
189     this.recordingState = null;
190     this.start = -1;
191     this.type = Type.UpdateProperties;
192   }
193 
194   /**
195    * Constructor to build a delete event {@link SchedulerItem}.
196    *
197    */
198   public SchedulerItem(Type type) {
199     this.event = null;
200     this.properties = null;
201     this.acl = null;
202     this.agentId = null;
203     this.end = -1;
204     this.presenters = null;
205     this.recordingState = null;
206     this.start = -1;
207     this.type = type;
208   }
209 
210   /**
211    * Constructor to build an update access control list event {@link SchedulerItem}.
212    *
213    * @param accessControlList
214    *          The access control list
215    */
216   public SchedulerItem(AccessControlList accessControlList) {
217     this.event = null;
218     this.properties = null;
219     try {
220       this.acl = AccessControlParser.toJson(accessControlList);
221     } catch (IOException e) {
222       throw new IllegalStateException();
223     }
224     this.agentId = null;
225     this.end = -1;
226     this.presenters = null;
227     this.recordingState = null;
228     this.start = -1;
229     this.type = Type.UpdateAcl;
230   }
231 
232   /**
233    * Constructor to build an update recording status event {@link SchedulerItem}.
234    *
235    * @param state
236    *          the recording status
237    * @param lastHeardFrom
238    *          the last heard from time
239    */
240   public SchedulerItem(String state, Long lastHeardFrom) {
241     this.event = null;
242     this.properties = null;
243     this.acl = null;
244     this.agentId = null;
245     this.end = -1;
246     this.presenters = null;
247     this.recordingState = state;
248     this.start = -1;
249     this.type = Type.UpdateRecordingStatus;
250   }
251 
252   public SchedulerItem(Date start, Date end, Type type) {
253     this.event = null;
254     this.acl = null;
255     this.agentId = null;
256     this.end = end == null ? -1 : end.getTime();
257     this.presenters = null;
258     this.properties = null;
259     this.recordingState = null;
260     this.start = start == null ? -1 : start.getTime();
261     this.type = type;
262   }
263 
264   public SchedulerItem(String agentId) {
265     this.event = null;
266     this.acl = null;
267     this.agentId = agentId;
268     this.end = -1;
269     this.presenters = null;
270     this.properties = null;
271     this.recordingState = null;
272     this.start = -1;
273     this.type = Type.UpdateAgentId;
274   }
275 
276   public SchedulerItem(Set<String> presenters) {
277     this.event = null;
278     this.acl = null;
279     this.agentId = null;
280     this.end = -1;
281     this.presenters = gson.toJson(presenters);
282     this.properties = null;
283     this.recordingState = null;
284     this.start = -1;
285     this.type = Type.UpdatePresenters;
286   }
287   public DublinCoreCatalog getEvent() {
288     if (StringUtils.isBlank(event)) {
289       return null;
290     }
291 
292     return DublinCoreXmlFormat.readOpt(event).orNull();
293   }
294 
295   public Map<String, String> getProperties() {
296     try {
297       return parseProperties(properties);
298     } catch (IOException e) {
299       throw new IllegalStateException();
300     }
301   }
302 
303   public AccessControlList getAcl() {
304     try {
305       return acl == null ? null : AccessControlParser.parseAcl(acl);
306     } catch (Exception e) {
307       throw new IllegalStateException(e);
308     }
309   }
310 
311   public String getAgentId() {
312     return agentId;
313   }
314 
315   public Date getEnd() {
316     return end < 0 ? null : new Date(end);
317   }
318 
319   @SuppressWarnings("unchecked")
320   public Set<String> getPresenters() {
321     return gson.fromJson(presenters, Set.class);
322   }
323 
324   public String getRecordingState() {
325     return recordingState;
326   }
327 
328   public Date getStart() {
329     return start < 0 ? null : new Date(start);
330   }
331 
332   public Type getType() {
333     return type;
334   }
335 
336   /**
337    * Serializes Properties to String.
338    *
339    * @param caProperties
340    *          properties to be serialized
341    * @return serialized properties
342    */
343   private String serializeProperties(Map<String, String> caProperties) {
344     StringBuilder wfPropertiesString = new StringBuilder();
345     for (Map.Entry<String, String> entry : caProperties.entrySet()) {
346       wfPropertiesString.append(entry.getKey() + "=" + entry.getValue() + "\n");
347     }
348     return wfPropertiesString.toString();
349   }
350 
351   /**
352    * Parses Properties represented as String.
353    *
354    * @param serializedProperties
355    *          properties to be parsed.
356    * @return parsed properties
357    * @throws IOException
358    *           if parsing fails
359    */
360   private Map<String, String> parseProperties(String serializedProperties) throws IOException {
361     Properties caProperties = new Properties();
362     caProperties.load(new StringReader(serializedProperties));
363     return new HashMap<String, String>((Map) caProperties);
364   }
365 
366 }