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  package org.opencastproject.editor.remote;
22  
23  import org.opencastproject.editor.api.EditingData;
24  import org.opencastproject.editor.api.EditorService;
25  import org.opencastproject.editor.api.EditorServiceException;
26  import org.opencastproject.editor.api.ErrorStatus;
27  import org.opencastproject.editor.api.LockData;
28  import org.opencastproject.security.api.TrustedHttpClient;
29  import org.opencastproject.serviceregistry.api.RemoteBase;
30  import org.opencastproject.serviceregistry.api.ServiceRegistry;
31  
32  import org.apache.http.HttpEntity;
33  import org.apache.http.HttpResponse;
34  import org.apache.http.HttpStatus;
35  import org.apache.http.client.entity.UrlEncodedFormEntity;
36  import org.apache.http.client.methods.HttpDelete;
37  import org.apache.http.client.methods.HttpGet;
38  import org.apache.http.client.methods.HttpPost;
39  import org.apache.http.entity.StringEntity;
40  import org.apache.http.message.BasicNameValuePair;
41  import org.apache.http.util.EntityUtils;
42  import org.osgi.service.component.annotations.Component;
43  import org.osgi.service.component.annotations.Reference;
44  import org.slf4j.Logger;
45  import org.slf4j.LoggerFactory;
46  
47  import java.io.IOException;
48  import java.io.UnsupportedEncodingException;
49  import java.nio.charset.StandardCharsets;
50  import java.util.ArrayList;
51  import java.util.HashMap;
52  import java.util.List;
53  import java.util.Map;
54  
55  @Component(
56      property = {
57          "service.description=Editor Service Remote Proxy"
58      },
59      immediate = true,
60      service = EditorService.class
61  )
62  public class EditorServiceRemoteImpl extends RemoteBase implements EditorService {
63    private static final Logger logger = LoggerFactory.getLogger(EditorServiceRemoteImpl.class);
64    public static final String EDIT_SUFFIX = "/edit.json";
65    public static final String LOCK_SUFFIX = "/lock";
66    public static final String METADATA_SUFFIX = "/metadata.json";
67  
68    /**
69     * Creates a remote implementation for the given type of service.
70     */
71    public EditorServiceRemoteImpl() {
72      super(EditorService.JOB_TYPE);
73    }
74  
75    @Override
76    public EditingData getEditData(String mediaPackageId)
77            throws EditorServiceException {
78      return EditingData.parse(doGetForMediaPackage(mediaPackageId, EDIT_SUFFIX));
79    }
80  
81    @Override
82    public void setEditData(String mediaPackageId, EditingData editingData) throws EditorServiceException {
83      doPostForMediaPackage(mediaPackageId, EDIT_SUFFIX, editingData.toString());
84    }
85  
86    @Override
87    public String getMetadata(String mediaPackageId) throws EditorServiceException {
88      return doGetForMediaPackage(mediaPackageId, METADATA_SUFFIX);
89    }
90  
91    @Override
92    public void lockMediaPackage(String mediaPackageId, LockData lockData) throws EditorServiceException {
93      Map<String, String> params = new HashMap<>();
94      params.put("uuid", lockData.getUUID());
95      params.put("user", lockData.getUser());
96      doPostFormForMediaPackage(mediaPackageId, LOCK_SUFFIX, params);
97    }
98  
99    @Override
100   public void unlockMediaPackage(String mediaPackageId, LockData lockData) throws EditorServiceException {
101     doDeleteForMediaPackage(mediaPackageId, LOCK_SUFFIX + "/" + lockData.getUUID());
102   }
103 
104   protected String doDeleteForMediaPackage(String mediaPackageId, final String urlSuffix)
105           throws EditorServiceException {
106     logger.debug("Editor Remote Lock POST Request for mediaPackage : '{}'", mediaPackageId);
107     HttpDelete delete = new HttpDelete(mediaPackageId + urlSuffix);
108     HttpResponse response = null;
109     try {
110       response = getResponse(delete, HttpStatus.SC_OK, HttpStatus.SC_NOT_FOUND, HttpStatus.SC_CONFLICT);
111       if (response == null || response.getStatusLine() == null) {
112         throw new EditorServiceException("Editor Remote call failed to respond", ErrorStatus.UNKNOWN);
113       }
114       if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
115         evaluateResponseCode(response);
116       }
117       return null;
118     } catch (Exception e) {
119       throw new EditorServiceException("Editor Remote call failed", ErrorStatus.UNKNOWN, e);
120     } finally {
121       closeConnection(response);
122     }
123   }
124 
125   protected String doGetForMediaPackage(final String mediaPackageId, final String urlSuffix)
126           throws EditorServiceException {
127     logger.debug("Editor Remote GET Request for mediaPackage: '{}' to url: '{}'", mediaPackageId, urlSuffix);
128     HttpGet get = new HttpGet(mediaPackageId + urlSuffix);
129     HttpResponse response = null;
130     try {
131       response = getResponse(get, HttpStatus.SC_OK, HttpStatus.SC_NOT_FOUND, HttpStatus.SC_CONFLICT,
132         HttpStatus.SC_BAD_REQUEST);
133       if (response == null || response.getStatusLine() == null) {
134         throw new EditorServiceException("HTTP Request failed", ErrorStatus.UNKNOWN);
135       }
136       if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
137         evaluateResponseCode(response);
138         return null;
139       } else {
140         HttpEntity httpEntity = response.getEntity();
141         if (httpEntity != null) {
142           return EntityUtils.toString(httpEntity);
143         } else {
144           throw new EditorServiceException("Editor Remote call failed", ErrorStatus.UNKNOWN);
145         }
146       }
147     } catch (IOException e) {
148       throw new EditorServiceException("Editor Remote call failed", ErrorStatus.UNKNOWN, e);
149     } finally {
150       closeConnection(response);
151     }
152   }
153 
154   protected void doPostForMediaPackage(final String mediaPackageId, final String urlSuffix, final String data)
155           throws EditorServiceException {
156     logger.debug("Editor Remote POST Request for mediaPackage : '{}' to url: '{}'", mediaPackageId, urlSuffix);
157     HttpPost post = new HttpPost(mediaPackageId + urlSuffix);
158     HttpResponse response = null;
159     try {
160       StringEntity editJson = new StringEntity(data, StandardCharsets.UTF_8);
161       post.setEntity(editJson);
162       post.setHeader("Content-type", "application/json");
163       response = getResponse(post, HttpStatus.SC_OK, HttpStatus.SC_NOT_FOUND, HttpStatus.SC_BAD_REQUEST,
164               HttpStatus.SC_CONFLICT);
165       if (response == null || response.getStatusLine() == null) {
166         throw new EditorServiceException("No response for setEditData", ErrorStatus.UNKNOWN);
167       }
168       if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
169         evaluateResponseCode(response);
170       }
171     } finally {
172       closeConnection(response);
173     }
174   }
175 
176   protected void doPostFormForMediaPackage(final String mediaPackageId, final String urlSuffix,
177           final Map<String, String> params)
178           throws EditorServiceException {
179     logger.debug("Editor Remote POST Request for mediaPackage : '{}' to url: '{}'", mediaPackageId, urlSuffix);
180     HttpPost post = new HttpPost(mediaPackageId + urlSuffix);
181     HttpResponse response = null;
182     try {
183       List<BasicNameValuePair> formParams = new ArrayList<>();
184       for (String field : params.keySet()) {
185         formParams.add(new BasicNameValuePair(field, params.get(field)));
186       }
187       post.setEntity(new UrlEncodedFormEntity(formParams, "UTF-8"));
188       response = getResponse(post, HttpStatus.SC_OK, HttpStatus.SC_NOT_FOUND, HttpStatus.SC_BAD_REQUEST,
189               HttpStatus.SC_CONFLICT);
190       if (response == null || response.getStatusLine() == null) {
191         throw new EditorServiceException("No response for setEditData", ErrorStatus.UNKNOWN);
192       }
193       if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
194         evaluateResponseCode(response);
195       }
196     } catch (UnsupportedEncodingException e) {
197       throw new EditorServiceException(e.getMessage(), ErrorStatus.UNKNOWN);
198     } finally {
199       closeConnection(response);
200     }
201   }
202 
203   protected void evaluateResponseCode(HttpResponse response) throws EditorServiceException {
204     switch (response.getStatusLine().getStatusCode()) {
205       case HttpStatus.SC_NOT_FOUND:
206         throw new EditorServiceException("MediaPackage not found", ErrorStatus.MEDIAPACKAGE_NOT_FOUND);
207       case HttpStatus.SC_CONFLICT:
208         throw new EditorServiceException(response.getEntity().toString(), ErrorStatus.MEDIAPACKAGE_LOCKED);
209       case HttpStatus.SC_BAD_REQUEST:
210         throw new EditorServiceException("Request invalid", ErrorStatus.UNKNOWN);
211       default:
212         throw new EditorServiceException("Editor Remote call failed", ErrorStatus.UNKNOWN);
213     }
214   }
215 
216   @Reference
217   public void setTrustedHttpClient(TrustedHttpClient client) {
218     this.client = client;
219   }
220 
221   @Reference
222   public void setRemoteServiceManager(ServiceRegistry remoteServiceManager) {
223     this.remoteServiceManager = remoteServiceManager;
224   }
225 }