| /******************************************************************************* |
| * Copyright (c) 2003, 2005 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| |
| package org.eclipse.osgi.framework.internal.protocol; |
| |
| import java.io.IOException; |
| 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; |
| |
| /** |
| * The URLStreamHandlerProxy is a URLStreamHandler that acts as a proxy for registered |
| * URLStreamHandlerServices. When a URLStreamHandler is requested from the URLStreamHandlerFactory |
| * and it exists in the service registry, a URLStreamHandlerProxy is created which will pass all the |
| * requests from the requestor to the real URLStreamHandlerService. We can't return the real |
| * URLStreamHandlerService from the URLStreamHandlerFactory because the JVM caches URLStreamHandlers |
| * and therefore would not support a dynamic environment of URLStreamHandlerServices being registered |
| * and unregistered. |
| */ |
| |
| public class URLStreamHandlerProxy extends URLStreamHandler implements ServiceTrackerCustomizer { |
| // TODO lots of type-based names |
| protected URLStreamHandlerService realHandlerService; |
| |
| protected URLStreamHandlerSetter urlSetter; |
| |
| protected ServiceTracker urlStreamHandlerServiceTracker; |
| |
| protected BundleContext context; |
| protected ServiceReference urlStreamServiceReference; |
| |
| protected String protocol; |
| |
| protected int ranking = Integer.MIN_VALUE; |
| |
| public URLStreamHandlerProxy(String protocol, ServiceReference reference, BundleContext context) { |
| this.context = context; |
| this.protocol = protocol; |
| |
| urlSetter = new URLStreamHandlerSetter(this); |
| |
| //set the handler and ranking |
| setNewHandler(reference, getRank(reference)); |
| |
| urlStreamHandlerServiceTracker = new ServiceTracker(context, StreamHandlerFactory.URLSTREAMHANDLERCLASS, this); |
| StreamHandlerFactory.secureAction.open(urlStreamHandlerServiceTracker); |
| } |
| |
| private void setNewHandler(ServiceReference reference, int rank) { |
| if (urlStreamServiceReference != null) |
| context.ungetService(urlStreamServiceReference); |
| |
| urlStreamServiceReference = reference; |
| ranking = rank; |
| |
| if (reference == null) |
| realHandlerService = new NullURLStreamHandlerService(); |
| else |
| realHandlerService = (URLStreamHandlerService) StreamHandlerFactory.secureAction.getService(reference, context); |
| } |
| |
| /** |
| * @see java.net.URLStreamHandler#equals(URL, URL) |
| */ |
| protected boolean equals(URL url1, URL url2) { |
| return realHandlerService.equals(url1, url2); |
| } |
| |
| /** |
| * @see java.net.URLStreamHandler#getDefaultPort() |
| */ |
| protected int getDefaultPort() { |
| return realHandlerService.getDefaultPort(); |
| } |
| |
| /** |
| * @see java.net.URLStreamHandler#getHostAddress(URL) |
| */ |
| protected InetAddress getHostAddress(URL url) { |
| return realHandlerService.getHostAddress(url); |
| } |
| |
| /** |
| * @see java.net.URLStreamHandler#hashCode(URL) |
| */ |
| protected int hashCode(URL url) { |
| return realHandlerService.hashCode(url); |
| } |
| |
| /** |
| * @see java.net.URLStreamHandler#hostsEqual(URL, URL) |
| */ |
| protected boolean hostsEqual(URL url1, URL url2) { |
| return realHandlerService.hostsEqual(url1, url2); |
| } |
| |
| /** |
| * @see java.net.URLStreamHandler#openConnection(URL) |
| */ |
| protected URLConnection openConnection(URL url) throws IOException { |
| return realHandlerService.openConnection(url); |
| } |
| |
| /** |
| * @see java.net.URLStreamHandler#parseURL(URL, String, int, int) |
| */ |
| protected void parseURL(URL url, String str, int start, int end) { |
| realHandlerService.parseURL(urlSetter, url, str, start, end); |
| } |
| |
| /** |
| * @see java.net.URLStreamHandler#sameFile(URL, URL) |
| */ |
| protected boolean sameFile(URL url1, URL url2) { |
| return realHandlerService.sameFile(url1, url2); |
| } |
| |
| /** |
| * @see java.net.URLStreamHandler#toExternalForm(URL) |
| */ |
| protected String toExternalForm(URL url) { |
| return realHandlerService.toExternalForm(url); |
| } |
| |
| /** |
| * @see java.net.URLStreamHandler#setURL(URL, String, String, int, String, String, String, String, String) |
| */ |
| 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); |
| } |
| |
| |
| public void setURL(URL url, String protocol, String host, int port, String file, String ref) { |
| |
| //using non-deprecated URLStreamHandler.setURL method. |
| //setURL(URL u, String protocol, String host, int port, String authority, String userInfo, String file, String query, String ref) |
| super.setURL(url, protocol, host, port, null, null, file, null, ref); |
| } |
| |
| /** |
| * @see org.osgi.util.tracker.ServiceTrackerCustomizer#addingService(ServiceReference) |
| */ |
| public Object addingService(ServiceReference reference) { |
| //check to see if our protocol is being registered by another service |
| Object prop = reference.getProperty(URLConstants.URL_HANDLER_PROTOCOL); |
| if (!(prop instanceof String[])) |
| return null; |
| String[] protocols = (String[]) prop; |
| for (int i = 0; i < protocols.length; i++) { |
| if (protocols[i].equals(protocol)) { |
| //If our protocol is registered by another service, check the service ranking and switch URLStreamHandlers if nessecary. |
| int newServiceRanking = getRank(reference); |
| if (newServiceRanking > ranking || urlStreamServiceReference == null) |
| setNewHandler(reference, newServiceRanking); |
| return (reference); |
| } |
| } |
| |
| //we don't want to continue hearing events about a URLStreamHandlerService not registered under our protocol |
| return (null); |
| } |
| |
| /** |
| * @see org.osgi.util.tracker.ServiceTrackerCustomizer#modifiedService(ServiceReference, Object) |
| */ |
| // check to see if the ranking has changed. If so, re-select a new URLHandler |
| public void modifiedService(ServiceReference reference, Object service) { |
| int newRank = getRank(reference); |
| if (reference == urlStreamServiceReference) { |
| if (newRank < ranking) { |
| // The URLHandler we are currently using has dropped it's ranking below a URLHandler registered |
| // for the same protocol. We need to swap out URLHandlers. |
| // this should get us the highest ranked service, if available |
| ServiceReference newReference = urlStreamHandlerServiceTracker.getServiceReference(); |
| if (newReference != urlStreamServiceReference && newReference != null) { |
| setNewHandler(newReference, ((Integer) newReference.getProperty(Constants.SERVICE_RANKING)).intValue()); |
| } |
| } |
| } else if (newRank > ranking) { |
| // the service changed is another URLHandler that we are not currently using |
| // If it's ranking is higher, we must swap it in. |
| setNewHandler(reference, newRank); |
| } |
| } |
| |
| /** |
| * @see org.osgi.util.tracker.ServiceTrackerCustomizer#removedService(ServiceReference, Object) |
| */ |
| public void removedService(ServiceReference reference, Object service) { |
| // check to see if our URLStreamHandler was unregistered. |
| if (reference != urlStreamServiceReference) |
| return; |
| // If so, look for a lower ranking URLHandler |
| // this should get us the highest ranking service left, if available |
| ServiceReference newReference = urlStreamHandlerServiceTracker.getServiceReference(); |
| // if newReference == null then we will use the NullURLStreamHandlerService here |
| 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; |
| } |
| |
| } |