package org.springframework.roo.addon.security; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; import java.util.List; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.Validate; import org.apache.felix.scr.annotations.Component; import org.apache.felix.scr.annotations.Reference; import org.apache.felix.scr.annotations.Service; import org.springframework.roo.addon.web.mvc.controller.WebMvcOperations; import org.springframework.roo.addon.web.mvc.jsp.tiles.TilesOperations; import org.springframework.roo.process.manager.FileManager; import org.springframework.roo.project.Dependency; import org.springframework.roo.project.FeatureNames; import org.springframework.roo.project.Path; import org.springframework.roo.project.PathResolver; import org.springframework.roo.project.ProjectOperations; import org.springframework.roo.project.Property; import org.springframework.roo.support.util.DomUtils; import org.springframework.roo.support.util.FileUtils; import org.springframework.roo.support.util.WebXmlUtils; import org.springframework.roo.support.util.XmlElementBuilder; import org.springframework.roo.support.util.XmlUtils; import org.w3c.dom.Document; import org.w3c.dom.Element; /** * Provides security installation services. * * @author Ben Alex * @author Stefan Schmidt * @author Alan Stewart * @since 1.0 */ @Component @Service public class SecurityOperationsImpl implements SecurityOperations { private static final Dependency SPRING_SECURITY = new Dependency( "org.springframework.security", "spring-security-core", "3.1.0.RELEASE"); @Reference private FileManager fileManager; @Reference private PathResolver pathResolver; @Reference private ProjectOperations projectOperations; @Reference private TilesOperations tilesOperations; public void installSecurity() { // Parse the configuration.xml file final Element configuration = XmlUtils.getConfiguration(getClass()); // Add POM properties updatePomProperties(configuration, projectOperations.getFocusedModuleName()); // Add dependencies to POM updateDependencies(configuration, projectOperations.getFocusedModuleName()); // Copy the template across final String destination = pathResolver.getFocusedIdentifier( Path.SPRING_CONFIG_ROOT, "applicationContext-security.xml"); if (!fileManager.exists(destination)) { InputStream inputStream = null; OutputStream outputStream = null; try { inputStream = FileUtils.getInputStream(getClass(), "applicationContext-security-template.xml"); outputStream = fileManager.createFile(destination) .getOutputStream(); IOUtils.copy(inputStream, outputStream); } catch (final IOException ioe) { throw new IllegalStateException(ioe); } finally { IOUtils.closeQuietly(inputStream); IOUtils.closeQuietly(outputStream); } } // Copy the template across final String loginPage = pathResolver.getFocusedIdentifier( Path.SRC_MAIN_WEBAPP, "WEB-INF/views/login.jspx"); if (!fileManager.exists(loginPage)) { InputStream inputStream = null; OutputStream outputStream = null; try { inputStream = FileUtils .getInputStream(getClass(), "login.jspx"); outputStream = fileManager.createFile(loginPage) .getOutputStream(); IOUtils.copy(inputStream, outputStream); } catch (final IOException ioe) { throw new IllegalStateException(ioe); } finally { IOUtils.closeQuietly(inputStream); IOUtils.closeQuietly(outputStream); } } if (fileManager.exists(pathResolver.getFocusedIdentifier( Path.SRC_MAIN_WEBAPP, "WEB-INF/views/views.xml"))) { tilesOperations.addViewDefinition("", pathResolver.getFocusedPath(Path.SRC_MAIN_WEBAPP), "login", TilesOperations.PUBLIC_TEMPLATE, "/WEB-INF/views/login.jspx"); } final String webXmlPath = pathResolver.getFocusedIdentifier( Path.SRC_MAIN_WEBAPP, "WEB-INF/web.xml"); final Document webXmlDocument = XmlUtils.readXml(fileManager .getInputStream(webXmlPath)); WebXmlUtils.addFilterAtPosition(WebXmlUtils.FilterPosition.BETWEEN, WebMvcOperations.HTTP_METHOD_FILTER_NAME, WebMvcOperations.OPEN_ENTITYMANAGER_IN_VIEW_FILTER_NAME, SecurityOperations.SECURITY_FILTER_NAME, "org.springframework.web.filter.DelegatingFilterProxy", "/*", webXmlDocument, null); fileManager.createOrUpdateTextFileIfRequired(webXmlPath, XmlUtils.nodeToString(webXmlDocument), false); // Include static view controller handler to webmvc-config.xml final String webConfigPath = pathResolver.getFocusedIdentifier( Path.SRC_MAIN_WEBAPP, "WEB-INF/spring/webmvc-config.xml"); final Document webConfigDocument = XmlUtils.readXml(fileManager .getInputStream(webConfigPath)); final Element webConfig = webConfigDocument.getDocumentElement(); final Element viewController = DomUtils.findFirstElementByName( "mvc:view-controller", webConfig); Validate.notNull(viewController, "Could not find mvc:view-controller in " + webConfig); viewController.getParentNode() .insertBefore( new XmlElementBuilder("mvc:view-controller", webConfigDocument).addAttribute("path", "/login").build(), viewController); fileManager.createOrUpdateTextFileIfRequired(webConfigPath, XmlUtils.nodeToString(webConfigDocument), false); } public boolean isSecurityInstallationPossible() { // Permit installation if they have a web project (as per ROO-342) and // no version of Spring Security is already installed. return projectOperations.isFocusedProjectAvailable() && fileManager.exists(pathResolver.getFocusedIdentifier( Path.SRC_MAIN_WEBAPP, "WEB-INF/web.xml")) && !projectOperations.getFocusedModule() .hasDependencyExcludingVersion(SPRING_SECURITY) && !projectOperations.isFeatureInstalledInFocusedModule( FeatureNames.JSF, FeatureNames.GWT); } private void updateDependencies(final Element configuration, final String moduleName) { final List<Dependency> dependencies = new ArrayList<Dependency>(); final List<Element> securityDependencies = XmlUtils.findElements( "/configuration/spring-security/dependencies/dependency", configuration); for (final Element dependencyElement : securityDependencies) { dependencies.add(new Dependency(dependencyElement)); } projectOperations.addDependencies(moduleName, dependencies); } private void updatePomProperties(final Element configuration, final String moduleName) { final List<Element> databaseProperties = XmlUtils.findElements( "/configuration/spring-security/properties/*", configuration); for (final Element property : databaseProperties) { projectOperations.addProperty(moduleName, new Property(property)); } } }