CCM NG: Added associations between CcmApplication and Site

git-svn-id: https://svn.libreccm.org/ccm/ccm_ng@5085 8810af33-2d31-482b-a856-94f89814c4df

Former-commit-id: bf4b3b567b
pull/2/head
jensp 2017-10-26 08:10:20 +00:00
parent 31c0df1b36
commit 5aa1d661f8
14 changed files with 429 additions and 112 deletions

View File

@ -55,19 +55,19 @@ import org.librecms.contentsection.privileges.ItemPrivileges;
import java.util.Optional;
/**
* <p>A <tt>CMSPage</tt> is a Bebop {@link com.arsdigita.bebop.Page}
* implementation of the {@link com.arsdigita.cms.dispatcher.ResourceHandler}
* interface.</p>
* <p>
* A <tt>CMSPage</tt> is a Bebop {@link com.arsdigita.bebop.Page} implementation
* of the {@link com.arsdigita.cms.dispatcher.ResourceHandler} interface.</p>
*
* <p>It stores the current {@link com.arsdigita.cms.ContentSection} and, if
* <p>
* It stores the current {@link com.arsdigita.cms.ContentSection} and, if
* applicable, the {@link com.arsdigita.cms.ContentItem} in the page state as
* request local objects. Components that are part of the <tt>CMSPage</tt>
* may access these objects by calling:</p>
* <blockquote><code><pre>
* <blockquote><code><pre>
* getContentSection(PageState state);
* </pre></code></blockquote>
* </pre></code></blockquote>
*
* @author Michael Pih (pihman@arsdigita.com)
* @author Uday Mathur (umathur@arsdigita.com)
@ -76,16 +76,23 @@ public class CMSPage extends Page implements ResourceHandler {
private static final Logger LOGGER = LogManager.getLogger(CMSPage.class);
/** The global assets URL stub XML parameter name. */
/**
* The global assets URL stub XML parameter name.
*/
public final static String ASSETS = "ASSETS";
/** The XML page class. */
/**
* The XML page class.
*/
public final static String PAGE_CLASS = "CMS";
/** Map of XML parameters */
/**
* Map of XML parameters
*/
private HashMap m_params;
/** */
/**
* */
private PageTransformer m_transformer;
public CMSPage() {
@ -135,18 +142,21 @@ public class CMSPage extends Page implements ResourceHandler {
// Make sure the error display gets rendered.
getErrorDisplay().setIdAttr("page-body");
final Class<PresentationManager> presenterClass = BebopConfig.getConfig().getPresenterClass();
final Class<PresentationManager> presenterClass = BebopConfig
.getConfig().getPresenterClass();
final PresentationManager pm;
try {
pm = presenterClass.getDeclaredConstructor().newInstance();
} catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException ex) {
} catch (InstantiationException
| IllegalAccessException
| InvocationTargetException
| NoSuchMethodException ex) {
throw new RuntimeException(ex);
}
if (pm instanceof PageTransformer) {
m_transformer = (PageTransformer) pm;
}
else {
} else {
m_transformer = new PageTransformer();
}
}
@ -172,7 +182,9 @@ public class CMSPage extends Page implements ResourceHandler {
* Fetches the value of the XML parameter.
*
* @param name The parameter name
*
* @return The parameter value
*
* @pre (name != null)
*/
public String getXMLParameter(String name) {
@ -182,8 +194,9 @@ public class CMSPage extends Page implements ResourceHandler {
/**
* Set an XML parameter.
*
* @param name The parameter name
* @param name The parameter name
* @param value The parameter value
*
* @pre (name != null)
*/
public void setXMLParameter(String name, String value) {
@ -194,20 +207,19 @@ public class CMSPage extends Page implements ResourceHandler {
* Fetch the request-local content section.
*
* @param request The HTTP request
*
* @return The current content section
*
* @deprecated use com.arsdigita.cms.CMS.getContext().getContentSection()
* instead
* Despite of being deprecated it can not be removed because it
* is required by the interface Resourcehandler which is
* implemented by this class.
* On the other hand, if deprecated, implementing ResourceHandler
* may not be required
* instead Despite of being deprecated it can not be removed because it is
* required by the interface Resourcehandler which is implemented by this
* class. On the other hand, if deprecated, implementing ResourceHandler may
* not be required
*/
@Override
public ContentSection getContentSection(HttpServletRequest request) {
// Resets all content sections associations.
// return ContentSectionDispatcher.getContentSection(request);
// return ContentSectionDispatcher.getContentSection(request);
return ContentSectionServlet.getContentSection(request);
}
@ -215,13 +227,12 @@ public class CMSPage extends Page implements ResourceHandler {
* Fetch the request-local content section.
*
* @param state The page state
*
* @return The current content section
*
* @deprecated use com.arsdigita.cms.CMS.getContext().getContentSection()
* instead
* Despite of being deprecated it can not be removed because it
* is required by ContentItemPage which extends CMSPage and
* uses this method.
* instead Despite of being deprecated it can not be removed because it is
* required by ContentItemPage which extends CMSPage and uses this method.
*/
public ContentSection getContentSection(PageState state) {
return getContentSection(state.getRequest());
@ -231,15 +242,14 @@ public class CMSPage extends Page implements ResourceHandler {
* Fetch the request-local content item.
*
* @param request The HTTP request
*
* @return The current content item
*
* @deprecated use com.arsdigita.cms.CMS.getContext().getContentItem()
* instead
* Despite of being deprecated it can not be removed because it
* is required by the interface Resourcehandler which is
* implemented by this class.
* On the other hand, if deprecated, implementing ResourceHandler
* may not be required
* instead Despite of being deprecated it can not be removed because it is
* required by the interface Resourcehandler which is implemented by this
* class. On the other hand, if deprecated, implementing ResourceHandler may
* not be required
*/
public ContentItem getContentItem(HttpServletRequest request) {
// resets all content item associations
@ -250,12 +260,12 @@ public class CMSPage extends Page implements ResourceHandler {
* Fetch the request-local content item.
*
* @param state The page state
*
* @return The current content item
*
* @deprecated use com.arsdigita.cms.CMS.getContext().getContentItem()
* instead.
* Despite of being deprecated it can not be removed because it
* is required by ContentItemPage which extends CMSPage and
* uses this method.
* instead. Despite of being deprecated it can not be removed because it is
* required by ContentItemPage which extends CMSPage and uses this method.
*/
public ContentItem getContentItem(PageState state) {
return getContentItem(state.getRequest());
@ -264,15 +274,15 @@ public class CMSPage extends Page implements ResourceHandler {
/**
* Services the Bebop page.
*
* @param request The servlet request object
* @param request The servlet request object
* @param response the servlet response object
* @param actx The request context
* @param actx The request context
*
* @pre m_transformer != null
*/
@Override
public void dispatch(final HttpServletRequest request,
final HttpServletResponse response ,
final HttpServletResponse response,
final RequestContext actx)
throws IOException, ServletException {
@ -281,7 +291,7 @@ public class CMSPage extends Page implements ResourceHandler {
if (app == null) {
//Nothing to do
} else if(app instanceof ContentSection) {
} else if (app instanceof ContentSection) {
section = (ContentSection) app;
}
@ -293,7 +303,8 @@ public class CMSPage extends Page implements ResourceHandler {
if (itemId != null) {
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final ContentItemRepository itemRepo = cdiUtil.findBean(ContentItemRepository.class);
final ContentItemRepository itemRepo = cdiUtil.findBean(
ContentItemRepository.class);
final ContentItem item = itemRepo
.findById(Long.parseLong(itemId)).get();
final PermissionChecker permissionChecker = cdiUtil.findBean(
@ -311,18 +322,22 @@ public class CMSPage extends Page implements ResourceHandler {
/**
* Overwrites bebop.Page#generateXMLHelper to add the name of the user
* logged in to the page (displayed as part of the header).
*
* @param ps
* @param parent
*
* @return
*/
@Override
protected Element generateXMLHelper(PageState ps, Document parent) {
Element page = super.generateXMLHelper(ps,parent);
final Optional<User> user = CdiUtil.createCdiUtil().findBean(Shiro.class).getUser();
if ( user.isPresent()) {
page.addAttribute("name",user.get().getName());
Element page = super.generateXMLHelper(ps, parent);
final Optional<User> user = CdiUtil.createCdiUtil()
.findBean(Shiro.class).getUser();
if (user.isPresent()) {
page.addAttribute("name", user.get().getName());
}
return page;
}
}

View File

@ -131,14 +131,15 @@ public class CMSApplicationPage extends Page {
getErrorDisplay().setIdAttr("page-body");
final Class<PresentationManager> presenterClass = BebopConfig
.getConfig().getPresenterClass();
.getConfig()
.getPresenterClass();
final PresentationManager presenter;
try {
presenter = presenterClass.getDeclaredConstructor().newInstance();
} catch (InstantiationException
| IllegalAccessException
| NoSuchMethodException
| InvocationTargetException ex) {
| IllegalAccessException
| NoSuchMethodException
| InvocationTargetException ex) {
throw new RuntimeException("Failed to create PresentationManager",
ex);
}

View File

@ -20,7 +20,6 @@ package org.librecms.pages;
import org.libreccm.categorization.Category;
import org.libreccm.core.AbstractEntityRepository;
import org.libreccm.core.CoreConstants;
import org.libreccm.security.RequiresPrivilege;
import java.util.Optional;
@ -28,6 +27,7 @@ import java.util.Optional;
import javax.enterprise.context.RequestScoped;
import javax.persistence.NoResultException;
import javax.persistence.TypedQuery;
import javax.transaction.Transactional;
/**
* Repository for {@link Page} entities.
@ -37,12 +37,16 @@ import javax.persistence.TypedQuery;
@RequestScoped
public class PageRepository extends AbstractEntityRepository<Long, Page>{
private static final long serialVersionUID = -338101684757468443L;
/**
* Find the {@link Page} associated with a {@link Category}.
*
* @param category The {@link Category} associated with the {@link Page}.
* @return
*/
@RequiresPrivilege(PagesPrivileges.ADMINISTER_PAGES)
@Transactional(Transactional.TxType.REQUIRED)
public Optional<Page> findPageForCategory(final Category category) {
final TypedQuery<Page> query = getEntityManager()
@ -56,14 +60,14 @@ public class PageRepository extends AbstractEntityRepository<Long, Page>{
}
}
@RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN)
@Override
@RequiresPrivilege(PagesPrivileges.ADMINISTER_PAGES)
@Transactional(Transactional.TxType.REQUIRED)
public void save(final Page page) {
super.save(page);
}
@RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN)
@Override
@RequiresPrivilege(PagesPrivileges.ADMINISTER_PAGES)
@Transactional(Transactional.TxType.REQUIRED)
public void delete(final Page page) {
super.delete(page);
}

View File

@ -19,8 +19,7 @@
package org.librecms.pages;
import org.libreccm.categorization.Domain;
import org.libreccm.sites.Site;
import org.libreccm.web.CcmApplication;
import org.libreccm.sites.SiteAwareApplication;
import java.io.Serializable;
import java.util.Objects;
@ -35,8 +34,8 @@ import javax.persistence.Table;
import static org.librecms.CmsConstants.*;
/**
* The {@code Pages} application. Each instance of this application provides
* the page tree for specific site.
* The {@code Pages} application. Each instance of this application provides the
* page tree for specific site.
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
@ -66,17 +65,10 @@ import static org.librecms.CmsConstants.*;
+ "FROM Pages p JOIN p.site s "
+ "WHERE s.defaultSite = true")
})
public class Pages extends CcmApplication implements Serializable {
public class Pages extends SiteAwareApplication implements Serializable {
private static final long serialVersionUID = -352205318143692477L;
/**
* The {@link Site} to which this pages instance belongs.
*/
@OneToOne
@JoinColumn(name = "SITE_ID")
private Site site;
/**
* The category {@link Domain} which is used the model the page tree.
*/
@ -84,14 +76,6 @@ public class Pages extends CcmApplication implements Serializable {
@JoinColumn(name = "CATEGORY_DOMAIN_ID")
private Domain categoryDomain;
public Site getSite() {
return site;
}
protected void setSite(final Site site) {
this.site = site;
}
public Domain getCategoryDomain() {
return categoryDomain;
}
@ -104,7 +88,6 @@ public class Pages extends CcmApplication implements Serializable {
public int hashCode() {
int hash = 7;
hash = 17 * hash + Objects.hashCode(categoryDomain);
hash = 17 * hash + Objects.hashCode(site);
return hash;
}
@ -132,10 +115,6 @@ public class Pages extends CcmApplication implements Serializable {
return false;
}
if (!Objects.equals(site, other.getSite())) {
return false;
}
return Objects.equals(categoryDomain, other.getCategoryDomain());
}
@ -143,15 +122,4 @@ public class Pages extends CcmApplication implements Serializable {
public boolean canEqual(final Object obj) {
return obj instanceof Pages;
}
@Override
public String toString(final String data) {
return super.toString(String.format(
", site = \"%s\"%s",
Objects.toString(site),
data
));
}
}

View File

@ -19,9 +19,15 @@
package org.librecms.pages;
import org.libreccm.categorization.Domain;
import org.libreccm.security.RequiresPrivilege;
import org.libreccm.sites.Site;
import org.libreccm.sites.SiteManager;
import java.io.Serializable;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.transaction.Transactional;
/**
* Manager class for {@link Pages}.
@ -29,16 +35,26 @@ import javax.inject.Inject;
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
@RequestScoped
public class PagesManager {
public class PagesManager implements Serializable {
private static final long serialVersionUID = 888880071212859827L;
@Inject
private PagesRepository pagesRepo;
public Pages createPages(final Domain domain) {
@Inject
private SiteManager siteManager;
@RequiresPrivilege(PagesPrivileges.ADMINISTER_PAGES)
@Transactional(Transactional.TxType.REQUIRED)
public Pages createPages(final Site site,
final Domain domain) {
final Pages pages = new Pages();
pages.setCategoryDomain(domain);
siteManager.addApplicationToSite(site, pages);
pagesRepo.save(pages);
return pages;

View File

@ -0,0 +1,34 @@
/*
* Copyright (C) 2017 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.librecms.pages;
/**
* Constants for privileges allowing administrative actions on pages.
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
public final class PagesPrivileges {
public static final String ADMINISTER_PAGES = "administer_pages";
private PagesPrivileges() {
//Nothing
}
}

View File

@ -0,0 +1,13 @@
alter table CCM_CMS.PAGES_APP
drop constraint FK3wkyn4oxa65f7svtj917m61jc;
alter table CCM_CMS.PAGES_APP
drop contraint FKrrk4g7my3e4qkdoeiygkqxduy;
alter table CCM_CMS.PAGES_APP
drop column if exists SITE_ID;
alter table CCM_CMS.PAGES_APP
add constraint FKk4jb5fylibg2pbbaypyt6f8lb
foreign key (OBJECT_ID)
references SITE_AWARE_APPLICATIONS;

View File

@ -0,0 +1,13 @@
alter table CCM_CMS.PAGES_APP
drop constraint FK3wkyn4oxa65f7svtj917m61jc;
alter table CCM_CMS.PAGES_APP
drop contraint FKrrk4g7my3e4qkdoeiygkqxduy;
alter table CCM_CMS.PAGES_APP
drop column if exists SITE_ID;
alter table CCM_CMS.PAGES_APP
add constraint FKk4jb5fylibg2pbbaypyt6f8lb
foreign key (OBJECT_ID)
references SITE_AWARE_APPLICATIONS;

View File

@ -22,12 +22,16 @@ import static org.libreccm.core.CoreConstants.*;
import org.libreccm.core.CcmObject;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.Table;
/**
@ -66,6 +70,14 @@ public class Site extends CcmObject {
@Column(name = "DEFAULT_THEME")
private String defaultTheme;
@OneToMany(mappedBy = "site")
private List<SiteAwareApplication> applications;
public Site() {
super();
applications = new ArrayList<>();
}
public String getDomainOfSite() {
return domainOfSite;
}
@ -90,6 +102,22 @@ public class Site extends CcmObject {
this.defaultTheme = defaultTheme;
}
public List<SiteAwareApplication> getApplications() {
return Collections.unmodifiableList(applications);
}
protected void setApplications(final List<SiteAwareApplication> applications) {
this.applications = new ArrayList<>(applications);
}
protected void addApplication(final SiteAwareApplication application) {
applications.add(application);
}
protected void removeApplication(final SiteAwareApplication application) {
applications.remove(application);
}
@Override
public int hashCode() {
int hash = 3;

View File

@ -0,0 +1,122 @@
/*
* Copyright (C) 2017 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.sites;
import org.libreccm.web.CcmApplication;
import java.util.Objects;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
/**
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
@Entity
@Table(name = "SITE_AWARE_APPLICATIONS")
public class SiteAwareApplication extends CcmApplication {
private static final long serialVersionUID = -8892544588904174406L;
@ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
@JoinColumn(name = "SITE_ID")
private Site site;
public Site getSite() {
return site;
}
protected void setSite(final Site site) {
this.site = site;
}
@Override
public int hashCode() {
int hash = 3;
if (site != null) {
hash = 59 * hash + Objects.hashCode(site.getDomainOfSite());
hash = 59 * hash + Objects.hashCode(site.isDefaultSite());
hash = 59 * hash + Objects.hashCode(site.getDefaultTheme());
}
return hash;
}
@Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (!(obj instanceof SiteAwareApplication)) {
return false;
}
final SiteAwareApplication other = (SiteAwareApplication) obj;
if (!other.canEqual(this)) {
return false;
}
if (site == null && other.getSite() != null) {
return false;
} else if (site != null && other.getSite() == null) {
return false;
} else {
if (!Objects.equals(site.getDomainOfSite(),
other.getSite().getDomainOfSite())) {
return false;
}
if (site.isDefaultSite() != other.getSite().isDefaultSite()) {
return false;
}
if (!Objects.equals(site.getDefaultTheme(),
other.getSite().getDefaultTheme())) {
return false;
}
}
return true;
}
@Override
public boolean canEqual(final Object obj) {
return obj instanceof SiteAwareApplication;
}
@Override
public String toString(final String data) {
if (site == null) {
return super.toString(String.format(", site = null%d", data));
} else {
return super.toString(String.format(", site = { "
+ "domainOfSite = \"%s\", "
+ "isDefaultSite = %b,"
+ "defaultTheme = \"%s\" }%s",
site.getDomainOfSite(),
site.isDefaultSite(),
site.getDefaultTheme(),
data));
}
}
}

View File

@ -0,0 +1,71 @@
/*
* Copyright (C) 2017 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.sites;
import static org.libreccm.core.CoreConstants.*;
import org.libreccm.security.RequiresPrivilege;
import org.libreccm.web.ApplicationRepository;
import java.io.Serializable;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.transaction.Transactional;
/**
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
@RequestScoped
public class SiteManager implements Serializable {
private static final long serialVersionUID = 1834820718630385805L;
@Inject
private ApplicationRepository applicationRepo;
@Inject
private SiteRepository siteRepo;
@RequiresPrivilege(PRIVILEGE_ADMIN)
@Transactional(Transactional.TxType.REQUIRED)
public void addApplicationToSite(final Site site,
final SiteAwareApplication application) {
site.addApplication(application);
application.setSite(site);
siteRepo.save(site);
applicationRepo.save(application);
}
@RequiresPrivilege(PRIVILEGE_ADMIN)
@Transactional(Transactional.TxType.REQUIRED)
public void removeApplicationFromSite(final Site site,
final SiteAwareApplication application) {
site.removeApplication(application);
application.setSite(null);
siteRepo.save(site);
applicationRepo.save(application);
}
}

View File

@ -36,6 +36,8 @@ import javax.transaction.Transactional;
@RequestScoped
public class SiteRepository extends AbstractEntityRepository<Long, Site> {
private static final long serialVersionUID = 3120528987720524155L;
@Transactional(Transactional.TxType.REQUIRED)
public Optional<Site> findByDomain(final String domain) {

View File

@ -0,0 +1,15 @@
create table SITE_AWARE_APPLICATIONS (
OBJECT_ID bigint not null,
SITE_ID bigint,
primary key (OBJECT_ID)
);
alter table SITE_AWARE_APPLICATIONS
add constraint FKopo91c29jaunpcusjwlphhxkd
foreign key (SITE_ID)
references CCM_CORE.SITES;
alter table SITE_AWARE_APPLICATIONS
add constraint FKslbu2qagg23dmdu01lun7oh7x
foreign key (OBJECT_ID)
references CCM_CORE.APPLICATIONS;

View File

@ -0,0 +1,15 @@
create table SITE_AWARE_APPLICATIONS (
OBJECT_ID int8 not null,
SITE_ID int8,
primary key (OBJECT_ID)
);
alter table SITE_AWARE_APPLICATIONS
add constraint FKopo91c29jaunpcusjwlphhxkd
foreign key (SITE_ID)
references CCM_CORE.SITES;
alter table SITE_AWARE_APPLICATIONS
add constraint FKslbu2qagg23dmdu01lun7oh7x
foreign key (OBJECT_ID)
references CCM_CORE.APPLICATIONS;