001: package acegifier;
002:
003: import java.io.IOException;
004: import java.io.InputStream;
005: import java.util.List;
006:
007: import javax.xml.transform.Source;
008: import javax.xml.transform.Transformer;
009: import javax.xml.transform.TransformerConfigurationException;
010: import javax.xml.transform.TransformerException;
011: import javax.xml.transform.TransformerFactory;
012: import javax.xml.transform.stream.StreamSource;
013:
014: import org.dom4j.Document;
015: import org.dom4j.DocumentException;
016: import org.dom4j.DocumentHelper;
017: import org.dom4j.Node;
018: import org.dom4j.io.DocumentResult;
019: import org.dom4j.io.DocumentSource;
020: import org.dom4j.io.SAXReader;
021: import org.springframework.core.io.ClassPathResource;
022: import org.springframework.util.Assert;
023:
024: /**
025: * A utility to translate a web.xml file into a set of acegi security spring beans.
026: *
027: * <p>
028: * Also produces a new "acegified" web.xml file with the necessary filters installed
029: * and the security elements defined by the servlet DTD removed.
030: *
031: * <p>
032: * This class wraps the XSL transform which actually does most of the work.
033: * </p>
034: *
035: * @author Luke Taylor
036: * @version $Id: WebXmlConverter.java 1784 2007-02-24 21:00:24Z luke_t $
037: */
038: public class WebXmlConverter {
039: private static final String WEB_TO_SPRING_XSL_FILE = "web-to-spring.xsl";
040: private static final String NEW_WEB_XSLT_FILE = "acegi-web.xsl";
041:
042: private Transformer acegiSecurityTransformer, newWebXmlTransformer;
043:
044: /**
045: * The name of the spring-beans file which the beans will be stored in.
046: * This is required when writing the new web.xml content.
047: */
048: private String acegiOutputFileName = "applicationContext-acegi-security.xml";
049:
050: /** The web.xml content to be converted */
051: private Source xmlSource;
052: /** The results of the conversion */
053: private Document newWebXml, acegiBeansXml;
054:
055: public WebXmlConverter() throws IOException,
056: TransformerConfigurationException {
057: TransformerFactory tf = TransformerFactory.newInstance();
058: Source source = createTransformerSource(WEB_TO_SPRING_XSL_FILE);
059: System.out.println("1");
060: acegiSecurityTransformer = tf.newTransformer(source);
061: System.out.println("2");
062: newWebXmlTransformer = tf
063: .newTransformer(createTransformerSource(NEW_WEB_XSLT_FILE));
064: System.out.println("3");
065: }
066:
067: private Source createTransformerSource(String fileName)
068: throws IOException {
069: ClassPathResource resource = new ClassPathResource(fileName);
070: Source source = new StreamSource(resource.getInputStream());
071: return source;
072: }
073:
074: /**
075: * Performs the transformations on the input source.
076: * Creates new web.xml content and a set of acegi-security Spring beans which can be
077: * accessed through the appropriate getter methods.
078: */
079: public void doConversion() throws IOException, TransformerException {
080: Assert.notNull(xmlSource, "The XML input must be set");
081:
082: // Create the modified web.xml file
083: newWebXmlTransformer.setParameter(
084: "acegi-security-context-file", acegiOutputFileName);
085: // newWebXmlTransformer.setParameter("cas-proxy-url", "http://localhost:8433/cas/proxy");
086: DocumentResult result = new DocumentResult();
087: newWebXmlTransformer.transform(xmlSource, result);
088: newWebXml = result.getDocument();
089:
090: result = new DocumentResult();
091: acegiSecurityTransformer.transform(xmlSource, result);
092: acegiBeansXml = result.getDocument();
093: }
094:
095: /** Set the input as an xml string */
096: public void setInput(String xml) throws DocumentException {
097: setInput(DocumentHelper.parseText(xml));
098: }
099:
100: /** Set the input as a stream */
101: public void setInput(InputStream in) throws DocumentException {
102: SAXReader reader = new SAXReader();
103: setInput(reader.read(in));
104: }
105:
106: /** set the input as a dom4j document */
107: public void setInput(Document document) throws DocumentException {
108: validateWebXml(document);
109: xmlSource = new DocumentSource(document);
110: }
111:
112: /** Checks the web.xml to make sure it contains correct data */
113: private void validateWebXml(Document document)
114: throws DocumentException {
115: Node authMethodNode = document
116: .selectSingleNode("/web-app/login-config/auth-method");
117: if (authMethodNode == null)
118: throw new DocumentException(
119: "login-config and auth-method must be present");
120: String authMethod = authMethodNode.getStringValue()
121: .toUpperCase();
122: if (!authMethod.equals("BASIC") && !authMethod.equals("FORM")) {
123: throw new DocumentException("unsupported auth-method: "
124: + authMethod);
125: }
126: List roles = document.selectNodes("/web-app/security-role");
127: if (roles.isEmpty()) {
128: throw new DocumentException(
129: "Each role used must be defined in a security-role element");
130: }
131: }
132:
133: public String getAcegiOutputFileName() {
134: return acegiOutputFileName;
135: }
136:
137: public void setAcegiOutputFileName(String acegiOutputFileName) {
138: this .acegiOutputFileName = acegiOutputFileName;
139: }
140:
141: /** Returns the converted web.xml content */
142: public Document getNewWebXml() {
143: return newWebXml;
144: }
145:
146: /**
147: * Returns the created spring-beans xml content which should be used in
148: * the application context file.
149: */
150: public Document getAcegiBeans() {
151: return acegiBeansXml;
152: }
153: }
|