1 package acegifier;
2
3 import java.io.IOException;
4 import java.io.InputStream;
5 import java.util.List;
6
7 import javax.xml.transform.Source;
8 import javax.xml.transform.Transformer;
9 import javax.xml.transform.TransformerConfigurationException;
10 import javax.xml.transform.TransformerException;
11 import javax.xml.transform.TransformerFactory;
12 import javax.xml.transform.stream.StreamSource;
13
14 import org.dom4j.Document;
15 import org.dom4j.DocumentException;
16 import org.dom4j.DocumentHelper;
17 import org.dom4j.Node;
18 import org.dom4j.io.DocumentResult;
19 import org.dom4j.io.DocumentSource;
20 import org.dom4j.io.SAXReader;
21 import org.springframework.core.io.ClassPathResource;
22 import org.springframework.util.Assert;
23
24 /***
25 * A utility to translate a web.xml file into a set of acegi security spring beans.
26 *
27 * Also produces a new "acegified" web.xml file with the necessary filters installed
28 * and the security elements defined by the servlet DTD removed.
29 *
30 * <p>
31 * This class wraps the XSL transform which actually does most of the work.
32 * </p>
33 *
34 * @author Luke Taylor
35 * @version $Id: WebXmlConverter.java,v 1.1 2005/11/29 02:33:40 benalex Exp $
36 */
37 public class WebXmlConverter {
38 private static final String WEB_TO_SPRING_XSL_FILE = "web-to-spring.xsl";
39 private static final String NEW_WEB_XSLT_FILE = "acegi-web.xsl";
40
41 private Transformer acegiSecurityTransformer, newWebXmlTransformer;
42
43 /***
44 * The name of the spring-beans file which the beans will be stored in.
45 * This is required when writing the new web.xml content.
46 */
47 private String acegiOutputFileName = "applicationContext-acegi-security.xml";
48
49 /*** The web.xml content to be converted */
50 private Source xmlSource;
51 /*** The results of the conversion */
52 private Document newWebXml, acegiBeansXml;
53
54 public WebXmlConverter() throws IOException, TransformerConfigurationException {
55 TransformerFactory tf = TransformerFactory.newInstance();
56 Source source = createTransformerSource(WEB_TO_SPRING_XSL_FILE);
57 System.out.println("1");
58 acegiSecurityTransformer = tf.newTransformer(source);
59 System.out.println("2");
60 newWebXmlTransformer = tf.newTransformer(createTransformerSource(NEW_WEB_XSLT_FILE));
61 System.out.println("3");
62 }
63
64 private Source createTransformerSource(String fileName) throws IOException {
65 ClassPathResource resource = new ClassPathResource(fileName);
66 Source source = new StreamSource(resource.getInputStream());
67 return source;
68 }
69
70 /***
71 * Performs the transformations on the input source.
72 * Creates new web.xml content and a set of acegi-security Spring beans which can be
73 * accessed through the appropriate getter methods.
74 */
75 public void doConversion() throws IOException, TransformerException {
76 Assert.notNull(xmlSource, "The XML input must be set");
77
78
79 newWebXmlTransformer.setParameter("acegi-security-context-file", acegiOutputFileName);
80
81 DocumentResult result = new DocumentResult();
82 newWebXmlTransformer.transform(xmlSource, result);
83 newWebXml = result.getDocument();
84
85 result = new DocumentResult();
86 acegiSecurityTransformer.transform(xmlSource, result);
87 acegiBeansXml = result.getDocument();
88 }
89
90 /*** Set the input as an xml string */
91 public void setInput(String xml) throws DocumentException {
92 setInput(DocumentHelper.parseText(xml));
93 }
94
95 /*** Set the input as a stream */
96 public void setInput(InputStream in) throws DocumentException {
97 SAXReader reader = new SAXReader();
98 setInput(reader.read(in));
99 }
100
101 /*** set the input as a dom4j document */
102 public void setInput(Document document) throws DocumentException {
103 validateWebXml(document);
104 xmlSource = new DocumentSource(document);
105 }
106
107 /*** Checks the web.xml to make sure it contains correct data */
108 private void validateWebXml(Document document) throws DocumentException {
109 Node authMethodNode =
110 document.selectSingleNode("/web-app/login-config/auth-method");
111 if(authMethodNode == null)
112 throw new DocumentException("login-config and auth-method must be present");
113 String authMethod = authMethodNode.getStringValue().toUpperCase();
114 if(!authMethod.equals("BASIC") && !authMethod.equals("FORM")) {
115 throw new DocumentException("unsupported auth-method: " + authMethod);
116 }
117 List roles = document.selectNodes("/web-app/security-role");
118 if(roles.isEmpty()) {
119 throw new DocumentException("Each role used must be defined in a security-role element");
120 }
121 }
122
123 public String getAcegiOutputFileName() {
124 return acegiOutputFileName;
125 }
126
127 public void setAcegiOutputFileName(String acegiOutputFileName) {
128 this.acegiOutputFileName = acegiOutputFileName;
129 }
130
131 /*** Returns the converted web.xml content */
132 public Document getNewWebXml() {
133 return newWebXml;
134 }
135
136 /***
137 * Returns the created spring-beans xml content which should be used in
138 * the application context file.
139 */
140 public Document getAcegiBeans() {
141 return acegiBeansXml;
142 }
143 }