CCM NG: Todays progress of getting Bebop running in full Java EE 7 environment

git-svn-id: https://svn.libreccm.org/ccm/ccm_ng@3839 8810af33-2d31-482b-a856-94f89814c4df
pull/2/head
jensp 2016-02-03 19:00:18 +00:00
parent 9b6c50fd8a
commit f446d50fc7
10 changed files with 183 additions and 103 deletions

View File

@ -0,0 +1,3 @@
version = 7.0.0-SNAPSHOT
appname = LibreCCM
apphomepage = http://www.libreccm.org

View File

@ -18,6 +18,7 @@
*/ */
package com.arsdigita.ui.admin; package com.arsdigita.ui.admin;
import com.arsdigita.bebop.Label;
import com.arsdigita.bebop.Page; import com.arsdigita.bebop.Page;
import com.arsdigita.bebop.PageFactory; import com.arsdigita.bebop.PageFactory;
import com.arsdigita.bebop.TabbedPane; import com.arsdigita.bebop.TabbedPane;
@ -31,6 +32,7 @@ import com.arsdigita.xml.Document;
import org.apache.shiro.subject.Subject; import org.apache.shiro.subject.Subject;
import org.libreccm.cdi.utils.CdiUtil; import org.libreccm.cdi.utils.CdiUtil;
import org.libreccm.configuration.ConfigurationManager;
import org.libreccm.security.PermissionChecker; import org.libreccm.security.PermissionChecker;
import org.libreccm.web.CcmApplication; import org.libreccm.web.CcmApplication;
@ -38,6 +40,7 @@ import java.io.IOException;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import javax.inject.Inject;
import javax.servlet.ServletException; import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet; import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
@ -61,10 +64,12 @@ import static com.arsdigita.ui.admin.AdminConstants.*;
* @author pb * @author pb
*/ */
@WebServlet(urlPatterns = {ADMIN_SERVLET_PATH}) @WebServlet(urlPatterns = {ADMIN_SERVLET_PATH})
public class AdminServlet extends BaseApplicationServlet implements public class AdminServlet
AdminConstants { extends BaseApplicationServlet
implements AdminConstants {
private static final long serialVersionUID = -3912367600768871630L; private static final long serialVersionUID = -3912367600768871630L;
/** /**
* Logger instance for debugging * Logger instance for debugging
*/ */
@ -82,7 +87,7 @@ public class AdminServlet extends BaseApplicationServlet implements
*/ */
@Override @Override
public void doInit() throws ServletException { public void doInit() throws ServletException {
addPage("/", buildAdminIndexPage()); // index page at address ~/ds //addPage("/", buildAdminIndexPage()); // index page at address ~/ds
// addPage("/index.jsp", buildIndexPage()); // index page at address ~/ds // addPage("/index.jsp", buildIndexPage()); // index page at address ~/ds
} }
@ -107,7 +112,8 @@ public class AdminServlet extends BaseApplicationServlet implements
/* Determine access privilege: only logged in users may access */ /* Determine access privilege: only logged in users may access */
final CdiUtil cdiUtil = new CdiUtil(); final CdiUtil cdiUtil = new CdiUtil();
final Subject subject = cdiUtil.findBean(Subject.class); final Subject subject = cdiUtil.findBean(Subject.class);
final PermissionChecker permissionChecker = cdiUtil.findBean(PermissionChecker.class); final PermissionChecker permissionChecker = cdiUtil.findBean(
PermissionChecker.class);
if (!subject.isAuthenticated()) { if (!subject.isAuthenticated()) {
throw new LoginSignal(sreq); throw new LoginSignal(sreq);
@ -133,13 +139,18 @@ public class AdminServlet extends BaseApplicationServlet implements
pathInfo = pathInfo.substring(0, pathInfo.length() - 1); pathInfo = pathInfo.substring(0, pathInfo.length() - 1);
} }
final Page page = pages.get(pathInfo); // final Page page = pages.get(pathInfo);
if (page == null) { // if (page == null) {
sresp.sendError(404, "No such page for path " + pathInfo); // sresp.sendError(404, "No such page for path " + pathInfo);
} else { // } else {
final Document doc = page.buildDocument(sreq, sresp); // final Document doc = page.buildDocument(sreq, sresp);
Templating.getPresentationManager().servePage(doc, sreq, sresp); // Templating.getPresentationManager().servePage(doc, sreq, sresp);
} // }
final Page page = new Page();
page.add(new Label("admin"));
final Document doc = page.buildDocument(sreq, sresp);
Templating.getPresentationManager().servePage(doc, sreq, sresp);
} }
/** /**

View File

@ -66,19 +66,19 @@ import org.libreccm.security.UserManager;
* *
*/ */
public class ChangePasswordForm extends Form public class ChangePasswordForm extends Form
implements FormProcessListener, implements FormProcessListener,
FormValidationListener { FormValidationListener {
private static final Logger s_log = Logger.getLogger( private static final Logger s_log = Logger.getLogger(
ChangePasswordForm.class.getName()); ChangePasswordForm.class.getName());
final static String CHANGE_PASSWORD_FORM_NAME = "change-password"; final static String CHANGE_PASSWORD_FORM_NAME = "change-password";
final static String OLD_PASSWORD_PARAM_NAME = "old-password"; final static String OLD_PASSWORD_PARAM_NAME = "old-password";
final static String NEW_PASSWORD_PARAM_NAME = "new-password"; final static String NEW_PASSWORD_PARAM_NAME = "new-password";
final static String CONFIRM_PASSWORD_PARAM_NAME = "confirm-password"; final static String CONFIRM_PASSWORD_PARAM_NAME = "confirm-password";
final static String RETURN_URL_PARAM_NAME final static String RETURN_URL_PARAM_NAME
= LoginHelper.RETURN_URL_PARAM_NAME; = LoginHelper.RETURN_URL_PARAM_NAME;
private final UserAuthenticationListener m_listener private final UserAuthenticationListener m_listener
= new UserAuthenticationListener(); = new UserAuthenticationListener();
private Hidden m_returnURL; private Hidden m_returnURL;
// private Hidden m_recovery; // private Hidden m_recovery;
private Label m_oldPasswordLabel; private Label m_oldPasswordLabel;
@ -129,21 +129,30 @@ public class ChangePasswordForm extends Form
final KernelConfig kernelConfig = KernelConfig.getConfig(); final KernelConfig kernelConfig = KernelConfig.getConfig();
final User user = shiro.getUser(); final User user = shiro.getUser();
final Label greeting = new Label(LoginHelper.getMessage( final Label greeting;
if (user == null) {
greeting = new Label(LoginHelper.getMessage(
"login.changePasswordForm.greeting",
new Object[]{String.format("%s %s",
"",
"")}));
} else {
greeting = new Label(LoginHelper.getMessage(
"login.changePasswordForm.greeting", "login.changePasswordForm.greeting",
new Object[]{String.format("%s %s", new Object[]{String.format("%s %s",
user.getGivenName(), user.getGivenName(),
user.getFamilyName())})); user.getFamilyName())}));
}
greeting.setFontWeight(Label.BOLD); greeting.setFontWeight(Label.BOLD);
greeting.setClassAttr("greeting"); greeting.setClassAttr("greeting");
add(greeting); add(greeting);
add(new Label(LoginHelper.getMessage( add(new Label(LoginHelper.getMessage(
"login.changePasswortForm.introText"))); "login.changePasswortForm.introText")));
// old password // old password
m_oldPasswordLabel = new Label(LoginHelper.getMessage( m_oldPasswordLabel = new Label(LoginHelper.getMessage(
"login.changePasswordForm.oldPasswordLabel")); "login.changePasswordForm.oldPasswordLabel"));
add(m_oldPasswordLabel); add(m_oldPasswordLabel);
m_oldPassword = new Password(OLD_PASSWORD_PARAM_NAME); m_oldPassword = new Password(OLD_PASSWORD_PARAM_NAME);
// don't use NotNullValidationListener because // don't use NotNullValidationListener because
@ -153,14 +162,14 @@ public class ChangePasswordForm extends Form
// new password // new password
Object[] params = new Object[]{PasswordValidationListener.MIN_LENGTH}; Object[] params = new Object[]{PasswordValidationListener.MIN_LENGTH};
add(new Label(LoginHelper.getMessage( add(new Label(LoginHelper.getMessage(
"login.changePasswordForm.newPasswordLabel", params))); "login.changePasswordForm.newPasswordLabel", params)));
m_newPassword = new Password(NEW_PASSWORD_PARAM_NAME); m_newPassword = new Password(NEW_PASSWORD_PARAM_NAME);
m_newPassword.addValidationListener(new PasswordValidationListener()); m_newPassword.addValidationListener(new PasswordValidationListener());
add(m_newPassword); add(m_newPassword);
// confirm new password // confirm new password
add(new Label(LoginHelper.getMessage( add(new Label(LoginHelper.getMessage(
"login.changePasswordForm.confirmPasswordLabel"))); "login.changePasswordForm.confirmPasswordLabel")));
m_confirmPassword = new Password(CONFIRM_PASSWORD_PARAM_NAME); m_confirmPassword = new Password(CONFIRM_PASSWORD_PARAM_NAME);
// don't use PasswordValidationListener to avoid duplicate errors // don't use PasswordValidationListener to avoid duplicate errors
m_confirmPassword.addValidationListener(new NotNullValidationListener()); m_confirmPassword.addValidationListener(new NotNullValidationListener());
@ -173,7 +182,7 @@ public class ChangePasswordForm extends Form
@Override @Override
public void validate(final FormSectionEvent event) public void validate(final FormSectionEvent event)
throws FormProcessException { throws FormProcessException {
PageState state = event.getPageState(); PageState state = event.getPageState();
FormData data = event.getFormData(); FormData data = event.getFormData();
try { try {
@ -181,8 +190,8 @@ public class ChangePasswordForm extends Form
if (!m_listener.isLoggedIn(state)) { if (!m_listener.isLoggedIn(state)) {
// this error should never appear // this error should never appear
data.addError(LoginHelper.localize( data.addError(LoginHelper.localize(
"login.changePasswordForm.noUserError", "login.changePasswordForm.noUserError",
state.getRequest())); state.getRequest()));
return; return;
} }
// User user = m_listener.getUser(state); // User user = m_listener.getUser(state);
@ -228,7 +237,7 @@ public class ChangePasswordForm extends Form
@Override @Override
public void process(final FormSectionEvent event) public void process(final FormSectionEvent event)
throws FormProcessException { throws FormProcessException {
PageState state = event.getPageState(); PageState state = event.getPageState();
FormData data = event.getFormData(); FormData data = event.getFormData();
@ -236,8 +245,8 @@ public class ChangePasswordForm extends Form
if (!m_listener.isLoggedIn(state)) { if (!m_listener.isLoggedIn(state)) {
// this error should never appear (checked in validate) // this error should never appear (checked in validate)
data.addError(LoginHelper.localize( data.addError(LoginHelper.localize(
"login.changePasswordForm.noUserError", "login.changePasswordForm.noUserError",
state.getRequest())); state.getRequest()));
return; return;
} }

View File

@ -35,7 +35,9 @@ import com.arsdigita.web.ReturnSignal;
import com.arsdigita.web.URL; import com.arsdigita.web.URL;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.libreccm.configuration.ConfigurationManager;
import javax.inject.Inject;
import javax.servlet.ServletException; import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet; import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
@ -125,6 +127,9 @@ public class LoginServlet extends BebopApplicationServlet {
public static final String APPLICATION_NAME = "login"; public static final String APPLICATION_NAME = "login";
@Inject
private ConfigurationManager confManager;
/** /**
* User extension point used to create the pages to server and setup a * User extension point used to create the pages to server and setup a
* URL_MSG - page mapping. * URL_MSG - page mapping.
@ -133,6 +138,9 @@ public class LoginServlet extends BebopApplicationServlet {
*/ */
@Override @Override
public void doInit() throws ServletException { public void doInit() throws ServletException {
final SecurityConfig securityConfig = confManager.findConfiguration(
SecurityConfig.class);
// Allow world caching for pages without authentication, // Allow world caching for pages without authentication,
// ie, /register, /register/explain-persistent-cookies, // ie, /register, /register/explain-persistent-cookies,
// /register/login-expired, /register/recover-password // /register/login-expired, /register/recover-password
@ -145,8 +153,7 @@ public class LoginServlet extends BebopApplicationServlet {
put("/", put("/",
buildSimplePage( buildSimplePage(
"login.userRegistrationForm.title", "login.userRegistrationForm.title",
new UserLoginForm(SecurityConfig.getConfig() new UserLoginForm(securityConfig.isAutoRegistrationEnabled()),
.isAutoRegistrationEnabled()),
"login")); "login"));
disableClientCaching("/"); disableClientCaching("/");

View File

@ -100,7 +100,7 @@ public class UserLoginForm extends Form implements LoginConstants,
private TextField m_loginName; private TextField m_loginName;
private final Password m_password; private final Password m_password;
private final boolean m_autoRegistrationOn; private final boolean m_autoRegistrationOn;
private final SecurityConfig securityConfig = SecurityConfig.getConfig(); private final SecurityConfig securityConfig;// = SecurityConfig.getConfig();
/** /**
* Default constructor delegates to a constructor which creates a LoginForm * Default constructor delegates to a constructor which creates a LoginForm
@ -128,6 +128,8 @@ public class UserLoginForm extends Form implements LoginConstants,
final boolean autoRegistrationOn) { final boolean autoRegistrationOn) {
super(FORM_NAME, panel); super(FORM_NAME, panel);
securityConfig = SecurityConfig.getConfig();
setMethod(Form.POST); setMethod(Form.POST);
addInitListener(this); addInitListener(this);
addValidationListener(this); addValidationListener(this);

View File

@ -25,6 +25,7 @@ import org.libreccm.web.CcmApplication;
import java.io.IOException; import java.io.IOException;
import javax.inject.Inject;
import javax.servlet.ServletException; import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
@ -86,6 +87,12 @@ public abstract class BaseApplicationServlet extends BaseServlet {
*/ */
public static final String APPLICATION_ID_PARAMETER = "app-id"; public static final String APPLICATION_ID_PARAMETER = "app-id";
/**
* {@link ApplicationRepository} provided by CDI.
*/
@Inject
private ApplicationRepository appRepository;
/** /**
* <p> * <p>
* Augments the context of the request and delegates to {@link * Augments the context of the request and delegates to {@link
@ -174,10 +181,7 @@ public abstract class BaseApplicationServlet extends BaseServlet {
+ "database"); + "database");
} }
final CdiUtil cdiUtil = new CdiUtil(); return appRepository.findById(appId);
final ApplicationRepository appRepo = cdiUtil.findBean(
ApplicationRepository.class);
return appRepo.findById(appId);
} }
/** /**

View File

@ -86,11 +86,23 @@ public abstract class BaseServlet extends HttpServlet {
private void internalService(final HttpServletRequest request, private void internalService(final HttpServletRequest request,
final HttpServletResponse response) final HttpServletResponse response)
throws ServletException, IOException { throws ServletException, IOException {
//This method was present in the old implemention and was responsible
//for managing the application managed transactions. Because we now use
//container managed transactions we may don't need this method anymore.
doService(request, response); Web.init(request, getServletContext());
Web.getWebContext().setRequestURL(getRequestURL(request));
try {
doService(request, response);
} catch (RedirectSignal signal) {
redirect(response, signal);
} catch (ServletException ex) {
final RedirectSignal signal = findRedirectSignal(ex);
if (signal == null) {
throw ex;
} else {
redirect(response, signal);
}
}
} }
/** /**
@ -107,7 +119,7 @@ public abstract class BaseServlet extends HttpServlet {
* @throws java.io.IOException * @throws java.io.IOException
*/ */
protected abstract void doService(final HttpServletRequest request, protected abstract void doService(final HttpServletRequest request,
final HttpServletResponse response) final HttpServletResponse response)
throws ServletException, IOException; throws ServletException, IOException;
/** /**
@ -134,26 +146,62 @@ public abstract class BaseServlet extends HttpServlet {
internalService(request, response); internalService(request, response);
} }
/** /**
* <p>Processes HTTP POST requests.</p> * <p>
* Processes HTTP POST requests.</p>
* *
* @param request * @param request
* @param response * @param response
*
* @throws javax.servlet.ServletException * @throws javax.servlet.ServletException
* @throws java.io.IOException * @throws java.io.IOException
* *
* @see javax.servlet.http.HttpServlet#doPost(HttpServletRequest,HttpServletResponse) * @see
* javax.servlet.http.HttpServlet#doPost(HttpServletRequest,HttpServletResponse)
*/ */
@Override @Override
protected final void doPost(final HttpServletRequest request, protected final void doPost(final HttpServletRequest request,
final HttpServletResponse response) final HttpServletResponse response)
throws ServletException, IOException { throws ServletException, IOException {
LOGGER.info("Serving POST request path %s with servlet %s (class: %s)", LOGGER.info("Serving POST request path %s with servlet %s (class: %s)",
request.getPathInfo(), request.getPathInfo(),
getServletConfig().getServletName(), getServletConfig().getServletName(),
getClass().getName()); getClass().getName());
internalService(request, response); internalService(request, response);
} }
private URL getRequestURL(final HttpServletRequest request) {
URL url = (URL) request.getAttribute(REQUEST_URL_ATTRIBUTE);
if (url == null) {
url = new URL(request);
}
return url;
}
private RedirectSignal findRedirectSignal(final ServletException ex) {
Throwable root = ex.getRootCause();
while (root instanceof ServletException) {
root = ((ServletException) root).getRootCause();
}
if (root instanceof RedirectSignal) {
return (RedirectSignal) root;
} else {
return null;
}
}
private void redirect(final HttpServletResponse response,
final RedirectSignal redirectSignal)
throws IOException {
final String url = response.encodeRedirectURL(redirectSignal
.getDestinationURL());
response.sendRedirect(url);
}
} }

View File

@ -40,6 +40,7 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.apache.shiro.subject.Subject; import org.apache.shiro.subject.Subject;
import org.libreccm.configuration.ConfigurationManager;
import org.libreccm.web.ApplicationManager; import org.libreccm.web.ApplicationManager;
import org.libreccm.web.ApplicationType; import org.libreccm.web.ApplicationType;

View File

@ -47,11 +47,10 @@ public class Web {
*/ */
private static final Logger s_log = Logger.getLogger(Web.class); private static final Logger s_log = Logger.getLogger(Web.class);
private static final WebConfig s_config = WebConfig.getConfig(); // private static final WebConfig s_config = WebConfig.getConfig();
private static final ThreadLocal s_request = new InternalRequestLocal(); private static final ThreadLocal s_request = new InternalRequestLocal();
private static final ThreadLocal s_servletContext private static final ThreadLocal s_servletContext
= new InternalRequestLocal(); = new InternalRequestLocal();
private static final ThreadLocal s_userContext = new InternalRequestLocal(); private static final ThreadLocal s_userContext = new InternalRequestLocal();
private static ThreadLocal s_context; private static ThreadLocal s_context;
@ -93,7 +92,8 @@ public class Web {
* @return A <code>WebConfig</code> configuration record; it cannot be null * @return A <code>WebConfig</code> configuration record; it cannot be null
*/ */
public static WebConfig getConfig() { public static WebConfig getConfig() {
return s_config; // return s_config;
return WebConfig.getConfig();
} }
/** /**
@ -127,26 +127,25 @@ public class Web {
return (ServletContext) s_servletContext.get(); return (ServletContext) s_servletContext.get();
} }
/** /**
* Gets the webapp context path portion of the WEB application where this * Gets the webapp context path portion of the WEB application where this
* CCM instance is executed. (I.e. where the WEB-INF directory is located * CCM instance is executed. (I.e. where the WEB-INF directory is located in
* in the servlet container webapps directory, known as ServletContext in * the servlet container webapps directory, known as ServletContext in the
* the Servlet API) * Servlet API)
* *
* @return web context path portion as a String, may be used to construct * @return web context path portion as a String, may be used to construct a
* a URL (NOT the RealPath!). The ROOT context returns an empty * URL (NOT the RealPath!). The ROOT context returns an empty
* String(""). * String("").
*/ */
public static String getWebappContextPath() { public static String getWebappContextPath() {
return (String) s_contextPath; return (String) s_contextPath;
} }
/** /**
* Sets the webapp context path portion of the WEB application where this * Sets the webapp context path portion of the WEB application where this
* CCM instance is executed. (I.e. where the WEB-INF directory is located * CCM instance is executed. (I.e. where the WEB-INF directory is located in
* in the servlet container webapps directory, known as ServletContext in * the servlet container webapps directory, known as ServletContext in the
* the Servlet API) * Servlet API) Meant to be executed by CCMDispatcherServlet only.
* Meant to be executed by CCMDispatcherServlet only.
* *
* @param contextPath * @param contextPath
*/ */
@ -154,7 +153,6 @@ public class Web {
s_contextPath = contextPath; s_contextPath = contextPath;
} }
/** /**
* Processes an URL String trying to identify a corresponding recource which * Processes an URL String trying to identify a corresponding recource which
* is mapped to the given path String. The method ensures that the resource * is mapped to the given path String. The method ensures that the resource
@ -249,10 +247,8 @@ public class Web {
s_log.debug("Got URL " + url + " for " + path); s_log.debug("Got URL " + url + " for " + path);
} }
return url; // Return adjusted resourcePath url return url; // Return adjusted resourcePath url
} else { } else if (s_log.isDebugEnabled()) {
if (s_log.isDebugEnabled()) { s_log.debug("No URL present for " + path);
s_log.debug("No URL present for " + path);
}
} }
} catch (MalformedURLException exc) { } catch (MalformedURLException exc) {
if (s_log.isDebugEnabled()) { if (s_log.isDebugEnabled()) {
@ -282,7 +278,7 @@ public class Web {
if (!ctxPath.startsWith("/")) { if (!ctxPath.startsWith("/")) {
ctxPath = "/" + ctxPath; ctxPath = "/" + ctxPath;
} }
// No trailing slash allowed by servlet API! // No trailing slash allowed by servlet API!
// if (!ctxPath.endsWith("/")) { // if (!ctxPath.endsWith("/")) {
// ctxPath = ctxPath + "/"; // ctxPath = ctxPath + "/";
// } // }
@ -299,10 +295,8 @@ public class Web {
s_log.debug("Got URL " + url + " for " + path); s_log.debug("Got URL " + url + " for " + path);
} }
return url; // Return adjusted resourcePath url return url; // Return adjusted resourcePath url
} else { } else if (s_log.isDebugEnabled()) {
if (s_log.isDebugEnabled()) { s_log.debug("No URL present for " + path);
s_log.debug("No URL present for " + path);
}
} }
} catch (MalformedURLException ex) { } catch (MalformedURLException ex) {
if (s_log.isDebugEnabled()) { if (s_log.isDebugEnabled()) {

View File

@ -31,6 +31,7 @@ import java.util.Set;
import javax.persistence.Column; import javax.persistence.Column;
import javax.persistence.ElementCollection; import javax.persistence.ElementCollection;
import javax.persistence.Embeddable; import javax.persistence.Embeddable;
import javax.persistence.FetchType;
import javax.persistence.Lob; import javax.persistence.Lob;
import javax.persistence.MapKeyColumn; import javax.persistence.MapKeyColumn;
import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElement;
@ -54,7 +55,7 @@ public class LocalizedString implements Serializable {
/** /**
* The localised values of the string. * The localised values of the string.
*/ */
@ElementCollection @ElementCollection(fetch = FetchType.EAGER)
@MapKeyColumn(name = "LOCALE") @MapKeyColumn(name = "LOCALE")
@Column(name = "LOCALIZED_VALUE") @Column(name = "LOCALIZED_VALUE")
@Lob @Lob