 ;;;; Session management
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
+
+
+(defn security-options
+  "TODO"
+  ([ssl-context] (security-options ssl-context nil))
+  ([ssl-context {:keys [protocols cipher-suites]}]
+   (let [sec-opts (SecurityOptions. ssl-context)]
+     (when (seq protocols)
+       (.setEnabledProtocols sec-opts (into-array String protocols)))
+     (when (seq cipher-suites)
+       (.setEnabledCipherSuites sec-opts (into-array String cipher-suites)))
+     sec-opts)))
+
+
+(defn uri-content-source
+  "TODO"
+  ([uri] (uri-content-source uri nil))
+  ;; Return a ContentSource object that will serve as the source of
+  ;; connections to the server specified by the given URI.
+  ([uri security-opts]
+   ;; TODO enforce or construct SecurityOptions for security-opts
+   (ContentSourceFactory/newContentSource (if (instance? URI uri)
+                                            uri (URI. uri))
+                                          security-opts)))
+
+(defn hosted-content-source
+  "TODO"
+  ([host port]
+   ;; Return a ContentSource object that will serve as the source of
+   ;; connections to the server on the given host and port, with no
+   ;; default login credentials.
+   (ContentSourceFactory/newContentSource host port))
+  ([host port user password]
+   (hosted-content-source host port user password nil nil))
+  ([host port user password content-base]
+   (hosted-content-source host port user password content-base nil))
+
+  ;; Return a ContentSource object that will serve as the source of
+  ;; connections to the server on the given host and port, with login
+  ;; credentials of the given user and password.
+  ([host port user password content-base security-opts]
+   ;; TODO enforce or construct SecurityOptions for security-opts
+   (ContentSourceFactory/newContentSource host port
+                                          user password
+                                          content-base
+                                          security-opts)))
+
+(defn managed-content-source
+  "TODO"
+  [cxn-provider user password content-base]
+  ;; Return a ContentSource object that will use the provided
+  ;; ConnectionProvider instance to obtain server connections, with the
+  ;; given default login credentials and contentbase values.
+  ;; XXX advanced
+  (when-not (instance? ConnectionProvider cxn-provider)
+    (throw (IllegalArgumentException. "Content Source cxn-provider must be a ConnectionProvider")))
+  (ContentSourceFactory/newContentSource cxn-provider
+                                         user password
+                                         content-base))
+
+
+
+
 (defn- create-session*
-  "Creates session, given map of database info."
-  [{:keys [uri user password content-base]}]
-  (let [cs (ContentSourceFactory/newContentSource (URI. uri))]
+  "Creates session, given map of database info. If complex connection
+  options are necessary, pass in a preconfigured content source."
+  [{:keys [uri user password content-base]} & [content-source]]
+  (let [cs (if (instance? ContentSource content-source)
+             content-source
+             (ContentSourceFactory/newContentSource (URI. uri)))]
     (cond
       (and (nil? content-base)
            (or (nil? user)

           (seq content-base)) (.newSession cs user password content-base))))

(defn create-session
  "Create a Session for querying and transacting with. Parameter
  `db-info` describing database connection information must
  include :uri key, and may optionally include connection information

  https://docs.marklogic.com/javadoc/xcc/com/marklogic/xcc/Session.html
  for valid options. (Note that request options are distinct from
  session options, though *default* request options can be set for the
  session.)

  If optional `content-source` is passed, the Session is created from
  the given ContentSource rather than creating one from the database info URI."
  ([db-info]
   (create-session* db-info))
  ([db-info {:keys [default-request-options logger user-object
                    transaction-mode transaction-timeout]}]
   (create-session db-info
                   nil
                   {:default-request-options default-request-options
                    :logger logger :user-object user-object
                    :transaction-mode transaction-mode
                    :transaction-timeout transaction-timeout}))
  ([db-info content-source {:keys [default-request-options logger user-object
                                   transaction-mode transaction-timeout]}]
   (let [session (create-session* db-info content-source)]
     (when (map? default-request-options)
       (.setDefaultRequestOptions session (request-options default-request-options)))
     (when (instance? Logger logger)
