You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by nk...@apache.org on 2016/02/08 23:36:08 UTC

[33/50] [abbrv] lucene-solr git commit: SOLR-8373: KerberosPlugin: Using multiple nodes on same machine leads clients to fetch TGT for every request

SOLR-8373: KerberosPlugin: Using multiple nodes on same machine leads clients to fetch TGT for every request


git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/branches/lucene_solr_5_4@1724179 13f79535-47bb-0310-9956-ffa450edef68


Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/268e01f9
Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/268e01f9
Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/268e01f9

Branch: refs/heads/branch_5_4
Commit: 268e01f93fae9f6d327bef07bc9fba942f9b5bf6
Parents: 3c173f1
Author: Adrien Grand <jp...@apache.org>
Authored: Tue Jan 12 09:11:08 2016 +0000
Committer: Adrien Grand <jp...@apache.org>
Committed: Tue Jan 12 09:11:08 2016 +0000

----------------------------------------------------------------------
 solr/CHANGES.txt                                |   3 +
 .../org/apache/solr/core/CoreContainer.java     |   8 +-
 .../apache/solr/core/SolrResourceLoader.java    |  17 +-
 .../apache/solr/security/KerberosPlugin.java    |  38 +++-
 .../solrj/impl/Krb5HttpClientConfigurer.java    |   5 +
 .../impl/SolrPortAwareCookieSpecFactory.java    | 114 +++++++++++
 .../solrj/impl/SolrPortAwareCookieSpecTest.java | 197 +++++++++++++++++++
 7 files changed, 370 insertions(+), 12 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/268e01f9/solr/CHANGES.txt
----------------------------------------------------------------------
diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index 85b9d35..bb0a692 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -467,6 +467,9 @@ Bug Fixes
 
 * SOLR-8460: /analysis/field could throw exceptions for custom attributes. (David Smiley, Uwe Schindler)
 
+* SOLR-8373: KerberosPlugin: Using multiple nodes on same machine leads clients to
+  fetch TGT for every request (Ishan Chattopadhyaya via noble)
+
 ==================  5.3.1 ==================
 
 Bug Fixes

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/268e01f9/solr/core/src/java/org/apache/solr/core/CoreContainer.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/core/CoreContainer.java b/solr/core/src/java/org/apache/solr/core/CoreContainer.java
index 2aabdc8..94e84aa 100644
--- a/solr/core/src/java/org/apache/solr/core/CoreContainer.java
+++ b/solr/core/src/java/org/apache/solr/core/CoreContainer.java
@@ -278,10 +278,14 @@ public class CoreContainer {
     SecurityPluginHolder<AuthenticationPlugin> old = authenticationPlugin;
     SecurityPluginHolder<AuthenticationPlugin> authenticationPlugin = null;
 
-    // Initialize the filter
+    // Initialize the plugin
     if (pluginClassName != null) {
       authenticationPlugin = new SecurityPluginHolder<>(readVersion(authenticationConfig),
-          getResourceLoader().newInstance(pluginClassName, AuthenticationPlugin.class));
+          getResourceLoader().newInstance(pluginClassName,
+              AuthenticationPlugin.class,
+              null,
+              new Class[]{CoreContainer.class},
+              new Object[]{this}));
     }
     if (authenticationPlugin != null) {
       authenticationPlugin.plugin.init(authenticationConfig);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/268e01f9/solr/core/src/java/org/apache/solr/core/SolrResourceLoader.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/core/SolrResourceLoader.java b/solr/core/src/java/org/apache/solr/core/SolrResourceLoader.java
index a142b2f..cffaf58 100644
--- a/solr/core/src/java/org/apache/solr/core/SolrResourceLoader.java
+++ b/solr/core/src/java/org/apache/solr/core/SolrResourceLoader.java
@@ -622,7 +622,7 @@ public class SolrResourceLoader implements ResourceLoader,Closeable
     return obj;
   }
 
- 
+
 
   public <T> T newInstance(String cName, Class<T> expectedType, String [] subPackages, Class[] params, Object[] args){
     Class<? extends T> clazz = findClass(cName, expectedType, subPackages);
@@ -634,8 +634,19 @@ public class SolrResourceLoader implements ResourceLoader,Closeable
     T obj = null;
     try {
 
-      Constructor<? extends T> constructor = clazz.getConstructor(params);
-      obj = constructor.newInstance(args);
+      Constructor<? extends T> constructor = null;
+      try {
+        constructor = clazz.getConstructor(params);
+        obj = constructor.newInstance(args);
+      } catch (NoSuchMethodException e) {
+        //look for a zero arg constructor if the constructor args do not match
+        try {
+          constructor = clazz.getConstructor();
+          obj = constructor.newInstance();
+        } catch (NoSuchMethodException e1) {
+          throw e;
+        }
+      }
 
     } catch (Error err) {
       log.error("Loading Class " + cName + " ("+clazz.getName() + ") triggered serious java error: "

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/268e01f9/solr/core/src/java/org/apache/solr/security/KerberosPlugin.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/security/KerberosPlugin.java b/solr/core/src/java/org/apache/solr/security/KerberosPlugin.java
index ba27f09..34ea396 100644
--- a/solr/core/src/java/org/apache/solr/security/KerberosPlugin.java
+++ b/solr/core/src/java/org/apache/solr/security/KerberosPlugin.java
@@ -29,8 +29,10 @@ import javax.servlet.descriptor.JspConfigDescriptor;
 import org.apache.commons.collections.iterators.IteratorEnumeration;
 import org.apache.solr.client.solrj.impl.HttpClientConfigurer;
 import org.apache.solr.client.solrj.impl.Krb5HttpClientConfigurer;
+import org.apache.solr.cloud.ZkController;
 import org.apache.solr.common.SolrException;
 import org.apache.solr.common.SolrException.ErrorCode;
+import org.apache.solr.core.CoreContainer;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -57,12 +59,18 @@ public class KerberosPlugin extends AuthenticationPlugin implements HttpClientIn
   HttpClientConfigurer kerberosConfigurer = new Krb5HttpClientConfigurer();
   Filter kerberosFilter = new KerberosFilter();
   
-  final String NAME_RULES_PARAM = "solr.kerberos.name.rules";
-  final String COOKIE_DOMAIN_PARAM = "solr.kerberos.cookie.domain";
-  final String COOKIE_PATH_PARAM = "solr.kerberos.cookie.path";
-  final String PRINCIPAL_PARAM = "solr.kerberos.principal";
-  final String KEYTAB_PARAM = "solr.kerberos.keytab";
-  final String TOKEN_VALID_PARAM = "solr.kerberos.token.valid";
+  public static final String NAME_RULES_PARAM = "solr.kerberos.name.rules";
+  public static final String COOKIE_DOMAIN_PARAM = "solr.kerberos.cookie.domain";
+  public static final String COOKIE_PATH_PARAM = "solr.kerberos.cookie.path";
+  public static final String PRINCIPAL_PARAM = "solr.kerberos.principal";
+  public static final String KEYTAB_PARAM = "solr.kerberos.keytab";
+  public static final String TOKEN_VALID_PARAM = "solr.kerberos.token.valid";
+  public static final String COOKIE_PORT_AWARE_PARAM = "solr.kerberos.cookie.portaware";
+  private final CoreContainer coreContainer;
+
+  public KerberosPlugin(CoreContainer coreContainer) {
+    this.coreContainer = coreContainer;
+  }
 
   @Override
   public void init(Map<String, Object> pluginConfig) {
@@ -71,11 +79,27 @@ public class KerberosPlugin extends AuthenticationPlugin implements HttpClientIn
       params.put("type", "kerberos");
       putParam(params, "kerberos.name.rules", NAME_RULES_PARAM, "DEFAULT");
       putParam(params, "token.valid", TOKEN_VALID_PARAM, "30");
-      putParam(params, "cookie.domain", COOKIE_DOMAIN_PARAM, null);
       putParam(params, "cookie.path", COOKIE_PATH_PARAM, "/");
       putParam(params, "kerberos.principal", PRINCIPAL_PARAM, null);
       putParam(params, "kerberos.keytab", KEYTAB_PARAM, null);
 
+      // Special handling for the "cookie.domain" based on whether port should be
+      // appended to the domain. Useful for situations where multiple solr nodes are
+      // on the same host.
+      String usePortStr = System.getProperty(COOKIE_PORT_AWARE_PARAM, null);
+      boolean needPortAwareCookies = (usePortStr == null) ? false: Boolean.parseBoolean(usePortStr);
+
+      if (!needPortAwareCookies || !coreContainer.isZooKeeperAware()) {
+        putParam(params, "cookie.domain", COOKIE_DOMAIN_PARAM, null);
+      } else { // we need port aware cookies and we are in SolrCloud mode.
+        String host = System.getProperty(COOKIE_DOMAIN_PARAM, null);
+        if (host==null) {
+          throw new SolrException(ErrorCode.SERVER_ERROR, "Missing required parameter '"+COOKIE_DOMAIN_PARAM+"'.");
+        }
+        int port = coreContainer.getZkController().getHostPort();
+        params.put("cookie.domain", host + ":" + port);
+      }
+      
       log.info("Params: "+params);
 
       FilterConfig conf = new FilterConfig() {

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/268e01f9/solr/solrj/src/java/org/apache/solr/client/solrj/impl/Krb5HttpClientConfigurer.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/impl/Krb5HttpClientConfigurer.java b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/Krb5HttpClientConfigurer.java
index d4c4f7c..9bfbc6c 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/impl/Krb5HttpClientConfigurer.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/Krb5HttpClientConfigurer.java
@@ -40,6 +40,7 @@ import org.apache.http.impl.auth.SPNegoSchemeFactory;
 import org.apache.http.impl.client.DefaultHttpClient;
 import org.apache.http.protocol.HttpContext;
 import org.apache.http.client.config.AuthSchemes;
+import org.apache.http.client.params.ClientPNames;
 import org.apache.solr.common.params.SolrParams;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -93,6 +94,10 @@ public class Krb5HttpClientConfigurer extends HttpClientConfigurer {
           }
         };
 
+        SolrPortAwareCookieSpecFactory cookieFactory = new SolrPortAwareCookieSpecFactory();
+        httpClient.getCookieSpecs().register(cookieFactory.POLICY_NAME, cookieFactory);
+        httpClient.getParams().setParameter(ClientPNames.COOKIE_POLICY, cookieFactory.POLICY_NAME);
+        
         httpClient.getCredentialsProvider().setCredentials(AuthScope.ANY, useJaasCreds);
 
         httpClient.addRequestInterceptor(bufferedEntityInterceptor);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/268e01f9/solr/solrj/src/java/org/apache/solr/client/solrj/impl/SolrPortAwareCookieSpecFactory.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/impl/SolrPortAwareCookieSpecFactory.java b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/SolrPortAwareCookieSpecFactory.java
new file mode 100644
index 0000000..63c4405
--- /dev/null
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/SolrPortAwareCookieSpecFactory.java
@@ -0,0 +1,114 @@
+package org.apache.solr.client.solrj.impl;
+
+import java.util.Collection;
+
+import org.apache.http.cookie.ClientCookie;
+import org.apache.http.cookie.Cookie;
+import org.apache.http.cookie.CookieOrigin;
+import org.apache.http.cookie.CookieSpec;
+import org.apache.http.cookie.CookieSpecFactory;
+import org.apache.http.cookie.CookieSpecProvider;
+import org.apache.http.cookie.MalformedCookieException;
+import org.apache.http.cookie.params.CookieSpecPNames;
+import org.apache.http.impl.cookie.NetscapeDomainHandler;
+import org.apache.http.impl.cookie.NetscapeDraftSpec;
+import org.apache.http.params.HttpParams;
+import org.apache.http.protocol.HttpContext;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+@SuppressWarnings("deprecation")
+public class SolrPortAwareCookieSpecFactory implements CookieSpecFactory, CookieSpecProvider {
+  public static final String POLICY_NAME = "solr-portaware";
+  private final CookieSpec cookieSpec;
+
+  public SolrPortAwareCookieSpecFactory(final String[] datepatterns) {
+    super();
+    this.cookieSpec = new PortAwareCookieSpec(datepatterns);
+  }
+
+  public SolrPortAwareCookieSpecFactory() {
+    this(null);
+  }
+
+  @Override
+  public CookieSpec newInstance(final HttpParams params) {
+    if (params != null) {
+      String[] patterns = null;
+      final Collection<?> param = (Collection<?>) params.getParameter(
+          CookieSpecPNames.DATE_PATTERNS);
+      if (param != null) {
+        patterns = new String[param.size()];
+        patterns = param.toArray(patterns);
+      }
+      return new PortAwareCookieSpec(patterns);
+    } else {
+      return new PortAwareCookieSpec(null);
+    }
+  }
+
+  @Override
+  public CookieSpec create(final HttpContext context) {
+    return this.cookieSpec;
+  }
+
+  public static class PortAwareCookieSpec extends NetscapeDraftSpec {
+    public PortAwareCookieSpec(String patterns[]) {
+      super(patterns);
+      super.registerAttribHandler(ClientCookie.DOMAIN_ATTR, new PortAwareDomainHandler());
+    }
+
+    public PortAwareCookieSpec() {
+      this(null);
+    }
+  }
+
+  /**
+   * A domain handler to validate and match cookies based on the domain and origin.
+   * The domain is tested against host and port both, and if it doesn't match, it
+   * delegates the handling to the base class' matching/validation logic.
+   */
+  public static class PortAwareDomainHandler extends NetscapeDomainHandler {
+
+    public void validate(final Cookie cookie, final CookieOrigin origin)
+        throws MalformedCookieException {
+      if (origin != null && origin.getHost() != null && cookie != null) {
+        String hostPort = origin.getHost() + ":" + origin.getPort();
+        String domain = cookie.getDomain();
+
+        if (hostPort.equals(domain)) {
+          return;
+        }
+      }
+      super.validate(cookie, origin);
+    }
+
+    @Override
+    public boolean match(final Cookie cookie, final CookieOrigin origin) {
+      if (origin != null && origin.getHost() != null && cookie != null) {
+        String hostPort = origin.getHost() + ":" + origin.getPort();
+        String domain = cookie.getDomain();
+        if (hostPort.equals(domain)) {
+          return true;
+        }
+      }
+      return super.match(cookie, origin);
+    }
+  }
+}
+

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/268e01f9/solr/solrj/src/test/org/apache/solr/client/solrj/impl/SolrPortAwareCookieSpecTest.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/SolrPortAwareCookieSpecTest.java b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/SolrPortAwareCookieSpecTest.java
new file mode 100644
index 0000000..dbdee66
--- /dev/null
+++ b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/SolrPortAwareCookieSpecTest.java
@@ -0,0 +1,197 @@
+package org.apache.solr.client.solrj.impl;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.apache.http.cookie.CookieAttributeHandler;
+import org.apache.http.cookie.CookieOrigin;
+import org.apache.http.cookie.MalformedCookieException;
+import org.apache.http.impl.cookie.BasicClientCookie;
+import org.junit.Assert;
+import org.junit.Test;
+
+// Test cases imported from TestNetscapeCookieAttribHandlers of HttpClient project
+public class SolrPortAwareCookieSpecTest {
+
+  @Test
+  public void testDomainHostPortValidate() throws Exception {
+    final BasicClientCookie cookie = new BasicClientCookie("name", "value");
+    final CookieOrigin origin = new CookieOrigin("somehost", 80, "/", false);
+    final CookieAttributeHandler h = new SolrPortAwareCookieSpecFactory.PortAwareDomainHandler();
+
+    cookie.setDomain("somehost:80");
+    h.validate(cookie, origin);
+
+    cookie.setDomain("somehost:1234");
+    try {
+      h.validate(cookie, origin);
+      Assert.fail("MalformedCookieException should have been thrown");
+    } catch (final MalformedCookieException ex) {
+      // expected
+    }
+  }
+
+  @Test
+  public void testDomainHostPortMatch() throws Exception {
+    final BasicClientCookie cookie = new BasicClientCookie("name", "value");
+    final CookieOrigin origin = new CookieOrigin("myhost", 80, "/", false);
+    final CookieAttributeHandler h = new SolrPortAwareCookieSpecFactory.PortAwareDomainHandler();
+
+    cookie.setDomain("myhost");
+    try {
+      h.match(cookie, null);
+      Assert.fail("IllegalArgumentException should have been thrown, since origin is null.");
+    } catch (final IllegalArgumentException ex) {
+      // expected
+    }
+
+    cookie.setDomain(null);
+    Assert.assertFalse(h.match(cookie, origin));
+
+    cookie.setDomain("otherhost");
+    Assert.assertFalse(h.match(cookie, origin));
+
+    cookie.setDomain("myhost");
+    Assert.assertTrue(h.match(cookie, origin));
+
+    cookie.setDomain("myhost:80");
+    Assert.assertTrue(h.match(cookie, origin));
+
+    cookie.setDomain("myhost:8080");
+    Assert.assertFalse(h.match(cookie, origin));
+  }
+
+  @Test
+  public void testDomainValidate1() throws Exception {
+    final BasicClientCookie cookie = new BasicClientCookie("name", "value");
+    final CookieOrigin origin = new CookieOrigin("somehost", 80, "/", false);
+    final CookieAttributeHandler h = new SolrPortAwareCookieSpecFactory.PortAwareDomainHandler();
+
+    cookie.setDomain("somehost");
+    h.validate(cookie, origin);
+
+    cookie.setDomain("otherhost");
+    try {
+      h.validate(cookie, origin);
+      Assert.fail("MalformedCookieException should have been thrown");
+    } catch (final MalformedCookieException ex) {
+      // expected
+    }
+  }
+
+  @Test
+  public void testDomainValidate2() throws Exception {
+    final BasicClientCookie cookie = new BasicClientCookie("name", "value");
+    final CookieOrigin origin = new CookieOrigin("www.somedomain.com", 80, "/", false);
+    final CookieAttributeHandler h = new SolrPortAwareCookieSpecFactory.PortAwareDomainHandler();
+
+    cookie.setDomain(".somedomain.com");
+    h.validate(cookie, origin);
+
+    cookie.setDomain(".otherdomain.com");
+    try {
+      h.validate(cookie, origin);
+      Assert.fail("MalformedCookieException should have been thrown");
+    } catch (final MalformedCookieException ex) {
+      // expected
+    }
+    cookie.setDomain("www.otherdomain.com");
+    try {
+      h.validate(cookie, origin);
+      Assert.fail("MalformedCookieException should have been thrown");
+    } catch (final MalformedCookieException ex) {
+      // expected
+    }
+  }
+
+  @Test
+  public void testDomainValidate3() throws Exception {
+    final BasicClientCookie cookie = new BasicClientCookie("name", "value");
+    final CookieOrigin origin = new CookieOrigin("www.a.com", 80, "/", false);
+    final CookieAttributeHandler h = new SolrPortAwareCookieSpecFactory.PortAwareDomainHandler();
+
+    cookie.setDomain(".a.com");
+    h.validate(cookie, origin);
+
+    cookie.setDomain(".com");
+    try {
+      h.validate(cookie, origin);
+      Assert.fail("MalformedCookieException should have been thrown");
+    } catch (final MalformedCookieException ex) {
+      // expected
+    }
+  }
+
+  @Test
+  public void testDomainValidate4() throws Exception {
+    final BasicClientCookie cookie = new BasicClientCookie("name", "value");
+    final CookieOrigin origin = new CookieOrigin("www.a.b.c", 80, "/", false);
+    final CookieAttributeHandler h = new SolrPortAwareCookieSpecFactory.PortAwareDomainHandler();
+
+    cookie.setDomain(".a.b.c");
+    h.validate(cookie, origin);
+
+    cookie.setDomain(".b.c");
+    try {
+      h.validate(cookie, origin);
+      Assert.fail("MalformedCookieException should have been thrown");
+    } catch (final MalformedCookieException ex) {
+      // expected
+    }
+  }
+
+  @Test
+  public void testDomainMatch1() throws Exception {
+    final BasicClientCookie cookie = new BasicClientCookie("name", "value");
+    final CookieOrigin origin = new CookieOrigin("www.somedomain.com", 80, "/", false);
+    final CookieAttributeHandler h = new SolrPortAwareCookieSpecFactory.PortAwareDomainHandler();
+
+    cookie.setDomain(null);
+    Assert.assertFalse(h.match(cookie, origin));
+
+    cookie.setDomain(".somedomain.com");
+    Assert.assertTrue(h.match(cookie, origin));
+  }
+
+  @Test
+  public void testDomainMatch2() throws Exception {
+    final BasicClientCookie cookie = new BasicClientCookie("name", "value");
+    final CookieOrigin origin = new CookieOrigin("www.whatever.somedomain.com", 80, "/", false);
+    final CookieAttributeHandler h = new SolrPortAwareCookieSpecFactory.PortAwareDomainHandler();
+
+    cookie.setDomain(".somedomain.com");
+    Assert.assertTrue(h.match(cookie, origin));
+  }
+
+  @Test
+  public void testDomainInvalidInput() throws Exception {
+    final CookieAttributeHandler h = new SolrPortAwareCookieSpecFactory.PortAwareDomainHandler();
+    try {
+      h.match(null, null);
+      Assert.fail("IllegalArgumentException must have been thrown");
+    } catch (final IllegalArgumentException ex) {
+      // expected
+    }
+    try {
+      h.match(new BasicClientCookie("name", "value"), null);
+      Assert.fail("IllegalArgumentException must have been thrown");
+    } catch (final IllegalArgumentException ex) {
+      // expected
+    }
+  }
+
+}