View Javadoc

1   /* Rfc2617Credential
2    *
3    * Created on Apr 7, 2004
4    *
5    * Copyright (C) 2004 Internet Archive.
6    *
7    * This file is part of the Heritrix web crawler (crawler.archive.org).
8    *
9    * Heritrix is free software; you can redistribute it and/or modify
10   * it under the terms of the GNU Lesser Public License as published by
11   * the Free Software Foundation; either version 2.1 of the License, or
12   * any later version.
13   *
14   * Heritrix is distributed in the hope that it will be useful,
15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   * GNU Lesser Public License for more details.
18   *
19   * You should have received a copy of the GNU Lesser Public License
20   * along with Heritrix; if not, write to the Free Software
21   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22   */
23  package org.archive.crawler.datamodel.credential;
24  
25  
26  import java.util.Iterator;
27  import java.util.Set;
28  import java.util.logging.Logger;
29  
30  import javax.management.AttributeNotFoundException;
31  
32  import org.apache.commons.httpclient.HttpClient;
33  import org.apache.commons.httpclient.HttpMethod;
34  import org.apache.commons.httpclient.URIException;
35  import org.apache.commons.httpclient.UsernamePasswordCredentials;
36  import org.apache.commons.httpclient.auth.AuthScope;
37  import org.archive.crawler.datamodel.CrawlURI;
38  import org.archive.crawler.settings.SimpleType;
39  import org.archive.crawler.settings.Type;
40  
41  
42  
43  /***
44   * A Basic/Digest auth RFC2617 credential.
45   *
46   * @author stack
47   * @version $Revision: 4668 $, $Date: 2006-09-26 21:49:01 +0000 (Tue, 26 Sep 2006) $
48   */
49  public class Rfc2617Credential extends Credential {
50  
51      private static final long serialVersionUID = -1909614285968756188L;
52  
53      private static Logger logger =
54          Logger.getLogger(Rfc2617Credential.class.getName());
55  
56      private static final String ATTR_REALM = "realm";
57      private static final String ATTR_LOGIN = "login";
58      private static final String ATTR_PASSWORD = "password";
59  
60  
61      /***
62       * Constructor.
63       *
64       * A constructor that takes name of the credential is required by settings
65       * framework.
66       *
67       * @param name Name of this credential.
68       */
69      public Rfc2617Credential(String name) {
70          super(name, "Basic/Digest Auth type credential.");
71  
72          Type t = addElementToDefinition(new SimpleType(ATTR_REALM,
73              "Basic/Digest Auth realm.", "Realm"));
74          t.setOverrideable(false);
75          t.setExpertSetting(true);
76  
77          t = addElementToDefinition(new SimpleType(ATTR_LOGIN, "Login.",
78              "login"));
79          t.setOverrideable(false);
80          t.setExpertSetting(true);
81  
82          t = addElementToDefinition(new SimpleType(ATTR_PASSWORD, "Password.",
83              "password"));
84          t.setOverrideable(false);
85          t.setExpertSetting(true);
86      }
87  
88      /***
89       * @param context Context to use when searching the realm.
90       * @return Realm using set context.
91       * @throws AttributeNotFoundException
92       */
93      public String getRealm(CrawlURI context)
94              throws AttributeNotFoundException {
95          return (String)getAttribute(ATTR_REALM, context);
96      }
97  
98      /***
99       * @param context CrawlURI ontext to use.
100      * @return login to use doing credential.
101      * @throws AttributeNotFoundException
102      */
103     public String getLogin(CrawlURI context)
104             throws AttributeNotFoundException {
105         return (String)getAttribute(ATTR_LOGIN, context);
106     }
107 
108     /***
109      * @param context CrawlURI ontext to use.
110      * @return Password to use doing credential.
111      * @throws AttributeNotFoundException
112      */
113     public String getPassword(CrawlURI context)
114             throws AttributeNotFoundException {
115         return (String)getAttribute(ATTR_PASSWORD, context);
116     }
117 
118     public boolean isPrerequisite(CrawlURI curi) {
119         // Return false.  Later when we implement preemptive
120         // rfc2617, this will change.
121         return false;
122     }
123 
124     public boolean hasPrerequisite(CrawlURI curi) {
125         // Return false.  Later when we implement preemptive
126         // rfc2617, this will change.
127         return false;
128     }
129 
130     public String getPrerequisite(CrawlURI curi) {
131         // Return null.  Later when we implement preemptive
132         // rfc2617, this will change.
133         return null;
134     }
135 
136     public String getKey(CrawlURI context) throws AttributeNotFoundException {
137         return getRealm(context);
138     }
139 
140     public boolean isEveryTime() {
141         return true;
142     }
143 
144     public boolean populate(CrawlURI curi, HttpClient http, HttpMethod method,
145             String payload) {
146         boolean result = false;
147         String authRealm = payload;
148         if (authRealm == null) {
149             logger.severe("No authscheme though creds: " + curi);
150             return result;
151         }
152 
153         // Always add the credential to HttpState. Doing this because no way of
154         // removing the credential once added AND there is a bug in the
155         // credentials management system in that it always sets URI root to
156         // null: it means the key used to find a credential is NOT realm + root
157         // URI but just the realm. Unless I set it everytime, there is
158         // possibility that as this thread progresses, it might come across a
159         // realm already loaded but the login and password are from another
160         // server. We'll get a failed authentication that'd be difficult to
161         // explain.
162         //
163         // Have to make a UsernamePasswordCredentials. The httpclient auth code
164         // does an instanceof down in its guts.
165         UsernamePasswordCredentials upc = null;
166         try {
167         	upc = new UsernamePasswordCredentials(getLogin(curi),
168         	    getPassword(curi));
169         	http.getState().setCredentials(new AuthScope(curi.getUURI().getHost(),
170         	    curi.getUURI().getPort(), authRealm), upc);
171         	logger.fine("Credentials for realm " + authRealm +
172         	    " for CrawlURI " + curi.toString() + " added to request: " +
173 				result);
174         	result = true;
175         } catch (AttributeNotFoundException e1) {
176         	logger.severe("Failed to get login and password for " +
177         			curi + " and " + authRealm);
178         } catch (URIException e) {
179         	logger.severe("Failed to parse host from " + curi + ": " +
180         			e.getMessage());
181         }
182         
183         return result;
184     }
185 
186     public boolean isPost(CrawlURI curi) {
187         // Return false.  This credential type doesn't care whether posted or
188         // get'd.
189         return false;
190     }
191 
192     /***
193      * Convenience method that does look up on passed set using realm for key.
194      *
195      * @param rfc2617Credentials Set of Rfc2617 credentials.  If passed set is
196      * not pure Rfc2617Credentials then will be ClassCastExceptions.
197      * @param realm Realm to find in passed set.
198      * @param context Context to use when searching the realm.
199      * @return Credential of passed realm name else null.  If more than one
200      * credential w/ passed realm name, and there shouldn't be, we return first
201      * found.
202      */
203     public static Rfc2617Credential getByRealm(Set rfc2617Credentials,
204             String realm, CrawlURI context) {
205 
206         Rfc2617Credential result = null;
207         if (rfc2617Credentials == null || rfc2617Credentials.size() <= 0) {
208             return result;
209         }
210         if (rfc2617Credentials != null && rfc2617Credentials.size() > 0) {
211             for (Iterator i = rfc2617Credentials.iterator(); i.hasNext();) {
212                 Rfc2617Credential c = (Rfc2617Credential)i.next();
213                 try {
214                     if (c.getRealm(context).equals(realm)) {
215                         result = c;
216                         break;
217                     }
218                 } catch (AttributeNotFoundException e) {
219                     logger.severe("Failed look up by realm " + realm + " " + e);
220                 }
221             }
222         }
223         return result;
224     }
225 }