Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/framework/internal/protocol/ContentHandlerProxy.java')
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/framework/internal/protocol/ContentHandlerProxy.java152
1 files changed, 152 insertions, 0 deletions
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/framework/internal/protocol/ContentHandlerProxy.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/framework/internal/protocol/ContentHandlerProxy.java
new file mode 100644
index 000000000..b60b7940c
--- /dev/null
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/framework/internal/protocol/ContentHandlerProxy.java
@@ -0,0 +1,152 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2010 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.ContentHandler;
+import java.net.URLConnection;
+import org.osgi.framework.*;
+import org.osgi.service.url.URLConstants;
+import org.osgi.util.tracker.ServiceTracker;
+import org.osgi.util.tracker.ServiceTrackerCustomizer;
+
+/**
+ * The ContentHandlerProxy is a ContentHandler that acts as a proxy for registered ContentHandlers.
+ * When a ContentHandler is requested from the ContentHandlerFactory and it exists in the service
+ * registry, a ContentHandlerProxy is created which will pass all the requests from the requestor to
+ * the real ContentHandler. We can't return the real ContentHandler from the ContentHandlerFactory
+ * because the JVM caches ContentHandlers and therefore would not support a dynamic environment of
+ * ContentHandlers being registered and unregistered.
+ */
+public class ContentHandlerProxy extends ContentHandler implements ServiceTrackerCustomizer<ContentHandler, ServiceReference<ContentHandler>> {
+ protected ContentHandler realHandler;
+
+ //TODO avoid type-based names
+ protected ServiceTracker<ContentHandler, ServiceReference<ContentHandler>> contentHandlerServiceTracker;
+
+ protected BundleContext context;
+ protected ServiceReference<ContentHandler> contentHandlerServiceReference;
+
+ protected String contentType;
+
+ protected int ranking = Integer.MIN_VALUE;
+
+ public ContentHandlerProxy(String contentType, ServiceReference<ContentHandler> reference, BundleContext context) {
+ this.context = context;
+ this.contentType = contentType;
+
+ // In case the reference == null, the proxy is constructed with DefaultContentHandler for a Content Handler
+ // until a real ContentHandler for this mime-type is registered
+ setNewHandler(reference, getRank(reference));
+
+ contentHandlerServiceTracker = new ServiceTracker<ContentHandler, ServiceReference<ContentHandler>>(context, ContentHandler.class.getName(), this);
+ StreamHandlerFactory.secureAction.open(contentHandlerServiceTracker);
+ }
+
+ private void setNewHandler(ServiceReference<ContentHandler> reference, int rank) {
+ if (contentHandlerServiceReference != null)
+ context.ungetService(contentHandlerServiceReference);
+
+ contentHandlerServiceReference = reference;
+ ranking = rank;
+
+ if (reference == null)
+ realHandler = new DefaultContentHandler();
+ else
+ realHandler = StreamHandlerFactory.secureAction.getService(reference, context);
+ }
+
+ /**
+ * @see org.osgi.util.tracker.ServiceTrackerCustomizer#addingService(ServiceReference)
+ */
+ public ServiceReference<ContentHandler> addingService(ServiceReference<ContentHandler> reference) {
+ //check to see if our contentType is being registered by another service
+ Object prop = reference.getProperty(URLConstants.URL_CONTENT_MIMETYPE);
+ if (!(prop instanceof String[]))
+ return null;
+ String[] contentTypes = (String[]) prop;
+ for (int i = 0; i < contentTypes.length; i++) {
+ if (contentTypes[i].equals(contentType)) {
+ //If our contentType is registered by another service, check the service ranking and switch URLStreamHandlers if nessecary.
+ int newServiceRanking = getRank(reference);
+ if (newServiceRanking > ranking || contentHandlerServiceReference == null)
+ setNewHandler(reference, newServiceRanking);
+ return (reference);
+ }
+ }
+
+ //we don't want to continue hearing events about a ContentHandler service not registered under our contentType
+ return (null);
+ }
+
+ /**
+ * @see org.osgi.util.tracker.ServiceTrackerCustomizer#modifiedService(ServiceReference, Object)
+ */
+
+ public void modifiedService(ServiceReference<ContentHandler> reference, ServiceReference<ContentHandler> service) {
+ int newrank = getRank(reference);
+ if (reference == contentHandlerServiceReference) {
+ if (newrank < ranking) {
+ // The ContentHandler we are currently using has dropped it's ranking below a ContentHandler
+ // registered for the same protocol. We need to swap out ContentHandlers.
+ // this should get us the highest ranked service, if available
+ ServiceReference<ContentHandler> newReference = contentHandlerServiceTracker.getServiceReference();
+ if (newReference != contentHandlerServiceReference && 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<ContentHandler> reference, ServiceReference<ContentHandler> service) {
+ //check to see if our URLStreamHandler was unregistered.
+ if (reference != contentHandlerServiceReference)
+ return;
+ // If so, look for a lower ranking URLHandler
+ // this should get us the highest ranking service left, if available
+ ServiceReference<ContentHandler> newReference = contentHandlerServiceTracker.getServiceReference();
+ // if newReference == null then we will use the DefaultContentHandler here
+ setNewHandler(newReference, getRank(newReference));
+ }
+
+ /**
+ * @see java.net.ContentHandler#getContent(URLConnection)
+ */
+
+ public Object getContent(URLConnection uConn) throws IOException {
+ return realHandler.getContent(uConn);
+ }
+
+ 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;
+ }
+
+ class DefaultContentHandler extends ContentHandler {
+
+ /**
+ * @see java.net.ContentHandler#getContent(URLConnection)
+ */
+ public Object getContent(URLConnection uConn) throws IOException {
+ return uConn.getInputStream();
+ }
+ }
+}

Back to the top