/**
   * Request the next track from the trackmanager and play it. When a 404 is returned, delete this
   * show. On any other error: log it and try again in 0.5s.
   */
  private void play_next_track() {
    try {
      last_action = "get next track";
      current_track = new JSONObject(get_url(pop_url));
      WMSLoggerFactory.getLogger(null).info(current_path() + " on " + id);
      boolean success = stream.play("mp3:" + current_path(), 0, -1, true);
      pop_error = false;
      last_action = "play " + current_path();
      if (!success) {
        last_action = "failed play " + current_path();
        schedule_play_next_track();
      }

    } catch (Callback404Exception e) {
      last_action = "remove show";
      Shows.remove_show(app.getName(), id);
      return;
    } catch (IOException e) { // streamer offline?
      WMSLoggerFactory.getLogger(null)
          .error("streamer unreachable (IOException in get_url) in " + id);
      WMSLoggerFactory.getLogger(null).error("asdf", e);
      pop_error = true;
      wait(500);
      schedule_play_next_track();
    } catch (Exception e) {
      WMSLoggerFactory.getLogger(null).error("Unexpected exception in " + id, e);
      pop_error = true;
      wait(500);
      schedule_play_next_track();
    }
  }
  @Override
  public void onHTTPRequest(IVHost vhost, IHTTPRequest req, IHTTPResponse resp) {
    int clientId;
    HashMap<String, HashMap<String, String>> returnMap =
        new HashMap<String, HashMap<String, String>>();
    HashMap<String, String> returnKeyValues = new HashMap<String, String>();
    String strClientId;

    if (!doHTTPAuthentication(vhost, req, resp) || req.getMethod().equalsIgnoreCase("get")) return;

    req.parseBodyForParams();
    strClientId = req.getParameter("clientId");
    returnKeyValues.put("type", null);
    returnKeyValues.put("msg", "Request unsuccessful");
    returnKeyValues.put("isPublic", "true");
    returnMap.put("error", returnKeyValues);

    if (strClientId != null) {
      WMSLoggerFactory.getLogger(null)
          .info("*** Attempting to stop stream with clientId " + strClientId);
      try {
        clientId = Integer.parseInt(strClientId);
        IClient client = vhost.getClient(clientId);
        if (client != null) {
          client.setShutdownClient(true);
          returnMap.remove("error");
          returnKeyValues.remove("type");
          returnKeyValues.remove("msg");
          returnKeyValues.remove("isPublic");
          returnKeyValues.put("result", "Id " + clientId + " killed");
          returnMap.put("success", returnKeyValues);
        }
      } catch (NumberFormatException e) {
        WMSLoggerFactory.getLogger(null).error("******* NaN: " + strClientId);
        returnKeyValues.put("type", "NumberFormatException");
        returnKeyValues.put("msg", "NaN: " + strClientId);
        returnKeyValues.put("isPublic", "true");
        returnMap.put("error", returnKeyValues);
      }
    }

    JSONSerializer serializer = new JSONSerializer().exclude("*.class");
    String returnJSONStr = serializer.serialize(returnMap);

    try {
      resp.setHeader("Content-Type", "application/json");
      OutputStream out = resp.getOutputStream();
      byte[] outBytes = returnJSONStr.getBytes();
      out.write(outBytes);
    } catch (Exception e) {
      WMSLoggerFactory.getLogger(null).error("*** HTTPProvider failed: " + e.toString());
    }
  }
  /**
   * Get the body of the given url.
   *
   * @param url
   * @return
   * @throws IOException when the connection fails or dies
   * @throws Callback404Exception when 404 is returned by the other side.
   */
  public String get_url(String url) throws IOException, Callback404Exception {
    URL u = new URL(url);
    HttpURLConnection uc = (HttpURLConnection) u.openConnection();
    uc.setConnectTimeout(5000);
    uc.setReadTimeout(5000);
    WMSLoggerFactory.getLogger(null).debug("get url: >" + url + "<");

    if (uc.getResponseCode() == 404) {
      WMSLoggerFactory.getLogger(null).info("404 returned");
      throw new Callback404Exception(id);
    }

    return slurp(uc.getInputStream());
  }
 /** Delete the file we're currently playing if delete_after_play == true */
 private void maybe_delete_current_track() {
   try {
     if (current_track.getBoolean("delete_after_play?")) {
       boolean b = new File(current_absolute_path()).delete();
       last_action += " -> delete";
       if (!b) WMSLoggerFactory.getLogger(null).error("Delete file returned false " + id);
       else WMSLoggerFactory.getLogger(null).info("Deleted file " + current_absolute_path());
     }
   } catch (JSONException e) {
     WMSLoggerFactory.getLogger(null).error("Json exception " + id, e);
     /* delete_after_play not found, so we don't delete.
     if current_track was the reason for the fail, the track would not have been played. */
   } catch (Exception e) {
     /* Just making sure streams don't die by unknown errors */
     WMSLoggerFactory.getLogger(null).error("Unexpected exception in " + id, e);
   }
 }
 public StatisticLoggingStreamListenerTest()
     throws FileNotFoundException, IOException, SQLException {
   super();
   this.logger = WMSLoggerFactory.getLogger(this.getClass());
   try {
     Class.forName("org.hsqldb.jdbcDriver");
   } catch (Exception e) {
     System.out.println("ERROR: failed to load HSQLDB JDBC driver.");
     e.printStackTrace();
     return;
   }
   this.connection = DriverManager.getConnection("jdbc:hsqldb:mem:streamingstats");
   StreamingEventLogger.createInstanceForTestPurpose(logger, connection, true);
   this.streamingEventLogger = StreamingEventLogger.getInstance();
 }
 public TicketChecker(String presentationType, TicketToolInterface ticketTool) {
   super();
   this.presentationType = presentationType;
   this.logger = WMSLoggerFactory.getLogger(this.getClass());
   this.ticketTool = ticketTool;
 }
public class Show implements IStreamActionNotify {
  private static final WMSLogger logger = WMSLoggerFactory.getLogger(Show.class);
  private Stream stream = null;
  private String pop_url = null;
  private String id = null;
  private IApplication app = null;
  /**
   * there might still be callbacks scheduled after closing the stream We can check this var to stop
   * the loop.
   */
  private boolean closed = false;

  public boolean pop_error = false;
  public String last_action = "";
  private JSONObject current_track = null;
  private static ThreadPool pop_track_thread_pool = null;

  /**
   * Create underlying stream and queue the first play_next_track.
   *
   * @param id Name of the stream.
   * @param pop_url The url to request the next track from.
   */
  Show(IApplication app, String id, String pop_url) {
    stream = Stream.createInstance(app.getVHost(), app.getName(), id);
    stream.setRepeat(false);
    stream.addListener(this);
    this.pop_url = pop_url;
    this.id = id;
    this.app = app;
    schedule_play_next_track();
  }

  /* Schedule play_next_track in the threadpool of the server,
   * so it won't block the thread on errors or on creation.
   */
  private void schedule_play_next_track() {
    if (closed) return;

    pop_track_thread_pool.execute(
        new Runnable() {
          @Override
          public void run() {
            play_next_track();
          }
        });
  }

  /**
   * Request the next track from the trackmanager and play it. When a 404 is returned, delete this
   * show. On any other error: log it and try again in 0.5s.
   */
  private void play_next_track() {
    try {
      last_action = "get next track";
      current_track = new JSONObject(get_url(pop_url));
      WMSLoggerFactory.getLogger(null).info(current_path() + " on " + id);
      boolean success = stream.play("mp3:" + current_path(), 0, -1, true);
      pop_error = false;
      last_action = "play " + current_path();
      if (!success) {
        last_action = "failed play " + current_path();
        schedule_play_next_track();
      }

    } catch (Callback404Exception e) {
      last_action = "remove show";
      Shows.remove_show(app.getName(), id);
      return;
    } catch (IOException e) { // streamer offline?
      WMSLoggerFactory.getLogger(null)
          .error("streamer unreachable (IOException in get_url) in " + id);
      WMSLoggerFactory.getLogger(null).error("asdf", e);
      pop_error = true;
      wait(500);
      schedule_play_next_track();
    } catch (Exception e) {
      WMSLoggerFactory.getLogger(null).error("Unexpected exception in " + id, e);
      pop_error = true;
      wait(500);
      schedule_play_next_track();
    }
  }

  /** Delete the file we're currently playing if delete_after_play == true */
  private void maybe_delete_current_track() {
    try {
      if (current_track.getBoolean("delete_after_play?")) {
        boolean b = new File(current_absolute_path()).delete();
        last_action += " -> delete";
        if (!b) WMSLoggerFactory.getLogger(null).error("Delete file returned false " + id);
        else WMSLoggerFactory.getLogger(null).info("Deleted file " + current_absolute_path());
      }
    } catch (JSONException e) {
      WMSLoggerFactory.getLogger(null).error("Json exception " + id, e);
      /* delete_after_play not found, so we don't delete.
      if current_track was the reason for the fail, the track would not have been played. */
    } catch (Exception e) {
      /* Just making sure streams don't die by unknown errors */
      WMSLoggerFactory.getLogger(null).error("Unexpected exception in " + id, e);
    }
  }

  private String current_absolute_path() throws JSONException {
    return this.app.getAppInstance("_definst_").getStreamStoragePath() + '/' + current_path();
  }

  private String current_path() throws JSONException {
    return "" + current_track.getString("bucket") + '/' + current_track.getString("filename");
  }

  /**
   * Thread.sleep, but just returns when InterruptedException is thrown.
   *
   * @param ms
   */
  private static void wait(int ms) {
    try {
      Thread.sleep(ms);
    } catch (InterruptedException e1) {
    }
  }

  //	private String s3bucket() {
  //		return Server.getInstance().getProperties().getPropertyStr("s3bucket");
  //	}

  public void onPlaylistItemStop(Stream stream, PlaylistItem item) {
    WMSLoggerFactory.getLogger(null)
        .info("Track finished: " + item.getName() + "on Stream: " + stream.getName());
    maybe_delete_current_track();
    play_next_track();
  }

  public void onPlaylistItemStart(Stream stream, PlaylistItem item) {
    WMSLoggerFactory.getLogger(null)
        .info("Item Started: " + item.getName() + "on Stream: " + stream.getName());
    send_stream_title();
  }

  private void send_stream_title() {
    AMFDataMixedArray data = new AMFDataMixedArray();
    try {
      String stream_title = current_track.getString("stream_title");
      byte[] title2 = stream_title.getBytes(java.nio.charset.Charset.defaultCharset().name());
      data.put("StreamTitle", new AMFDataItem(new String(title2, "UTF-8")));
      stream.getPublisher().getStream().send("onMetaData", data);
    } catch (java.io.UnsupportedEncodingException e) {
    } catch (JSONException e) {
    }
  }

  /**
   * Get the body of the given url.
   *
   * @param url
   * @return
   * @throws IOException when the connection fails or dies
   * @throws Callback404Exception when 404 is returned by the other side.
   */
  public String get_url(String url) throws IOException, Callback404Exception {
    URL u = new URL(url);
    HttpURLConnection uc = (HttpURLConnection) u.openConnection();
    uc.setConnectTimeout(5000);
    uc.setReadTimeout(5000);
    WMSLoggerFactory.getLogger(null).debug("get url: >" + url + "<");

    if (uc.getResponseCode() == 404) {
      WMSLoggerFactory.getLogger(null).info("404 returned");
      throw new Callback404Exception(id);
    }

    return slurp(uc.getInputStream());
  }

  private String slurp(java.io.InputStream istream) throws IOException {
    String ret = "";
    BufferedReader in = new BufferedReader(new InputStreamReader(istream));
    String inputLine;

    while ((inputLine = in.readLine()) != null) ret += inputLine;
    in.close();
    return ret;
  }

  public class Callback404Exception extends java.lang.Exception {
    private static final long serialVersionUID = 1L;

    Callback404Exception(String msg) {
      super(msg);
    }
  }

  public void close() {
    closed = true;
    stream.removeListener(this);
    stream.getPublisher().unpublish();
    stream.close();

    stream = null;
    app = null;
  }

  {
    pop_track_thread_pool = new ThreadPool(null, "pop_retry");
    pop_track_thread_pool.init(5);
  }
}
 public void onPlaylistItemStart(Stream stream, PlaylistItem item) {
   WMSLoggerFactory.getLogger(null)
       .info("Item Started: " + item.getName() + "on Stream: " + stream.getName());
   send_stream_title();
 }
 public void onPlaylistItemStop(Stream stream, PlaylistItem item) {
   WMSLoggerFactory.getLogger(null)
       .info("Track finished: " + item.getName() + "on Stream: " + stream.getName());
   maybe_delete_current_track();
   play_next_track();
 }