package org.eclipse.osgi.internal.url;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.*;
import org.osgi.framework.*;
import org.osgi.service.url.URLConstants;
import org.osgi.service.url.URLStreamHandlerService;
import org.osgi.util.tracker.ServiceTracker;
import org.osgi.util.tracker.ServiceTrackerCustomizer;
public class URLStreamHandlerProxy extends URLStreamHandler implements ServiceTrackerCustomizer<URLStreamHandlerService, ServiceReference<URLStreamHandlerService>> {
protected URLStreamHandlerService realHandlerService;
protected URLStreamHandlerSetter urlSetter;
protected ServiceTracker<URLStreamHandlerService, ServiceReference<URLStreamHandlerService>> urlStreamHandlerServiceTracker;
protected BundleContext context;
protected ServiceReference<URLStreamHandlerService> urlStreamServiceReference;
protected String protocol;
protected int ranking = Integer.MIN_VALUE;
public URLStreamHandlerProxy(String protocol, ServiceReference<URLStreamHandlerService> reference, BundleContext context) {
this.context = context;
this.protocol = protocol;
urlSetter = new URLStreamHandlerSetter(this);
setNewHandler(reference, getRank(reference));
urlStreamHandlerServiceTracker = new ServiceTracker<>(context, URLStreamHandlerFactoryImpl.URLSTREAMHANDLERCLASS, this);
URLStreamHandlerFactoryImpl.secureAction.open(urlStreamHandlerServiceTracker);
}
private void setNewHandler(ServiceReference<URLStreamHandlerService> reference, int rank) {
if (urlStreamServiceReference != null)
context.ungetService(urlStreamServiceReference);
urlStreamServiceReference = reference;
ranking = rank;
if (reference == null)
realHandlerService = new NullURLStreamHandlerService();
else
realHandlerService = URLStreamHandlerFactoryImpl.secureAction.getService(reference, context);
}
@Override
protected boolean equals(URL url1, URL url2) {
return realHandlerService.equals(url1, url2);
}
@Override
protected int getDefaultPort() {
return realHandlerService.getDefaultPort();
}
@Override
protected InetAddress getHostAddress(URL url) {
return realHandlerService.getHostAddress(url);
}
@Override
protected int hashCode(URL url) {
return realHandlerService.hashCode(url);
}
@Override
protected boolean hostsEqual(URL url1, URL url2) {
return realHandlerService.hostsEqual(url1, url2);
}
@Override
protected URLConnection openConnection(URL url) throws IOException {
return realHandlerService.openConnection(url);
}
@Override
protected void parseURL(URL url, String str, int start, int end) {
realHandlerService.parseURL(urlSetter, url, str, start, end);
}
@Override
protected boolean sameFile(URL url1, URL url2) {
return realHandlerService.sameFile(url1, url2);
}
@Override
protected String toExternalForm(URL url) {
return realHandlerService.toExternalForm(url);
}
@Override
public void setURL(URL u, String protocol, String host, int port, String authority, String userInfo, String file, String query, String ref) {
super.setURL(u, protocol, host, port, authority, userInfo, file, query, ref);
}
@SuppressWarnings("deprecation")
@Override
public void setURL(URL url, String protocol, String host, int port, String file, String ref) {
super.setURL(url, protocol, host, port, null, null, file, null, ref);
}
@Override
public ServiceReference<URLStreamHandlerService> addingService(ServiceReference<URLStreamHandlerService> reference) {
Object prop = reference.getProperty(URLConstants.URL_HANDLER_PROTOCOL);
if (prop instanceof String) {
prop = new String[] {(String) prop};
}
if (!(prop instanceof String[])) {
return null;
}
String[] protocols = (String[]) prop;
for (String candidateProtocol : protocols) {
if (candidateProtocol.equals(protocol)) {
int newServiceRanking = getRank(reference);
if (newServiceRanking > ranking || urlStreamServiceReference == null)
setNewHandler(reference, newServiceRanking);
return reference;
}
}
return null;
}
@Override
public void modifiedService(ServiceReference<URLStreamHandlerService> reference, ServiceReference<URLStreamHandlerService> service) {
int newRank = getRank(reference);
if (reference == urlStreamServiceReference) {
if (newRank < ranking) {
ServiceReference<URLStreamHandlerService> newReference = urlStreamHandlerServiceTracker.getServiceReference();
if (newReference != urlStreamServiceReference && newReference != null) {
setNewHandler(newReference, ((Integer) newReference.getProperty(Constants.SERVICE_RANKING)).intValue());
}
}
} else if (newRank > ranking) {
setNewHandler(reference, newRank);
}
}
@Override
public void removedService(ServiceReference<URLStreamHandlerService> reference, ServiceReference<URLStreamHandlerService> service) {
if (reference != urlStreamServiceReference)
return;
ServiceReference<URLStreamHandlerService> newReference = urlStreamHandlerServiceTracker.getServiceReference();
setNewHandler(newReference, getRank(newReference));
}
private int getRank(ServiceReference<?> reference) {
if (reference == null)
return Integer.MIN_VALUE;
Object property = reference.getProperty(Constants.SERVICE_RANKING);
return (property instanceof Integer) ? ((Integer) property).intValue() : 0;
}
@Override
protected URLConnection openConnection(URL u, Proxy p) throws IOException {
try {
Method openConn = realHandlerService.getClass().getMethod("openConnection", new Class[] {URL.class, Proxy.class});
openConn.setAccessible(true);
return (URLConnection) openConn.invoke(realHandlerService, new Object[] {u, p});
} catch (InvocationTargetException e) {
if (e.getTargetException() instanceof IOException)
throw (IOException) e.getTargetException();
throw (RuntimeException) e.getTargetException();
} catch (Exception e) {
throw new UnsupportedOperationException(e);
}
}
}