private ServiceRegistration register()

in src/main/java/org/apache/sling/servlets/resolver/internal/bundle/BundledScriptTracker.java [378:490]


    private ServiceRegistration<Servlet> register(
            BundleContext context, Servlet servlet, Hashtable<String, Object> properties) { // NOSONAR
        if (mounter.mountProviders()) {
            return context.registerService(Servlet.class, servlet, properties);
        } else {
            final Long id = idCounter.getAndIncrement();
            properties.put(Constants.SERVICE_ID, id);
            properties.put(BundledHooks.class.getName(), "true");
            @SuppressWarnings("unchecked")
            final ServiceReference<Servlet> reference = (ServiceReference<Servlet>) Proxy.newProxyInstance(
                    getClass().getClassLoader(), new Class[] {ServiceReference.class}, new InvocationHandler() {
                        @Override
                        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                            if (method.equals(ServiceReference.class.getMethod("getProperty", String.class))) {
                                return properties.get(args[0]);
                            } else if (method.equals(ServiceReference.class.getMethod("getPropertyKeys"))) {
                                return properties.keySet().toArray(new String[0]);
                            } else if (method.equals(ServiceReference.class.getMethod("getBundle"))) {
                                return context.getBundle();
                            } else if (method.equals(ServiceReference.class.getMethod("getUsingBundles"))) {
                                BundleContext bc = bundleContext.get();
                                if (bc != null) {
                                    return new Bundle[] {bc.getBundle()};
                                } else {
                                    return new Bundle[0];
                                }
                            } else if (method.equals(
                                    ServiceReference.class.getMethod("isAssignableTo", Bundle.class, String.class))) {
                                return Servlet.class.getName().equals(args[1]);
                            } else if (method.equals(ServiceReference.class.getMethod("compareTo", Object.class))) {
                                return compareTo(args[0]);
                            } else if (method.getName().equals("equals")
                                    && Arrays.equals(method.getParameterTypes(), new Class[] {Object.class})) {
                                return args[0] instanceof ServiceReference && compareTo(args[0]) == 0;
                            } else if (method.getName().equals("hashCode") && method.getParameterCount() == 0) {
                                return id.intValue();
                            } else if (method.getName().equals("toString")) {
                                return "Internal reference: " + id.toString();
                            } else {
                                throw new UnsupportedOperationException(method.toGenericString());
                            }
                        }

                        private int compareTo(Object arg) {
                            ServiceReference<?> other = (ServiceReference<?>) arg;
                            Long id;
                            if ("true".equals(other.getProperty(BundledHooks.class.getName()))) {
                                id = (Long) properties.get(Constants.SERVICE_ID);
                            } else {
                                id = -1L;
                            }

                            Long otherId = (Long) other.getProperty(Constants.SERVICE_ID);

                            if (id.equals(otherId)) {
                                return 0; // same service
                            }

                            Object rankObj = properties.get(Constants.SERVICE_RANKING);
                            Object otherRankObj = other.getProperty(Constants.SERVICE_RANKING);

                            // If no rank, then spec says it defaults to zero.
                            rankObj = (rankObj == null) ? Integer.valueOf(0) : rankObj;
                            otherRankObj = (otherRankObj == null) ? Integer.valueOf(0) : otherRankObj;

                            // If rank is not Integer, then spec says it defaults to zero.
                            Integer rank = (rankObj instanceof Integer) ? (Integer) rankObj : Integer.valueOf(0);
                            Integer otherRank =
                                    (otherRankObj instanceof Integer) ? (Integer) otherRankObj : Integer.valueOf(0);

                            // Sort by rank in ascending order.
                            if (rank.compareTo(otherRank) < 0) {
                                return -1; // lower rank
                            } else if (rank.compareTo(otherRank) > 0) {
                                return 1; // higher rank
                            }

                            // If ranks are equal, then sort by service id in descending order.
                            return (id.compareTo(otherId) < 0) ? 1 : -1;
                        }
                    });

            mounter.bindJakartaServlet(servlet, reference);

            @SuppressWarnings("unchecked")
            ServiceRegistration<Servlet> newProxyInstance = (ServiceRegistration<Servlet>) Proxy.newProxyInstance(
                    getClass().getClassLoader(), new Class[] {ServiceRegistration.class}, new InvocationHandler() {
                        @Override
                        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                            if (method.equals(ServiceRegistration.class.getMethod("getReference"))) {
                                return reference;
                            } else if (method.equals(
                                    ServiceRegistration.class.getMethod("setProperties", Dictionary.class))) {
                                return null;
                            } else if (method.equals(ServiceRegistration.class.getMethod("unregister"))) {
                                mounter.unbindJakartaServlet(reference);
                                return null;
                            } else if (method.getName().equals("equals")
                                    && Arrays.equals(method.getParameterTypes(), new Class[] {Object.class})) {
                                return args[0] instanceof ServiceRegistration
                                        && reference.compareTo(((ServiceRegistration<?>) args[0]).getReference()) == 0;
                            } else if (method.getName().equals("hashCode") && method.getParameterCount() == 0) {
                                return id.intValue();
                            } else if (method.getName().equals("toString")) {
                                return "Internal registration: " + id;
                            } else {
                                throw new UnsupportedOperationException(method.toGenericString());
                            }
                        }
                    });
            return newProxyInstance;
        }
    }