View Javadoc
1   /*
2    * #%L
3    * CredentialEditor.java - mongodb-async-driver - Allanbank Consulting, Inc.
4    * %%
5    * Copyright (C) 2011 - 2014 Allanbank Consulting, Inc.
6    * %%
7    * Licensed under the Apache License, Version 2.0 (the "License");
8    * you may not use this file except in compliance with the License.
9    * You may obtain a copy of the License at
10   * 
11   *      http://www.apache.org/licenses/LICENSE-2.0
12   * 
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the License is distributed on an "AS IS" BASIS,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the License for the specific language governing permissions and
17   * limitations under the License.
18   * #L%
19   */
20  package com.allanbank.mongodb;
21  
22  import java.beans.PropertyEditorSupport;
23  import java.util.Collections;
24  import java.util.HashSet;
25  import java.util.Map;
26  import java.util.Set;
27  
28  import com.allanbank.mongodb.util.log.Log;
29  import com.allanbank.mongodb.util.log.LogFactory;
30  
31  /**
32   * CredentialEditor provides the ability to parse the credentials from a MongoDB
33   * URI.
34   * <p>
35   * This editor will parses a full MongoDB URI to extract the specified
36   * {@link Credential}. See the <a href=
37   * "http://docs.mongodb.org/manual/reference/connection-string/#authentication-options"
38   * >Connection String URI Format</a> documentation for information on
39   * constructing a MongoDB URI.
40   * </p>
41   * 
42   * @api.yes This class is part of the driver's API. Public and protected members
43   *          will be deprecated for at least 1 non-bugfix release (version
44   *          numbers are &lt;major&gt;.&lt;minor&gt;.&lt;bugfix&gt;) before being
45   *          removed or modified.
46   * @copyright 2014, Allanbank Consulting, Inc., All Rights Reserved
47   */
48  public class CredentialEditor extends PropertyEditorSupport {
49  
50      /**
51       * The fields parsed out of a MongoDB URI to construct a {@link Credential}.
52       */
53      public static final Set<String> MONGODB_URI_FIELDS;
54  
55      /** The logger for the {@link CredentialEditor}. */
56      protected static final Log LOG = LogFactory.getLog(CredentialEditor.class);
57  
58      static {
59          final Set<String> fields = new HashSet<String>();
60          fields.add("gssapiservicename");
61          fields.add("authsource");
62          fields.add("authmechanism");
63  
64          MONGODB_URI_FIELDS = Collections.unmodifiableSet(fields);
65      }
66  
67      /**
68       * Creates a new CredentialEditor.
69       */
70      public CredentialEditor() {
71          super();
72      }
73  
74      /**
75       * {@inheritDoc}
76       * <p>
77       * Overridden to parse a string to a {@link Credential}.
78       * </p>
79       * 
80       * @throws IllegalArgumentException
81       *             If the string cannot be parsed into a {@link Credential}.
82       */
83      @Override
84      public void setAsText(final String credentialString)
85              throws IllegalArgumentException {
86  
87          if (MongoDbUri.isUri(credentialString)) {
88              Credential.Builder builder = null;
89  
90              final MongoDbUri uri = new MongoDbUri(credentialString);
91              if (uri.getUserName() != null) {
92                  builder = Credential.builder().userName(uri.getUserName())
93                          .password(uri.getPassword().toCharArray());
94                  final String database = uri.getDatabase();
95                  if (!database.isEmpty()) {
96                      builder.database(database);
97                  }
98              }
99              final Credential parsed = fromUriParameters(builder,
100                     uri.getParsedOptions());
101             if (parsed != null) {
102                 setValue(parsed);
103             }
104         }
105         else {
106             throw new IllegalArgumentException(
107                     "Could not determine the credentials for '"
108                             + credentialString + "'.");
109         }
110     }
111 
112     /**
113      * Creates a Credential from the MongoDB URI parameters. Any fields used
114      * from the parameters are removed from the {@code parameters} map.
115      * 
116      * @param builder
117      *            The credentials builder to update.
118      * @param parameters
119      *            The map of URI parameters.
120      * @return The Credential.
121      */
122     private Credential fromUriParameters(final Credential.Builder builder,
123             final Map<String, String> parameters) {
124 
125         final String gssapiServiceName = parameters.remove("gssapiservicename");
126         if ((gssapiServiceName != null)) {
127             if (builder != null) {
128                 builder.kerberos().addOption("kerberos.service.name",
129                         gssapiServiceName);
130             }
131             else {
132                 LOG.info("Must supply a user name "
133                         + "to set a gssapiServiceName: '{}'.",
134                         gssapiServiceName);
135             }
136         }
137 
138         final String authSource = parameters.remove("authsource");
139         if (authSource != null) {
140             if (builder != null) {
141                 builder.setDatabase(authSource);
142             }
143             else {
144                 LOG.info("Must supply a user name "
145                         + "to set a authSource: '{}'.", authSource);
146             }
147         }
148 
149         final String authMechanism = parameters.remove("authmechanism");
150         if (authMechanism != null) {
151             if (builder != null) {
152                 if ("MONGODB-CR".equalsIgnoreCase(authMechanism)) {
153                     builder.mongodbCR();
154                 }
155                 else if ("MONGODB-X509".equalsIgnoreCase(authMechanism)) {
156                     builder.x509();
157                 }
158                 else if ("GSSAPI".equalsIgnoreCase(authMechanism)) {
159                     builder.kerberos();
160                 }
161                 else if ("PLAIN".equalsIgnoreCase(authMechanism)) {
162                     builder.plainSasl();
163                 }
164                 else {
165                     LOG.warn("Unknown authMechanism: '{}'. "
166                             + "Not authenticating.", authMechanism);
167                 }
168             }
169             else {
170                 LOG.info("Must supply a user name and password "
171                         + "to set a authMechanism: '{}'.", authMechanism);
172             }
173         }
174 
175         if (builder != null) {
176             return builder.build();
177         }
178         return null;
179     }
180 
181 }