CCM NG: Todays results of getting login and admin apps running. Login should work now, but there are some problems with lazily fetched collections...
Also this commits adds the DefaultEntityGraph annotation which allows it to name a (named) EntityGraph which should be applied by default to when the entity is loaded from the database. git-svn-id: https://svn.libreccm.org/ccm/ccm_ng@3859 8810af33-2d31-482b-a856-94f89814c4dfpull/2/head
parent
5bb5bf7ac6
commit
3ac09f8510
|
|
@ -9,6 +9,12 @@
|
|||
<Root level="info">
|
||||
<AppenderRef ref="Console"/>
|
||||
</Root>
|
||||
<Logger name="com.arsdigita.ui.admin.AdminServlet"
|
||||
level="debug">
|
||||
</Logger>
|
||||
<Logger name="com.arsdigita.ui.login.UserLoginForm"
|
||||
level="debug">
|
||||
</Logger>
|
||||
<Logger name="com.arsdigita.packaging.Config"
|
||||
level="debug">
|
||||
</Logger>
|
||||
|
|
@ -19,6 +25,9 @@
|
|||
level="debug">
|
||||
|
||||
</Logger>
|
||||
<Logger name="org.libreccm.core.AbstractEntityRepository"
|
||||
level="debug">
|
||||
</Logger>
|
||||
<Logger name="org.libreccm.security.Shiro"
|
||||
level="debug">
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,12 @@
|
|||
|
||||
<display-name>LibreCCM Devel Bundle for Wildfly</display-name>
|
||||
|
||||
<!-- No JSESSIONID!!! -->
|
||||
<session-config>
|
||||
<tracking-mode>COOKIE</tracking-mode>
|
||||
<!--<tracking-mode>URL</tracking-mode>-->
|
||||
</session-config>
|
||||
|
||||
<filter>
|
||||
<filter-name>ShiroFilter</filter-name>
|
||||
<filter-class>org.apache.shiro.web.servlet.ShiroFilter</filter-class>
|
||||
|
|
@ -15,10 +21,10 @@
|
|||
<filter-mapping>
|
||||
<filter-name>ShiroFilter</filter-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
<dispatcher>REQUEST</dispatcher>
|
||||
<!--<dispatcher>REQUEST</dispatcher>
|
||||
<dispatcher>FORWARD</dispatcher>
|
||||
<dispatcher>INCLUDE</dispatcher>
|
||||
<dispatcher>ERROR</dispatcher>
|
||||
<dispatcher>ERROR</dispatcher>-->
|
||||
</filter-mapping>
|
||||
|
||||
<listener>
|
||||
|
|
|
|||
|
|
@ -28,7 +28,6 @@ import java.util.Arrays;
|
|||
import java.util.HashSet;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.StringJoiner;
|
||||
|
||||
import org.libreccm.cdi.utils.CdiUtil;
|
||||
import org.libreccm.configuration.Configuration;
|
||||
|
|
@ -83,9 +82,8 @@ public final class BebopConfig {
|
|||
private Boolean showClassName = false;
|
||||
|
||||
public static BebopConfig getConfig() {
|
||||
final CdiUtil cdiUtil = new CdiUtil();
|
||||
final ConfigurationManager confManager = cdiUtil.findBean(
|
||||
ConfigurationManager.class);
|
||||
final ConfigurationManager confManager = CdiUtil.createCdiUtil()
|
||||
.findBean(ConfigurationManager.class);
|
||||
return confManager.findConfiguration(BebopConfig.class);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -25,7 +25,9 @@ import com.arsdigita.util.Assert;
|
|||
import com.arsdigita.web.BaseApplicationServlet;
|
||||
import com.arsdigita.xml.Document;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.shiro.subject.Subject;
|
||||
import org.libreccm.web.CcmApplication;
|
||||
|
||||
import java.io.IOException;
|
||||
|
|
@ -34,6 +36,7 @@ import java.util.HashSet;
|
|||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.enterprise.inject.spi.CDI;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
|
@ -61,7 +64,7 @@ public class BebopApplicationServlet extends BaseApplicationServlet {
|
|||
|
||||
private static final long serialVersionUID = -6004503025521189639L;
|
||||
|
||||
private static final Logger s_log = Logger.getLogger(
|
||||
private static final Logger LOGGER = LogManager.getLogger(
|
||||
BebopApplicationServlet.class);
|
||||
|
||||
/**
|
||||
|
|
@ -149,6 +152,11 @@ public class BebopApplicationServlet extends BaseApplicationServlet {
|
|||
final String pathInfo = sreq.getPathInfo();
|
||||
Assert.exists(pathInfo, "String pathInfo");
|
||||
|
||||
final Subject subject = CDI.current().select(Subject.class).get();
|
||||
LOGGER.debug("Current session is: {}", sreq.getSession().getId());
|
||||
LOGGER.debug("Current Shiro session is {}",
|
||||
subject.getSession().getId().toString());
|
||||
|
||||
final Page page = (Page) m_pages.get(pathInfo);
|
||||
|
||||
if (page == null) {
|
||||
|
|
|
|||
|
|
@ -70,9 +70,11 @@ public final class KernelConfig {
|
|||
private String defaultLanguage = "en";
|
||||
|
||||
public static KernelConfig getConfig() {
|
||||
final CdiUtil cdiUtil = new CdiUtil();
|
||||
final ConfigurationManager confManager = cdiUtil.findBean(
|
||||
ConfigurationManager.class);
|
||||
// final CdiUtil cdiUtil = new CdiUtil();
|
||||
// final ConfigurationManager confManager = cdiUtil.findBean(
|
||||
// ConfigurationManager.class);
|
||||
final ConfigurationManager confManager = CdiUtil.createCdiUtil()
|
||||
.findBean(ConfigurationManager.class);
|
||||
return confManager.findConfiguration(KernelConfig.class);
|
||||
}
|
||||
|
||||
|
|
@ -259,9 +261,10 @@ public final class KernelConfig {
|
|||
if (supportedLanguages == null) {
|
||||
languages = "";
|
||||
} else {
|
||||
languages = supportedLanguages.stream().collect(Collectors.joining(", "));
|
||||
languages = supportedLanguages.stream().collect(Collectors.joining(
|
||||
", "));
|
||||
}
|
||||
|
||||
|
||||
return String.format(
|
||||
"%s{ "
|
||||
+ "debugEnabled = %b, "
|
||||
|
|
|
|||
|
|
@ -56,9 +56,8 @@ public final class SecurityConfig {
|
|||
private Integer hashIterations = 50000;
|
||||
|
||||
public static SecurityConfig getConfig() {
|
||||
final CdiUtil cdiUtil = new CdiUtil();
|
||||
final ConfigurationManager confManager = cdiUtil.findBean(
|
||||
ConfigurationManager.class);
|
||||
final ConfigurationManager confManager = CdiUtil.createCdiUtil()
|
||||
.findBean(ConfigurationManager.class);
|
||||
return confManager.findConfiguration(SecurityConfig.class);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -30,6 +30,8 @@ import com.arsdigita.web.BaseApplicationServlet;
|
|||
import com.arsdigita.web.LoginSignal;
|
||||
import com.arsdigita.xml.Document;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.shiro.subject.Subject;
|
||||
import org.libreccm.security.PermissionChecker;
|
||||
import org.libreccm.web.CcmApplication;
|
||||
|
|
@ -37,15 +39,16 @@ import org.libreccm.web.CcmApplication;
|
|||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.enterprise.inject.spi.CDI;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.annotation.WebServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
javax.servlet.http.HttpServletResponse;
|
||||
import org.libreccm.cdi.utils.CdiUtil;
|
||||
import org.libreccm.configuration.ConfigurationManager;
|
||||
|
||||
import static com.arsdigita.ui.admin.AdminConstants.*;
|
||||
|
||||
|
|
@ -65,12 +68,14 @@ import static com.arsdigita.ui.admin.AdminConstants.*;
|
|||
* @author pb
|
||||
*/
|
||||
@WebServlet(urlPatterns = {ADMIN_SERVLET_PATH})
|
||||
public class AdminServlet
|
||||
public class AdminServlet
|
||||
extends BaseApplicationServlet
|
||||
implements AdminConstants {
|
||||
|
||||
private static final long serialVersionUID = -3912367600768871630L;
|
||||
|
||||
private static final Logger LOGGER = LogManager.getLogger(AdminServlet.class);
|
||||
|
||||
/**
|
||||
* Logger instance for debugging
|
||||
*/
|
||||
|
|
@ -111,21 +116,40 @@ public class AdminServlet
|
|||
ServletException, IOException {
|
||||
// /////// Some preparational steps ///////////////
|
||||
/* 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 = CDI.current().select(Subject.class).get();
|
||||
final PermissionChecker permissionChecker = cdiUtil.findBean(
|
||||
PermissionChecker.class);
|
||||
// final PermissionChecker permissionChecker = cdiUtil.findBean(
|
||||
// PermissionChecker.class);
|
||||
final PermissionChecker permissionChecker = CDI.current().select(
|
||||
PermissionChecker.class).get();
|
||||
|
||||
final ConfigurationManager confManager = CDI.current().select(ConfigurationManager.class).get();
|
||||
if (confManager == null) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
LOGGER.debug("Checking if subject {} is authenticated...",
|
||||
subject.toString());
|
||||
LOGGER.debug("Current session is: {}", sreq.getSession().getId());
|
||||
LOGGER.debug("Current Shiro session is {}",
|
||||
subject.getSession().getId().toString());
|
||||
if (!subject.isAuthenticated()) {
|
||||
LOGGER.debug("Subject {} is not authenticated, redirecting to login...",
|
||||
subject.toString());
|
||||
throw new LoginSignal(sreq);
|
||||
}
|
||||
|
||||
|
||||
/* Determine access privilege: Admin privileges must be granted */
|
||||
LOGGER.debug("Subject is loggedin, checking if subject has required permissions...");
|
||||
if (!permissionChecker.isPermitted("admin")) {
|
||||
LOGGER.debug("Subject does *not* have required permissions. "
|
||||
+ "Access denied.");
|
||||
throw new AccessDeniedException("User is not an administrator");
|
||||
}
|
||||
|
||||
|
||||
LOGGER.debug("Serving admin page...");
|
||||
/* Want admin to always show the latest stuff... */
|
||||
DispatcherHelper.cacheDisable(sresp);
|
||||
|
||||
|
|
|
|||
|
|
@ -122,7 +122,7 @@ public class ChangePasswordForm extends Form
|
|||
m_returnURL.setPassIn(true);
|
||||
add(m_returnURL);
|
||||
|
||||
final CdiUtil cdiUtil = new CdiUtil();
|
||||
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
|
||||
final Subject subject = cdiUtil.findBean(Subject.class);
|
||||
final Shiro shiro = cdiUtil.findBean(Shiro.class);
|
||||
|
||||
|
|
|
|||
|
|
@ -143,25 +143,27 @@ public class UserLoginForm extends Form implements LoginConstants,
|
|||
|
||||
// final ConfigurationManager confManager = CDI.current().select(
|
||||
// ConfigurationManager.class).get();
|
||||
final BeanManager beanManager = CDI.current().getBeanManager();
|
||||
final Set<Bean<?>> beans = beanManager.getBeans(
|
||||
ConfigurationManager.class);
|
||||
final Iterator<Bean<?>> iterator = beans.iterator();
|
||||
final ConfigurationManager confManager;
|
||||
if (iterator.hasNext()) {
|
||||
@SuppressWarnings("unchecked")
|
||||
final Bean<ConfigurationManager> bean
|
||||
= (Bean<ConfigurationManager>) iterator
|
||||
.next();
|
||||
final CreationalContext<ConfigurationManager> ctx = beanManager.
|
||||
createCreationalContext(bean);
|
||||
|
||||
confManager = (ConfigurationManager) beanManager.getReference(
|
||||
bean, ConfigurationManager.class, ctx);
|
||||
} else {
|
||||
throw new UncheckedWrapperException(
|
||||
"Failed to lookup ConfigurationManager");
|
||||
}
|
||||
// final BeanManager beanManager = CDI.current().getBeanManager();
|
||||
// final Set<Bean<?>> beans = beanManager.getBeans(
|
||||
// ConfigurationManager.class);
|
||||
// final Iterator<Bean<?>> iterator = beans.iterator();
|
||||
// final ConfigurationManager confManager;
|
||||
// if (iterator.hasNext()) {
|
||||
// @SuppressWarnings("unchecked")
|
||||
// final Bean<ConfigurationManager> bean
|
||||
// = (Bean<ConfigurationManager>) iterator
|
||||
// .next();
|
||||
// final CreationalContext<ConfigurationManager> ctx = beanManager.
|
||||
// createCreationalContext(bean);
|
||||
//
|
||||
// confManager = (ConfigurationManager) beanManager.getReference(
|
||||
// bean, ConfigurationManager.class, ctx);
|
||||
// } else {
|
||||
// throw new UncheckedWrapperException(
|
||||
// "Failed to lookup ConfigurationManager");
|
||||
// }
|
||||
final ConfigurationManager confManager = CdiUtil.createCdiUtil()
|
||||
.findBean(ConfigurationManager.class);
|
||||
securityConfig = confManager.findConfiguration(SecurityConfig.class);
|
||||
|
||||
setMethod(Form.POST);
|
||||
|
|
@ -385,12 +387,19 @@ public class UserLoginForm extends Form implements LoginConstants,
|
|||
);
|
||||
token.setRememberMe(getPersistentLoginValue(state, false));
|
||||
try {
|
||||
LOGGER.debug("Trying to login user {}...", subject.toString());
|
||||
subject.login(token);
|
||||
} catch (AuthenticationException ex) {
|
||||
onLoginFail(event, ex);
|
||||
}
|
||||
|
||||
LOGGER.debug("User {} logged in successfully.", token.getUsername());
|
||||
LOGGER.debug("subject = {}", subject.toString());
|
||||
LOGGER.debug("Current session is: {}",
|
||||
state.getRequest().getSession().getId());
|
||||
LOGGER.debug("Current Shiro session is {}",
|
||||
subject.getSession().getId().toString());
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -21,15 +21,28 @@ package com.arsdigita.web;
|
|||
import com.arsdigita.dispatcher.DispatcherHelper;
|
||||
//import com.arsdigita.kernel.security.Util;
|
||||
import com.arsdigita.util.Assert;
|
||||
import com.arsdigita.util.UncheckedWrapperException;
|
||||
import com.arsdigita.util.servlet.HttpHost;
|
||||
|
||||
import oracle.jrockit.jfr.tools.ConCatRepository;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.libreccm.configuration.ConfigurationManager;
|
||||
import org.libreccm.web.CcmApplication;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.enterprise.context.spi.CreationalContext;
|
||||
import javax.enterprise.inject.spi.Bean;
|
||||
import javax.enterprise.inject.spi.BeanManager;
|
||||
import javax.naming.InitialContext;
|
||||
import javax.naming.NamingException;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* URL models a future request according to the servlet worldview. Its principal
|
||||
|
|
@ -516,8 +529,8 @@ public class URL {
|
|||
* starts with a "/". For example, <code>"/ccm/forum/thread.jsp"</code>.</p>
|
||||
*
|
||||
* <p>
|
||||
* This method is defined to return the equivalent of * <code>getWebContextPath() + getServletPath() +
|
||||
getPathInfo()</code>.</p>
|
||||
* This method is defined to return the equivalent of * <code>getWebContextPath() + getServletPath() +
|
||||
* getPathInfo()</code>.</p>
|
||||
*
|
||||
* @see javax.servlet.http.HttpServletRequest#getRequestURI()
|
||||
* @return a <code>String</code> comprised of the context path, servlet
|
||||
|
|
@ -679,7 +692,37 @@ public class URL {
|
|||
public static final URL there(final HttpServletRequest sreq,
|
||||
final String path,
|
||||
final ParameterMap params) {
|
||||
final WebConfig config = Web.getConfig();
|
||||
final BeanManager beanManager;
|
||||
try {
|
||||
final InitialContext context = new InitialContext();
|
||||
beanManager = (BeanManager) context.lookup(
|
||||
"java:comp/BeanManager");
|
||||
|
||||
} catch (NamingException ex) {
|
||||
throw new UncheckedWrapperException(ex);
|
||||
}
|
||||
|
||||
final Set<Bean<?>> beans = beanManager.getBeans(
|
||||
ConfigurationManager.class);
|
||||
final Iterator<Bean<?>> iterator = beans.iterator();
|
||||
final ConfigurationManager confManager;
|
||||
if (iterator.hasNext()) {
|
||||
@SuppressWarnings("unchecked")
|
||||
final Bean<ConfigurationManager> bean
|
||||
= (Bean<ConfigurationManager>) iterator
|
||||
.next();
|
||||
final CreationalContext<ConfigurationManager> ctx = beanManager
|
||||
.createCreationalContext(bean);
|
||||
confManager = (ConfigurationManager) beanManager.getReference(
|
||||
bean, ConfigurationManager.class, ctx);
|
||||
} else {
|
||||
throw new IllegalStateException("No configuration manager");
|
||||
}
|
||||
|
||||
// final ConfigurationManager confManager = CDI.current().select(
|
||||
// ConfigurationManager.class).get();
|
||||
final WebConfig config = confManager.findConfiguration(WebConfig.class);
|
||||
// final WebConfig config = Web.getConfig();
|
||||
|
||||
Assert.exists(sreq, "HttpServletRequest sreq");
|
||||
Assert.exists(config, "WebConfig config");
|
||||
|
|
@ -797,8 +840,8 @@ public class URL {
|
|||
if (pathInfo == null) {
|
||||
return URL.there(sreq, app.getPrimaryUrl().toString(), params);
|
||||
} else {
|
||||
return URL.there(sreq, app.getPrimaryUrl().toString() + pathInfo,
|
||||
params);
|
||||
return URL.there(sreq, app.getPrimaryUrl().toString() + pathInfo,
|
||||
params);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -913,7 +956,7 @@ public class URL {
|
|||
|
||||
static URL login(final HttpServletRequest sreq) {
|
||||
//Replace register eventuelly...
|
||||
return URL.excursion(sreq,
|
||||
return URL.excursion(sreq,
|
||||
"/register/",
|
||||
(ParameterMap) s_empty.get());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -84,29 +84,32 @@ public final class WebConfig {
|
|||
private String dynamicHostProviderClass;
|
||||
|
||||
public static WebConfig getConfig() {
|
||||
final BeanManager beanManager = CDI.current().getBeanManager();
|
||||
final Set<Bean<?>> beans = beanManager.getBeans(
|
||||
ConfigurationManager.class);
|
||||
final Iterator<Bean<?>> iterator = beans.iterator();
|
||||
final ConfigurationManager confManager;
|
||||
if (iterator.hasNext()) {
|
||||
@SuppressWarnings("unchecked")
|
||||
final Bean<ConfigurationManager> bean
|
||||
= (Bean<ConfigurationManager>) iterator
|
||||
.next();
|
||||
final CreationalContext<ConfigurationManager> ctx = beanManager
|
||||
.createCreationalContext(bean);
|
||||
final ConfigurationManager confManager = CDI.current().select(
|
||||
ConfigurationManager.class).get();
|
||||
|
||||
confManager = (ConfigurationManager) beanManager.getReference(
|
||||
bean, ConfigurationManager.class, ctx);
|
||||
} else {
|
||||
LOGGER.error(new ParameterizedMessage(
|
||||
"No CDI Bean for type {} found.",
|
||||
ConfigurationManager.class.getName()));
|
||||
throw new IllegalStateException(String.format(
|
||||
"No CDI Bean for type \"%s\" found",
|
||||
ConfigurationManager.class.getName()));
|
||||
}
|
||||
// final BeanManager beanManager = CDI.current().getBeanManager();
|
||||
// final Set<Bean<?>> beans = beanManager.getBeans(
|
||||
// ConfigurationManager.class);
|
||||
// final Iterator<Bean<?>> iterator = beans.iterator();
|
||||
// final ConfigurationManager confManager;
|
||||
// if (iterator.hasNext()) {
|
||||
// @SuppressWarnings("unchecked")
|
||||
// final Bean<ConfigurationManager> bean
|
||||
// = (Bean<ConfigurationManager>) iterator
|
||||
// .next();
|
||||
// final CreationalContext<ConfigurationManager> ctx = beanManager
|
||||
// .createCreationalContext(bean);
|
||||
//
|
||||
// confManager = (ConfigurationManager) beanManager.getReference(
|
||||
// bean, ConfigurationManager.class, ctx);
|
||||
// } else {
|
||||
// LOGGER.error(new ParameterizedMessage(
|
||||
// "No CDI Bean for type {} found.",
|
||||
// ConfigurationManager.class.getName()));
|
||||
// throw new IllegalStateException(String.format(
|
||||
// "No CDI Bean for type \"%s\" found",
|
||||
// ConfigurationManager.class.getName()));
|
||||
// }
|
||||
|
||||
// final CdiUtil cdiUtil = new CdiUtil();
|
||||
// final ConfigurationManager confManager = cdiUtil.findBean(
|
||||
|
|
|
|||
|
|
@ -24,9 +24,9 @@ import static org.libreccm.core.CoreConstants.*;
|
|||
import org.hibernate.validator.constraints.NotBlank;
|
||||
import org.hibernate.validator.constraints.URL;
|
||||
import org.libreccm.core.CcmObject;
|
||||
import org.libreccm.core.DefaultEntityGraph;
|
||||
import org.libreccm.l10n.LocalizedString;
|
||||
import org.libreccm.web.CcmApplication;
|
||||
import org.omg.CORBA.DomainManager;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
|
|
@ -91,6 +91,7 @@ import javax.xml.bind.annotation.XmlRootElement;
|
|||
@NamedAttributeNode("subCategories")
|
||||
})})
|
||||
})
|
||||
@DefaultEntityGraph("Domain.allCategories")
|
||||
@XmlRootElement(name = "domain", namespace = CAT_XML_NS)
|
||||
public class Domain extends CcmObject implements Serializable {
|
||||
|
||||
|
|
|
|||
|
|
@ -29,6 +29,8 @@ import javax.enterprise.context.spi.CreationalContext;
|
|||
import javax.enterprise.inject.spi.Bean;
|
||||
import javax.enterprise.inject.spi.BeanManager;
|
||||
import javax.enterprise.inject.spi.CDI;
|
||||
import javax.naming.InitialContext;
|
||||
import javax.naming.NamingException;
|
||||
|
||||
/**
|
||||
*
|
||||
|
|
@ -43,7 +45,24 @@ public class CdiUtil {
|
|||
public CdiUtil() {
|
||||
beanManager = CDI.current().getBeanManager();
|
||||
}
|
||||
|
||||
private CdiUtil(final BeanManager beanManager) {
|
||||
this.beanManager = beanManager;
|
||||
}
|
||||
|
||||
public static CdiUtil createCdiUtil() {
|
||||
try {
|
||||
final InitialContext context = new InitialContext();
|
||||
final BeanManager beanManager = (BeanManager) context.lookup(
|
||||
"java:comp/BeanManager");
|
||||
return new CdiUtil(beanManager);
|
||||
} catch(NamingException ex) {
|
||||
throw new IllegalStateException("Unable to lookup BeanManager.", ex);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T findBean(final Class<T> beanType) {
|
||||
final Set<Bean<?>> beans = beanManager.getBeans(beanType);
|
||||
|
|
|
|||
|
|
@ -18,13 +18,18 @@
|
|||
*/
|
||||
package org.libreccm.core;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.persistence.EntityGraph;
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.Query;
|
||||
import javax.persistence.TypedQuery;
|
||||
import javax.persistence.criteria.CriteriaBuilder;
|
||||
import javax.persistence.criteria.CriteriaQuery;
|
||||
|
|
@ -39,7 +44,11 @@ import javax.persistence.criteria.Root;
|
|||
*/
|
||||
public abstract class AbstractEntityRepository<K, E> {
|
||||
|
||||
static final String FETCH_GRAPH_HINT_KEY = "javax.persistence.fetchgraph";
|
||||
private static final Logger LOGGER = LogManager.getLogger(
|
||||
AbstractEntityRepository.class);
|
||||
|
||||
protected static final String FETCH_GRAPH_HINT_KEY
|
||||
= "javax.persistence.fetchgraph";
|
||||
|
||||
/**
|
||||
* The {@link EntityManager} instance to use. Provided by the container via
|
||||
|
|
@ -57,12 +66,99 @@ public abstract class AbstractEntityRepository<K, E> {
|
|||
return entityManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an {@link EntityGraph} for the entity class of this repository.
|
||||
*
|
||||
* For more details about entity graphs/fetch graphs refer to the JPA
|
||||
* documentation. Internally this method uses
|
||||
* {@link EntityManager#createEntityGraph(java.lang.Class)}.
|
||||
*
|
||||
* @return An EntityGraph for this entity graph.
|
||||
*/
|
||||
public EntityGraph<E> createEntityGraph() {
|
||||
return entityManager.createEntityGraph(getEntityClass());
|
||||
}
|
||||
|
||||
protected void applyDefaultEntityGraph(final TypedQuery<E> query) {
|
||||
if (getEntityClass().isAnnotationPresent(DefaultEntityGraph.class)) {
|
||||
LOGGER.debug("The following EntityGraphs are available for the "
|
||||
+ "entity class {}:",
|
||||
getEntityClass().getName());
|
||||
getEntityManager().getEntityGraphs(getEntityClass()).stream()
|
||||
.forEach(g -> LOGGER.debug("\t{}", g.getName()));
|
||||
LOGGER.debug("Entity class {} has default entity graphs:",
|
||||
getEntityClass().getName());
|
||||
LOGGER.debug("Applying entity graph {}",
|
||||
getEntityClass().getAnnotation(
|
||||
DefaultEntityGraph.class).value());
|
||||
query.setHint(FETCH_GRAPH_HINT_KEY,
|
||||
entityManager.getEntityGraph(
|
||||
getEntityClass().getAnnotation(
|
||||
DefaultEntityGraph.class).value()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method for retrieving a single result from a query.
|
||||
*
|
||||
* @param query The query from which the result is retrieved.
|
||||
*
|
||||
* @return A first result or the query or {@code null} of there is no
|
||||
* result.
|
||||
*/
|
||||
protected E getSingleResultOrNull(final TypedQuery<E> query) {
|
||||
final List<E> result = query.getResultList();
|
||||
if (result.isEmpty()) {
|
||||
return null;
|
||||
} else {
|
||||
return result.get(0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method for retrieving a single result from a query. In contrast to
|
||||
* {@link #getSingleResultOrNull(javax.persistence.TypedQuery)} this method
|
||||
* return an {@link Optional} for the result.
|
||||
*
|
||||
* @param query The query from which the result is retrieved.
|
||||
*
|
||||
* @return An {@link Optional} instance wrapping the first result of the
|
||||
* query. If there is no result the {@code Optional} is empty.
|
||||
*/
|
||||
protected Optional<E> getSingleResult(final TypedQuery<E> query) {
|
||||
final List<E> result = query.getResultList();
|
||||
if (result.isEmpty()) {
|
||||
return Optional.empty();
|
||||
} else {
|
||||
return Optional.of(result.get(0));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a mutable copy of a named entity graph which an be further
|
||||
* customised.
|
||||
*
|
||||
* Internally this method uses
|
||||
* {@link EntityManager#createEntityGraph(java.lang.String)}.
|
||||
*
|
||||
* @param entityGraphName The name of the named entity graph.
|
||||
*
|
||||
* @return A mutable copy of the named entity graph identified by the
|
||||
* provided name or {@code null} if there is no such named entity
|
||||
* graph.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public EntityGraph<E> createEntityGraph(final String entityGraphName) {
|
||||
return (EntityGraph<E>) entityManager.createEntityGraph(
|
||||
entityGraphName);
|
||||
}
|
||||
|
||||
/**
|
||||
* The class of entities for which this repository can be used. For creating
|
||||
* a repository class overwrite this method.
|
||||
*
|
||||
* @return The {@code Class} of the Entity which are managed by this
|
||||
* repository.
|
||||
* repository.
|
||||
*/
|
||||
public abstract Class<E> getEntityClass();
|
||||
|
||||
|
|
@ -72,15 +168,21 @@ public abstract class AbstractEntityRepository<K, E> {
|
|||
* @param entityId The ID of the entity to retrieve.
|
||||
*
|
||||
* @return The entity identified by the provided ID of {@code null} if there
|
||||
* is no such entity.
|
||||
* is no such entity.
|
||||
*/
|
||||
public E findById(final K entityId) {
|
||||
return entityManager.find(getEntityClass(), entityId);
|
||||
if (getEntityClass().isAnnotationPresent(DefaultEntityGraph.class)) {
|
||||
return findById(entityId, getEntityClass().getAnnotation(
|
||||
DefaultEntityGraph.class).value());
|
||||
} else {
|
||||
return entityManager.find(getEntityClass(), entityId);
|
||||
}
|
||||
}
|
||||
|
||||
public E findById(final K entityId, final String entityGraphName) {
|
||||
@SuppressWarnings("unchecked")
|
||||
final EntityGraph<E> entityGraph = (EntityGraph<E>) entityManager.
|
||||
getEntityGraph(entityGraphName);
|
||||
getEntityGraph(entityGraphName);
|
||||
return findById(entityId, entityGraph);
|
||||
}
|
||||
|
||||
|
|
@ -95,15 +197,15 @@ public abstract class AbstractEntityRepository<K, E> {
|
|||
* responsible for.
|
||||
*
|
||||
* @return The list of entities in the database which are of the type
|
||||
* provided by {@link #getEntityClass()}.
|
||||
* provided by {@link #getEntityClass()}.
|
||||
*/
|
||||
public List<E> findAll() {
|
||||
// We are using the Critiera API here because otherwise we can't
|
||||
// pass the type of the entity dynmacially.
|
||||
final CriteriaBuilder criteriaBuilder = entityManager
|
||||
.getCriteriaBuilder();
|
||||
.getCriteriaBuilder();
|
||||
final CriteriaQuery<E> criteriaQuery = criteriaBuilder.createQuery(
|
||||
getEntityClass());
|
||||
getEntityClass());
|
||||
final Root<E> root = criteriaQuery.from(getEntityClass());
|
||||
criteriaQuery.select(root);
|
||||
|
||||
|
|
@ -117,8 +219,9 @@ public abstract class AbstractEntityRepository<K, E> {
|
|||
* entity is a a new one.
|
||||
*
|
||||
* @param entity The entity to check.
|
||||
*
|
||||
* @return {@code true} if the entity is new (isn't in the database yet),
|
||||
* {@code false} otherwise.
|
||||
* {@code false} otherwise.
|
||||
*/
|
||||
public abstract boolean isNew(final E entity);
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Copyright (C) 2016 LibreCCM Foundation.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
* MA 02110-1301 USA
|
||||
*/
|
||||
package org.libreccm.core;
|
||||
|
||||
import java.lang.annotation.Inherited;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import static java.lang.annotation.ElementType.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Inherited
|
||||
@Target({TYPE})
|
||||
public @interface DefaultEntityGraph {
|
||||
|
||||
String value();
|
||||
|
||||
}
|
||||
|
|
@ -20,6 +20,8 @@ package org.libreccm.security;
|
|||
|
||||
import static org.libreccm.core.CoreConstants.*;
|
||||
|
||||
import org.libreccm.core.DefaultEntityGraph;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
|
|
@ -33,6 +35,9 @@ import javax.persistence.GenerationType;
|
|||
import javax.persistence.Id;
|
||||
import javax.persistence.Inheritance;
|
||||
import javax.persistence.InheritanceType;
|
||||
import javax.persistence.NamedAttributeNode;
|
||||
import javax.persistence.NamedEntityGraph;
|
||||
import javax.persistence.NamedEntityGraphs;
|
||||
import javax.persistence.NamedQueries;
|
||||
import javax.persistence.NamedQuery;
|
||||
import javax.persistence.OneToMany;
|
||||
|
|
@ -56,6 +61,12 @@ import javax.xml.bind.annotation.XmlElementWrapper;
|
|||
@NamedQuery(name = "Party.findByName",
|
||||
query = "SELECT p FROM Party p WHERE p.name = :name")
|
||||
})
|
||||
@NamedEntityGraphs({
|
||||
@NamedEntityGraph(name = "Party.withRoleMemberships",
|
||||
attributeNodes = @NamedAttributeNode(
|
||||
value = "roleMemberships"))
|
||||
})
|
||||
@DefaultEntityGraph("Party.withRoleMemberships")
|
||||
public class Party implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 3319997992281332204L;
|
||||
|
|
|
|||
|
|
@ -62,7 +62,8 @@ public class Shiro {
|
|||
@Produces
|
||||
@Named("securityManager")
|
||||
public SecurityManager getSecurityManager() {
|
||||
return proxy(SecurityManager.class, new SubjectInvocationHandler());
|
||||
return proxy(SecurityManager.class,
|
||||
new SecurityManagerInvocationHandler());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -115,6 +116,7 @@ public class Shiro {
|
|||
return publicUser;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> T proxy(final Class<T> clazz, final InvocationHandler handler) {
|
||||
return (T) Proxy.newProxyInstance(getClass().getClassLoader(),
|
||||
new Class<?>[]{clazz},
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ package org.libreccm.security;
|
|||
|
||||
import static org.libreccm.core.CoreConstants.*;
|
||||
|
||||
import org.libreccm.core.DefaultEntityGraph;
|
||||
import org.libreccm.core.EmailAddress;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
|
@ -37,9 +38,13 @@ import javax.persistence.Entity;
|
|||
import javax.persistence.FetchType;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.JoinTable;
|
||||
import javax.persistence.NamedAttributeNode;
|
||||
import javax.persistence.NamedEntityGraph;
|
||||
import javax.persistence.NamedEntityGraphs;
|
||||
import javax.persistence.NamedQueries;
|
||||
import javax.persistence.NamedQuery;
|
||||
import javax.persistence.OneToMany;
|
||||
import javax.persistence.OrderColumn;
|
||||
import javax.persistence.Table;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
|
|
@ -59,9 +64,18 @@ import javax.xml.bind.annotation.XmlTransient;
|
|||
@NamedQuery(name = "User.findByName",
|
||||
query = "SELECT u FROM User u WHERE u.name = :name"),
|
||||
@NamedQuery(name = "User.findByEmailAddress",
|
||||
query = "SELECT u FROM User u WHERE " +
|
||||
"u.primaryEmailAddress.address = :emailAddress")
|
||||
query = "SELECT u FROM User u WHERE "
|
||||
+ "u.primaryEmailAddress.address = :emailAddress")
|
||||
})
|
||||
@NamedEntityGraphs({
|
||||
@NamedEntityGraph(name = "User.withGroupAndRoleMemberships",
|
||||
attributeNodes = {
|
||||
@NamedAttributeNode(
|
||||
value = "groupMemberships"),
|
||||
@NamedAttributeNode(
|
||||
value = "roleMemberships")})
|
||||
})
|
||||
@DefaultEntityGraph("User.withGroupAndRoleMemberships")
|
||||
@XmlRootElement(name = "user", namespace = CORE_XML_NS)
|
||||
//Supressing a few warnings from PMD because they misleading here.
|
||||
//User is perfectly fine class name, and the complexity is not to high...
|
||||
|
|
@ -112,9 +126,9 @@ public class User extends Party implements Serializable {
|
|||
private List<EmailAddress> emailAddresses;
|
||||
|
||||
/**
|
||||
* A user can be banned which means that he or she can't login into
|
||||
* the system anymore. We use this approach rather than simply deleting users
|
||||
* to preserve the edit history of several objects.
|
||||
* A user can be banned which means that he or she can't login into the
|
||||
* system anymore. We use this approach rather than simply deleting users to
|
||||
* preserve the edit history of several objects.
|
||||
*/
|
||||
@Column(name = "BANNED")
|
||||
@XmlElement(name = "banned", namespace = CORE_XML_NS)
|
||||
|
|
|
|||
|
|
@ -21,8 +21,10 @@ package org.libreccm.security;
|
|||
import org.libreccm.core.AbstractEntityRepository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import javax.enterprise.context.RequestScoped;
|
||||
import javax.persistence.EntityGraph;
|
||||
import javax.persistence.TypedQuery;
|
||||
|
||||
/**
|
||||
|
|
@ -52,20 +54,59 @@ public class UserRepository extends AbstractEntityRepository<Long, User> {
|
|||
* @param name The name of the user to find.
|
||||
*
|
||||
* @return The user identified by the provided name. If there are multiple
|
||||
* user matching the user name (should be possible) the first one is
|
||||
* returned. If there is no matching user {@code null} is returned.
|
||||
* user matching the user name (should be possible) the first one is
|
||||
* returned. If there is no matching user {@code null} is returned.
|
||||
*/
|
||||
public User findByName(final String name) {
|
||||
final TypedQuery<User> query = getEntityManager().createNamedQuery(
|
||||
"User.findByName",
|
||||
User.class);
|
||||
"User.findByName", User.class);
|
||||
applyDefaultEntityGraph(query);
|
||||
query.setParameter("name", name);
|
||||
final List<User> result = query.getResultList();
|
||||
if (result.isEmpty()) {
|
||||
return null;
|
||||
} else {
|
||||
return result.get(0);
|
||||
}
|
||||
|
||||
return getSingleResultOrNull(query);
|
||||
|
||||
// final List<User> result = query.getResultList();
|
||||
// if (result.isEmpty()) {
|
||||
// return null;
|
||||
// } else {
|
||||
// return result.get(0);
|
||||
// }
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds a user by its name and applies the given named entity graph to the
|
||||
* query.
|
||||
*
|
||||
* @param name The name of the user to find.
|
||||
* @param entityGraphName The named entity graph to use.
|
||||
*
|
||||
* @return The user identified by the provided name. If there are multiple
|
||||
* user matching the user name (should be possible) the first one is
|
||||
* returned. If there is no matching user {@code null} is returned.
|
||||
*/
|
||||
public User findByName(final String name, final String entityGraphName) {
|
||||
@SuppressWarnings("unchecked")
|
||||
final EntityGraph<User> entityGraph
|
||||
= (EntityGraph<User>) getEntityManager()
|
||||
.getEntityGraph(entityGraphName);
|
||||
return findByName(name, entityGraph);
|
||||
}
|
||||
|
||||
public User findByName(final String name,
|
||||
final EntityGraph<User> entityGraph) {
|
||||
final TypedQuery<User> query = getEntityManager().createNamedQuery(
|
||||
"User.findByName", User.class);
|
||||
query.setParameter("name", name);
|
||||
query.setHint(FETCH_GRAPH_HINT_KEY, entityGraph);
|
||||
|
||||
return getSingleResultOrNull(query);
|
||||
|
||||
// final List<User> result = query.getResultList();
|
||||
// if (result.isEmpty()) {
|
||||
// return null;
|
||||
// } else {
|
||||
// return result.get(0);
|
||||
// }
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -74,19 +115,42 @@ public class UserRepository extends AbstractEntityRepository<Long, User> {
|
|||
* @param emailAddress The email address which identifies the user.
|
||||
*
|
||||
* @return The user identified by the provided email address. If there are
|
||||
* multiple matching users only the first one is returned. If there is no
|
||||
* matching user {@code null} is returned.
|
||||
* multiple matching users only the first one is returned. If there
|
||||
* is no matching user {@code null} is returned.
|
||||
*/
|
||||
public User findByEmailAddress(final String emailAddress) {
|
||||
final TypedQuery<User> query = getEntityManager().createNamedQuery(
|
||||
"User.findByEmailAddress", User.class);
|
||||
"User.findByEmailAddress", User.class);
|
||||
query.setParameter("emailAddress", emailAddress);
|
||||
final List<User> result = query.getResultList();
|
||||
if (result.isEmpty()) {
|
||||
return null;
|
||||
} else {
|
||||
return result.get(0);
|
||||
}
|
||||
applyDefaultEntityGraph(query);
|
||||
|
||||
return getSingleResultOrNull(query);
|
||||
|
||||
// final List<User> result = query.getResultList();
|
||||
// if (result.isEmpty()) {
|
||||
// return null;
|
||||
// } else {
|
||||
// return result.get(0);
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
public User findByEmailAddress(final String emailAddress,
|
||||
final String entityGraphName) {
|
||||
@SuppressWarnings("unchecked")
|
||||
final EntityGraph<User> entityGraph
|
||||
= (EntityGraph<User>) getEntityManager()
|
||||
.getEntityGraph(entityGraphName);
|
||||
return findByEmailAddress(emailAddress, entityGraph);
|
||||
}
|
||||
|
||||
public User findByEmailAddress(final String emailAddress,
|
||||
final EntityGraph<User> entityGraph) {
|
||||
final TypedQuery<User> query = getEntityManager().createNamedQuery(
|
||||
"User.findByEmailAddress", User.class);
|
||||
query.setParameter("emailAddress", emailAddress);
|
||||
query.setHint(FETCH_GRAPH_HINT_KEY, entityGraph);
|
||||
|
||||
return getSingleResultOrNull(query);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue