+ *
+ * @author krloss
+ * @since 1.1.0
+ * @see com.amazon.sqs.javamessaging.SQSSession
+ */
+public enum ResourceType {
+ // Types for Connection Pooling
+ CA(false,AUTO_ACKNOWLEDGE),
+ CC(false,CLIENT_ACKNOWLEDGE),
+ CD(false,DUPS_OK_ACKNOWLEDGE),
+ CU(false,UNORDERED_ACKNOWLEDGE),
+
+ // Types for Session Pooling
+ SA(true,AUTO_ACKNOWLEDGE),
+ SC(true,CLIENT_ACKNOWLEDGE),
+ SD(true,DUPS_OK_ACKNOWLEDGE),
+ SU(true,UNORDERED_ACKNOWLEDGE);
+
+ /**
+ * Reports whether the type is a session pooling.
+ * Externally visible information.
+ */
+ public final boolean isSessionPooling;
+
+ /**
+ * Reports the acknowledgment mode.
+ * Externally visible information.
+ */
+ public final int acknowledgeMode;
+
+ private ResourceType(boolean isSessionPooling,int acknowledgeMode) {
+ this.isSessionPooling = isSessionPooling;
+ this.acknowledgeMode = acknowledgeMode;
+ }
+}
diff --git a/src/main/java/com/amazon/sqs/javamessaging/jndi/SQSContext.java b/src/main/java/com/amazon/sqs/javamessaging/jndi/SQSContext.java
new file mode 100644
index 0000000..bd08450
--- /dev/null
+++ b/src/main/java/com/amazon/sqs/javamessaging/jndi/SQSContext.java
@@ -0,0 +1,248 @@
+package com.amazon.sqs.javamessaging.jndi;
+
+import java.util.Hashtable;
+import java.util.concurrent.ConcurrentHashMap;
+
+import javax.jms.Destination;
+import javax.jms.JMSException;
+import javax.naming.Binding;
+import javax.naming.Context;
+import javax.naming.InterruptedNamingException;
+import javax.naming.Name;
+import javax.naming.NameClassPair;
+import javax.naming.NameParser;
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.OperationNotSupportedException;
+import javax.naming.ServiceUnavailableException;
+import javax.naming.directory.InvalidAttributeValueException;
+
+import com.amazon.sqs.javamessaging.SQSConnectionFactory;
+
+/**
+ * Represents a naming context, which consists of a set of name-to-object bindings.
+ *
+ * It works with a {@link ConnectionsManager connections manager} associated with a {@link SQSConnectionFactory} instance
+ * and creates {@link Destination} instances through {@link DestinationResource}.
+ *
+ * Binded Objects:
+ *
{@link SQSConnectionFactory} - set of connection configuration parameters.
+ *
{@link Destination} - JMS administered object that encapsulates a specific provider address.
+ *
+ *
+ * @author krloss
+ * @since 1.1.0
+ * @see Context
+ * @see DestinationResource
+ */
+public class SQSContext implements Context {
+ private final Hashtable,?> environment;
+ private final ConnectionsManager connectionsManager;
+ private final ConcurrentHashMap bindings = new ConcurrentHashMap<>();
+
+ /**
+ * Public constructor of a naming context that requires {@link SQSConnectionFactory} parameter.
+ *
+ * @param connectionFactory - set of connection configuration parameters.
+ * @param environment - set of configuration informations.
+ * @throws InvalidAttributeValueException
+ */
+ public SQSContext(final ConnectionsManager connectionsManager, final Hashtable,?> environment) throws InvalidAttributeValueException {
+ if(connectionsManager == null ) throw new InvalidAttributeValueException("SQSContext Requires ConnectionsManager.");
+
+ this.connectionsManager = connectionsManager;
+ this.environment = environment;
+ }
+
+ private synchronized Object getDestination(String name) throws NamingException {
+ Object destination = bindings.get(name); // Double-Checked Locking.
+
+ if(destination != null) return destination;
+
+ DestinationResource resource = new DestinationResource(name);
+
+ try {
+ destination = resource.getDestination(connectionsManager);
+ }
+ catch(JMSException e) {
+ throw new ServiceUnavailableException(e.getMessage());
+ }
+
+ bind(name,destination);
+ return destination;
+ }
+
+ /**
+ * Get the {@link SQSConnectionFactory} instance or a {@link Destination} instance.
+ *
+ * @param name - string with name of the object.
+ * @return {@link SQSConnectionFactory} or {@link Destination}
+ * @throws NamingException
+ */
+ @Override
+ public Object lookup(String name) throws NamingException {
+ if(SQSConnectionFactory.class.getName().equals(name)) return connectionsManager.connectionFactory;
+
+ Object destination = bindings.get(name);
+
+ if(destination != null) return destination;
+
+ return getDestination(name);
+ }
+
+ /**
+ * Get the {@link SQSConnectionFactory} instance or a {@link Destination} instance.
+ *
+ * @param name - {@link Name name} of the object.
+ * @return {@link SQSConnectionFactory} or {@link Destination}
+ * @throws NamingException
+ */
+ @Override
+ public Object lookup(Name name) throws NamingException {
+ return lookup(name.toString());
+ }
+
+ /**
+ * Closes this {@link SQSContext context} and its associated {@link ConnectionsManager connection manager}.
+ *
+ * @throws NamingException
+ * @see {@link ConnectionsManager#close()}
+ */
+ @Override
+ public void close() throws NamingException {
+ try {
+ bindings.clear();
+ connectionsManager.close();
+ }
+ catch(JMSException e) {
+ throw new InterruptedNamingException(e.getMessage());
+ }
+ }
+
+ /**
+ * Binds a name to an {@link Destination}.
+ *
+ * @param name - string with name of the {@link Destination}.
+ * @throws NamingException
+ */
+ @Override
+ public void bind(String name, Object destination) throws NamingException {
+ bindings.put(name,destination);
+ }
+
+ /**
+ * Binds a name to an {@link Destination}.
+ *
+ * @param name - {@link Name name} of the {@link Destination}.
+ * @throws NamingException
+ */
+ @Override
+ public void bind(Name name, Object destination) throws NamingException {
+ bind(name.toString(),destination);
+ }
+
+ /**
+ * Get the set of configuration informations.
+ *
+ * @return {@link Hashtable}
+ * @throws NamingException
+ */
+ @Override
+ public Hashtable, ?> getEnvironment() throws NamingException {
+ return environment;
+ }
+
+ @Override
+ public NamingEnumeration list(String name) throws NamingException {
+ throw new OperationNotSupportedException();
+ }
+ @Override
+ public NamingEnumeration list(Name name) throws NamingException {
+ throw new OperationNotSupportedException();
+ }
+
+ @Override
+ public Object addToEnvironment(String arg0, Object arg1) throws NamingException {
+ throw new OperationNotSupportedException();
+ }
+ @Override
+ public Name composeName(Name arg0, Name arg1) throws NamingException {
+ throw new OperationNotSupportedException();
+ }
+ @Override
+ public String composeName(String arg0, String arg1) throws NamingException {
+ throw new OperationNotSupportedException();
+ }
+ @Override
+ public Context createSubcontext(Name arg0) throws NamingException {
+ throw new OperationNotSupportedException();
+ }
+ @Override
+ public Context createSubcontext(String arg0) throws NamingException {
+ throw new OperationNotSupportedException();
+ }
+ @Override
+ public void destroySubcontext(Name arg0) throws NamingException {
+ throw new OperationNotSupportedException();
+ }
+ @Override
+ public void destroySubcontext(String arg0) throws NamingException {
+ throw new OperationNotSupportedException();
+ }
+ @Override
+ public String getNameInNamespace() throws NamingException {
+ throw new OperationNotSupportedException();
+ }
+ @Override
+ public NameParser getNameParser(Name arg0) throws NamingException {
+ throw new OperationNotSupportedException();
+ }
+ @Override
+ public NameParser getNameParser(String arg0) throws NamingException {
+ throw new OperationNotSupportedException();
+ }
+ @Override
+ public NamingEnumeration listBindings(Name arg0) throws NamingException {
+ throw new OperationNotSupportedException();
+ }
+ @Override
+ public NamingEnumeration listBindings(String arg0) throws NamingException {
+ throw new OperationNotSupportedException();
+ }
+ @Override
+ public Object lookupLink(Name arg0) throws NamingException {
+ throw new OperationNotSupportedException();
+ }
+ @Override
+ public Object lookupLink(String arg0) throws NamingException {
+ throw new OperationNotSupportedException();
+ }
+ @Override
+ public void rebind(Name arg0, Object arg1) throws NamingException {
+ throw new OperationNotSupportedException();
+ }
+ @Override
+ public void rebind(String arg0, Object arg1) throws NamingException {
+ throw new OperationNotSupportedException();
+ }
+ @Override
+ public Object removeFromEnvironment(String arg0) throws NamingException {
+ throw new OperationNotSupportedException();
+ }
+ @Override
+ public void rename(Name arg0, Name arg1) throws NamingException {
+ throw new OperationNotSupportedException();
+ }
+ @Override
+ public void rename(String arg0, String arg1) throws NamingException {
+ throw new OperationNotSupportedException();
+ }
+ @Override
+ public void unbind(Name arg0) throws NamingException {
+ throw new OperationNotSupportedException();
+ }
+ @Override
+ public void unbind(String arg0) throws NamingException {
+ throw new OperationNotSupportedException();
+ }
+}
diff --git a/src/main/java/com/amazon/sqs/javamessaging/jndi/SQSContextFactory.java b/src/main/java/com/amazon/sqs/javamessaging/jndi/SQSContextFactory.java
new file mode 100644
index 0000000..58bc044
--- /dev/null
+++ b/src/main/java/com/amazon/sqs/javamessaging/jndi/SQSContextFactory.java
@@ -0,0 +1,47 @@
+package com.amazon.sqs.javamessaging.jndi;
+
+import java.util.Hashtable;
+
+import javax.naming.Context;
+import javax.naming.NamingException;
+import javax.naming.spi.InitialContextFactory;
+
+import com.amazon.sqs.javamessaging.ProviderConfiguration;
+import com.amazon.sqs.javamessaging.SQSConnectionFactory;
+import com.amazonaws.services.sqs.AmazonSQSClientBuilder;
+
+/**
+ * A factory of Amazon Simple Queue Service (SQS) initial context that provides a method for creating instances of
+ * {@link SQSContext} that contain a {@link ConnectionsManager} instance.
+ *
+ * It uses {@link Context#PROVIDER_URL PROVIDER_URL} in the {@link ProviderEndpointConfiguration},
+ * as well as {@link Context#SECURITY_PRINCIPAL SECURITY_PRINCIPAL} and
+ * {@link Context#SECURITY_CREDENTIALS SECURITY_CREDENTIALS} in the {@link CredentialsProvider}.
+ *
+ * @author krloss
+ * @since 1.1.0
+ * @see InitialContextFactory
+ */
+public class SQSContextFactory implements InitialContextFactory {
+ // Factory method to create a new connection factory from the given environment.
+ private static SQSConnectionFactory createConnectionFactory(Hashtable,?> environment) throws NamingException {
+ ProviderEndpointConfiguration providerEndpoint = new ProviderEndpointConfiguration(environment.get(Context.PROVIDER_URL));
+ CredentialsProvider credentials = CredentialsProvider.create(
+ environment.get(Context.SECURITY_PRINCIPAL),environment.get(Context.SECURITY_CREDENTIALS));
+
+ return new SQSConnectionFactory(new ProviderConfiguration(),AmazonSQSClientBuilder.standard()
+ .withEndpointConfiguration(providerEndpoint.createConfiguration()).withCredentials(credentials));
+ }
+
+ /**
+ * Create instances of context which contains {@link SQSConnectionFactory}.
+ *
+ * @param environment - set of configuration informations.
+ * @return {@link SQSContext}
+ * @throws NamingException
+ */
+ @Override
+ public SQSContext getInitialContext(Hashtable,?> environment) throws NamingException {
+ return new SQSContext(new ConnectionsManager(createConnectionFactory(environment)),environment);
+ }
+}
diff --git a/src/main/java/com/amazon/sqs/javamessaging/jndi/package-info.java b/src/main/java/com/amazon/sqs/javamessaging/jndi/package-info.java
new file mode 100644
index 0000000..68ee146
--- /dev/null
+++ b/src/main/java/com/amazon/sqs/javamessaging/jndi/package-info.java
@@ -0,0 +1,14 @@
+/**
+ * Provides classes for accessing naming services that allows to be specified at runtime.
+ *
+ * It facilitates the migration of messages to the cloud of industry-application
+ * that supports the Java Naming API and Directory InterfaceTM (JNDI) standard.
+ *