blob: 05253bb30ee6a7be6e12bdd1fb51349de28a1f47 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2012 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 - Initial Developer tests for Reference Implementation
******************************************************************************/
package org.eclipse.gemini.naming.test;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.management.ManagementFactory;
import java.net.ConnectException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLStreamHandler;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import javax.management.MBeanServer;
import javax.management.remote.JMXConnectorServer;
import javax.management.remote.JMXConnectorServerFactory;
import javax.management.remote.JMXServiceURL;
import javax.naming.CommunicationException;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.Name;
import javax.naming.NameNotFoundException;
import javax.naming.NameParser;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.Reference;
import javax.naming.Referenceable;
import javax.naming.StringRefAddr;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import javax.naming.spi.InitialContextFactory;
import javax.naming.spi.InitialContextFactoryBuilder;
import javax.naming.spi.NamingManager;
import javax.naming.spi.ObjectFactory;
import javax.naming.spi.ObjectFactoryBuilder;
import org.osgi.framework.*;
/**
* Test case used to verify the Factory resolution process
* in Gemini Naming.
*
*/
public class FactoryResolutionTestCase extends NamingTestCase {
private ClassLoader m_oldClassLoader = null;
protected void onSetUp() throws Exception {
super.onSetUp();
m_oldClassLoader = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(new TestClassLoaderTwo());
}
protected void onTearDown() throws Exception {
super.onTearDown();
Thread.currentThread().setContextClassLoader(m_oldClassLoader);
}
/**
* Verifies that the Factory Manager allows access to the JNDI implementations
* provided by the JDK. This test will verify access to the RMI JNDI implementation as
* an example of how to test this.
*
* @TODO, add tests for the other factories provided by the JDK
* @throws Exception
*/
public void testAccessToJDK_RMIContext() throws Exception {
Hashtable environment = new Hashtable();
environment.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.rmi.registry.RegistryContextFactory");
environment.put("osgi.service.jndi.bundleContext", bundleContext);
// verify that context can be created without any errors
Context context = null;
try {
context = new InitialContext(environment);
} finally {
context.close();
}
}
/**
* Verifies access to the LDAP context factory provided by the
* JDK. This test does not verify any LDAP connectivity, it merely
* ensures that the JDK-provided implementation is available in an OSGi
* environment.
*
* @throws Exception
*/
public void testAccessToJDK_LDAPContext() throws Exception {
Hashtable environment = new Hashtable();
environment.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.ldap.LdapCtxFactory");
environment.put("osgi.service.jndi.bundleContext", bundleContext);
DirContext dirContext = null;
try {
dirContext = new InitialDirContext(environment);
// verify that a communication exception is thrown,
// since this test does not include an LDAP server
// the intention of this test is to verify that the factory
// can be made available by the factory manager.
fail("CommunicationException should have been thrown");
}
catch (CommunicationException communicationException) {
// expected exception for this test
assertTrue("Did not receive expected root exception for this test",
communicationException.getCause() instanceof ConnectException);
} finally {
if (dirContext != null) {
dirContext.close();
}
}
}
/**
* Verify that if an ObjectFactory classname is specified in a Reference, and that
* ObjectFactory is not available to the Factory Manager, that the manager will
* query the existing ObjectFactoryBuilder services in order to attempt to
* find a matching ObjectFactory.
*
* Please see section 5.2.2.1 of RFC 142 for more details.
*
* @throws Exception
*/
public void testSpecificObjectFactoryResolvedByBuilder() throws Exception {
final int expectedValue = 100;
// stub builder to be used in test
ObjectFactoryBuilder factoryBuilder = new ObjectFactoryBuilder() {
public ObjectFactory createObjectFactory(Object var0, Hashtable var1) throws NamingException {
return new ObjectFactory() {
public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable environment) throws Exception {
return new Integer(expectedValue);
}
};
}
};
// only register the builder implementation
registerService(ObjectFactoryBuilder.class.getName(), factoryBuilder, null);
// reference data does not matter, since we're testing that
// the factory manager can locate the only ObjectFactory registered.
Reference reference = new Reference("test", "com.test.factory.DoesNotExist", null);
Object result = NamingManager.getObjectInstance(reference, null, null, null);
assertEquals("JNDI Factory Manager did not locate the correct ObjectFactory",
new Integer(expectedValue), result);
}
/**
* Verify that the Factory Manager can resolve a reference that includes an
* address (StringRefAddr) of type "URL". This address can be used by the Factory
* Manager in order to locate a URL context factory that supports the given scheme.
*
* Please see section 5.2.2.1 of RFC 142 for more details.
*
* @throws Exception
*/
public void testObjectFactoryResolvedUsingURLContextFactory() throws Exception {
final int expectedValue = 100;
ObjectFactory urlContextFactory = new ObjectFactory() {
public Object getObjectInstance(Object var0, Name var1,
Context var2, Hashtable var3) throws Exception {
return new Integer(expectedValue);
}
};
Hashtable serviceProperties = new Hashtable();
serviceProperties.put("osgi.jndi.url.scheme", "testURL");
registerService(ObjectFactory.class.getName(),
urlContextFactory,
serviceProperties);
// reference data does not matter, since we're testing that
// the factory manager can locate the URL context factory
// to support this URL scheme
Reference reference = new Reference("test", null, null);
// create a string reference address of type URL
// and add it to the reference
reference.add(new StringRefAddr("URL", "testURL://testOne"));
Object result = NamingManager.getObjectInstance(reference, null, null, null);
assertEquals("Incorrect type returned by URL context factory",
new Integer(expectedValue), result);
}
/**
* Verify that if no ObjectFactories are found to resolve the reference,
* then the Reference object itself is returned. This behavior complies with the
* behavior of the NamingManager.getObjectInstance() method. In this test case
* the Reference specifies a factory class that is not available.
*
*/
public void testReturnValueWhenSpecifiedAndNoObjectFactoriesFound() throws Exception {
// no ObjectFactory services or builder services are registered for this test
Reference reference = new Reference("test", "com.test.factory.FactoryDoesNotExist", null);
Object result = NamingManager.getObjectInstance(reference, null, null, null);
assertSame("Factory Manager did not return the refInfo as expected",
reference, result);
}
/**
* Verify that if no ObjectFactories are found to resolve the reference,
* then the Reference object itself is returned. This behavior complies with the
* behavior of the NamingManager.getObjectInstance() method. In this test case
* the Reference does not specify a factory class.
*
*/
public void testReturnValueWhenNotSpecifiedAndNoObjectFactoriesFound() throws Exception {
// no ObjectFactory services or builder services are registered for this test
Reference reference = new Reference("test", null, null);
Object result = NamingManager.getObjectInstance(reference, null, null, null);
assertSame("Factory Manager did not return the refInfo as expected",
reference, result);
}
/**
* Verify that an ObjectFactoryBuilder can be queried in the attempt
* to resolve a reference. Verify that this process works as expected
* when the NamingManager.getObjectInstance() method is called.
* @throws Exception
*/
public void testReferenceableSupportWithBuilder() throws Exception {
final int expectedValue = 100;
// stub builder to be used in test
ObjectFactoryBuilder factoryBuilder = new ObjectFactoryBuilder() {
public ObjectFactory createObjectFactory(Object var0, Hashtable var1) throws NamingException {
return new ObjectFactory() {
public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable environment) throws Exception {
return new Integer(expectedValue);
}
};
}
};
// only register the builder implementation
registerService(ObjectFactoryBuilder.class.getName(), factoryBuilder, null);
// create implementation of Referenceable that can
// create a reference to resolve
Referenceable referenceable = new Referenceable() {
public Reference getReference() throws NamingException {
return new Reference("test", "com.test.factory.DoesNotExist", null);
}
};
Object result = NamingManager.getObjectInstance(referenceable, null, null, null);
assertEquals("JNDI Factory Manager did not locate the correct ObjectFactory",
new Integer(expectedValue), result);
}
/**
* Verify that the Gemini Naming bundle can support calls to resolve
* a reference from the NamingManager.getObjectInstance() method. This test
* verifies that an ObjectFactory registered as an OSGi service can be queried in
* the attempt to resolve the reference.
*/
public void testReferenceableSupportWithObjectFactory() throws Exception {
final int expectedValue = 100;
// stub builder to be used in test
final ObjectFactory objectFactory = new ObjectFactory() {
public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable environment) throws Exception {
return new Integer(expectedValue);
}
};
String[] serviceInterfaces = { ObjectFactory.class.getName(),
objectFactory.getClass().getName() };
ServiceRegistration serviceRegistration =
bundleContext.registerService(serviceInterfaces, objectFactory, null);
try {
// create implementation of Referenceable that can
// create a reference to resolve
Referenceable referenceable = new Referenceable() {
public Reference getReference() throws NamingException {
return new Reference("test", objectFactory.getClass().getName(), null);
}
};
Object result = NamingManager.getObjectInstance(referenceable, null, null, null);
assertEquals("JNDI Factory Manager did not locate the correct ObjectFactory",
new Integer(expectedValue), result);
}
finally {
serviceRegistration.unregister();
}
}
/**
* Verify that a "jndi.properties" file can be used in a Bundle to
* specify the desired InitialContextFactory implementation.
*/
public void testJndiPropertiesFileFromArchive() throws Exception {
final String expectedLookupName = "test-binding-one";
final String expectedLookupValue = "this is only a test!";
// setup a stub context factory
Context testContext = new TestContext() {
public Object lookup(String name) throws NamingException {
if(name.equals(expectedLookupName)) {
return expectedLookupValue;
}
throw new NameNotFoundException("Error in test");
}
};
InitialContextFactory initialContextFactory = new TestContextFactory(testContext);
String[] interfaceNames = { InitialContextFactory.class.getName(), TestContextFactory.class.getName() };
// register context factory
ServiceRegistration serviceRegistration =
bundleContext.registerService(interfaceNames, initialContextFactory, null);
// create and setup a temp file for testing
File jndiPropertiesFile = File.createTempFile("jndi", "properties");
FileOutputStream outputStream = new FileOutputStream(jndiPropertiesFile);
Properties tempProperties = new Properties();
tempProperties.put(Context.INITIAL_CONTEXT_FACTORY, TestContextFactory.class.getName());
tempProperties.store(outputStream, "test properties file");
ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader();
InitialContext context = null;
try {
URL testURL =
new URL("", "", -1, "", new TestURLStreamHandler(jndiPropertiesFile));
final TestClassLoader testClassLoader = new TestClassLoader(testURL);
// set context classloader that can provide the jndi.properties file
Thread.currentThread().setContextClassLoader(testClassLoader);
//System.setProperty(Context.INITIAL_CONTEXT_FACTORY, "this.package.doesNotExist.Factory");
Hashtable environment = new Hashtable();
environment.put("osgi.service.jndi.bundleContext", bundleContext);
context = new InitialContext(environment);
assertEquals("Incorrect value returned by context factory",
expectedLookupValue, context.lookup(expectedLookupName));
} finally {
context.close();
serviceRegistration.unregister();
// clean up context classloader
Thread.currentThread().setContextClassLoader(oldClassLoader);
if (jndiPropertiesFile != null) {
// clean up temp file
jndiPropertiesFile.delete();
}
// clean up system property
Properties sysProperties = System.getProperties();
sysProperties.remove(Context.INITIAL_CONTEXT_FACTORY);
}
}
/**
* Verify that RMI URL Context Factory can be used by default.
*/
public void testRMIURLContextFactory() throws Exception {
MBeanServer theMBeanServer = ManagementFactory.getPlatformMBeanServer();
// Create the RMI registry
try {
LocateRegistry.createRegistry(1515);
} catch (RemoteException e) {
fail("Can't create registry: " + e.toString());
}
// Build the connection string with fixed ports
StringBuilder url = new StringBuilder();
url.append("service:jmx:rmi://localhost:");
url.append(1516);
url.append("/jndi/rmi://localhost:");
url.append(1515);
url.append("/jmxrmi");
JMXServiceURL serviceUrl = null;
try {
serviceUrl = new JMXServiceURL(url.toString());
} catch (MalformedURLException e) {
fail("Can't create registry: " + e.toString());
}
Map<String, Object> env = new HashMap<String, Object>();
ClassLoader currentTCCL = Thread.currentThread().getContextClassLoader();
JMXConnectorServer cs = null;
try {
Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
cs = JMXConnectorServerFactory.newJMXConnectorServer(serviceUrl, env, theMBeanServer);
cs.start();
System.out.println("Start MBean JMX registry with ports: registry=" + 1515 + ", server=" + 1516);
assertTrue(cs.isActive());
} catch (IOException e) {
fail("Can't create registry: " + e.toString());
} finally {
Thread.currentThread().setContextClassLoader(currentTCCL);
if (cs != null) {
cs.stop();
}
}
}
// Stub implementations of JNDI factories used for simpler unit testing
static class TestContextFactoryBuilder implements InitialContextFactoryBuilder {
private final Context m_context;
TestContextFactoryBuilder(Context context) {
m_context = context;
}
public InitialContextFactory createInitialContextFactory(Hashtable var0)
throws NamingException {
return new TestContextFactory(m_context);
}
}
private static class TestContextFactory implements InitialContextFactory {
private final Context m_context;
TestContextFactory(Context context) {
m_context = context;
}
public Context getInitialContext(Hashtable var0) throws NamingException {
return m_context;
}
}
static class TestContext implements Context {
private int m_numOfCloseCalls = 0;
int getNumCloseCalls() {
return m_numOfCloseCalls;
}
public Object addToEnvironment(String var0, Object var1)
throws NamingException {
return null;
}
public void bind(String var0, Object var1) throws NamingException {
}
public void bind(Name var0, Object var1) throws NamingException {
}
public void close() throws NamingException {
m_numOfCloseCalls++;
}
public String composeName(String var0, String var1)
throws NamingException {
return null;
}
public Name composeName(Name var0, Name var1) throws NamingException {
return null;
}
public Context createSubcontext(String var0) throws NamingException {
return null;
}
public Context createSubcontext(Name var0) throws NamingException {
return null;
}
public void destroySubcontext(String var0) throws NamingException {
}
public void destroySubcontext(Name var0) throws NamingException {
}
public Hashtable getEnvironment() throws NamingException {
return null;
}
public String getNameInNamespace() throws NamingException {
return null;
}
public NameParser getNameParser(String var0) throws NamingException {
return null;
}
public NameParser getNameParser(Name var0) throws NamingException {
return null;
}
public NamingEnumeration list(String var0) throws NamingException {
return null;
}
public NamingEnumeration list(Name var0) throws NamingException {
return null;
}
public NamingEnumeration listBindings(String var0)
throws NamingException {
return null;
}
public NamingEnumeration listBindings(Name var0) throws NamingException {
return null;
}
public Object lookup(String var0) throws NamingException {
return null;
}
public Object lookup(Name var0) throws NamingException {
return null;
}
public Object lookupLink(String var0) throws NamingException {
return null;
}
public Object lookupLink(Name var0) throws NamingException {
return null;
}
public void rebind(String var0, Object var1) throws NamingException {
}
public void rebind(Name var0, Object var1) throws NamingException {
}
public Object removeFromEnvironment(String var0) throws NamingException {
return null;
}
public void rename(String var0, String var1) throws NamingException {
}
public void rename(Name var0, Name var1) throws NamingException {
}
public void unbind(String var0) throws NamingException {
}
public void unbind(Name var0) throws NamingException {
}
}
private static class TestURLStreamHandler extends URLStreamHandler {
private final File m_propertiesFile;
TestURLStreamHandler(File propertiesFile) {
m_propertiesFile = propertiesFile;
}
protected URLConnection openConnection(URL var0) throws IOException {
return new URLConnection(null) {
public void connect() throws IOException {
// no-op
}
public Object getContent() throws IOException {
return m_propertiesFile;
}
};
}
}
private static class TestClassLoader extends ClassLoader implements BundleReference {
private final URL m_fileURL;
TestClassLoader(URL fileURL) {
m_fileURL = fileURL;
}
public Bundle getBundle() {
return new TestBundle() {
public URL getResource(String name) {
if(name.equals("jndi.properties")) {
return m_fileURL;
}
return null;
}
};
}
}
private static class TestBundle implements Bundle {
public Enumeration findEntries(String path, String filePattern,
boolean recurse) {
return null;
}
public BundleContext getBundleContext() {
return null;
}
public long getBundleId() {
return 0;
}
public URL getEntry(String path) {
return null;
}
public Enumeration getEntryPaths(String path) {
return null;
}
public Dictionary getHeaders() {
return null;
}
public Dictionary getHeaders(String locale) {
return null;
}
public long getLastModified() {
return 0;
}
public String getLocation() {
return null;
}
public ServiceReference[] getRegisteredServices() {
return null;
}
public URL getResource(String name) {
return null;
}
public Enumeration getResources(String name) throws IOException {
return null;
}
public ServiceReference[] getServicesInUse() {
return null;
}
public Map getSignerCertificates(int signersType) {
return null;
}
public int getState() {
return 0;
}
public String getSymbolicName() {
return null;
}
public Version getVersion() {
return null;
}
public boolean hasPermission(Object permission) {
return false;
}
public Class loadClass(String name) throws ClassNotFoundException {
return null;
}
public void start() throws BundleException {
}
public void start(int options) throws BundleException {
}
public void stop() throws BundleException {
}
public void stop(int options) throws BundleException {
}
public void uninstall() throws BundleException {
}
public void update() throws BundleException {
}
public void update(InputStream input) throws BundleException {
}
}
private class TestClassLoaderTwo extends ClassLoader implements BundleReference {
public Bundle getBundle() {
return new Bundle() {
public Enumeration findEntries(String path, String filePattern, boolean recurse) {
return null;
}
public BundleContext getBundleContext() {
return getContext();
}
public long getBundleId() {
return 0;
}
public URL getEntry(String path) {
return null;
}
public Enumeration getEntryPaths(String path) {
return null;
}
public Dictionary getHeaders() {
return null;
}
public Dictionary getHeaders(String locale) {
return null;
}
public long getLastModified() {
return 0;
}
public String getLocation() {
return null;
}
public ServiceReference[] getRegisteredServices() {
return null;
}
public URL getResource(String name) {
return null;
}
public Enumeration getResources(String name) throws IOException {
return null;
}
public ServiceReference[] getServicesInUse() {
return null;
}
public Map getSignerCertificates(int signersType) {
return null;
}
public int getState() {
return 0;
}
public String getSymbolicName() {
return null;
}
public Version getVersion() {
return null;
}
public boolean hasPermission(Object permission) {
return false;
}
public Class loadClass(String name) throws ClassNotFoundException {
return null;
}
public void start() throws BundleException {
}
public void start(int options) throws BundleException {
}
public void stop() throws BundleException {
}
public void stop(int options) throws BundleException {
}
public void uninstall() throws BundleException {
}
public void update() throws BundleException {
}
public void update(InputStream input) throws BundleException {
}
};
}
}
}