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;
}
}