/* This file is part of JFLICKS. JFLICKS is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. JFLICKS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with JFLICKS. If not, see <http://www.gnu.org/licenses/>. */ package org.jflicks.stream.http; import java.io.File; import java.text.FieldPosition; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import org.jflicks.nms.BaseNMS; import org.jflicks.nms.NMS; import org.jflicks.nms.NMSConstants; import org.jflicks.nms.NMSUtil; import org.jflicks.nms.State; import org.jflicks.nms.Video; import org.jflicks.tv.Airing; import org.jflicks.tv.Channel; import org.jflicks.tv.Recording; import org.jflicks.tv.RecordingRule; import org.jflicks.tv.Show; import org.jflicks.tv.ShowAiring; import org.jflicks.tv.Task; import org.jflicks.tv.Upcoming; import org.jflicks.util.LogUtil; import org.jflicks.util.Util; import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceReference; import org.osgi.service.http.HttpService; import org.osgi.service.http.NamespaceException; /** * This is a base class servlet that will handle the lower level chores. * * @author Doug Barnum * @version 1.0 */ public abstract class BaseFeed extends HttpServlet implements HttpServiceProperty { public static final String NOT_RECORDING_TEXT = "NOT recording"; public static final String NOT_RECORDING = "NOT_RECORDING"; public static final String ONCE_TEXT = "Recording Just this Episode"; public static final String ONCE = "ONCE"; public static final String SERIES_TEXT = "Recording this Series"; public static final String SERIES = "SERIES"; private String alias; private HttpService httpService; private BundleContext bundleContext; private SimpleDateFormat originalDateFormat; private SimpleDateFormat upcomingDateFormat; private boolean requireMp4; private ArrayList<NMS> nmsList; /** * Default constructor. */ public BaseFeed() { setNMSList(new ArrayList<NMS>()); } /** * Constructor with one required argument. * * @param s A given alias name. */ public BaseFeed(String s) { this(); setAlias(s); } public BundleContext getBundleContext() { return (bundleContext); } public void setBundleContext(BundleContext bc) { bundleContext = bc; } public SimpleDateFormat getOriginalDateFormat() { return (originalDateFormat); } public void setOriginalDateFormat(SimpleDateFormat df) { originalDateFormat = df; } public SimpleDateFormat getUpcomingDateFormat() { return (upcomingDateFormat); } public void setUpcomingDateFormat(SimpleDateFormat df) { upcomingDateFormat = df; } public boolean isRequireMp4() { return (requireMp4); } public void setRequireMp4(boolean b) { requireMp4 = b; } /** * A feed servlet has an alias name property. * * @return A String instance. */ public String getAlias() { return (alias); } /** * A feed servlet has an alias name property. * * @param s A String instance. */ public void setAlias(String s) { alias = s; } /** * A tracker updates us when the http service comes and goes. * * @return The OSGi HttpService instance. */ public HttpService getHttpService() { return (httpService); } /** * A tracker updates us when the http service comes and goes. * * @param hs The OSGi HttpService instance. */ public void setHttpService(HttpService hs) { httpService = hs; if (httpService != null) { try { httpService.registerServlet("/" + getAlias(), this, null, null); } catch (ServletException ex) { LogUtil.log(LogUtil.WARNING, "BaseFeed: " + ex.getMessage()); } catch (NamespaceException ex) { LogUtil.log(LogUtil.WARNING, "NamespaceException: " + ex.getMessage()); } } } private ArrayList<NMS> getNMSList() { return (nmsList); } private void setNMSList(ArrayList<NMS> l) { nmsList = l; } public NMS[] getNMS() { NMS[] result = null; ArrayList<NMS> l = getNMSList(); if ((l != null) && (l.size() > 0)) { result = l.toArray(new NMS[l.size()]); } return (result); } public void setNMS(NMS[] array) { ArrayList<NMS> l = getNMSList(); if (l != null) { NMS[] oldArray = null; if (l.size() > 0) { oldArray = l.toArray(new NMS[l.size()]); } l.clear(); if ((array != null) && (array.length > 0)) { for (int i = 0; i < array.length; i++) { l.add(array[i]); } } NMS[] newArray = null; if (l.size() > 0) { newArray = l.toArray(new NMS[l.size()]); } } } /* public NMS getNMS() { NMS result = null; BundleContext bc = getBundleContext(); if (bc != null) { ServiceReference ref = bc.getServiceReference(NMS.class.getName()); if (ref != null) { result = (NMS) bc.getService(ref); } } return (result); } */ public String getBaseURL(HttpServletRequest req) { String result = null; if (req != null) { String uri = req.getRequestURI(); String url = req.getRequestURL().toString(); if ((uri != null) && (url != null)) { int index = url.indexOf(uri); if (index != -1) { result = url.substring(0, index); } else { result = url; } } } return (result); } protected String formatUnknown(String s) { String result = "unknown"; if (s != null) { result = s; } return (result); } protected String formatDate(SimpleDateFormat df, Date d) { String result = null; if (df != null) { if (d != null) { StringBuffer sb = new StringBuffer(); df.format(d, sb, new FieldPosition(0)); result = sb.toString(); } } else { if (d != null) { result = d.toString(); } } return (result); } public File getImageHome() { File result = null; NMS[] array = getNMS(); if ((array != null) && (array.length > 0) && (array[0] instanceof BaseNMS)) { BaseNMS bn = (BaseNMS) array[0]; String path = bn.getConfiguredImageHome(); if (path != null) { result = new File(path); } } return (result); } public String getImageName(String s) { String result = "no_image.jpg"; if (s != null) { File f = getImageHome(); if (f != null) { File iname = new File(f, s); if ((iname.exists()) && (iname.isFile())) { result = s; } } } return (result); } public State getState() { State result = null; NMS[] array = getNMS(); if ((array != null) && (array.length > 0)) { result = array[0].getState(); if (result != null) { for (int i = 1; i < array.length; i++) { result = result.merge(array[i].getState()); } } } return (result); } public Recording[] getRecordings() { Recording[] result = null; NMS[] array = getNMS(); if ((array != null) && (array.length > 0)) { ArrayList<Recording> rlist = new ArrayList<Recording>(); for (int i = 0; i < array.length; i++) { Recording[] rarray = getRecordings(array[i]); if ((rarray != null) && (rarray.length > 0)) { for (int j = 0; j < rarray.length; j++) { rlist.add(rarray[j]); } } } if (rlist.size() > 0) { result = rlist.toArray(new Recording[rlist.size()]); } } return (result); } public Recording[] getRecordings(NMS n) { Recording[] result = null; if (n != null) { Recording[] array = n.getRecordings(); if ((array != null) && (array.length > 0)) { ArrayList<Recording> l = new ArrayList<Recording>(); for (int i = 0; i < array.length; i++) { String surl = array[i].getStreamURL(); String iext = array[i].getIndexedExtension(); if (isRequireMp4()) { if ((surl != null) && (iext != null) && (iext.equals("mp4")) && (surl.endsWith(iext))) { l.add(array[i]); } } else { if (surl != null) { l.add(array[i]); } } } if (l.size() > 0) { result = l.toArray(new Recording[l.size()]); } } } return (result); } public Upcoming[] getUpcomings() { Upcoming[] result = null; NMS[] array = getNMS(); if ((array != null) && (array.length > 0)) { ArrayList<Upcoming> ulist = new ArrayList<Upcoming>(); for (int i = 0; i < array.length; i++) { Upcoming[] uarray = getUpcomings(array[i]); if ((uarray != null) && (uarray.length > 0)) { for (int j = 0; j < uarray.length; j++) { ulist.add(uarray[j]); } } } if (ulist.size() > 0) { result = ulist.toArray(new Upcoming[ulist.size()]); } } return (result); } public Upcoming[] getUpcomings(NMS n) { Upcoming[] result = null; if (n != null) { result = n.getUpcomings(); } return (result); } public Video[] getVideos() { Video[] result = null; NMS[] array = getNMS(); if ((array != null) && (array.length > 0)) { ArrayList<Video> vlist = new ArrayList<Video>(); for (int i = 0; i < array.length; i++) { Video[] varray = getVideos(array[i]); if ((varray != null) && (varray.length > 0)) { for (int j = 0; j < varray.length; j++) { vlist.add(varray[j]); } } } if (vlist.size() > 0) { result = vlist.toArray(new Video[vlist.size()]); } } return (result); } public Video[] getVideos(NMS n) { Video[] result = null; if (n != null) { result = n.getVideos(); } return (result); } public Channel[] getChannels() { Channel[] result = null; NMS[] array = getNMS(); if ((array != null) && (array.length > 0)) { ArrayList<Channel> clist = new ArrayList<Channel>(); for (int i = 0; i < array.length; i++) { Channel[] carray = getChannels(array[i]); if ((carray != null) && (carray.length > 0)) { for (int j = 0; j < carray.length; j++) { clist.add(carray[j]); } } } if (clist.size() > 0) { result = clist.toArray(new Channel[clist.size()]); } } return (result); } public Channel[] getChannels(NMS n) { Channel[] result = null; if (n != null) { result = n.getRecordableChannels(); } return (result); } public RecordingRule[] getRecordingRules() { RecordingRule[] result = null; NMS[] array = getNMS(); if ((array != null) && (array.length > 0)) { ArrayList<RecordingRule> rlist = new ArrayList<RecordingRule>(); for (int i = 0; i < array.length; i++) { RecordingRule[] rarray = getRecordingRules(array[i]); if ((rarray != null) && (rarray.length > 0)) { for (int j = 0; j < rarray.length; j++) { rlist.add(rarray[j]); } } } if (rlist.size() > 0) { result = rlist.toArray(new RecordingRule[rlist.size()]); } } return (result); } public RecordingRule[] getRecordingRules(NMS n) { RecordingRule[] result = null; if (n != null) { result = n.getRecordingRules(); } return (result); } public Task[] getTasks() { Task[] result = null; NMS[] array = getNMS(); if ((array != null) && (array.length > 0)) { ArrayList<Task> tlist = new ArrayList<Task>(); for (int i = 0; i < array.length; i++) { Task[] tarray = getTasks(array[i]); if ((tarray != null) && (tarray.length > 0)) { for (int j = 0; j < tarray.length; j++) { tlist.add(tarray[j]); } } } if (tlist.size() > 0) { result = tlist.toArray(new Task[tlist.size()]); } } return (result); } public Task[] getTasks(NMS n) { Task[] result = null; if (n != null) { result = n.getTasks(); } return (result); } public Channel getChannelById(Airing a) { Channel result = null; if (a != null) { result = getChannelById(a.getChannelId(), a.getListingId()); } return (result); } public Channel getChannelById(int cid, String listingId) { Channel result = null; NMS[] array = getNMS(); if ((array != null) && (array.length > 0) && (listingId != null)) { for (int i = 0; i < array.length; i++) { result = array[i].getChannelById(cid, listingId); if (result != null) { break; } } } return (result); } public ShowAiring[] getShowAiringByChannelListing(String channelListing) { ShowAiring[] result = null; NMS[] array = getNMS(); if ((array != null) && (array.length > 0) && (channelListing != null)) { String[] parts = channelListing.split("_"); if ((parts != null) && (parts.length == 2)) { int id = Util.str2int(parts[0], 0); Channel c = null; NMS n = null; for (int i = 0; i < array.length; i++) { c = array[i].getChannelById(id, parts[1]); if (c != null) { n = array[i]; break; } } if ((n != null) && (c != null)) { result = n.getShowAiringsByChannel(c); } } } return (result); } public ShowAiring getShowAiringByChannel(Channel c, String showAiringId) { ShowAiring result = null; NMS[] array = getNMS(); if ((array != null) && (array.length > 0)) { for (int i = 0; i < array.length; i++) { result = getShowAiringByChannel(array[i], c, showAiringId); if (result != null) { break; } } } return (result); } public ShowAiring getShowAiringByChannel(NMS n, Channel c, String showAiringId) { ShowAiring result = null; if ((n != null) && (c != null) && (showAiringId != null)) { ShowAiring[] array = n.getShowAiringsByChannel(c); if (array != null) { for (int i = 0; i < array.length; i++) { if (showAiringId.equals(array[i].getId())) { result = array[i]; break; } } } } return (result); } public void schedule(RecordingRule rr) { if (rr != null) { NMS n = NMSUtil.select(getNMS(), rr.getHostPort()); if (n != null) { n.schedule(rr); } } } public Upcoming getUpcomingByShowId(String showId) { Upcoming result = null; Upcoming[] array = getUpcomings(); if ((array != null) && (showId != null)) { for (int i = 0; i < array.length; i++) { if (showId.equals(array[i].getShowId())) { result = array[i]; break; } } } return (result); } public Video[] getVideoByCategory(String s) { Video[] result = null; Video[] array = getVideos(); if ((s != null) && (array != null)) { ArrayList<Video> vlist = new ArrayList<Video>(); for (int i = 0; i < array.length; i++) { if (s.equals(array[i].getCategory())) { vlist.add(array[i]); } } if (vlist.size() > 0) { result = vlist.toArray(new Video[vlist.size()]); } } return (result); } public Video[] getVideoByCategoryAndSubcategory(String cat, String sub) { Video[] result = null; Video[] array = getVideoByCategory(cat); if ((sub != null) && (array != null)) { ArrayList<Video> vlist = new ArrayList<Video>(); for (int i = 0; i < array.length; i++) { if (sub.equals(array[i].getSubcategory())) { vlist.add(array[i]); } } if (vlist.size() > 0) { result = vlist.toArray(new Video[vlist.size()]); } } return (result); } public HashMap<String, Video[]> getCategoryVideoMap() { HashMap<String, Video[]> result = null; Video[] array = getVideos(); if ((array != null) && (array.length > 0)) { // First pass to find all the cats. ArrayList<String> catlist = new ArrayList<String>(); for (int i = 0; i < array.length; i++) { String cat = array[i].getCategory(); if (cat != null) { if (!catlist.contains(cat)) { catlist.add(cat); } } } if (catlist.size() > 0) { result = new HashMap<String, Video[]>(); // Now do a pass for each cat. for (int i = 0; i < catlist.size(); i++) { String cat = catlist.get(i); Video[] varray = getVideoByCategory(cat); if (varray != null) { result.put(cat, varray); } } } } return (result); } public RecordingRule getRecordingRuleById(String s) { RecordingRule result = null; RecordingRule[] rules = getRecordingRules(); if ((s != null) && (rules != null)) { for (int i = 0; i < rules.length; i++) { if (s.equals(rules[i].getId())) { result = rules[i]; break; } } } return (result); } public RecordingRule getRecordingRuleByShowAiring(ShowAiring sa) { RecordingRule result = null; if (sa != null) { Show s = sa.getShow(); RecordingRule[] rules = getRecordingRules(); if ((s != null) && (rules != null)) { for (int i = 0; i < rules.length; i++) { if (rules[i].isOnceType()) { if (sa.equals(rules[i].getShowAiring())) { result = rules[i]; break; } } else { String sid = s.getSeriesId(); if ((sid != null) && (sid.equals(rules[i].getSeriesId()))) { result = rules[i]; break; } } } } } return (result); } public String checkRule(ShowAiring sa) { String result = NOT_RECORDING_TEXT; if (sa != null) { Show s = sa.getShow(); RecordingRule[] rules = getRecordingRules(); if ((s != null) && (rules != null)) { for (int i = 0; i < rules.length; i++) { if (rules[i].isOnceType()) { if (sa.equals(rules[i].getShowAiring())) { result = ONCE_TEXT; break; } } else { String sid = s.getSeriesId(); if ((sid != null) && (sid.equals(rules[i].getSeriesId()))) { result = SERIES_TEXT; break; } } } } } return (result); } public int checkRulePriority(ShowAiring sa) { int result = RecordingRule.NORMAL_PRIORITY; if (sa != null) { Show s = sa.getShow(); RecordingRule[] rules = getRecordingRules(); if ((s != null) && (rules != null)) { for (int i = 0; i < rules.length; i++) { if (rules[i].isOnceType()) { if (sa.equals(rules[i].getShowAiring())) { result = rules[i].getPriority(); break; } } else { String sid = s.getSeriesId(); if ((sid != null) && (sid.equals(rules[i].getSeriesId()))) { result = rules[i].getPriority(); break; } } } } } return (result); } public String priorityToString(int i) { String result = "Normal"; if (i == RecordingRule.HIGHEST_PRIORITY) { result = "Highest"; } else if (i == RecordingRule.HIGH_PRIORITY) { result = "High"; } else if (i == RecordingRule.LOW_PRIORITY) { result = "Low"; } else if (i == RecordingRule.LOWEST_PRIORITY) { result = "Lowest"; } return (result); } public String typeToString(int i) { String result = "Series"; if (i == RecordingRule.ONCE_TYPE) { result = "Once"; } else if (i == RecordingRule.DO_NOT_RECORD_TYPE) { result = "Do Not Record"; } return (result); } public int toPriority(String s) { int result = RecordingRule.NORMAL_PRIORITY; if (s != null) { if (s.equals("Highest")) { result = RecordingRule.HIGHEST_PRIORITY; } else if (s.equals("High")) { result = RecordingRule.HIGH_PRIORITY; } else if (s.equals("Low")) { result = RecordingRule.LOW_PRIORITY; } else if (s.equals("Lowest")) { result = RecordingRule.LOWEST_PRIORITY; } } return (result); } public int toType(String s) { int result = RecordingRule.SERIES_TYPE; if (s != null) { if (s.equals("Once")) { result = RecordingRule.ONCE_TYPE; } else if (s.equals("Do Not Record")) { result = RecordingRule.DO_NOT_RECORD_TYPE; } } return (result); } public void editRule(String id, String type, String priority) { RecordingRule rr = getRecordingRuleById(id); if (rr != null) { rr = new RecordingRule(rr); LogUtil.log(LogUtil.DEBUG, "type: <" + type + ">"); LogUtil.log(LogUtil.DEBUG, "priority: <" + priority + ">"); int itype = toType(type); int ipriority = toPriority(priority); rr.setType(itype); rr.setPriority(ipriority); schedule(rr); } else { LogUtil.log(LogUtil.WARNING, "Can't find rule for id <" + id + ">"); } } public void processRule(String action, String showAiringId, String channelId, String listingId, String priority) { if ((action != null) && (showAiringId != null) && (channelId != null) && (listingId != null)) { int pint = toPriority(priority); int cid = Util.str2int(channelId, 0); Channel c = getChannelById(cid, listingId); if (c != null) { ShowAiring sa = getShowAiringByChannel(c, showAiringId); if (sa != null) { // We have the exact ShowAiring submitted by the roku // user. if (action.equals(NOT_RECORDING)) { // We should have a recording rule so we have to // find it and change it to not record. RecordingRule rr = getRecordingRuleByShowAiring(sa); if (rr != null) { rr.setType(RecordingRule.DO_NOT_RECORD_TYPE); schedule(rr); } } else if (action.equals(ONCE)) { Show show = sa.getShow(); Airing airing = sa.getAiring(); if ((show != null) && (airing != null)) { // We might have a recording rule that needs to be // changed to ONCE. Or it may be a new rule. RecordingRule rr = getRecordingRuleByShowAiring(sa); if (rr == null) { // We have to make a new one. rr = new RecordingRule(); rr.setHostPort(sa.getHostPort()); } rr.setShowAiring(sa); rr.setType(RecordingRule.ONCE_TYPE); rr.setName(show.getTitle()); rr.setShowId(show.getId()); rr.setSeriesId(show.getSeriesId()); rr.setChannelId(airing.getChannelId()); rr.setListingId(airing.getListingId()); rr.setDuration(airing.getDuration()); rr.setPriority(pint); rr.setTasks(getTasks()); schedule(rr); } } else if (action.equals(SERIES)) { Show show = sa.getShow(); Airing airing = sa.getAiring(); if ((show != null) && (airing != null)) { // We might have a recording rule that needs to be // changed to SERIES. Or it may be a new rule. RecordingRule rr = getRecordingRuleByShowAiring(sa); if (rr == null) { // We have to make a new one. rr = new RecordingRule(); rr.setHostPort(sa.getHostPort()); } // Lots to set for a series rule. rr.setShowAiring(sa); rr.setType(RecordingRule.SERIES_TYPE); rr.setName(show.getTitle()); rr.setShowId(show.getId()); rr.setSeriesId(show.getSeriesId()); rr.setChannelId(airing.getChannelId()); rr.setListingId(airing.getListingId()); rr.setDuration(airing.getDuration()); rr.setPriority(pint); rr.setTasks(getTasks()); schedule(rr); } } } } } } public String processOverride(String showId) { String result = ""; if (showId != null) { Upcoming u = getUpcomingByShowId(showId); if (u != null) { overrideUpcoming(u); u = getUpcomingByShowId(showId); if (u != null) { result = formatDate(getUpcomingDateFormat(), u.getDate()) + " - " + u.getStatus(); } } } return (result); } public ShowAiring[] getShowAirings(String term) { ShowAiring[] result = null; NMS[] array = getNMS(); if ((array != null) && (array.length > 0)) { ArrayList<ShowAiring> slist = new ArrayList<ShowAiring>(); for (int i = 0; i < array.length; i++) { ShowAiring[] sarray = getShowAirings(array[i], term); if ((sarray != null) && (sarray.length > 0)) { for (int j = 0; j < sarray.length; j++) { slist.add(sarray[j]); } } } if (slist.size() > 0) { result = slist.toArray(new ShowAiring[slist.size()]); } } return (result); } public ShowAiring[] getShowAirings(NMS n, String term) { ShowAiring[] result = null; if ((term != null) && (n != null)) { result = n.getShowAirings(term, NMSConstants.SEARCH_TITLE); if (result != null) { LogUtil.log(LogUtil.DEBUG, "result.length: " + result.length); } } return (result); } public String processDelete(String id, boolean b) { String result = "\n"; NMS[] array = getNMS(); if ((id != null) && (array != null) && (array.length > 0)) { NMS n = null; Recording r = null; for (int i = 0; i < array.length; i++) { r = array[i].getRecordingById(id); if (r != null) { n = array[i]; break; } } if ((n != null) && (r != null)) { n.removeRecording(r, b); } } return (result); } public void overrideUpcoming(Upcoming u) { if (u != null) { NMS n = NMSUtil.select(getNMS(), u.getHostPort()); if (n != null) { n.overrideUpcoming(u); } } } }