diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/dispatcher/CMSPage.java b/ccm-cms/src/main/java/com/arsdigita/cms/dispatcher/CMSPage.java
index 35c1fab3f..5ba7e4c3e 100755
--- a/ccm-cms/src/main/java/com/arsdigita/cms/dispatcher/CMSPage.java
+++ b/ccm-cms/src/main/java/com/arsdigita/cms/dispatcher/CMSPage.java
@@ -55,19 +55,19 @@ import org.librecms.contentsection.privileges.ItemPrivileges;
import java.util.Optional;
-
/**
- *
A CMSPage is a Bebop {@link com.arsdigita.bebop.Page}
- * implementation of the {@link com.arsdigita.cms.dispatcher.ResourceHandler}
- * interface.
+ *
+ * A CMSPage is a Bebop {@link com.arsdigita.bebop.Page} implementation
+ * of the {@link com.arsdigita.cms.dispatcher.ResourceHandler} interface.
*
- * It stores the current {@link com.arsdigita.cms.ContentSection} and, if
+ *
+ * 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 CMSPage
* may access these objects by calling:
- *
+ *
* getContentSection(PageState state);
- *
+ *
*
* @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 presenterClass = BebopConfig.getConfig().getPresenterClass();
+ final Class 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
+ * @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
*/
@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,65 +274,70 @@ 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 {
final CcmApplication app = Web.getWebContext().getApplication();
ContentSection section = null;
-
+
if (app == null) {
//Nothing to do
- } else if(app instanceof ContentSection) {
+ } else if (app instanceof ContentSection) {
section = (ContentSection) app;
- }
-
+ }
+
if (section != null) {
CMS.getContext().setContentSection(section);
}
-
+
final String itemId = request.getParameter("item_id");
-
+
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(
PermissionChecker.class);
- permissionChecker.checkPermission(ItemPrivileges.PREVIEW,
+ permissionChecker.checkPermission(ItemPrivileges.PREVIEW,
item);
CMS.getContext().setContentItem(item);
}
-
+
final Document document = buildDocument(request, response);
-
+
m_transformer.servePage(document, request, response);
}
/**
* 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
+ *
+ * @return
*/
@Override
protected Element generateXMLHelper(PageState ps, Document parent) {
- Element page = super.generateXMLHelper(ps,parent);
- final Optional 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 = CdiUtil.createCdiUtil()
+ .findBean(Shiro.class).getUser();
+ if (user.isPresent()) {
+ page.addAttribute("name", user.get().getName());
}
return page;
}
+
}
diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/CMSApplicationPage.java b/ccm-cms/src/main/java/com/arsdigita/cms/ui/CMSApplicationPage.java
index 2bc576f56..a39a58456 100644
--- a/ccm-cms/src/main/java/com/arsdigita/cms/ui/CMSApplicationPage.java
+++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/CMSApplicationPage.java
@@ -131,14 +131,15 @@ public class CMSApplicationPage extends Page {
getErrorDisplay().setIdAttr("page-body");
final Class 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);
}
diff --git a/ccm-cms/src/main/java/org/librecms/pages/PageRepository.java b/ccm-cms/src/main/java/org/librecms/pages/PageRepository.java
index 64f820968..53299f1fd 100644
--- a/ccm-cms/src/main/java/org/librecms/pages/PageRepository.java
+++ b/ccm-cms/src/main/java/org/librecms/pages/PageRepository.java
@@ -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{
+ 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 findPageForCategory(final Category category) {
final TypedQuery query = getEntityManager()
@@ -56,14 +60,14 @@ public class PageRepository extends AbstractEntityRepository{
}
}
- @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);
}
diff --git a/ccm-cms/src/main/java/org/librecms/pages/Pages.java b/ccm-cms/src/main/java/org/librecms/pages/Pages.java
index 374c74825..9f6f254cc 100644
--- a/ccm-cms/src/main/java/org/librecms/pages/Pages.java
+++ b/ccm-cms/src/main/java/org/librecms/pages/Pages.java
@@ -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,9 +34,9 @@ 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 Jens Pelzetter
*/
@Entity
@@ -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
- ));
- }
-
}
diff --git a/ccm-cms/src/main/java/org/librecms/pages/PagesManager.java b/ccm-cms/src/main/java/org/librecms/pages/PagesManager.java
index a35e18a15..2d36cee12 100644
--- a/ccm-cms/src/main/java/org/librecms/pages/PagesManager.java
+++ b/ccm-cms/src/main/java/org/librecms/pages/PagesManager.java
@@ -19,29 +19,45 @@
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}.
- *
+ *
* @author Jens Pelzetter
*/
@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) {
-
+ private PagesRepository pagesRepo;
+
+ @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;
}
-
+
}
diff --git a/ccm-cms/src/main/java/org/librecms/pages/PagesPrivileges.java b/ccm-cms/src/main/java/org/librecms/pages/PagesPrivileges.java
new file mode 100644
index 000000000..4d27cb7f2
--- /dev/null
+++ b/ccm-cms/src/main/java/org/librecms/pages/PagesPrivileges.java
@@ -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 Jens Pelzetter
+ */
+public final class PagesPrivileges {
+
+ public static final String ADMINISTER_PAGES = "administer_pages";
+
+ private PagesPrivileges() {
+ //Nothing
+ }
+
+}
diff --git a/ccm-cms/src/main/resources/db/migrations/org/librecms/ccm_cms/h2/V7_0_0_19__pages_site_aware.sql b/ccm-cms/src/main/resources/db/migrations/org/librecms/ccm_cms/h2/V7_0_0_19__pages_site_aware.sql
new file mode 100644
index 000000000..4eeeb7706
--- /dev/null
+++ b/ccm-cms/src/main/resources/db/migrations/org/librecms/ccm_cms/h2/V7_0_0_19__pages_site_aware.sql
@@ -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;
diff --git a/ccm-cms/src/main/resources/db/migrations/org/librecms/ccm_cms/pgsql/V7_0_0_19__pages_site_aware.sql b/ccm-cms/src/main/resources/db/migrations/org/librecms/ccm_cms/pgsql/V7_0_0_19__pages_site_aware.sql
new file mode 100644
index 000000000..4eeeb7706
--- /dev/null
+++ b/ccm-cms/src/main/resources/db/migrations/org/librecms/ccm_cms/pgsql/V7_0_0_19__pages_site_aware.sql
@@ -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;
diff --git a/ccm-core/src/main/java/org/libreccm/sites/Site.java b/ccm-core/src/main/java/org/libreccm/sites/Site.java
index 2a7dce615..56f0f4067 100644
--- a/ccm-core/src/main/java/org/libreccm/sites/Site.java
+++ b/ccm-core/src/main/java/org/libreccm/sites/Site.java
@@ -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 applications;
+
+ public Site() {
+ super();
+ applications = new ArrayList<>();
+ }
+
public String getDomainOfSite() {
return domainOfSite;
}
@@ -89,7 +101,23 @@ public class Site extends CcmObject {
public void setDefaultTheme(final String defaultTheme) {
this.defaultTheme = defaultTheme;
}
+
+ public List getApplications() {
+ return Collections.unmodifiableList(applications);
+ }
+
+ protected void setApplications(final List 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;
diff --git a/ccm-core/src/main/java/org/libreccm/sites/SiteAwareApplication.java b/ccm-core/src/main/java/org/libreccm/sites/SiteAwareApplication.java
new file mode 100644
index 000000000..1f98be983
--- /dev/null
+++ b/ccm-core/src/main/java/org/libreccm/sites/SiteAwareApplication.java
@@ -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 Jens Pelzetter
+ */
+@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));
+ }
+ }
+
+}
diff --git a/ccm-core/src/main/java/org/libreccm/sites/SiteManager.java b/ccm-core/src/main/java/org/libreccm/sites/SiteManager.java
new file mode 100644
index 000000000..fd609235e
--- /dev/null
+++ b/ccm-core/src/main/java/org/libreccm/sites/SiteManager.java
@@ -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 Jens Pelzetter
+ */
+@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);
+ }
+
+}
diff --git a/ccm-core/src/main/java/org/libreccm/sites/SiteRepository.java b/ccm-core/src/main/java/org/libreccm/sites/SiteRepository.java
index 84de9cfe0..91676f8c1 100644
--- a/ccm-core/src/main/java/org/libreccm/sites/SiteRepository.java
+++ b/ccm-core/src/main/java/org/libreccm/sites/SiteRepository.java
@@ -36,6 +36,8 @@ import javax.transaction.Transactional;
@RequestScoped
public class SiteRepository extends AbstractEntityRepository {
+ private static final long serialVersionUID = 3120528987720524155L;
+
@Transactional(Transactional.TxType.REQUIRED)
public Optional findByDomain(final String domain) {
diff --git a/ccm-core/src/main/resources/db/migrations/org/libreccm/ccm_core/h2/V7_0_0_17__site_aware_application.sql b/ccm-core/src/main/resources/db/migrations/org/libreccm/ccm_core/h2/V7_0_0_17__site_aware_application.sql
new file mode 100644
index 000000000..91defae62
--- /dev/null
+++ b/ccm-core/src/main/resources/db/migrations/org/libreccm/ccm_core/h2/V7_0_0_17__site_aware_application.sql
@@ -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;
\ No newline at end of file
diff --git a/ccm-core/src/main/resources/db/migrations/org/libreccm/ccm_core/pgsql/V7_0_0_17__site_aware_application.sql b/ccm-core/src/main/resources/db/migrations/org/libreccm/ccm_core/pgsql/V7_0_0_17__site_aware_application.sql
new file mode 100644
index 000000000..f5017b5cb
--- /dev/null
+++ b/ccm-core/src/main/resources/db/migrations/org/libreccm/ccm_core/pgsql/V7_0_0_17__site_aware_application.sql
@@ -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;
\ No newline at end of file