amichair commented on code in PR #104:
URL: https://github.com/apache/aries-rsa/pull/104#discussion_r3214426579


##########
rsa/src/main/java/org/apache/aries/rsa/core/EventListenerBridge.java:
##########
@@ -0,0 +1,366 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.aries.rsa.core;
+
+import org.apache.aries.rsa.util.StringPlus;
+import org.osgi.framework.*;
+import org.osgi.framework.hooks.service.ListenerHook;
+import org.osgi.service.remoteserviceadmin.EndpointDescription;
+import org.osgi.service.remoteserviceadmin.EndpointEvent;
+import org.osgi.service.remoteserviceadmin.EndpointEventListener;
+import org.osgi.service.remoteserviceadmin.EndpointListener;
+
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.stream.Stream;
+
+/**
+ * This service acts as a bridge between those consumers/producers of endopint
+ * events that support only the deprecated {@link EndpointListener} interface 
and
+ * those that support only the newer {@link EndpointEventListener} interface.
+ * <p>
+ * According to the RSA specification, all actors must be backward-compatible
+ * with the old interface - they must listen to both and notify both, with the
+ * caveat that if a listener implements both interfaces, notifiers should only
+ * send it events using the newer API in order to prevent event duplication.
+ * <p>
+ * Components in the Aries RSA implementation now only support the newer
+ * interface natively, as inter-compatibility with components using the old
+ * interface are rarely needed. However, for spec compatibility, TCK 
(compliance)
+ * tests, and those rare occasions - this bridge fills in the gap when needed.
+ * <p>
+ * Consumer (listener) and producer (notifier) implementations may support
+ * either only the old interface, or only the new interface, or both.
+ * <p>
+ * If they support both, they can directly notify peers of all the three types,
+ * and, trivially, new-only or old-only components already work with equivalent
+ * peers. So the only cases that need to be bridged are a pair of new-only and
+ * old-only peers that need to communicate with each other. Handling any other
+ * case via the bridge could produce duplicate events and must be avoided.
+ * <p>
+ * The bridge is implemented using four mechanisms:
+ * <ol>
+ *     <li>A {@link ServiceListener} keeps track of all registered services
+ *         implementing {@code EndpointListener} (old consumers) and
+ *         {@code EndpointEventListener} (new consumers), and ignores those
+ *         that implement both.
+ *     </li>
+ *     <li>A {@link ListenerHook} keeps track of all registered
+ *         ServiceListeners (including ServiceTrackers) that are looking
+ *         for services implementing {@code EndpointListener} (old producers)
+ *         or {@code EndpointEventListener} (new producers).
+ *     </li>
+ *     <li>A registered service that implements both interfaces (our own
+ *         listener/consumer) that is backed by a {@link ServiceFactory}
+ *         that gives each calling bundle (producer bundle) its own
+ *         {@code Adapter} instance.
+ *     </li>
+ *     <li>
+ *         An {@link Adapter Adapter} service object (per bundle) that
+ *         implements both interfaces, and depending on the interface types
+ *         supported by the producer bundle associated with it, either does
+ *         nothing (if the producer supports both interfaces or neither
+ *         of them) or converts invocations of the one interface supported
+ *         by the producer into a notification sent to all consumers of the
+ *         opposite type (old producer to all new consumers or new producer
+ *         to all old consumers).
+ *     </li>
+ * </ol>
+ * <p>
+ * Note that due to the limitations of {@code ListenerHook}, the adapter
+ * conversion policy is determined per bundle and not per individual producer
+ * within the bundle. This works as long as the (reasonable) assumption is
+ * made that all producers within the same bundle implement the same
+ * interface version (or both of them).
+ */
+@SuppressWarnings("deprecation")

Review Comment:
   I tried to explain this in the JIRA, and now added a @deprecated tag with 
additional explanation. In a nutshell, The EndpointListener interface itself is 
deprecated in the spec (i.e. should not be used by new code and will likely be 
removed in future spec releases), and this bridge only exists for that, so is 
transitively also deprecated. Users should upgrade their libraries/code to the 
new interface, not rely on this for the old one to work in the future. It's 
basically a stop-gap measure for TCK compatibility.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to