private ServiceRegistration register()

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


    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.bindServlet(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.unbindServlet(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;
        }
    }