/*
* Copyright 2003-2006 Rick Knowles <winstone-devel at lists sourceforge net>
* Distributed under the terms of either:
* - the common development and distribution license (CDDL), v1.0; or
* - the GNU Lesser General Public License, v2.1 or later
*/
package winstone.realm;
import org.eclipse.jetty.security.AbstractLoginService;
import org.eclipse.jetty.security.HashLoginService;
import org.eclipse.jetty.security.UserStore;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import winstone.Logger;
import winstone.WinstoneException;
import winstone.WinstoneResourceBundle;
import winstone.cmdline.Option;
import javax.security.auth.Subject;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.security.Principal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import static org.eclipse.jetty.util.security.Credential.*;
/**
* @author rickk
* @version $Id: FileRealm.java,v 1.4 2006/08/30 04:07:52 rickknowles Exp $
*/
public class FileRealm extends HashLoginService {
private static final WinstoneResourceBundle REALM_RESOURCES = new WinstoneResourceBundle("winstone.realm.LocalStrings");
final String DEFAULT_FILE_NAME = "users.xml";
final String ELEM_USER = "user";
final String ATT_USERNAME = "username";
final String ATT_PASSWORD = "password";
final String ATT_ROLELIST = "roles";
/**
* Constructor - this sets up an authentication realm, using the file
* supplied on the command line as a source of userNames/passwords/roles.
*/
public FileRealm(Map args) {
UserStore userStore = new UserStore();
setUserStore( userStore );
// Get the filename and parse the xml doc
File realmFile = Option.FILEREALM_CONFIGFILE.get(args);
if (realmFile==null) realmFile = new File(DEFAULT_FILE_NAME);
if (!realmFile.exists())
throw new WinstoneException(REALM_RESOURCES.getString(
"FileRealm.FileNotFound", realmFile.getPath()));
try {
int count=0;
InputStream inFile = new FileInputStream(realmFile);
Document doc = this.parseStreamToXML(inFile);
inFile.close();
Node rootElm = doc.getDocumentElement();
for (int n = 0; n < rootElm.getChildNodes().getLength(); n++) {
Node child = rootElm.getChildNodes().item(n);
if ((child.getNodeType() == Node.ELEMENT_NODE)
&& (child.getNodeName().equals(ELEM_USER))) {
String userName = null;
String password = null;
String roleList = null;
// Loop through for attributes
for (int j = 0; j < child.getAttributes().getLength(); j++) {
Node thisAtt = child.getAttributes().item(j);
if (thisAtt.getNodeName().equals(ATT_USERNAME))
userName = thisAtt.getNodeValue();
else if (thisAtt.getNodeName().equals(ATT_PASSWORD))
password = thisAtt.getNodeValue();
else if (thisAtt.getNodeName().equals(ATT_ROLELIST))
roleList = thisAtt.getNodeValue();
}
if ((userName == null) || (password == null)
|| (roleList == null))
Logger.log(Logger.FULL_DEBUG, REALM_RESOURCES,
"FileRealm.SkippingUser", userName);
else {
// Parse the role list into an array and sort it
StringTokenizer st = new StringTokenizer(roleList, ",");
List<String> rl = new ArrayList<String>();
for (; st.hasMoreTokens();) {
String currentRole = st.nextToken();
rl.add(currentRole);
}
String[] roleArray = rl.toArray(new String[rl.size()]);
Arrays.sort(roleArray);
userStore.addUser(userName, getCredential(password), roleArray);
count++;
}
}
}
Logger.log(Logger.DEBUG, REALM_RESOURCES, "FileRealm.Initialised",
"" + count);
} catch (java.io.IOException err) {
throw new WinstoneException(REALM_RESOURCES
.getString("FileRealm.ErrorLoading"), err);
}
}
/**
* Get a parsed XML DOM from the given inputstream. Used to process the
* web.xml application deployment descriptors.
*/
private Document parseStreamToXML(InputStream in) {
try {
// Use JAXP to create a document builder
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setExpandEntityReferences(false);
factory.setValidating(false);
factory.setNamespaceAware(false);
factory.setIgnoringComments(true);
factory.setCoalescing(true);
factory.setIgnoringElementContentWhitespace(true);
DocumentBuilder builder = factory.newDocumentBuilder();
return builder.parse(in);
} catch (Throwable errParser) {
throw new WinstoneException(REALM_RESOURCES
.getString("FileRealm.XMLParseError"), errParser);
}
}
}