/*
* gvNIX is an open source tool for rapid application development (RAD).
* Copyright (C) 2010 Generalitat Valenciana
*
* This program is free software: you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.gvnix.web.typicalsecurity.roo.addon;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.StringWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.logging.Logger;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
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.gvnix.support.WebProjectUtils;
import org.gvnix.web.typicalsecurity.roo.addon.listeners.TypicalSecurityDependencyListener;
import org.gvnix.web.typicalsecurity.roo.addon.utils.TokenReplacementFileCopyUtils;
import org.osgi.framework.BundleContext;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference;
import org.osgi.service.component.ComponentContext;
import org.springframework.roo.model.JavaPackage;
import org.springframework.roo.process.manager.FileManager;
import org.springframework.roo.process.manager.MutableFile;
import org.springframework.roo.project.Dependency;
import org.springframework.roo.project.FeatureNames;
import org.springframework.roo.project.LogicalPath;
import org.springframework.roo.project.Path;
import org.springframework.roo.project.PathResolver;
import org.springframework.roo.project.ProjectOperations;
import org.springframework.roo.shell.Shell;
import org.springframework.roo.support.logging.HandlerUtils;
import org.springframework.roo.support.util.DomUtils;
import org.springframework.roo.support.util.FileUtils;
import org.springframework.roo.support.util.XmlElementBuilder;
import org.springframework.roo.support.util.XmlUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
/**
* Implementation of commands that are available via the Roo shell.
*
* @author <a href="http://www.disid.com">DISID Corporation S.L.</a> made for <a
* href="http://www.dgti.gva.es">General Directorate for Information
* Technologies (DGTI)</a>
* @since 1.1
*/
@Component
@Service
public class TypicalsecurityOperationsImpl implements TypicalsecurityOperations {
private static final Logger LOGGER = HandlerUtils
.getLogger(TypicalsecurityOperationsImpl.class);
private static final String VIEWS = "views/";
private static final String SIGNUP = "signup";
private static final String INTERCEPT_URL = "intercept-url";
private static final String COULD_NOT_ACQUIRE = "Could not acquire ";
@Reference
private FileManager fileManager;
@Reference
private PathResolver pathResolver;
@Reference
private ProjectOperations projectOperations;
@Reference
private Shell shell;
private WebProjectUtils webProjectUtils;
/**
* Uses to ensure that dependencyListener will be loaded
*/
@Reference
private TypicalSecurityDependencyListener dependencyListener;
// ------------ OSGi component attributes ----------------
private BundleContext context;
protected void activate(ComponentContext cContext) {
context = cContext.getBundleContext();
}
/*
* Not available since Roo 1.1.2 (See ROO-2066)
*
* @Reference private ClasspathOperations classpathOperations;
*/
private static final char SEPARATOR = File.separatorChar;
public boolean isCommandAvailable() {
/*
* Not available since Roo 1.1.2 (See ROO-2066) return getPathResolver()
* != null && classpathOperations.isPersistentClassAvailable();
*/
return projectOperations.isFocusedProjectAvailable();
}
public String setup(String entityPackage, String controllerPackage) {
injectCaptchaDependency();
createUserRoleEntities(entityPackage);
createControllers(entityPackage, controllerPackage);
injectDatabasebasedSecurity(entityPackage, controllerPackage);
if (projectOperations
.isFeatureInstalledInFocusedModule("gvnix-bootstrap")) {
updateTypicalSecurityAddonToBootstrap();
}
return "Done";
}
private void injectCaptchaDependency() {
// <dependency>
// <groupId>net.tanesha.recaptcha4j</groupId>
// <artifactId>recaptcha4j</artifactId>
// <version>0.0.7</version>
// </dependency>
projectOperations.addDependency(projectOperations
.getFocusedModuleName(), new Dependency(
"net.tanesha.recaptcha4j", "recaptcha4j", "0.0.7"));
}
/**
* Create All the entities required for User, Role and User Role
*
* @param entityPackage
*/
private void createUserRoleEntities(String entityPackage) {
// -----------------------------------------------------------------------------------
// Create User entity
// -----------------------------------------------------------------------------------
shell.executeCommand("entity jpa --class ".concat(entityPackage)
.concat(".User --testAutomatically --permitReservedWords"));
shell.executeCommand("field string --fieldName firstName --sizeMin 1 --notNull");
shell.executeCommand("field string --fieldName lastName --sizeMin 1 --notNull");
shell.executeCommand("field string --fieldName emailAddress --sizeMin 1 --notNull --unique");
shell.executeCommand("field string --fieldName password --sizeMin 1 --notNull");
shell.executeCommand("field date --fieldName activationDate --type java.util.Date ");
shell.executeCommand("field string --fieldName activationKey ");
shell.executeCommand("field boolean --fieldName enabled ");
shell.executeCommand("field boolean --fieldName locked ");
// -----------------------------------------------------------------------------------
// Create Role entity
// -----------------------------------------------------------------------------------
shell.executeCommand("entity jpa --class ".concat(entityPackage)
.concat(".Role --testAutomatically --permitReservedWords"));
shell.executeCommand("field string --fieldName roleName --sizeMin 1 --notNull --unique");
shell.executeCommand("field string --fieldName roleDescription --sizeMin --sizeMax 200 --notNull");
// -----------------------------------------------------------------------------------
// Create User Role Mapping
// -----------------------------------------------------------------------------------
shell.executeCommand("entity jpa --class ".concat(entityPackage)
.concat(".UserRole --testAutomatically"));
shell.executeCommand("field reference --fieldName userEntry --type "
.concat(entityPackage).concat(".User --notNull"));
shell.executeCommand("field reference --fieldName roleEntry --type "
.concat(entityPackage).concat(".Role --notNull"));
// -----------------------------------------------------------------------------------
// Create Finders for find user by email address and find user role by
// user
// -----------------------------------------------------------------------------------
shell.executeCommand("finder add findUsersByEmailAddress --class "
.concat(entityPackage).concat(".User"));
shell.executeCommand("finder add findUsersByActivationKeyAndEmailAddress --class "
.concat(entityPackage).concat(".User"));
shell.executeCommand("finder add findUserRolesByUserEntry --class "
.concat(entityPackage).concat(".UserRole"));
}
/**
* Create an Controller for User, Role and UserRole
*
* @param entityPackage
* @param controllerPackage
*/
private void createControllers(String entityPackage,
String controllerPackage) {
// -----------------------------------------------------------------------------------
// Controller for User
// -----------------------------------------------------------------------------------
shell.executeCommand(String
.format("web mvc scaffold --class %s.UserController --backingType %s.User",
controllerPackage, entityPackage));
// -----------------------------------------------------------------------------------
// Controller for Role
// -----------------------------------------------------------------------------------
shell.executeCommand(String
.format("web mvc scaffold --class %s.RoleController --backingType %s.Role",
controllerPackage, entityPackage));
// -----------------------------------------------------------------------------------
// Controller for User Role
// -----------------------------------------------------------------------------------
shell.executeCommand(String
.format("web mvc scaffold --class %s.UserRoleController --backingType %s.UserRole",
controllerPackage, entityPackage));
}
/**
* Inject database based authentication provider in Spring Security
*
* @param entityPackage
*/
private void injectDatabasebasedSecurity(String entityPackage,
String controllerPackage) {
// ----------------------------------------------------------------------
// Run Security Setup Addon
// ----------------------------------------------------------------------
shell.executeCommand("security setup");
// ----------------------------------------------------------------------
// Copy DatabaseAuthenticationProvider from template
// ----------------------------------------------------------------------
createAuthenticationProvider(entityPackage, controllerPackage);
// ----------------------------------------------------------------------
// Inject database based authentication provider into
// applicationContext-security.xml
// ----------------------------------------------------------------------
injectDatabasebasedAuthProviderInXml();
// ----------------------------------------------------------------------
// Autowire MessageDigestPasswordEncoder in applicationContext.xml
// ----------------------------------------------------------------------
autowireMessageDigestPasswordEncoder();
createMailSender();
addForgotPasswordRegisterUserToLoginPage();
addChangePasswordToFooter();
}
private void createMailSender() {
shell.executeCommand("email sender setup --hostServer smtp.gmail.com --port 587 --protocol SMTP --username rohitsghatoltest@gmail.com --password password4me");
shell.executeCommand("email template setup --from rohitsghatoltest@gmail.com --subject \"Password Recovery\"");
}
/**
* Inject database based authentication provider into
* applicationContext-security.xml
*
*/
private void injectDatabasebasedAuthProviderInXml() {
String springSecurity = pathResolver.getFocusedIdentifier(
Path.SRC_MAIN_RESOURCES,
"META-INF/spring/applicationContext-security.xml");
MutableFile mutableConfigXml = null;
Document webConfigDoc;
try {
if (fileManager.exists(springSecurity)) {
mutableConfigXml = fileManager.updateFile(springSecurity);
webConfigDoc = XmlUtils.getDocumentBuilder().parse(
mutableConfigXml.getInputStream());
}
else {
throw new IllegalStateException(
COULD_NOT_ACQUIRE.concat(springSecurity));
}
}
catch (Exception e) {
throw new IllegalStateException(e);
}
Element firstInterceptUrl = XmlUtils.findFirstElementByName(
INTERCEPT_URL, webConfigDoc.getDocumentElement());
assert firstInterceptUrl != null : "Could not find intercept-url in "
+ springSecurity;
firstInterceptUrl.getParentNode().insertBefore(
new XmlElementBuilder(INTERCEPT_URL, webConfigDoc)
.addAttribute("pattern", "/forgotpassword/**")
.addAttribute("access", "permitAll").build(),
firstInterceptUrl);
firstInterceptUrl.getParentNode().insertBefore(
new XmlElementBuilder(INTERCEPT_URL, webConfigDoc)
.addAttribute("pattern", "/signup/**")
.addAttribute("access", "permitAll").build(),
firstInterceptUrl);
firstInterceptUrl.getParentNode().insertBefore(
new XmlElementBuilder(INTERCEPT_URL, webConfigDoc)
.addAttribute("pattern", "/")
.addAttribute("access", "isAuthenticated()").build(),
firstInterceptUrl);
JavaPackage topLevelPackage = projectOperations
.getFocusedTopLevelPackage();
String authenticationProviderClass = topLevelPackage
.getFullyQualifiedPackageName()
+ ".provider.DatabaseAuthenticationProvider";
Element dbProviderBean = new XmlElementBuilder("beans:bean",
webConfigDoc)
.addAttribute("id", "databaseAuthenticationProvider")
.addAttribute("class", authenticationProviderClass)
.addChild(
new XmlElementBuilder("beans:property", webConfigDoc)
.addAttribute("name", "adminUser")
.addAttribute("value", "admin").build())
.addChild(
new XmlElementBuilder("beans:property", webConfigDoc)
.addAttribute("name", "adminPassword")
.addAttribute("value",
"8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918")
.build()).build();
Element authenticationManager = XmlUtils.findFirstElementByName(
"authentication-manager", webConfigDoc.getDocumentElement());
authenticationManager.getParentNode().insertBefore(dbProviderBean,
authenticationManager);
Element oldAuthProvider = XmlUtils.findFirstElementByName(
"authentication-provider", webConfigDoc.getDocumentElement());
// <authentication-provider ref="databaseAuthenticationProvider" />
Element newAuthProvider = new XmlElementBuilder(
"authentication-provider", webConfigDoc).addAttribute("ref",
"databaseAuthenticationProvider").build();
authenticationManager.replaceChild(newAuthProvider, oldAuthProvider);
// newAuthProvider.appendChild(
// new XmlElementBuilder("password-encoder", webConfigDoc)
// .addAttribute("hash", "sha-256").build());
OutputStream out = null;
try {
out = mutableConfigXml.getOutputStream();
XmlUtils.writeXml(out, webConfigDoc);
}
finally {
IOUtils.closeQuietly(out);
}
}
/**
* Inject MessageDigestPasswordEncoder bean in applicationContext.xml
*
*/
private void autowireMessageDigestPasswordEncoder() {
String applicationContextSecurity = pathResolver.getFocusedIdentifier(
Path.SRC_MAIN_RESOURCES,
"META-INF/spring/applicationContext-security.xml");
MutableFile mutableConfigXml = null;
Document webConfigDoc;
try {
if (fileManager.exists(applicationContextSecurity)) {
mutableConfigXml = fileManager
.updateFile(applicationContextSecurity);
webConfigDoc = XmlUtils.getDocumentBuilder().parse(
mutableConfigXml.getInputStream());
}
else {
throw new IllegalStateException(COULD_NOT_ACQUIRE
+ applicationContextSecurity);
}
}
catch (Exception e) {
throw new IllegalStateException(e);
}
Element messageDigestPasswordEncoder = new XmlElementBuilder(
"beans:bean", webConfigDoc)
.addAttribute("id", "messageDigestPasswordEncoder")
.addAttribute(
"class",
"org.springframework.security.authentication.encoding.MessageDigestPasswordEncoder")
.addChild(
new XmlElementBuilder("beans:constructor-arg",
webConfigDoc).addAttribute("value", "sha-256")
.build()).build();
webConfigDoc.getDocumentElement().appendChild(
messageDigestPasswordEncoder);
XmlUtils.writeXml(mutableConfigXml.getOutputStream(), webConfigDoc);
}
/**
* Copy DatabaseAuthenticationProvider from template
*
* @param entityPackage
*/
private void createAuthenticationProvider(String entityPackage,
String controllerPackage) {
JavaPackage topLevelPackage = projectOperations
.getFocusedTopLevelPackage();
final String packagePath = topLevelPackage
.getFullyQualifiedPackageName().replace('.', SEPARATOR);
final String finalEntityPackage = entityPackage.replace("~",
topLevelPackage.getFullyQualifiedPackageName());
final String finalControllerPackage = controllerPackage.replace("~",
topLevelPackage.getFullyQualifiedPackageName());
Properties properties = new Properties();
properties.put("__TOP_LEVEL_PACKAGE__",
topLevelPackage.getFullyQualifiedPackageName());
properties.put("__ENTITY_LEVEL_PACKAGE__", finalEntityPackage);
properties.put("__CONTROLLER_PACKAGE__", finalControllerPackage);
Map<String, String> map = new HashMap<String, String>();
final String controllerPath = finalControllerPackage.replace('.',
SEPARATOR);
map.put(pathResolver.getFocusedIdentifier(Path.SRC_MAIN_JAVA,
joinPath(controllerPath, "ChangePasswordController.java")),
"ChangePasswordController.java-template");
map.put(pathResolver.getFocusedIdentifier(Path.SRC_MAIN_JAVA,
joinPath(controllerPath, "ChangePasswordForm.java")),
"ChangePasswordForm.java-template");
map.put(pathResolver.getFocusedIdentifier(Path.SRC_MAIN_JAVA,
joinPath(controllerPath, "ChangePasswordValidator.java")),
"ChangePasswordValidator.java-template");
map.put(pathResolver.getFocusedIdentifier(Path.SRC_MAIN_JAVA,
joinPath(controllerPath, "SignUpController.java")),
"SignUpController.java-template");
map.put(pathResolver.getFocusedIdentifier(Path.SRC_MAIN_JAVA,
joinPath(controllerPath, "UserRegistrationForm.java")),
"UserRegistrationForm.java-template");
map.put(pathResolver.getFocusedIdentifier(Path.SRC_MAIN_JAVA,
joinPath(controllerPath, "SignUpValidator.java")),
"SignUpValidator.java-template");
map.put(pathResolver.getFocusedIdentifier(Path.SRC_MAIN_JAVA,
joinPath(controllerPath, "ForgotPasswordController.java")),
"ForgotPasswordController.java-template");
map.put(pathResolver.getFocusedIdentifier(Path.SRC_MAIN_JAVA,
joinPath(controllerPath, "ForgotPasswordForm.java")),
"ForgotPasswordForm.java-template");
map.put(pathResolver.getFocusedIdentifier(
Path.SRC_MAIN_JAVA,
joinPath(packagePath, "provider",
"DatabaseAuthenticationProvider.java")),
"DatabaseAuthenticationProvider.java-template");
map.put(pathResolver.getFocusedIdentifier(Path.SRC_MAIN_JAVA,
joinPath(controllerPath, "UserController.java")),
"UserController.java-template");
final String prefix = SEPARATOR + "WEB-INF/views";
map.put(pathResolver.getFocusedIdentifier(Path.SRC_MAIN_WEBAPP,
joinPath(prefix, SIGNUP, "index.jspx")), "signup/index.jspx");
map.put(pathResolver.getFocusedIdentifier(Path.SRC_MAIN_WEBAPP,
joinPath(prefix, SIGNUP, "thanks.jspx")), "signup/thanks.jspx");
map.put(pathResolver.getFocusedIdentifier(Path.SRC_MAIN_WEBAPP,
joinPath(prefix, SIGNUP, "error.jspx")), "signup/error.jspx");
map.put(pathResolver.getFocusedIdentifier(Path.SRC_MAIN_WEBAPP,
joinPath(prefix, SIGNUP, "views.xml")), "signup/views.xml");
map.put(pathResolver.getFocusedIdentifier(Path.SRC_MAIN_WEBAPP,
joinPath(prefix, "forgotpassword", "index.jspx")),
"forgotpassword/index.jspx");
map.put(pathResolver.getFocusedIdentifier(Path.SRC_MAIN_WEBAPP,
joinPath(prefix, "forgotpassword", "thanks.jspx")),
"forgotpassword/thanks.jspx");
map.put(pathResolver.getFocusedIdentifier(Path.SRC_MAIN_WEBAPP,
joinPath(prefix, "forgotpassword", "views.xml")),
"forgotpassword/views.xml");
map.put(pathResolver.getFocusedIdentifier(Path.SRC_MAIN_WEBAPP,
joinPath(prefix, "changepassword", "index.jspx")),
"changepassword/index.jspx");
map.put(pathResolver.getFocusedIdentifier(Path.SRC_MAIN_WEBAPP,
joinPath(prefix, "changepassword", "thanks.jspx")),
"changepassword/thanks.jspx");
map.put(pathResolver.getFocusedIdentifier(Path.SRC_MAIN_WEBAPP,
joinPath(prefix, "changepassword", "views.xml")),
"changepassword/views.xml");
for (Entry<String, String> entry : map.entrySet()) {
MutableFile mutableFile = null;
final String path = entry.getKey();
final String file = entry.getValue();
InputStream ins = null;
OutputStream outs = null;
try {
if (fileManager.exists(path)) {
mutableFile = fileManager.updateFile(path);
}
else {
mutableFile = fileManager.createFile(path);
}
ins = FileUtils.getInputStream(getClass(), file);
outs = mutableFile.getOutputStream();
TokenReplacementFileCopyUtils.replaceAndCopy(ins, outs,
properties);
insertI18nMessages();
}
catch (IOException ioe) {
throw new IllegalStateException(ioe);
}
finally {
IOUtils.closeQuietly(ins);
IOUtils.closeQuietly(outs);
}
}
}
/**
* Join a list of element with {@link #SEPARATOR}
*
* @param elements
* @return
*/
private String joinPath(String... elements) {
return StringUtils.join(elements, SEPARATOR);
}
private void addChangePasswordToFooter() {
// Look for following in footer.jspx
// <a href="${logout}">
// <spring:message code="security_logout"/>
// </a>
// and append
// <a href="changePassword/index">Change Password</a>
String footerJspx = pathResolver.getFocusedIdentifier(
Path.SRC_MAIN_WEBAPP, "WEB-INF/views/footer.jspx");
MutableFile mutableFooterJspx = null;
Document footerJspxDoc;
OutputStream out = null;
try {
if (fileManager.exists(footerJspx)) {
mutableFooterJspx = fileManager.updateFile(footerJspx);
footerJspxDoc = XmlUtils.getDocumentBuilder().parse(
mutableFooterJspx.getInputStream());
Element logout = XmlUtils.findFirstElement(
"//a[@href=\"${logout}\"]",
footerJspxDoc.getDocumentElement());
Validate.notNull(logout,
"Could not find <a href=\"${logout}\"> in "
.concat(footerJspx));
logout.getParentNode().appendChild(
new XmlElementBuilder("div", footerJspxDoc).addChild(
footerJspxDoc.createTextNode("|")).build());
String contextPath = projectOperations.getFocusedProjectName();
logout.getParentNode().appendChild(
new XmlElementBuilder("a", footerJspxDoc)
.addAttribute(
"href",
"/".concat(contextPath).concat(
"/changepassword/index"))
.addChild(
footerJspxDoc
.createTextNode("password"))
.build());
out = mutableFooterJspx.getOutputStream();
XmlUtils.writeXml(out, footerJspxDoc);
}
else {
throw new IllegalStateException(
COULD_NOT_ACQUIRE.concat(footerJspx));
}
}
catch (Exception e) {
throw new IllegalStateException(e);
}
finally {
IOUtils.closeQuietly(out);
}
}
private void addForgotPasswordRegisterUserToLoginPage() {
// <div>
// <a href ="/TypicalSecurity/forgotpassword/index">Forgot Password</a>
// | Not a User Yet? <a href ="/TypicalSecurity/signup?form">Sign In</a>
// </div>
String loginJspx = pathResolver.getFocusedIdentifier(
Path.SRC_MAIN_WEBAPP, "WEB-INF/views/login.jspx");
MutableFile mutableLoginJspx = null;
Document loginJspxDoc;
OutputStream out = null;
try {
if (fileManager.exists(loginJspx)) {
mutableLoginJspx = fileManager.updateFile(loginJspx);
loginJspxDoc = XmlUtils.getDocumentBuilder().parse(
mutableLoginJspx.getInputStream());
Element form = XmlUtils.findFirstElementByName("form",
loginJspxDoc.getDocumentElement());
Validate.notNull(form,
"Could not find form in ".concat(loginJspx));
String contextPath = projectOperations.getFocusedProjectName();
form.appendChild(new XmlElementBuilder("div", loginJspxDoc)
.addChild(
loginJspxDoc
.createTextNode("<br/><a href =\"/"
.concat(contextPath)
.concat("/forgotpassword/index\">Forgot Password</a> | Not a User Yet? <a href =\"/")
.concat(contextPath)
.concat("/signup?form\">Sign Up</a>")))
.build());
out = mutableLoginJspx.getOutputStream();
XmlUtils.writeXml(out, loginJspxDoc);
}
else {
throw new IllegalStateException(COULD_NOT_ACQUIRE + loginJspx);
}
}
catch (Exception e) {
throw new IllegalStateException(e);
}
finally {
IOUtils.closeQuietly(out);
}
}
private void insertI18nMessages() {
String applicationProperties = pathResolver.getFocusedIdentifier(
Path.SRC_MAIN_WEBAPP, "WEB-INF/i18n/application.properties");
MutableFile mutableApplicationProperties = null;
BufferedWriter out = null;
InputStream ins = null;
try {
if (fileManager.exists(applicationProperties)) {
mutableApplicationProperties = fileManager
.updateFile(applicationProperties);
ins = mutableApplicationProperties.getInputStream();
String originalData = convertStreamToString(ins);
out = new BufferedWriter(new OutputStreamWriter(
mutableApplicationProperties.getOutputStream()));
out.write(originalData);
out.write("label_com_training_spring_roo_model_user_id=Id\n");
out.write("label_com_training_spring_roo_model_user_lastname=Last Name\n");
out.write("label_com_training_spring_roo_model_user_failedloginattempts=Failed\n");
out.write("label_com_training_spring_roo_model_user_password=Password\n");
out.write("label_com_training_spring_roo_model_userstatusmodel_failedloginattempts=Failed Login Attempts\n");
out.write("label_com_training_spring_roo_model_user_repeat_password=Repeat Password\n");
out.write("label_com_training_spring_roo_model_user_version=Version\n");
out.write("label_com_training_spring_roo_model_user_firstname=First Name\n");
out.write("label_com_training_spring_roo_model_user_plural=Users\n");
out.write("label_com_training_spring_roo_model_user=User\n");
out.write("label_com_training_spring_roo_model_user_enabled=Enabled\n");
out.write("label_com_training_spring_roo_model_user_repeatpassword=Repeat Password\n");
out.write("label_com_training_spring_roo_model_user_locked=Locked\n");
out.write("label_com_training_spring_roo_model_user_activationkey=Activation Key\n");
out.write("label_com_training_spring_roo_model_user_emailaddress=Email Address\n");
out.write("label_com_training_spring_roo_model_user_activationdate=Activation Date\n");
}
else {
throw new IllegalStateException(
COULD_NOT_ACQUIRE.concat(applicationProperties));
}
}
catch (Exception e) {
throw new IllegalStateException(e);
}
finally {
IOUtils.closeQuietly(ins);
IOUtils.closeQuietly(out);
}
}
private String convertStreamToString(InputStream is) throws IOException {
/*
* To convert the InputStream to String we use the Reader.read(char[]
* buffer) method. We iterate until the Reader return -1 which means
* there's no more data to read. We use the StringWriter class to
* produce the string.
*/
if (is != null) {
Writer writer = new StringWriter();
char[] buffer = new char[1024];
Reader reader = new BufferedReader(new InputStreamReader(is,
"UTF-8"));
int n;
while ((n = reader.read(buffer)) != -1) {
writer.write(buffer, 0, n);
}
return writer.toString();
}
else {
return "";
}
}
/**
* This method checks if typical security is installed. If is installed
* update views to use bootstrap
*/
@Override
public void updateTypicalSecurityAddonToBootstrap() {
// Checking if the addon is installed using features
if (projectOperations
.isFeatureInstalledInFocusedModule(FeatureNames.SECURITY)
&& isTypicalSecurityInstalled() && !isLoginModified()) {
List<String> viewsFolderFiles = new ArrayList<String>();
Collections.addAll(viewsFolderFiles,
"changepassword/bootstrap/index.jspx",
"changepassword/bootstrap/thanks.jspx",
"forgotpassword/bootstrap/index.jspx",
"forgotpassword/bootstrap/thanks.jspx",
"signup/bootstrap/error.jspx",
"signup/bootstrap/index.jspx",
"signup/bootstrap/thanks.jspx",
"roles/bootstrap/create.jspx", "roles/bootstrap/list.jspx",
"roles/bootstrap/show.jspx", "roles/bootstrap/update.jspx",
"userroles/bootstrap/create.jspx",
"userroles/bootstrap/list.jspx",
"userroles/bootstrap/show.jspx",
"userroles/bootstrap/update.jspx",
"users/bootstrap/create.jspx", "users/bootstrap/list.jspx",
"users/bootstrap/show.jspx", "users/bootstrap/update.jspx");
Iterator<String> viewsFolderIterator = viewsFolderFiles.iterator();
while (viewsFolderIterator.hasNext()) {
String fileName = viewsFolderIterator.next();
final String viewFile = pathResolver
.getFocusedIdentifier(Path.SRC_MAIN_WEBAPP,
"WEB-INF/views/".concat(fileName));
createFilesInLocationIfNotExistsUpdateIfExists(fileManager,
getClass(), viewFile, fileName, "");
}
// Copying typical-security login
final String loginView = pathResolver.getFocusedIdentifier(
Path.SRC_MAIN_WEBAPP, "WEB-INF/views/login.jspx");
createFilesInLocationIfNotExistsUpdateIfExists(fileManager,
getClass(), loginView, "login-typical.jspx", "");
}
}
/**
* Check if typical security is installed
*/
@Override
public boolean isTypicalSecurityInstalled() {
String dirPath = pathResolver.getIdentifier(getWebappPath(),
"WEB-INF/views/changepassword/index.jspx");
return fileManager.exists(dirPath);
}
/**
* Check if login.jspx is modified with bootstrap
*
* @return
*/
@Override
public boolean isLoginModified() {
String dirPath = pathResolver.getIdentifier(getWebappPath(),
"WEB-INF/views/login.jspx");
final Document document = XmlUtils.readXml(fileManager
.getInputStream(dirPath));
final Element config = document.getDocumentElement();
final Element urlElement = DomUtils.findFirstElementByName("div",
config);
String value = urlElement.getAttribute("class");
return value.contains("alert alert-danger");
}
/**
* Creates an instance with the {@code src/main/webapp} path in the current
* module
*
* @return
*/
public LogicalPath getWebappPath() {
return getWebPojectUtils().getWebappPath(projectOperations);
}
/**
* This method copy a new file in a directory if the file not exists and
* update the file if exists
*
* @param fileManager
* @param loadingClass
* @param filePath
* @param fileName
* @param directory
*/
public static void createFilesInLocationIfNotExistsUpdateIfExists(
FileManager fileManager, Class loadingClass, String filePath,
String fileName, String directory) {
InputStream inputStream = null;
OutputStream outputStream = null;
try {
inputStream = FileUtils.getInputStream(loadingClass,
directory.concat(fileName));
if (!fileManager.exists(filePath)) {
outputStream = fileManager.createFile(filePath)
.getOutputStream();
}
else {
outputStream = fileManager.updateFile(filePath)
.getOutputStream();
}
IOUtils.copy(inputStream, outputStream);
}
catch (final IOException ioe) {
throw new IllegalStateException(ioe);
}
finally {
IOUtils.closeQuietly(inputStream);
IOUtils.closeQuietly(outputStream);
}
}
public WebProjectUtils getWebPojectUtils() {
if (webProjectUtils == null) {
// Get all Services implement WebProjectUtils interface
try {
ServiceReference<?>[] references = this.context
.getAllServiceReferences(
WebProjectUtils.class.getName(), null);
for (ServiceReference<?> ref : references) {
webProjectUtils = (WebProjectUtils) this.context
.getService(ref);
return webProjectUtils;
}
return null;
}
catch (InvalidSyntaxException e) {
LOGGER.warning("Cannot load WebProjectUtils on TypicalSecurityOperationsImpl.");
return null;
}
}
else {
return webProjectUtils;
}
}
}