blob: c325e1b5026c56426d138a276e140eb817fe3aa2 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2010, 2015 Oracle.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Apache License v2.0 which accompanies this distribution.
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
* and the Apache License v2.0 is available at
* http://www.opensource.org/licenses/apache2.0.php.
* You may elect to redistribute this code under either of these licenses.
*
* Contributors:
* Bob Nettleton (Oracle) - Initial Reference Implementation
******************************************************************************/
package org.eclipse.gemini.naming;
import java.security.AccessControlException;
import java.security.AccessController;
import java.util.Hashtable;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.naming.Context;
import javax.naming.Name;
import javax.naming.NameNotFoundException;
import javax.naming.NamingException;
import javax.naming.spi.ObjectFactory;
import org.osgi.framework.AdminPermission;
import org.osgi.framework.BundleContext;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference;
/**
* A URL context factory that supports lookups of OSGi services.
*
*
*/
class OSGiURLContextFactory implements ObjectFactory {
private static final String OSGI_BUNDLE_CONTEXT_LOOKUP = "osgi:framework/bundleContext";
private static final Logger logger = Logger.getLogger(OSGiURLContextFactory.class.getName());
private final BundleContext m_bundleContext;
public OSGiURLContextFactory(BundleContext bundleContext) {
m_bundleContext = bundleContext;
}
@Override
public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable environment) throws Exception {
return new OSGiURLContext(m_bundleContext);
}
/**
* The OSGi URL Context that is handed back to the Gemini Naming Implementation.
* <p/>
* This URL Context only supports the Context.lookup(String) method.
* All other method invocations on this context will result in an
* OperationNotSupportedException being thrown.
*/
private static class OSGiURLContext extends NotSupportedContext {
private final BundleContext m_bundleContext;
public OSGiURLContext(BundleContext bundleContext) {
super("This operation is not supported by the OSGi URL Context");
m_bundleContext = bundleContext;
}
@Override
public Object lookup(String name) throws NamingException {
String osgiURL = name;
try {
if(osgiURL.equals(OSGI_BUNDLE_CONTEXT_LOOKUP)) {
// return the caller's BundleContext
AdminPermission adminPermission =
new AdminPermission(m_bundleContext.getBundle(), AdminPermission.CONTEXT);
try {
AccessController.checkPermission(adminPermission);
return m_bundleContext;
} catch (AccessControlException accessControlException) {
NamingException namingException = new NameNotFoundException("BundleContext not available, caller does not have the correct permission.");
namingException.setRootCause(accessControlException);
throw namingException;
}
}
Object requestedService = obtainService(osgiURL);
if (requestedService != null) {
return requestedService;
}
}
catch (InvalidSyntaxException e) {
NamingException namingException = new NamingException(
"Error occurred while parsing the OSGi URL");
namingException.initCause(e);
throw namingException;
}
throw new NameNotFoundException(
"The OSGi service referred to by the URL = "
+ osgiURL
+ " could not be located in the OSGi Service Registry");
}
/**
* Obtain the service requested in the "osgi" URL. Currently, this
* method uses the Factory Manager's bundle context.
*
* @param osgiURL the URL for the OSGi service requested
* @return the OSGi Service requested, or null if the service cannot be
* found
* @throws InvalidSyntaxException if an error occurs while parsing the
* OSGi filer (if specified)
*/
private Object obtainService(String osgiURL)
throws InvalidSyntaxException {
OSGiURLParser urlParser = new OSGiURLParser(osgiURL);
try {
urlParser.parse();
}
catch (IllegalStateException stateException) {
logger.log(Level.SEVERE, "An exception occurred while trying to parse this osgi URL", stateException);
return null;
}
if (urlParser.getServiceInterface() == null) {
return null;
}
return getService(m_bundleContext, urlParser);
}
private static Object getService(BundleContext bundleContext, OSGiURLParser urlParser) throws InvalidSyntaxException {
ServiceReference[] serviceReferences =
bundleContext.getServiceReferences(urlParser.getServiceInterface(),
urlParser.getFilter());
if (serviceReferences != null) {
final ServiceReference[] sortedServiceReferences =
ServiceUtils.sortServiceReferences(serviceReferences);
if (urlParser.isServiceListURL()) {
// return a Context that can handle service.id lookups
return new OSGiServiceListContext(bundleContext, sortedServiceReferences, urlParser);
}
else {
ServiceProxyInfo proxyInfo = ReflectionUtils.getProxyForSingleService(bundleContext, urlParser, sortedServiceReferences[0]);
return proxyInfo.getService();
}
}
else {
// service interface name may not map to a published name
// check the registry for a service that supports the
// osgi.jndi.serviceName property
ServiceReference[] serviceReferencesByName =
ServiceUtils.getServiceReferencesByServiceName(bundleContext, urlParser);
if (serviceReferencesByName != null) {
final ServiceReference[] sortedServiceReferences =
ServiceUtils.sortServiceReferences(serviceReferencesByName);
ServiceProxyInfo proxyInfo =
ReflectionUtils.getProxyForSingleService(bundleContext, urlParser, sortedServiceReferences[0]);
return proxyInfo.getService();
}
}
return null;
}
}
}