package org.eclipse.osgi.internal.url;
import java.lang.reflect.Method;
import java.net.ContentHandler;
import java.net.URLConnection;
import java.util.Arrays;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import org.eclipse.osgi.framework.log.FrameworkLogEntry;
import org.eclipse.osgi.internal.framework.EquinoxContainer;
import org.eclipse.osgi.internal.messages.Msg;
import org.eclipse.osgi.util.NLS;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.osgi.service.url.URLConstants;
import org.osgi.util.tracker.ServiceTracker;
public class ContentHandlerFactoryImpl extends MultiplexingFactory implements java.net.ContentHandlerFactory {
private ServiceTracker<ContentHandler, ContentHandler> contentHandlerTracker;
private static final String contentHandlerClazz = "java.net.ContentHandler";
private static final String CONTENT_HANDLER_PKGS = "java.content.handler.pkgs";
private static final String DEFAULT_VM_CONTENT_HANDLERS = "sun.net.www.content|sun.awt.www.content";
private static final List<Class<?>> ignoredClasses = Arrays.asList(new Class<?>[] {MultiplexingContentHandler.class, ContentHandlerFactoryImpl.class, URLConnection.class});
private Map<String, ContentHandlerProxy> proxies;
private java.net.ContentHandlerFactory parentFactory;
public ContentHandlerFactoryImpl(BundleContext context, EquinoxContainer container) {
super(context, container);
proxies = new Hashtable<>(5);
contentHandlerTracker = new ServiceTracker<>(context, contentHandlerClazz, null);
contentHandlerTracker.open();
}
@Override
public ContentHandler createContentHandler(String contentType) {
String builtInHandlers = URLStreamHandlerFactoryImpl.secureAction.getProperty(CONTENT_HANDLER_PKGS);
builtInHandlers = builtInHandlers == null ? DEFAULT_VM_CONTENT_HANDLERS : DEFAULT_VM_CONTENT_HANDLERS + '|' + builtInHandlers;
Class<?> clazz = null;
if (builtInHandlers != null) {
String convertedContentType = contentType.replace('.', '_');
convertedContentType = convertedContentType.replace('/', '.');
convertedContentType = convertedContentType.replace('-', '_');
StringTokenizer tok = new StringTokenizer(builtInHandlers, "|");
while (tok.hasMoreElements()) {
StringBuilder name = new StringBuilder();
name.append(tok.nextToken());
name.append(".");
name.append(convertedContentType);
try {
clazz = URLStreamHandlerFactoryImpl.secureAction.loadSystemClass(name.toString());
if (clazz != null) {
return (null);
}
} catch (ClassNotFoundException ex) {
}
}
}
if (isMultiplexing())
return new MultiplexingContentHandler(contentType, this);
return createInternalContentHandler(contentType);
}
public ContentHandler createInternalContentHandler(String contentType) {
ContentHandlerProxy proxy = proxies.get(contentType);
if (proxy != null) {
return (proxy);
}
ServiceReference<ContentHandler>[] serviceReferences = contentHandlerTracker.getServiceReferences();
if (serviceReferences != null) {
for (ServiceReference<ContentHandler> serviceReference : serviceReferences) {
Object prop = serviceReference.getProperty(URLConstants.URL_CONTENT_MIMETYPE);
if (prop instanceof String)
prop = new String[] {(String) prop};
if (!(prop instanceof String[])) {
String message = NLS.bind(Msg.URL_HANDLER_INCORRECT_TYPE, new Object[]{URLConstants.URL_CONTENT_MIMETYPE, contentHandlerClazz, serviceReference.getBundle()});
container.getLogServices().log(EquinoxContainer.NAME, FrameworkLogEntry.WARNING, message, null);
continue;
}
String[] contentHandler = (String[]) prop;
for (String typename : contentHandler) {
if (typename.equals(contentType)) {
proxy = new ContentHandlerProxy(contentType, serviceReference, context);
proxies.put(contentType, proxy);
return (proxy);
}
}
}
}
if (parentFactory != null) {
ContentHandler parentHandler = parentFactory.createContentHandler(contentType);
if (parentHandler != null)
return parentHandler;
}
proxy = new ContentHandlerProxy(contentType, null, context);
proxies.put(contentType, proxy);
return (proxy);
}
public synchronized ContentHandler findAuthorizedContentHandler(String contentType) {
Object factory = findAuthorizedFactory(ignoredClasses);
if (factory == null)
return null;
if (factory == this)
return createInternalContentHandler(contentType);
try {
Method createInternalContentHandlerMethod = factory.getClass().getMethod("createInternalContentHandler", new Class[] {String.class});
return (ContentHandler) createInternalContentHandlerMethod.invoke(factory, new Object[] {contentType});
} catch (Exception e) {
container.getLogServices().log(ContentHandlerFactoryImpl.class.getName(), FrameworkLogEntry.ERROR, "findAuthorizedContentHandler-loop", e);
throw new RuntimeException(e.getMessage(), e);
}
}
@Override
public Object getParentFactory() {
return parentFactory;
}
@Override
public void setParentFactory(Object parentFactory) {
if (this.parentFactory == null)
this.parentFactory = (java.net.ContentHandlerFactory) parentFactory;
}
}