View Javadoc
1   /******************************************************************************
2    * RestService.java - Service calls that want session protection
3    * $Id: RestService.java,v 1.16 2015/05/11 01:57:54 dick Exp $
4    * 
5    * BuckoVidLib - The BuckoSoft Video Library
6    * Copyright(c) 2015 - Dick Balaska
7    * 
8    * $Log: RestService.java,v $
9    * Revision 1.16  2015/05/11 01:57:54  dick
10   * /statistics wants a session so we don't count restricted movies.
11   *
12   * Revision 1.15  2015/05/08 02:37:14  dick
13   * findVideosAndThings(key, max) returns videos, actors, directors, and writers
14   *
15   * Revision 1.14  2015/05/07 00:15:38  dick
16   * findMaxResults is a user config option.
17   *
18   * Revision 1.13  2015/05/06 17:05:00  dick
19   * findVideos() looks up videos by partial strings.
20   *
21   * Revision 1.12  2015/05/06 03:36:53  dick
22   * hideRestricted allows a user with restricted access to temporarily turn it off.
23   *
24   * Revision 1.11  2015/05/05 04:26:00  dick
25   * Persist backgroundDelay and artShowDelay.
26   *
27   * Revision 1.10  2015/05/04 20:36:50  dick
28   * getBackgroundFit() needs to know if we are running the ArtShow, which may be different
29   * than the normal backgroundFit.
30   *
31   * Revision 1.9  2015/05/04 05:46:27  dick
32   * Always output OK for /config/backgroundFit.
33   *
34   * Revision 1.8  2015/05/03 17:53:46  dick
35   * /configBackground lets the User configure his background type.
36   *
37   * Revision 1.7  2015/05/01 19:59:27  dick
38   * Return 204 No Content if the database isn't ready.
39   *
40   * Revision 1.6  2015/04/30 14:51:13  dick
41   * Load prettyPrint from a properties.
42   *
43   * Revision 1.5  2015/04/30 06:34:27  dick
44   * Getting lists of VideoBase is always protected by session.
45   *
46   * Revision 1.4  2015/04/30 03:18:03  dick
47   * Deal mostly with VideoBase. Only fetch full Video when we really need it.
48   * Protect all (most) calls to the restricted section of the library by session.
49   *
50   * Revision 1.3  2015/04/29 14:34:08  dick
51   * Break up Video into base class VideoBase and Video.
52   * All of the parts to define a Video are in VideoBase.
53   * The idea is that I'm going to be throwing a lot of these things around, and I really don't
54   * want the memory baggage of Summaries and Actor Lists, when really, I just want the
55   * name of the video.
56   *
57   * Revision 1.2  2015/04/28 09:56:41  dick
58   * status returns a 204 No Content if the database isn't ready.
59   *
60   * Revision 1.1  2015/04/27 15:15:10  dick
61   * Handle REST service calls that want session protection.
62   *
63   */
64  package com.buckosoft.BuckoVidLib.web;
65  
66  import java.io.IOException;
67  import java.io.OutputStream;
68  import java.util.ArrayList;
69  import java.util.Collections;
70  import java.util.Comparator;
71  import java.util.List;
72  
73  import javax.servlet.http.HttpServletRequest;
74  import javax.servlet.http.HttpServletResponse;
75  import javax.xml.bind.JAXBContext;
76  import javax.xml.bind.JAXBException;
77  import javax.xml.bind.Marshaller;
78  
79  import org.apache.commons.logging.Log;
80  import org.apache.commons.logging.LogFactory;
81  import org.springframework.beans.factory.annotation.Autowired;
82  import org.springframework.http.MediaType;
83  import org.springframework.stereotype.Controller;
84  import org.springframework.web.bind.annotation.PathVariable;
85  import org.springframework.web.bind.annotation.RequestMapping;
86  
87  import com.buckosoft.BSAccount.BSAccountMan;
88  import com.buckosoft.BuckoVidLib.business.BuckoVidLib;
89  import com.buckosoft.BuckoVidLib.domain.LibrarySection;
90  import com.buckosoft.BuckoVidLib.domain.User;
91  import com.buckosoft.BuckoVidLib.domain.UserWebSession;
92  import com.buckosoft.BuckoVidLib.domain.Video;
93  import com.buckosoft.BuckoVidLib.domain.VideoBase;
94  import com.buckosoft.BuckoVidLib.domain.rest.RestDetailedVideo;
95  import com.buckosoft.BuckoVidLib.domain.rest.RestLibrarySection;
96  import com.buckosoft.BuckoVidLib.domain.rest.RestLibrarySections;
97  import com.buckosoft.BuckoVidLib.domain.rest.RestLibraryStatus;
98  import com.buckosoft.BuckoVidLib.domain.rest.RestStatistics;
99  import com.buckosoft.BuckoVidLib.domain.rest.RestVideo;
100 import com.buckosoft.BuckoVidLib.domain.rest.RestVideos;
101 import com.buckosoft.BuckoVidLib.util.ConfigManager;
102 import com.buckosoft.BuckoVidLib.util.DomainConverter;
103 
104 /** Handle REST service calls that want session protection.
105  * Some calls are only allowed access to the restricted sections by login session.
106  * 
107  * The CXF way that I was using doesn't seem to support HttpServletRequest, which is where the session is stashed.
108  * So for now, keep the unprotected calls over in BVLRestService and put the protected calls here.  
109  * @author dick
110  * @since 2015-04-27
111  *
112  */
113 @Controller
114 @RequestMapping("/rs")
115 public class RestService {
116 	private final Log log = LogFactory.getLog(getClass());
117 
118 	private	boolean logExceptions = true;
119 	private	boolean prettyPrint = true;
120 
121 	@Autowired
122 	BSAccountMan	bsAccountMan;
123 	
124 	@Autowired
125 	private BuckoVidLib		bvl;
126 
127 	public RestService() {
128 		prettyPrint = ConfigManager.getBoolean("BuckoVidLib.prettyPrint", true);
129 		logExceptions = ConfigManager.getBoolean("BuckoVidLib.logExceptions", true);
130 	}
131 
132 	@RequestMapping(value="/libraryList", produces=MediaType.APPLICATION_XML_VALUE)
133 	public void libraryList(HttpServletRequest request, OutputStream os) throws Exception {
134 		boolean allowRestricted = bvl.isAllowRestricted(request);
135 		List<LibrarySection> llist = bvl.getSectionList(allowRestricted);
136 		List<RestLibrarySection> rlist = new ArrayList<RestLibrarySection>();
137 		for (LibrarySection l : llist) {
138 			RestLibrarySection rl = new RestLibrarySection();
139 			rl.setKey(l.getKey());
140 			rl.setName(l.getName());
141 			rl.setVideoCount(l.getVideoCount());
142 			rlist.add(rl);
143 		}
144 		Collections.sort(rlist, new CountSort());
145 		RestLibrarySections rls = new RestLibrarySections();
146 		rls.setLibrarySections(rlist);
147 		JAXBContext context = JAXBContext.newInstance(RestLibrarySections.class);
148 		Marshaller m = context.createMarshaller();
149 		m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, prettyPrint);
150 		m.marshal(rls, os);
151 	}
152 	
153 	@RequestMapping(value="/status", produces=MediaType.APPLICATION_XML_VALUE)
154 	public void libraryStatus(HttpServletRequest request,  HttpServletResponse response) throws JAXBException {
155 		libraryStatus(request, response, 1);
156 	}
157 	
158 	@RequestMapping(value="/status/{count}", produces=MediaType.APPLICATION_XML_VALUE)
159 	public void libraryStatus(HttpServletRequest request, HttpServletResponse response, @PathVariable("count") Integer count) {
160 		if (count == null)
161 			count = 1;
162 		RestLibraryStatus rls = new RestLibraryStatus();
163 		List<VideoBase> vv = bvl.getRecentlyAdded(count, bvl.isAllowRestricted(request));
164 		ArrayList<RestVideo> al = new ArrayList<RestVideo>();
165 		try {
166 			if (vv == null) {
167 				response.sendError(204, "No content");
168 				log.info("Returning 204 no content");
169 				return;
170 			}
171 			for (VideoBase v : vv)
172 				al.add(DomainConverter.toRestVideo(v));
173 			rls.setRecentlyAddedVideos(al);
174 			try {
175 				rls.setLastUpdated(bvl.getLastUpdateTime());
176 			} catch (Exception e) {
177 				response.sendError(204, "No content");
178 				log.info("Returning 204 no content");
179 				return;
180 			}
181 			JAXBContext context;
182 			context = JAXBContext.newInstance(RestLibraryStatus.class);
183 			Marshaller m = context.createMarshaller();
184 			m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, prettyPrint);
185 			OutputStream os;
186 			os = response.getOutputStream();
187 			m.marshal(rls, os);
188 		} catch (IOException | JAXBException e) {
189 			if (logExceptions)
190 				e.printStackTrace();
191 			else
192 				log.warn(e.getMessage());
193 		}
194 	}
195 
196 	@RequestMapping(value="/statistics", produces=MediaType.APPLICATION_XML_VALUE)
197 	public void statistics(HttpServletRequest request, HttpServletResponse response) {
198 		RestStatistics rs = new RestStatistics();
199 		boolean allowRestricted =  bvl.isAllowRestricted(request);
200 		int ep = bvl.getTVEpisodeCount(allowRestricted);
201 		int m = bvl.getMovieCount(allowRestricted);
202 		rs.setMovieCount(m);
203 		rs.setTvShowCount(bvl.getTVShowCount(allowRestricted));
204 		rs.setEpisodeCount(ep);
205 		rs.setVideoCount(ep + m);
206 		outputXml(response, rs);
207 	}
208 
209 
210 	@RequestMapping(value="/detailedVideo/{key}", produces=MediaType.APPLICATION_XML_VALUE)
211 	public void detailedVideo(HttpServletRequest request, HttpServletResponse response, @PathVariable("key") String key) {
212 		int k = DomainConverter.keyToInt(key);
213 		Video v = bvl.getVideoFromKey(k, bvl.isAllowRestricted(request));
214 		try {
215 			if (v == null) {
216 				response.sendError(204, "Video not found");
217 				return;
218 			}
219 			RestDetailedVideo rdv = DomainConverter.toRestDetailedVideo(v);
220 			outputXml(response, rdv);
221 		} catch (IOException e) {
222 			if (logExceptions)
223 				e.printStackTrace();
224 			else
225 				log.warn(e.getMessage());
226 		}
227 	}
228 
229 	@RequestMapping(value="/randomVideo", produces=MediaType.APPLICATION_XML_VALUE)
230 	public void	randomVideo(HttpServletRequest request, HttpServletResponse response) {
231 		boolean allowRestricted = bvl.isAllowRestricted(request);
232 		try {
233 			RestVideo v = bvl.getRandomMovie(allowRestricted);
234 			if (v == null) {
235 				response.sendError(204, "Video not found");
236 				return;
237 			}
238 			outputXml(response, v);
239 		} catch (IOException e) {
240 			if (logExceptions)
241 				e.printStackTrace();
242 			else
243 				log.warn(e.getMessage());
244 		}
245 	}
246 	
247 	@RequestMapping(value="/videos/recent/{count}", produces=MediaType.APPLICATION_XML_VALUE)
248 	public void recentVideos(HttpServletRequest request, HttpServletResponse response, @PathVariable("count") Integer count) {
249 		List<VideoBase> vl = bvl.getRecentlyAdded(count, bvl.isAllowRestricted(request));
250 		outputVideos(response, vl);
251 	}
252 	
253 	@RequestMapping(value="/videos/section/{key}", produces=MediaType.APPLICATION_XML_VALUE)
254 	public void sectionVideos(HttpServletRequest request, HttpServletResponse response, @PathVariable("key") Integer key) {
255 		List<VideoBase> vl = bvl.getLibraryListVideos(key);
256 		outputVideos(response, vl);
257 	}
258 	@RequestMapping(value="/videos/director/{key}", produces=MediaType.APPLICATION_XML_VALUE)
259 	public void directorVideos(HttpServletRequest request, HttpServletResponse response, @PathVariable("key") Integer key) {
260 		List<VideoBase> vl = bvl.getDirectorVideos(key);
261 		outputVideos(response, vl);
262 	}
263 	
264 	@RequestMapping(value="/videos/actor/{key}", produces=MediaType.APPLICATION_XML_VALUE)
265 	public void actorVideos(HttpServletRequest request, HttpServletResponse response, @PathVariable("key") Integer key) {
266 		List<VideoBase> vl = bvl.getActorVideos(key);
267 		outputVideos(response, vl);
268 	}
269 	@RequestMapping(value="/videos/writer/{key}", produces=MediaType.APPLICATION_XML_VALUE)
270 	public void writerVideos(HttpServletRequest request, HttpServletResponse response, @PathVariable("key") Integer key) {
271 		List<VideoBase> vl = bvl.getWriterVideos(key);
272 		outputVideos(response, vl);
273 	}
274 
275 	@RequestMapping(value="/videos/find/{key}", produces=MediaType.APPLICATION_XML_VALUE)
276 	public void findVideosAndThings(HttpServletRequest request, HttpServletResponse response, @PathVariable("key") String key) {
277 		boolean allowRestricted = bvl.isAllowRestricted(request);
278 		List<RestVideo> vl = bvl.findVideosAndThings(key, allowRestricted, bvl.getFindMaxResults(request));
279 		outputRestVideos(response, vl);
280 	}
281 
282 	private	void outputVideos(HttpServletResponse response, List<VideoBase> videos) {
283 		List<RestVideo> rvl = new ArrayList<RestVideo>();
284 		for (VideoBase v : videos)
285 			rvl.add(DomainConverter.toRestVideo(v));
286 		outputRestVideos(response, rvl);
287 	}
288 	private	void outputRestVideos(HttpServletResponse response, List<RestVideo> videos) {
289 		RestVideos rvs = new RestVideos();
290 		rvs.setVideos(videos);
291 		outputXml(response, rvs);
292 	}
293 	private class CountSort implements Comparator<RestLibrarySection> {
294 		@Override
295 		public int compare(RestLibrarySection arg0, RestLibrarySection arg1) {
296 			return(Integer.compare(arg1.getVideoCount(), arg0.getVideoCount()));
297 		}
298 	}
299 	
300 	private void outputXml(HttpServletResponse response, Object object) {
301 		try {
302 			JAXBContext context = JAXBContext.newInstance(object.getClass());
303 			Marshaller m = context.createMarshaller();
304 			m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, prettyPrint);
305 			OutputStream os = response.getOutputStream();
306 			m.marshal(object, os);
307 		} catch (JAXBException | IOException e) {
308 			if (logExceptions)
309 				e.printStackTrace();
310 			else
311 				log.warn(e.getMessage());
312 		}
313 		
314 	}
315 
316 	@RequestMapping(value="/config/backgroundFit/{value}", produces=MediaType.TEXT_PLAIN_VALUE)
317 	public void configBackgroundFit(HttpServletRequest request, HttpServletResponse response, @PathVariable("value") Integer value) {
318 		UserWebSession userWebSession = (UserWebSession)this.bsAccountMan.getUserWebSession(request);
319 		User user = (User)userWebSession.getUser();
320 		log.info("backgroundFit: userWebSession = " + userWebSession);
321 		bvl.setBackgroundFit(request, value);
322 		log.info("setBackgroundFit to " + value + " (artShowFit = " + user.getArtShowFit() + ")");
323 		try {
324 			response.getWriter().print("OK");
325 		} catch (IOException e) {
326 			if (logExceptions)
327 				e.printStackTrace();
328 			else
329 				log.warn(e.getMessage());			
330 		}
331 	}
332 
333 	@RequestMapping(value="/config/backgroundDelays/{background}/{artShow}/{max}", produces=MediaType.TEXT_PLAIN_VALUE)
334 	public void configBackgroundDelays(HttpServletRequest request, HttpServletResponse response, 
335 			@PathVariable("background") Integer background, @PathVariable("artShow") Integer artShow,
336 			@PathVariable("max") Integer findMaxResults) {
337 		UserWebSession userWebSession = (UserWebSession)this.bsAccountMan.getUserWebSession(request);
338 		bvl.setBackgroundDelays(request, background, artShow);
339 		bvl.setFindMaxResults(request, findMaxResults);
340 		log.info("configBackgroundDelays: userWebSession = " + userWebSession);
341 		log.info("configBackgroundDelays to " + background + " artShow: " + artShow + " maxFind: " + findMaxResults);
342 		try {
343 			response.getWriter().print("OK");
344 		} catch (IOException e) {
345 			if (logExceptions)
346 				e.printStackTrace();
347 			else
348 				log.warn(e.getMessage());			
349 		}
350 	}
351 
352 	@RequestMapping(value="/config/hideRestricted/{hide}", produces=MediaType.TEXT_PLAIN_VALUE)
353 	public void configHideRestricted(HttpServletRequest request, HttpServletResponse response, 
354 			@PathVariable("hide") Boolean hideRestricted) {
355 		UserWebSession userWebSession = (UserWebSession)this.bsAccountMan.getUserWebSession(request);
356 		bvl.setHideRestricted(request, hideRestricted);
357 		log.info("configHideRestricted: userWebSession = " + userWebSession);
358 		log.info("configHideRestricted to " + hideRestricted);
359 		try {
360 			response.getWriter().print("OK");
361 		} catch (IOException e) {
362 			if (logExceptions)
363 				e.printStackTrace();
364 			else
365 				log.warn(e.getMessage());			
366 		}
367 	}
368 
369 	@RequestMapping(value="/config/findMaxResults/{max}", produces=MediaType.TEXT_PLAIN_VALUE)
370 	public void configFindMaxResults(HttpServletRequest request, HttpServletResponse response, 
371 			@PathVariable("max") Integer findMaxResults) {
372 		UserWebSession userWebSession = (UserWebSession)this.bsAccountMan.getUserWebSession(request);
373 		bvl.setFindMaxResults(request, findMaxResults);
374 		log.info("configFindMaxResults: userWebSession = " + userWebSession);
375 		log.info("configFindMaxResults to " + findMaxResults);
376 		try {
377 			response.getWriter().print("OK");
378 		} catch (IOException e) {
379 			if (logExceptions)
380 				e.printStackTrace();
381 			else
382 				log.warn(e.getMessage());			
383 		}
384 	}
385 }