@Override
  public <ET extends Event> void push(ET event) {
    List<Subscriber<ET>> subscribers;

    synchronized (registeredSubscribers) {
      if (!registeredSubscribers.containsKey(event.getClass())) return;

      // Inspection disabled because all inserts in to registeredSubscribers are type insured
      // due to type erasure, we can not have per-pair types.
      // noinspection unchecked
      subscribers =
          (List<Subscriber<ET>>) new ArrayList(registeredSubscribers.get(event.getClass()));
    }

    for (Subscriber<ET> subscriber : subscribers) {
      boolean txDeterminate = true;
      for (ListenerFilter filter : subscriber.getFilters()) {
        // This can only occur if someone f***s something up in an annotation, as listeners should
        // be typesafe when passed to subscribers
        // noinspection unchecked
        txDeterminate = txDeterminate && filter.shouldSend(event);
      }

      if (txDeterminate) subscriber.eventReceived(event);
    }
  }
  @Override
  public Subscriber<? super Observable<? extends T>> call(Subscriber<? super T> child) {
    final SerializedSubscriber<T> s = new SerializedSubscriber<T>(child);
    final CompositeSubscription csub = new CompositeSubscription();
    child.add(csub);

    SourceSubscriber<T> ssub = new SourceSubscriber<T>(maxConcurrency, s, csub);
    child.setProducer(new MergeMaxConcurrentProducer<T>(ssub));

    return ssub;
  }
  @Override
  public void onNext(T t) {
    synchronized (this) {
      if (emitting) {
        List<T> q = queue;
        if (q == null) {
          q = new ArrayList<T>(4);
          queue = q;
        }
        q.add(t);
        return;
      }
    }
    boolean skipFinal = false;
    try {
      child.onNext(t);

      long r = requested;
      if (r != Long.MAX_VALUE) {
        requested = r - 1;
      }

      emitLoop();
      skipFinal = true;
    } finally {
      if (!skipFinal) {
        synchronized (this) {
          emitting = false;
        }
      }
    }
  }
    @Override
    public void subscribe(final Subscriber<? super String> observer) {
      observer.onSubscribe(EmptySubscription.INSTANCE);
      t =
          new Thread(
              new Runnable() {

                @Override
                public void run() {
                  for (String s : valuesToReturn) {
                    if (s == null) {
                      System.out.println("throwing exception");
                      try {
                        Thread.sleep(100);
                      } catch (Throwable e) {

                      }
                      observer.onError(new NullPointerException());
                      return;
                    } else {
                      observer.onNext(s);
                    }
                  }
                  System.out.println("subscription complete");
                  observer.onComplete();
                }
              });
      t.start();
    }
 @Override
 public void subscribe(Subscriber<? super String> observer) {
   observer.onSubscribe(EmptySubscription.INSTANCE);
   boolean errorThrown = false;
   for (String s : valuesToReturn) {
     if (s == null) {
       System.out.println("throwing exception");
       observer.onError(new NullPointerException());
       errorThrown = true;
       // purposefully not returning here so it will continue calling onNext
       // so that we also test that we handle bad sequences like this
     } else {
       observer.onNext(s);
     }
   }
   if (!errorThrown) {
     observer.onComplete();
   }
 }
 @Override
 public void onCompleted() {
   synchronized (this) {
     if (emitting) {
       missedTerminal = true;
       return;
     }
     emitting = true;
   }
   child.onCompleted();
 }
  @Test
  public void testRequestFromChainedOperator() {
    TestSubscriber<String> s = new TestSubscriber<>();
    Operator<String, String> o =
        s1 ->
            new Subscriber<String>() {

              @Override
              public void onSubscribe(Subscription a) {
                s1.onSubscribe(a);
              }

              @Override
              public void onComplete() {}

              @Override
              public void onError(Throwable e) {}

              @Override
              public void onNext(String t) {}
            };
    s.request(10);
    Subscriber<? super String> ns = o.apply(s);

    final AtomicLong r = new AtomicLong();
    // set set the producer at the top of the chain (ns) and it should flow through the operator to
    // the (s) subscriber
    // and then it should request up with the value set on the final Subscriber (s)
    ns.onSubscribe(
        new Subscription() {

          @Override
          public void request(long n) {
            r.set(n);
          }

          @Override
          public void cancel() {}
        });
    assertEquals(10, r.get());
  }
    @Override
    public void subscribe(final Subscriber<? super String> observer) {
      observer.onSubscribe(EmptySubscription.INSTANCE);
      t =
          new Thread(
              new Runnable() {

                @Override
                public void run() {
                  observer.onNext("hello");
                  observer.onComplete();
                }
              });
      t.start();
    }
    void fastPath() {
      final Iterator<? extends T> a = iterator;
      final Subscriber<? super T> s = actual;

      for (; ; ) {

        if (cancelled) {
          return;
        }

        T t;

        try {
          t = a.next();
        } catch (Exception ex) {
          s.onError(ex);
          return;
        }

        if (cancelled) {
          return;
        }

        if (t == null) {
          s.onError(new NullPointerException("The iterator returned a null value"));
          return;
        }

        s.onNext(t);

        if (cancelled) {
          return;
        }

        boolean b;

        try {
          b = a.hasNext();
        } catch (Exception ex) {
          s.onError(ex);
          return;
        }

        if (cancelled) {
          return;
        }

        if (!b) {
          s.onComplete();
          return;
        }
      }
    }
 @Override
 public void onError(Throwable e) {
   boolean emit;
   synchronized (this) {
     if (emitting) {
       missedTerminal = e;
       emit = false;
     } else {
       emitting = true;
       emit = true;
     }
   }
   if (emit) {
     child.onError(e);
   } else {
     hasError = true;
   }
 }
    @Override
    public void subscribe(final Subscriber<? super String> observer) {
      observer.onSubscribe(EmptySubscription.INSTANCE);
      t =
          new Thread(
              new Runnable() {

                @Override
                public void run() {
                  try {
                    Thread.sleep(100);
                  } catch (InterruptedException e) {
                    observer.onError(e);
                  }
                  observer.onNext("hello");
                  observer.onComplete();
                }
              });
      t.start();
    }
    @Override
    public void onError(Throwable e) {
      Object[] active;
      synchronized (subscribers) {
        active = subscribers.toArray();
        subscribers.clear();
      }

      try {
        s.onError(e);

        unsubscribe();
      } finally {
        for (Object o : active) {
          @SuppressWarnings("unchecked")
          MergeItemSubscriber a = (MergeItemSubscriber) o;
          a.release();
        }
      }
    }
  /**
   * Common method to take an Iterator as a source of values.
   *
   * @param s
   * @param it
   */
  static <T> void subscribe(Subscriber<? super T> s, Iterator<? extends T> it) {
    if (it == null) {
      EmptySubscription.error(s, new NullPointerException("The iterator is null"));
      return;
    }

    boolean b;

    try {
      b = it.hasNext();
    } catch (Throwable e) {
      EmptySubscription.error(s, e);
      return;
    }
    if (!b) {
      EmptySubscription.complete(s);
      return;
    }

    s.onSubscribe(new PublisherIterableSubscription<>(s, it));
  }
    void slowPath(long n) {
      final Iterator<? extends T> a = iterator;
      final Subscriber<? super T> s = actual;

      long e = 0L;

      for (; ; ) {

        while (e != n) {
          T t;

          try {
            t = a.next();
          } catch (Throwable ex) {
            s.onError(ex);
            return;
          }

          if (cancelled) {
            return;
          }

          if (t == null) {
            s.onError(new NullPointerException("The iterator returned a null value"));
            return;
          }

          s.onNext(t);

          if (cancelled) {
            return;
          }

          boolean b;

          try {
            b = a.hasNext();
          } catch (Throwable ex) {
            s.onError(ex);
            return;
          }

          if (cancelled) {
            return;
          }

          if (!b) {
            s.onComplete();
            return;
          }

          e++;
        }

        n = requested;

        if (n == e) {
          n = REQUESTED.addAndGet(this, -e);
          if (n == 0L) {
            return;
          }
          e = 0L;
        }
      }
    }
Exemple #15
0
 public void publish(String message) {
   for (Subscriber subscriber : subscribers) {
     subscriber.receive(message);
   }
 }
 @Override
 public void subscribe(Subscriber<? super String> observer) {
   observer.onSubscribe(EmptySubscription.INSTANCE);
   observer.onNext("hello");
   observer.onComplete();
 }
  @Test
  public void testRequestFromDecoupledOperatorThatRequestsN() {
    TestSubscriber<String> s = new TestSubscriber<>();
    final AtomicLong innerR = new AtomicLong();
    Operator<String, String> o =
        child -> {
          // we want to decouple the chain so set our own Producer on the child instead of it coming
          // from the parent
          child.onSubscribe(
              new Subscription() {

                @Override
                public void request(long n) {
                  innerR.set(n);
                }

                @Override
                public void cancel() {}
              });

          AsyncObserver<String> as =
              new AsyncObserver<String>() {

                @Override
                protected void onStart() {
                  // we request 99 up to the parent
                  request(99);
                }

                @Override
                public void onComplete() {}

                @Override
                public void onError(Throwable e) {}

                @Override
                public void onNext(String t) {}
              };
          return as;
        };
    s.request(10);
    Subscriber<? super String> ns = o.apply(s);

    final AtomicLong r = new AtomicLong();
    // set set the producer at the top of the chain (ns) and it should flow through the operator to
    // the (s) subscriber
    // and then it should request up with the value set on the final Subscriber (s)
    ns.onSubscribe(
        new Subscription() {

          @Override
          public void request(long n) {
            r.set(n);
          }

          @Override
          public void cancel() {}
        });
    assertEquals(99, r.get());
    assertEquals(10, innerR.get());
  }
  void emitLoop() {
    final Subscriber<? super T> c = child;

    outer:
    for (; ; ) {
      long localRequested;
      Producer localProducer;
      Object localTerminal;
      List<T> q;
      synchronized (this) {
        localRequested = missedRequested;
        localProducer = missedProducer;
        localTerminal = missedTerminal;
        q = queue;
        if (localRequested == 0L && localProducer == null && q == null && localTerminal == null) {
          emitting = false;
          return;
        }
        missedRequested = 0L;
        missedProducer = null;
        queue = null;
        missedTerminal = null;
      }
      boolean empty = q == null || q.isEmpty();
      if (localTerminal != null) {
        if (localTerminal != Boolean.TRUE) {
          c.onError((Throwable) localTerminal);
          return;
        } else if (empty) {
          c.onCompleted();
          return;
        }
      }
      long e = 0;
      if (q != null) {
        for (T v : q) {
          if (c.isUnsubscribed()) {
            return;
          } else if (hasError) {
            continue outer; // if an error has been set, shortcut the loop and act on it
          }
          try {
            c.onNext(v);
          } catch (Throwable ex) {
            Exceptions.throwOrReport(ex, c, v);
            return;
          }
        }
        e += q.size();
      }
      long r = requested;
      // if requested is max, we don't do any accounting
      if (r != Long.MAX_VALUE) {
        // if there were missing requested, add it up
        if (localRequested != 0L) {
          long u = r + localRequested;
          if (u < 0) {
            u = Long.MAX_VALUE;
          }
          r = u;
        }
        // if there were emissions and we don't run on max since the last check, subtract
        if (e != 0L && r != Long.MAX_VALUE) {
          long u = r - e;
          if (u < 0) {
            throw new IllegalStateException("More produced than requested");
          }
          r = u;
        }
        requested = r;
      }
      if (localProducer != null) {
        if (localProducer == NULL_PRODUCER) {
          currentProducer = null;
        } else {
          currentProducer = localProducer;
          if (r != 0L) {
            localProducer.request(r);
          }
        }
      } else {
        Producer p = currentProducer;
        if (p != null && localRequested != 0L) {
          p.request(localRequested);
        }
      }
    }
  }
    protected void drain() {
      synchronized (this) {
        if (emitting) {
          missedEmitting++;
          return;
        }
        emitting = true;
        missedEmitting = 0;
      }
      final List<SourceSubscriber<T>.MergeItemSubscriber> subs = subscribers;
      final Subscriber<T> child = s;
      Object[] active = new Object[subs.size()];
      do {
        long r;

        outer:
        while ((r = requested) > 0) {
          int idx = lastIndex;
          synchronized (subs) {
            if (subs.size() == active.length) {
              active = subs.toArray(active);
            } else {
              active = subs.toArray();
            }
          }

          int resumeIndex = 0;
          int j = 0;
          for (Object o : active) {
            @SuppressWarnings("unchecked")
            MergeItemSubscriber e = (MergeItemSubscriber) o;
            if (e.index == idx) {
              resumeIndex = j;
              break;
            }
            j++;
          }
          int sumConsumed = 0;
          for (int i = 0; i < active.length; i++) {
            j = (i + resumeIndex) % active.length;

            @SuppressWarnings("unchecked")
            final MergeItemSubscriber e = (MergeItemSubscriber) active[j];
            final RxRingBuffer b = e.buffer;
            lastIndex = e.index;

            if (!e.once && b.peek() == null) {
              subs.remove(e);

              synchronized (guard) {
                this.active--;
              }
              csub.remove(e);

              e.release();

              subscribeNext();

              WIP.decrementAndGet(this);

              continue outer;
            }

            int consumed = 0;
            Object v;
            while (r > 0 && (v = b.poll()) != null) {
              nl.accept(child, v);
              if (child.isUnsubscribed()) {
                return;
              }
              r--;
              consumed++;
            }
            if (consumed > 0) {
              sumConsumed += consumed;
              REQUESTED.addAndGet(this, -consumed);
              e.requestMore(consumed);
            }
            if (r == 0) {
              break outer;
            }
          }
          if (sumConsumed == 0) {
            break;
          }
        }

        if (active.length == 0) {
          if (wip == 0) {
            child.onCompleted();
            return;
          }
        }
        synchronized (this) {
          if (missedEmitting == 0) {
            emitting = false;
            break;
          }
          missedEmitting = 0;
        }
      } while (true);
    }
  public void processSubscribe(Request request, ServerTransaction serverTransaction) {
    logger.debug("Processing SUBSCRIBE in progress ");
    try {

      MessageFactory messageFactory = imUA.getMessageFactory();
      HeaderFactory headerFactory = imUA.getHeaderFactory();
      AddressFactory addressFactory = imUA.getAddressFactory();
      Dialog dialog = serverTransaction.getDialog();

      // ********** Terminating subscriptions **********
      ExpiresHeader expiresHeader = (ExpiresHeader) request.getHeader(ExpiresHeader.NAME);
      if (expiresHeader != null && expiresHeader.getExpires() == 0) {
        if (dialog != null) {
          // Terminating an existing subscription
          Response response = messageFactory.createResponse(Response.OK, request);
          serverTransaction.sendResponse(response);
          IMNotifyProcessing imNotifyProcessing = imUA.getIMNotifyProcessing();
          imNotifyProcessing.sendNotify(response, null, dialog);
          return;
        } else {
          // Terminating an non existing subscription
          Response response =
              messageFactory.createResponse(Response.CALL_OR_TRANSACTION_DOES_NOT_EXIST, request);
          serverTransaction.sendResponse(response);
          return;
        }
      }

      // ********** Non-terminating subscriptions ************

      // send a 202 Accepted while waiting for authorization from user
      Response response = messageFactory.createResponse(Response.ACCEPTED, request);
      // Tag:
      ToHeader toHeader = (ToHeader) response.getHeader(ToHeader.NAME);
      if (toHeader.getTag() == null)
        toHeader.setTag(new Integer((int) (Math.random() * 10000)).toString());
      serverTransaction.sendResponse(response);
      logger.debug(response.toString());

      // We have to ask the user to authorize the guy to be in his buddy
      // list
      String presentityURL = IMUtilities.getKey(request, "From");
      SipProvider sipProvider = imUA.getSipProvider();
      InstantMessagingGUI imGUI = imUA.getInstantMessagingGUI();
      boolean authorization = imGUI.getAuthorizationForBuddy(presentityURL);
      if (authorization) {
        logger.debug(
            "DEBUG: SubscribeProcessing, processSubscribe(), " + " Response 202 Accepted sent.");

        // We have to create or update the subscriber!
        PresenceManager presenceManager = imUA.getPresenceManager();
        String subscriberURL = IMUtilities.getKey(request, "From");

        if (dialog != null) presenceManager.addSubscriber(subscriberURL, response, dialog);
        else {
          logger.debug(
              "ERROR, IMSubscribeProcessing, processSubscribe(), the"
                  + " dialog for the SUBSCRIBE we received is null!!! No subscriber added....");
          return;
        }

        // Let's see if this buddy is in our buddy list
        // if not let's ask to add him!
        BuddyList buddyList = imGUI.getBuddyList();
        ListenerInstantMessaging listenerIM = imGUI.getListenerInstantMessaging();
        if (!buddyList.hasBuddy(subscriberURL)) {
          // Let's ask:
          listenerIM.addContact(subscriberURL);
        }

        /** ********************** send NOTIFY ************************* */
        // We send a NOTIFY for any of our status but offline
        String localStatus = listenerIM.getLocalStatus();
        if (!localStatus.equals("offline")) {
          IMNotifyProcessing imNotifyProcessing = imUA.getIMNotifyProcessing();
          Subscriber subscriber = presenceManager.getSubscriber(subscriberURL);
          // Response okSent=subscriber.getOkSent();

          subscriberURL = subscriber.getSubscriberName();

          String contactAddress = imUA.getIMAddress() + ":" + imUA.getIMPort();

          String subStatus = listenerIM.getLocalStatus();
          String status = null;
          if (subStatus.equals("offline")) status = "closed";
          else status = "open";
          String xmlBody =
              imNotifyProcessing.xmlPidfParser.createXMLBody(
                  status, subStatus, subscriberURL, contactAddress);
          imNotifyProcessing.sendNotify(response, xmlBody, dialog);
        }
      } else {
        // User did not authorize subscription. Terminate it!
        logger.debug(
            "DEBUG, IMSubsribeProcessing, processSubscribe(), " + " Subscription declined!");
        logger.debug(
            "DEBUG, IMSubsribeProcessing, processSubscribe(), "
                + " Sending a Notify with Subscribe-state=terminated");

        IMNotifyProcessing imNotifyProcessing = imUA.getIMNotifyProcessing();
        if (dialog != null) {
          imNotifyProcessing.sendNotify(response, null, dialog);
          logger.debug(
              "DEBUG, IMSubsribeProcessing, processSubscribe(), "
                  + " Sending a Notify with Subscribe-state=terminated");
        } else {
          logger.debug(
              "ERROR, IMSubscribeProcessing, processSubscribe(), the"
                  + " dialog for the SUBSCRIBE we received is null!!! \n"
                  + "   No terminating Notify sent");
        }
        imNotifyProcessing.sendNotify(response, null, dialog);
      }
    } catch (Exception ex) {
      ex.printStackTrace();
    }
  }