Pre-instantiate a WebTarget 95/101695/6
authorRobert Varga <robert.varga@pantheon.tech>
Sat, 2 Jul 2022 23:57:42 +0000 (01:57 +0200)
committerRobert Varga <robert.varga@pantheon.tech>
Sun, 3 Jul 2022 02:31:29 +0000 (04:31 +0200)
Rather than building single-use targets, create one when it is
configured. Also fix a potential thread safety issue.

Change-Id: I40a044ab86a63e242f0e70995f9b6624a7a3acdd
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
aaa-shiro/impl/src/main/java/org/opendaylight/aaa/shiro/realm/MoonRealm.java

index 0172b9c5f0981598257e7b2a7a044663e6bb65db..fe4ac2c101ff0b8589163e130be65b4944b095d8 100644 (file)
@@ -7,12 +7,15 @@
  */
 package org.opendaylight.aaa.shiro.realm;
 
+import static com.google.common.base.Preconditions.checkArgument;
+
 import com.google.common.collect.ImmutableSet;
 import com.google.gson.JsonParser;
 import java.net.MalformedURLException;
 import java.net.URL;
 import javax.ws.rs.client.ClientBuilder;
 import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.WebTarget;
 import javax.ws.rs.core.MediaType;
 import org.apache.shiro.authc.AuthenticationException;
 import org.apache.shiro.authc.AuthenticationInfo;
@@ -35,7 +38,7 @@ public class MoonRealm extends AuthorizingRealm {
     private static final Logger LOG = LoggerFactory.getLogger(MoonRealm.class);
     private static final String MOON_DEFAULT_DOMAIN = "sdn";
 
-    private URL moonServerURL;
+    private volatile WebTarget moonServer;
 
     @Override
     protected AuthorizationInfo doGetAuthorizationInfo(final PrincipalCollection principalCollection) {
@@ -62,34 +65,19 @@ public class MoonRealm extends AuthorizingRealm {
     }
 
     public MoonPrincipal moonAuthenticate(final String username, final String password, final String domain) {
-        final String server = moonServerURL != null ? moonServerURL.getHost() : null;
-        if (server == null) {
-            LOG.debug("moon server was not specified appropriately, cannot authenticate");
+        final var moon = moonServer;
+        if (moon == null) {
+            LOG.debug("moon server not specified, cannot authenticate");
             return null;
         }
 
-        final int portFromShiro = moonServerURL != null ? moonServerURL.getPort() : -1;
-        if (portFromShiro <= 0) {
-            LOG.debug("moon server was not specified appropriately, cannot authetnicate");
-            return null;
-        }
-
-        final var port = Integer.toString(portFromShiro);
-        final var url = String.format("http://%s:%s/moon/auth/tokens", server, port);
-        LOG.debug("Moon server is at: {}:{} and will be accessed through {}", server, port, url);
-
-        final String output = ClientBuilder.newClient()
-            .target(url)
-            .request(MediaType.APPLICATION_JSON)
-            .post(
-                // FIXME: String literal when we have JDK17
-                Entity.entity("{\"username\": \"" + username + "\",\n"
-                    + "  \"password\": \"" + password + "\",\n"
-                    + "  \"project\": \"" + domain + "\"\n}",
-                    MediaType.APPLICATION_JSON),
-                String.class);
-
-        final var element = JsonParser.parseString(output);
+        final var element = JsonParser.parseString(moon.request(MediaType.APPLICATION_JSON).post(
+            // FIXME: String literal when we have JDK17
+            Entity.entity("{\"username\": \"" + username + "\",\n"
+                + "  \"password\": \"" + password + "\",\n"
+                + "  \"project\": \"" + domain + "\"\n}",
+                MediaType.APPLICATION_JSON),
+            String.class));
         if (!element.isJsonObject()) {
             throw new IllegalStateException("Authentication error: returned output is not a JSON object");
         }
@@ -123,12 +111,28 @@ public class MoonRealm extends AuthorizingRealm {
      * Injected from {@code shiro.ini}.
      *
      * @param moonServerURL specified in {@code shiro.ini}
+     * @throws NullPointerException If {@code moonServerURL} is {@code null}
+     * @throws IllegalArgumentException If the given string violates RFC&nbsp;2396 or it does not specify a host
+     *                                  and a port.
      */
     public void setMoonServerURL(final String moonServerURL) {
+        final URL url;
         try {
-            this.moonServerURL = new URL(moonServerURL);
+            url = new URL(moonServerURL);
         } catch (MalformedURLException e) {
-            throw new IllegalArgumentException("Cannot parse moon server URL \"" + moonServerURL + "\"", e);
+            throw new IllegalArgumentException(e);
         }
+
+        final var uriHost = url.getHost();
+        checkArgument(uriHost != null, "moon host not specified in %s", url);
+        final var uriPort = url.getPort();
+        checkArgument(uriPort >= 0, "moon port not specified in %s", url);
+
+        final var port = Integer.toString(uriPort);
+        // FIXME: allow HTTPS!
+        // FIXME: allow authentication: and that really means configuring a Client!
+        final var server = String.format("http://%s:%s/moon/auth/tokens", uriHost, port);
+        LOG.debug("Moon server is at: {}:{} and will be accessed through {}", uriHost, port, server);
+        moonServer = ClientBuilder.newClient().target(server);
     }
 }