001: /* Rfc2617Credential
002: *
003: * Created on Apr 7, 2004
004: *
005: * Copyright (C) 2004 Internet Archive.
006: *
007: * This file is part of the Heritrix web crawler (crawler.archive.org).
008: *
009: * Heritrix is free software; you can redistribute it and/or modify
010: * it under the terms of the GNU Lesser Public License as published by
011: * the Free Software Foundation; either version 2.1 of the License, or
012: * any later version.
013: *
014: * Heritrix is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
017: * GNU Lesser Public License for more details.
018: *
019: * You should have received a copy of the GNU Lesser Public License
020: * along with Heritrix; if not, write to the Free Software
021: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
022: */
023: package org.archive.crawler.datamodel.credential;
024:
025: import java.util.Iterator;
026: import java.util.Set;
027: import java.util.logging.Logger;
028:
029: import javax.management.AttributeNotFoundException;
030:
031: import org.apache.commons.httpclient.HttpClient;
032: import org.apache.commons.httpclient.HttpMethod;
033: import org.apache.commons.httpclient.URIException;
034: import org.apache.commons.httpclient.UsernamePasswordCredentials;
035: import org.apache.commons.httpclient.auth.AuthScope;
036: import org.archive.crawler.datamodel.CrawlURI;
037: import org.archive.crawler.settings.SimpleType;
038: import org.archive.crawler.settings.Type;
039:
040: /**
041: * A Basic/Digest auth RFC2617 credential.
042: *
043: * @author stack
044: * @version $Revision: 4668 $, $Date: 2006-09-26 21:49:01 +0000 (Tue, 26 Sep 2006) $
045: */
046: public class Rfc2617Credential extends Credential {
047:
048: private static final long serialVersionUID = -1909614285968756188L;
049:
050: private static Logger logger = Logger
051: .getLogger(Rfc2617Credential.class.getName());
052:
053: private static final String ATTR_REALM = "realm";
054: private static final String ATTR_LOGIN = "login";
055: private static final String ATTR_PASSWORD = "password";
056:
057: /**
058: * Constructor.
059: *
060: * A constructor that takes name of the credential is required by settings
061: * framework.
062: *
063: * @param name Name of this credential.
064: */
065: public Rfc2617Credential(String name) {
066: super (name, "Basic/Digest Auth type credential.");
067:
068: Type t = addElementToDefinition(new SimpleType(ATTR_REALM,
069: "Basic/Digest Auth realm.", "Realm"));
070: t.setOverrideable(false);
071: t.setExpertSetting(true);
072:
073: t = addElementToDefinition(new SimpleType(ATTR_LOGIN, "Login.",
074: "login"));
075: t.setOverrideable(false);
076: t.setExpertSetting(true);
077:
078: t = addElementToDefinition(new SimpleType(ATTR_PASSWORD,
079: "Password.", "password"));
080: t.setOverrideable(false);
081: t.setExpertSetting(true);
082: }
083:
084: /**
085: * @param context Context to use when searching the realm.
086: * @return Realm using set context.
087: * @throws AttributeNotFoundException
088: */
089: public String getRealm(CrawlURI context)
090: throws AttributeNotFoundException {
091: return (String) getAttribute(ATTR_REALM, context);
092: }
093:
094: /**
095: * @param context CrawlURI ontext to use.
096: * @return login to use doing credential.
097: * @throws AttributeNotFoundException
098: */
099: public String getLogin(CrawlURI context)
100: throws AttributeNotFoundException {
101: return (String) getAttribute(ATTR_LOGIN, context);
102: }
103:
104: /**
105: * @param context CrawlURI ontext to use.
106: * @return Password to use doing credential.
107: * @throws AttributeNotFoundException
108: */
109: public String getPassword(CrawlURI context)
110: throws AttributeNotFoundException {
111: return (String) getAttribute(ATTR_PASSWORD, context);
112: }
113:
114: public boolean isPrerequisite(CrawlURI curi) {
115: // Return false. Later when we implement preemptive
116: // rfc2617, this will change.
117: return false;
118: }
119:
120: public boolean hasPrerequisite(CrawlURI curi) {
121: // Return false. Later when we implement preemptive
122: // rfc2617, this will change.
123: return false;
124: }
125:
126: public String getPrerequisite(CrawlURI curi) {
127: // Return null. Later when we implement preemptive
128: // rfc2617, this will change.
129: return null;
130: }
131:
132: public String getKey(CrawlURI context)
133: throws AttributeNotFoundException {
134: return getRealm(context);
135: }
136:
137: public boolean isEveryTime() {
138: return true;
139: }
140:
141: public boolean populate(CrawlURI curi, HttpClient http,
142: HttpMethod method, String payload) {
143: boolean result = false;
144: String authRealm = payload;
145: if (authRealm == null) {
146: logger.severe("No authscheme though creds: " + curi);
147: return result;
148: }
149:
150: // Always add the credential to HttpState. Doing this because no way of
151: // removing the credential once added AND there is a bug in the
152: // credentials management system in that it always sets URI root to
153: // null: it means the key used to find a credential is NOT realm + root
154: // URI but just the realm. Unless I set it everytime, there is
155: // possibility that as this thread progresses, it might come across a
156: // realm already loaded but the login and password are from another
157: // server. We'll get a failed authentication that'd be difficult to
158: // explain.
159: //
160: // Have to make a UsernamePasswordCredentials. The httpclient auth code
161: // does an instanceof down in its guts.
162: UsernamePasswordCredentials upc = null;
163: try {
164: upc = new UsernamePasswordCredentials(getLogin(curi),
165: getPassword(curi));
166: http.getState().setCredentials(
167: new AuthScope(curi.getUURI().getHost(), curi
168: .getUURI().getPort(), authRealm), upc);
169: logger.fine("Credentials for realm " + authRealm
170: + " for CrawlURI " + curi.toString()
171: + " added to request: " + result);
172: result = true;
173: } catch (AttributeNotFoundException e1) {
174: logger.severe("Failed to get login and password for "
175: + curi + " and " + authRealm);
176: } catch (URIException e) {
177: logger.severe("Failed to parse host from " + curi + ": "
178: + e.getMessage());
179: }
180:
181: return result;
182: }
183:
184: public boolean isPost(CrawlURI curi) {
185: // Return false. This credential type doesn't care whether posted or
186: // get'd.
187: return false;
188: }
189:
190: /**
191: * Convenience method that does look up on passed set using realm for key.
192: *
193: * @param rfc2617Credentials Set of Rfc2617 credentials. If passed set is
194: * not pure Rfc2617Credentials then will be ClassCastExceptions.
195: * @param realm Realm to find in passed set.
196: * @param context Context to use when searching the realm.
197: * @return Credential of passed realm name else null. If more than one
198: * credential w/ passed realm name, and there shouldn't be, we return first
199: * found.
200: */
201: public static Rfc2617Credential getByRealm(Set rfc2617Credentials,
202: String realm, CrawlURI context) {
203:
204: Rfc2617Credential result = null;
205: if (rfc2617Credentials == null
206: || rfc2617Credentials.size() <= 0) {
207: return result;
208: }
209: if (rfc2617Credentials != null && rfc2617Credentials.size() > 0) {
210: for (Iterator i = rfc2617Credentials.iterator(); i
211: .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
220: + " " + e);
221: }
222: }
223: }
224: return result;
225: }
226: }
|