/**
   * To make life easier for the user we will figure out the type of {@link StreamListener} the user
   * passed and based on that setup the correct stream analyzer etc.
   *
   * <p>{@inheritDoc}
   */
  @SuppressWarnings("unchecked")
  @Override
  public void addStreamListener(final StreamListener<? extends Packet> listener) {

    try {
      final Method method = listener.getClass().getMethod("endStream", Stream.class);
      final ParameterizedType parameterizedType =
          (ParameterizedType) method.getGenericParameterTypes()[0];
      final Type[] parameterArgTypes = parameterizedType.getActualTypeArguments();

      // TODO: could actually be more.
      final Type parameterArgType = parameterArgTypes[0];
      final Class<?> parameterArgClass = (Class<?>) parameterArgType;
      if (parameterArgClass.equals(SipPacket.class)) {
        if (this.sipStreamHandler == null) {
          this.sipStreamHandler = new SipStreamHandler(this.framerManager);
        }
        this.sipStreamHandler.addListener((StreamListener<SipPacket>) listener);
      }

    } catch (final ArrayIndexOutOfBoundsException e) {
      throw new RuntimeException("Unable to figure out the paramterized type", e);
    } catch (final SecurityException e) {
      throw new RuntimeException(
          "Unable to access method information due to security constraints", e);
    } catch (final NoSuchMethodException e) {
      throw new RuntimeException("The startStream method doesn't exist. Signature changed?", e);
    } catch (final ClassCastException e) {
      // means that the user had not parameterized the StreamListener
      // interface, which means that we cannot actually detect streams.
      throw new IllegalArgumentException("The supplied listener has not been parameterized");
    }
  }