- Content Center Application now works again.
- JavaDoc for ContentItemRepository and ContentItemManager 
- A prototype/test for using JSF/PrimeFaces instead of Bebop for the Backend UI (will may be removed later)


git-svn-id: https://svn.libreccm.org/ccm/ccm_ng@4211 8810af33-2d31-482b-a856-94f89814c4df
pull/2/head
jensp 2016-08-04 16:45:18 +00:00
parent a704ef72a6
commit 23f682b16d
39 changed files with 2265 additions and 98 deletions

View File

@ -45,5 +45,8 @@
<Logger name="org.libreccm.security.Shiro"
level="debug">
</Logger>
<Logger name="org.librecms.contentsection.ContentSectionSetup"
level="debug">
</Logger>
</Loggers>
</Configuration>

View File

@ -0,0 +1,7 @@
<?xml version="1.0"?>
<faces-config version="2.2"
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-facesconfig_2_2.xsd">
</faces-config>

View File

@ -26,4 +26,20 @@
<listener>
<listener-class>org.apache.shiro.web.env.EnvironmentLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
<context-param>
<param-name>javax.faces.PROJECT_STAGE</param-name>
<param-value>Development</param-value>
</context-param>
</web-app>

View File

@ -0,0 +1,17 @@
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html">
<head>
<title>
JSF Test INDEX
</title>
</head>
<body>
<h:outputText value="JSF TEST INDEX"/>
</body>
</html>

View File

@ -0,0 +1,52 @@
/*
* 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 com.arsdigita.cms;
import org.libreccm.web.ApplicationCreator;
import org.libreccm.web.ApplicationRepository;
import org.libreccm.web.ApplicationType;
import org.libreccm.web.CcmApplication;
import org.librecms.CmsConstants;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
/**
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
@RequestScoped
public class ContentCenterAppCreator implements ApplicationCreator<CcmApplication> {
@Inject
private ApplicationRepository appRepository;
@Override
public CcmApplication createInstance(final String primaryUrl,
final ApplicationType type) {
if (!CmsConstants.CONTENT_CENTER_URL.equals(primaryUrl)) {
throw new IllegalArgumentException(
"ContentCenter is a singleton application which is mounted at "
+ "/content-center/");
}
return appRepository.retrieveApplicationForPath(primaryUrl);
}
}

View File

@ -48,7 +48,6 @@ import org.librecms.contentsection.ContentSectionRepository;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@ -136,7 +135,7 @@ public class ContentCenterServlet extends BaseApplicationServlet {
/* Check user and privilegies */
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final Shiro shiro = cdiUtil.findBean(Shiro.class);
if (shiro.getSubject().isAuthenticated()) {
if (!shiro.getSubject().isAuthenticated()) {
throw new LoginSignal(sreq); // send to login page
}
final PermissionChecker permissionChecker = cdiUtil.findBean(
@ -178,7 +177,7 @@ public class ContentCenterServlet extends BaseApplicationServlet {
// DispatcherHelper.sendRedirect(sresp, originalUrl + "/");
// return;
// }
final Page page = (Page) pages.get(pathInfo);
final Page page = pages.get(pathInfo);
if (page != null) {
// Check user access.
@ -274,7 +273,7 @@ public class ContentCenterServlet extends BaseApplicationServlet {
)
throws ServletException {
if (CdiUtil.createCdiUtil().findBean(Shiro.class).getSubject()
if (!CdiUtil.createCdiUtil().findBean(Shiro.class).getSubject()
.isAuthenticated()) {
throw new LoginSignal(request);
}

View File

@ -0,0 +1,48 @@
/*
* 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 com.arsdigita.cms;
import org.libreccm.modules.InstallEvent;
import org.libreccm.web.AbstractCcmApplicationSetup;
import org.libreccm.web.CcmApplication;
import org.librecms.CmsConstants;
import java.util.UUID;
/**
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
public class ContentCenterSetup extends AbstractCcmApplicationSetup {
public ContentCenterSetup(final InstallEvent event) {
super(event);
}
@Override
public void setup() {
final CcmApplication contentCenter = new CcmApplication();
contentCenter.setUuid(UUID.randomUUID().toString());
contentCenter.setApplicationType(CmsConstants.CONTENT_CENTER_APP_TYPE);
contentCenter.setPrimaryUrl(CmsConstants.CONTENT_CENTER_URL);
getEntityManager().persist(contentCenter);
}
}

View File

@ -0,0 +1,86 @@
/*
* Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
package com.arsdigita.cms.ui;
import com.arsdigita.bebop.Form;
import com.arsdigita.bebop.PageState;
import com.arsdigita.bebop.Resettable;
import com.arsdigita.bebop.SimpleContainer;
import com.arsdigita.search.QuerySpecification;
import com.arsdigita.search.ui.QueryGenerator;
/**
* A wrapper around the {@link ItemSearchSection} which embedds
* the form section in a form.
*
* @author Stanislav Freidin (sfreidin@arsdigita.com)
* @version $Id: ItemSearch.java 1940 2009-05-29 07:15:05Z terry $
*/
public class ItemSearch extends Form implements Resettable, QueryGenerator {
private static final org.apache.log4j.Logger s_log =
org.apache.log4j.Logger.getLogger(ItemSearch.class);
public static final String SINGLE_TYPE_PARAM = ItemSearchSection.SINGLE_TYPE_PARAM;
private ItemSearchSection m_section;
/**
* Construct a new <code>ItemSearch</code> component
* Default to limit the search to current content section
*
* @param context the context for the retrieved items. Should be
* {@link ContentItem#DRAFT} or {@link ContentItem#LIVE}
*/
public ItemSearch(String context) {
this(context, true);
}
/**
* Construct a new <code>ItemSearch</code> component
*
* @param context the context for the retrieved items. Should be
* {@link ContentItem#DRAFT} or {@link ContentItem#LIVE}
* @param limitToContentSection limit the search to the current content section
*/
public ItemSearch(String context, boolean limitToContentSection) {
super("itemSearch", new SimpleContainer());
//setMethod("GET");
m_section = createSearchSection(context, limitToContentSection);
add(m_section);
}
protected ItemSearchSection createSearchSection(String context, boolean limitToContentSection) {
return new ItemSearchSection(context, limitToContentSection);
}
@Override
public boolean hasQuery(PageState state) {
return m_section.hasQuery(state);
}
@Override
public QuerySpecification getQuerySpecification(PageState state) {
return m_section.getQuerySpecification(state);
}
@Override
public void reset(PageState state) {
m_section.reset(state);
}
}

View File

@ -0,0 +1,247 @@
/*
* Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
package com.arsdigita.cms.ui.authoring;
import com.arsdigita.bebop.BoxPanel;
import com.arsdigita.bebop.Form;
import com.arsdigita.bebop.Label;
import com.arsdigita.bebop.PageState;
import com.arsdigita.bebop.event.PrintEvent;
import com.arsdigita.bebop.event.PrintListener;
import com.arsdigita.bebop.form.Option;
import com.arsdigita.bebop.form.OptionGroup;
import com.arsdigita.bebop.form.SingleSelect;
import com.arsdigita.bebop.form.Submit;
import com.arsdigita.bebop.parameters.BigDecimalParameter;
import com.arsdigita.cms.ui.ItemSearch;
import com.arsdigita.globalization.GlobalizedMessage;
import com.arsdigita.ui.admin.GlobalizationUtil;
import com.arsdigita.util.UncheckedWrapperException;
import com.arsdigita.xml.Element;
import java.math.BigDecimal;
import org.apache.log4j.Logger;
import org.libreccm.security.Party;
import org.librecms.CmsConstants;
import org.librecms.contentsection.ContentSection;
import org.librecms.contentsection.ContentType;
import java.awt.image.Kernel;
import java.util.List;
/**
* A form element which displays a select box of all content types available
* under the given content section, and forwards to the item creation UI when
* the user selects a content type to instantiate.
*
* @author Stanislav Freidin (sfreidin@arsdigtia.com)
* @version $Revision: #12 $ $DateTime: 2004/08/17 23:15:09 $
* @version $Id: NewItemForm.java 2161 2011-02-02 00:16:13Z pboy $
*/
public abstract class NewItemForm extends Form {
/**
* Internal logger instance to faciliate debugging. Enable logging output by
* editing /WEB-INF/conf/log4j.properties int hte runtime environment and
* set com.arsdigita.cms.ui.authoring.NewItemForm=DEBUG by uncommenting or
* adding the line.
*/
private static final Logger s_log = Logger.getLogger(NewItemForm.class);
private final SingleSelect m_typeWidget;
private final Submit m_submit;
private final Label m_emptyLabel;
private final Label m_createLabel;
public static final String TYPE_ID = "tid";
public NewItemForm(String name) {
this(name, BoxPanel.HORIZONTAL);
}
/**
* Construct a new NewItemForm. It sets a vertical BoxPanel as the component
* container.
*
* @param name the name attribute of the form.
*/
public NewItemForm(String name, int orientation) {
super(name, new BoxPanel(BoxPanel.VERTICAL));
setIdAttr("new_item_form");
//BoxPanel panel = new BoxPanel(BoxPanel.HORIZONTAL);
BoxPanel panel = new BoxPanel(orientation);
panel.setWidth("2%");
panel.setBorder(0);
// create and add an "empty" component
m_emptyLabel = new Label(new GlobalizedMessage(
"cms.ui.authoring.no_types_registered", CmsConstants.CMS_BUNDLE),
false);
m_emptyLabel.setIdAttr("empty_label");
panel.add(m_emptyLabel);
m_createLabel = new Label(new GlobalizedMessage(
"cms.ui.authoring.create_new", CmsConstants.CMS_BUNDLE),
false);
m_createLabel.setIdAttr("create_label");
panel.add(m_createLabel);
m_typeWidget = new SingleSelect(new BigDecimalParameter(TYPE_ID),
OptionGroup.SortMode.ALPHABETICAL_ASCENDING);
try {
m_typeWidget.addPrintListener(new PrintListener() {
// Read the content section's content types and add them as options
@Override
public void prepare(PrintEvent e) {
OptionGroup o = (OptionGroup) e.getTarget();
o.clearOptions();
PageState state = e.getPageState();
// gather the content types of this section into a list
ContentSection section = getContentSection(state);
ContentType parentType = null;
List<ContentType> typesCollection = null;
BigDecimal singleTypeID = (BigDecimal) state.getValue(
new BigDecimalParameter(
ItemSearch.SINGLE_TYPE_PARAM));
if (singleTypeID != null) {
try {
parentType = new ContentType(singleTypeID);
} catch (DataObjectNotFoundException ex) {
parentType = null;
}
}
if (parentType == null) {
typesCollection = section.getCreatableContentTypes();
} else {
typesCollection = section.getDescendantsOfContentType(
parentType);
}
typesCollection.addOrder(ContentType.LABEL);
if (!typesCollection.isEmpty()) {
// Add content types
while (typesCollection.next()) {
boolean list = true;
ContentType type = typesCollection.getContentType();
if (PermissionService
.getDirectGrantedPermissions(type.getOID())
.size() > 0) {
// chris gilbert - allow restriction of some types
// to certain users/groups. No interface to do
// this, but group could be created and permission
// granted in a content type loader
//
// can't permission filter the collection because
// most types will have no permissions granted.
// This approach involves a small overhead getting
// the count of granted permissions for each type
// (mitigated by only checking DIRECT permissions)
Party party = Kernel.getContext().getParty();
if (party == null) {
party = Kernel.getPublicUser();
}
PermissionDescriptor create
= new PermissionDescriptor(
PrivilegeDescriptor
.get(SecurityManager.CMS_NEW_ITEM),
type,
party);
list = PermissionService.checkPermission(create);
}
if (list) {
// o.addOption(new Option(type.getID().toString(), type.getName()));
o.addOption(new Option(type.getID().toString(),
new Label(type.getLabel())));
}
}
typesCollection.reset();
}
}
});
} catch (java.util.TooManyListenersException e) {
throw new UncheckedWrapperException("Too many listeners: " + e
.getMessage(), e);
}
panel.add(m_typeWidget);
m_submit = new Submit("new", GlobalizationUtil.globalize(
"cms.ui.authoring.go"));
panel.add(m_submit);
add(panel);
}
public abstract ContentSection getContentSection(PageState state);
/**
*
* @param state
*
* @return
*/
public BigDecimal getTypeID(PageState state) {
return (BigDecimal) m_typeWidget.getValue(state);
}
/**
*
* @return
*/
public final SingleSelect getTypeSelect() {
return m_typeWidget;
}
/**
* Generate XML - show/hide labels/widgets
*
* @param state
* @param parent
*/
@Override
public void generateXML(PageState state, Element parent) {
if (isVisible(state)) {
ContentSection section = getContentSection(state);
ContentTypeCollection c = section.getCreatableContentTypes();
boolean isEmpty = c.isEmpty();
c.close();
m_createLabel.setVisible(state, !isEmpty);
m_typeWidget.setVisible(state, !isEmpty);
m_submit.setVisible(state, !isEmpty);
m_emptyLabel.setVisible(state, isEmpty);
super.generateXML(state, parent);
}
}
}

View File

@ -0,0 +1,649 @@
/*
* Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
package com.arsdigita.cms.ui.contentcenter;
import com.arsdigita.bebop.BoxPanel;
import java.math.BigDecimal;
import com.arsdigita.bebop.Component;
import com.arsdigita.bebop.Embedded;
import com.arsdigita.bebop.FormProcessException;
import com.arsdigita.bebop.Label;
import com.arsdigita.bebop.Link;
import com.arsdigita.bebop.Page;
import com.arsdigita.bebop.PageState;
import com.arsdigita.bebop.SingleSelectionModel;
import com.arsdigita.bebop.Table;
import com.arsdigita.bebop.event.FormProcessListener;
import com.arsdigita.bebop.event.FormSectionEvent;
import com.arsdigita.bebop.event.FormSubmissionListener;
import com.arsdigita.bebop.form.Hidden;
import com.arsdigita.bebop.parameters.BigDecimalParameter;
import com.arsdigita.bebop.table.TableCellRenderer;
import com.arsdigita.bebop.table.TableColumn;
import com.arsdigita.bebop.table.TableColumnModel;
import com.arsdigita.bebop.table.TableModel;
import com.arsdigita.bebop.table.TableModelBuilder;
import com.arsdigita.cms.ui.CMSContainer;
import com.arsdigita.ui.admin.GlobalizationUtil;
import com.arsdigita.util.Assert;
import com.arsdigita.util.LockableImpl;
import com.arsdigita.web.Web;
import org.libreccm.categorization.Category;
import org.libreccm.cdi.utils.CdiUtil;
import org.libreccm.security.PermissionChecker;
import org.libreccm.security.User;
import org.librecms.CmsConstants;
import org.librecms.contentsection.ContentSection;
import org.librecms.contentsection.ContentSectionConfig;
import org.librecms.contentsection.ContentSectionRepository;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;
import javax.mail.Folder;
/**
* Displays all the content sections in table, with links to the admin (and in
* legacy mode to legacy public pages as well). Also displays a form for each
* content section to create an object of a given type (configurable). The list
* of available types retrieved for each content section.
*
* <p>
* This class is a container for two other components: a form and a table. The
* form represents the drop down list of the content types available in a
* particular content section. It is an extension of the
* {@link com.arsdigita.cms.ui.authoring.NewItemForm}. The table displays each
* content section in one row, along with the specified form. The same form is
* reused in every row of the table.
*
* @author <a href="mailto:mbryzek@arsdigita.com">Michael Bryzek</a>
* @version $Id: ContentSectionContainer.java 287 2005-02-22 00:29:02Z sskracic$
*/
public class ContentSectionContainer extends CMSContainer {
private static final String CONTENT_SECTION_CLASS = "contentSections";
private final ContentSectionTable m_table;
private final FormContainer m_formContainer;
private final SingleSelectionModel m_typeSel;
private final SingleSelectionModel m_sectionSel;
/**
* Constructs a new ContentSectionContainer which containts:
*
* <ul>
* <li> SimpleContainer (to contain the form)
* <ul>
* <li> Form (for creating a new content item in each section)
* </ul>
* <li> Table (Displays all content sections)
* </ul>
*
* @param typeSel passthrough to {@link NewItemForm}
* @param sectionSel passthrough to {@link NewItemForm}
*/
public ContentSectionContainer(SingleSelectionModel typeSel,
SingleSelectionModel sectionSel) {
super();
setClassAttr(CONTENT_SECTION_CLASS);
m_typeSel = typeSel;
m_sectionSel = sectionSel;
m_formContainer = new FormContainer();
add(m_formContainer);
m_table = new ContentSectionTable();
add(m_table);
}
/**
*
* @param p
*/
@Override
public void register(Page p) {
super.register(p);
p.setVisibleDefault(m_formContainer, false);
}
/**
*
*/
private class FormContainer extends CMSContainer {
// private final StaticNewItemForm m_form;
private final BigDecimalParameter m_sectionIdParam;
/**
* Constructor
*/
private FormContainer() {
super();
m_sectionIdParam = new BigDecimalParameter("sectionId");
// m_form = new StaticNewItemForm(m_sectionIdParam);
// m_form.addSubmissionListener(new FormSubmissionListener() {
//
// /**
// * Cancels the form if the user lacks the "create new items"
// * privilege.
// */
// @Override
// public void submitted(FormSectionEvent event)
// throws FormProcessException {
// PageState state = event.getPageState();
// StaticNewItemForm form = (StaticNewItemForm) event
// .getSource();
//
// ContentSection section = form.getContentSection(state);
// final PermissionChecker permissionChecker = CdiUtil
// .createCdiUtil().findBean(PermissionChecker.class);
// Category folder = null;
// //ToDo
//// User user = Web.getWebContext().getUser();
//// if (user != null) {
//// folder = Folder.getUserHomeFolder(user, section);
//// }
//// if (folder == null) {
//// folder = section.getRootFolder();
//// }
////ToDo End
// folder = section.getRootDocumentsFolder();
//
// if (!permissionChecker.isPermitted(
// CmsConstants.PRIVILEGE_ITEMS_CREATE_NEW, folder)) {
// throw new FormProcessException(
// (GlobalizationUtil.globalize(
// "cms.ui.insufficient_privileges")));
// }
// }
//
// });
//
// m_form.addProcessListener(new FormProcessListener() {
//
// /**
// * Process listener: redirects to the authoring kit to create a
// * new item.
// */
// @Override
// public void process(FormSectionEvent e) throws
// FormProcessException {
// StaticNewItemForm form = (StaticNewItemForm) e.getSource();
// PageState state = e.getPageState();
//
// BigDecimal typeId = form.getTypeID(state);
// if (typeId != null) {
// Long sectionId = form.getContentSectionID(state);
// m_sectionSel.setSelectedKey(state, sectionId);
// m_typeSel.setSelectedKey(state, typeId);
// }
// }
//
// });
//
// add(m_form);
}
@Override
public void register(Page p) {
super.register(p);
p.addComponentStateParam(this, m_sectionIdParam);
}
// public StaticNewItemForm getNewItemForm() {
//// return m_form;
// }
}
// private static class StaticNewItemForm extends NewItemForm {
//
// private final Hidden m_sectionIDParamWidget;
//
// public StaticNewItemForm(BigDecimalParameter sectionParam) {
// super("StaticNewItemForm", BoxPanel.VERTICAL);
// setClassAttr("static-new-item-form");
// m_sectionIDParamWidget = new Hidden(sectionParam);
// add(m_sectionIDParamWidget);
// setProcessInvisible(true);
// }
//
// /**
// * Sets the id of the content section in this form. This ID is used to
// * generate a list of available content types in the section.
// *
// * @param state The current page state.
// * @param id The id of the ContentSection for which this form should
// * display a list of content types
// *
// * @pre ( state != null && id != null )
// */
// public void setSectionId(PageState state, BigDecimal id) {
// Assert.exists(id);
// m_sectionIDParamWidget.setValue(state, id);
// }
//
// /**
// * Retrieves the content section for this form given the specified page
// * state. This method will return null if there is no content section.
// *
// * @param state The current page state.
// *
// * @return The current content section or null if the section does not
// * exist
// *
// * @pre ( state != null )
// */
// @Override
// public ContentSection getContentSection(PageState state) {
// Long id = getContentSectionID(state);
// Assert.exists(id);
// ContentSection section;
// section = CdiUtil.createCdiUtil().findBean(
// ContentSectionRepository.class).findById(id);
// return section;
// }
//
// /**
// * Retrieves the ID of the content section for this form given the
// * specified page state. This method will return null if no content
// * section id has been set.
// *
// * @param state The current page state.
// *
// * @return The id of the content section or null if it has not been set.
// *
// * @pre ( state != null )
// */
// private Long getContentSectionID(PageState state) {
// return (Long) Long.parseLong((String) m_sectionIDParamWidget
// .getValue(state));
// }
//
// }
/**
* A table that displays all content sections, with links to their locations
* and admin pages and a {@link NewItemForm} next to each section.
*
* @author <a href="mailto:mbryzek@arsdigita.com">Michael Bryzek</a>
* @version $Revision$ $DateTime: 2004/08/17 23:15:09 $
*
*/
private class ContentSectionTable extends Table {
// We will use a (symboloc) headerKey to match columns. Because the
// number of columns depends on configuration for the llocation column,
// the index varies and con not be used.
private static final String COLUMN_SECTION = "Section";
private static final String COLUMN_LOCATION = "Public Site";
private static final String COLUMN_ACTION = "Action";
/**
* Constructs a new ContentSectionTable, using a default table model
* builder.
*/
private ContentSectionTable() {
super();
// we must use symbolic keys (instead of symbolic column index as
// usual) to identify a column because their number is dynamic
// depending on configuration of the location column!
Integer colNo = 0;
Label emptyView = new Label(GlobalizationUtil
.globalize("cms.ui.contentcenter.section"));
emptyView.setFontWeight(Label.ITALIC);
setEmptyView(emptyView);
setClassAttr("dataTable");
// add columns to the table
TableColumnModel columnModel = getColumnModel();
// prepare column headers
Label sectionHead = new Label(GlobalizationUtil
.globalize("cms.ui.contentcenter.section"));
sectionHead.setHint(GlobalizationUtil
.globalize("cms.ui.contentcenter.section_hint"));
Label locationHead = new Label(GlobalizationUtil
.globalize("cms.ui.contentcenter.location"));
locationHead.setHint(GlobalizationUtil
.globalize("cms.ui.contentcenter.location_hint"));
Label actionHead = new Label(GlobalizationUtil
.globalize("cms.ui.contentcenter.action"));
actionHead.setHint(GlobalizationUtil
.globalize("cms.ui.contentcenter.action_hint"));
//TableColumn contentSectionColumn = new TableColumn(colNo, COLUMN_SECTION);
TableColumn contentSectionColumn = new TableColumn(
colNo,
sectionHead,
COLUMN_SECTION);
contentSectionColumn
.setCellRenderer(new AdminURLTableCellRenderer());
columnModel.add(contentSectionColumn);
TableColumn actionColumn = new TableColumn(
colNo++,
actionHead,
COLUMN_ACTION);
actionColumn.setCellRenderer(new ActionTableCellRenderer());
columnModel.add(actionColumn);
setModelBuilder(new ContentSectionTableModelBuilder());
}
/**
* An ContentSections table model builder
*
* @author <a href="mailto:mbryzek@arsdigita.com">Michael Bryzek</a>
*
*/
private class ContentSectionTableModelBuilder extends LockableImpl
implements TableModelBuilder {
@Override
public TableModel makeModel(Table table, PageState state) {
table.getRowSelectionModel().clearSelection(state);
return new ContentSectionTableModel((ContentSectionTable) table,
state);
}
}
/**
* An ContentSections table model
*
* @author <a href="mailto:mbryzek@arsdigita.com">Michael Bryzek</a>
*
*/
private class ContentSectionTableModel implements TableModel {
private final ContentSectionTable m_table;
private final TableColumnModel m_columnModel;
private final PageState m_state;
private final List<ContentSection> m_contentSections;
private ContentSection m_section;
private int index = -1;
private ContentSectionTableModel(ContentSectionTable table,
PageState state) {
m_table = table;
m_columnModel = table.getColumnModel();
m_state = state;
// retrieve all Content Sections
m_contentSections = getContentSectionCollection();
}
/**
* Returns a collection of ContentSections to display in this table.
* This implementation orders the content sections by
* <code>lower(label)</code>. They are also already filtered for the
* sections to which the current user has no access.
*
*/
private List<ContentSection> getContentSectionCollection() {
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final PermissionChecker permissionChecker = cdiUtil.findBean(
PermissionChecker.class);
final List<ContentSection> allSections = cdiUtil.findBean(
ContentSectionRepository.class).findAll();
return allSections
.stream()
.filter(section -> permissionChecker
.isPermitted(CmsConstants.PRIVILEGE_ITEMS_VIEW_PUBLISHED,
section))
.collect(Collectors.toList());
}
@Override
public int getColumnCount() {
return m_columnModel.size();
}
@Override
public boolean nextRow() {
index++;
if (index < m_contentSections.size()) {
m_section = m_contentSections.get(index);
return true;
} else {
return false;
}
}
/**
* By default, we return null. For the section, location, and action
* columns, we return the current Content Section if there is one.
*
* @param columnIndex The index of the current column
*/
@Override
public Object getElementAt(int columnIndex) {
if (m_columnModel == null || m_section == null) {
return null;
}
TableColumn tc = m_columnModel.get(columnIndex);
String columnKey = (String) tc.getHeaderKey();
Object result = m_section;
if (columnKey.equals(COLUMN_SECTION)
|| columnKey.equals(COLUMN_LOCATION)
|| columnKey.equals(
COLUMN_ACTION)) {
result = m_section;
}
return result;
}
@Override
public Object getKeyAt(int columnIndex) {
return m_section.getObjectId();
}
/**
* Returns the table associated with this table model.
*
*/
protected Table getTable() {
return m_table;
}
/**
* Returns the current page state
*
*/
protected PageState getPageState() {
return m_state;
}
}
/**
* Sets the hidden parameter in the form containers form to the id of
* the current section. Then returns the form for display, but only if
* the user has permission to create new items in the current section.
*
* @author <a href="mailto:mbryzek@arsdigita.com">Michael Bryzek</a>
*
*/
private class ActionTableCellRenderer implements TableCellRenderer {
@Override
public Component getComponent(Table table, PageState state,
Object value,
boolean isSelected, Object key,
int row, int column) {
ContentSection section = (ContentSection) value;
Category folder = null;
//ToDo
// User user = Web.getWebContext().getUser();
// if (user != null) {
// folder = Folder.getUserHomeFolder(user, section);
// }
// if (folder == null) {
// folder = section.getRootFolder();
// }
folder = section.getRootDocumentsFolder();
// If the user has no access, return an empty Label
//
// SecurityManager sm = new SecurityManager(section);
//
// if (!sm.canAccess(state.getRequest(), SecurityManager.NEW_ITEM,
// folder)
// || !ContentSection.getConfig()
// .getAllowContentCreateInSectionListing()) {
// // return null; // produces NPE here but works somewhere else.
// // It's a kind of a hack. Label is supposed not to accept
// // not-gloabalized data. Usually aou will return null here
// // and xmlgenerator takes care of it. Doesn't work here.
// return new Embedded(
// "&nbsp;&nbsp;&nbsp;-&nbsp;-&nbsp;&nbsp;&nbsp;");
// } else {
// // set the value of the sectionIdParameter in the form
// // to this section
// m_formContainer.getNewItemForm().setSectionId(state, section
// .getID());
// return m_formContainer.getNewItemForm();
// }
//ToDo End
return new Embedded(
"&nbsp;&nbsp;&nbsp;-&nbsp;-&nbsp;&nbsp;&nbsp;");
}
}
}
/**
* Generates the correct URL to the public pages for a content section.
*
* @author <a href="mailto:mbryzek@arsdigita.com">Michael Bryzek</a>
*
*/
public static class URLTableCellRenderer implements TableCellRenderer {
/**
* The object passed in is the current content section. This returns a
* Link whose name and target are the url to the public pages.
*
* @return Link whose name and target are the url to the public pages of
* the current (passed in) content section or a Label if current
* use does not habe acces priviledge for the content section
*/
@Override
public Component getComponent(Table table,
PageState state,
Object value,
boolean isSelected,
Object key,
int row,
int column) {
/* cast to ContentSection for further processing */
ContentSection section = (ContentSection) value;
String name = section.getLabel();
String path = section.getPrimaryUrl(); // from Application
// If the user has no access, return a Label instead of a Link
// Kind of a hack because Label is supposed not to accept
// "un-globalized" display data. Label had been abused here to
// to display a DataValue
return new Embedded("/" + name + "/", false);
// return null; // produces NPE here
}
}
/**
* Generates the correct URL to the admin pages for a content section.
*
* @author <a href="mailto:mbryzek@arsdigita.com">Michael Bryzek</a>
*
*/
public static class AdminURLTableCellRenderer extends URLTableCellRenderer {
/**
* The object passed in is the current content section
*
* @param table
* @param state
* @param row
* @param value
* @param column
* @param isSelected
* @param key
*
* @return
*
*/
@Override
public Component getComponent(Table table, PageState state, Object value,
boolean isSelected, Object key,
int row, int column) {
ContentSection section = (ContentSection) value;
final PermissionChecker permissionChecker = CdiUtil.createCdiUtil()
.findBean(PermissionChecker.class);
// If the user has no access, return a Label instead of a Link
if (permissionChecker.isPermitted(
CmsConstants.PRIVILEGE_ITEMS_EDIT,
section.getRootDocumentsFolder())) {
return new Link(section.getLabel(),
generateURL(section.getPrimaryUrl() + "/"));
} else {
//return new Label(section.getName(), false);
// return null; // Produces a NPE although it shouldn't and
// indeed doesn't elsewhere
// Kind of a hack because Label is supposed not to accept
// "un-globalized" display data. Label had been abused here to
// to display a DataValue
return new Embedded(section.getLabel(), false);
}
}
/**
* Generates the admin url for the specified prefix. Always returns
* something that does not start with a forward slash.
*
* @param prefix The prefix of the URL
*
* @return
*/
protected String generateURL(String prefix) {
return prefix;// + PageLocations.SECTION_PAGE;
}
}
}

View File

@ -75,8 +75,12 @@ public class TasksPanel extends CMSContainer {
// private ActionLink m_viewAllLink;
// private ActionLink m_viewShortLink;
private Paginator m_paginator;
private ActionLink m_viewLockLink, m_viewUnlockLink, m_viewAllLockLink;
private Label m_viewLockLabel, m_viewUnlockLabel, m_viewAllLockLabel;
private ActionLink m_viewLockLink;
private ActionLink m_viewUnlockLink;
private ActionLink m_viewAllLockLink;
private Label m_viewLockLabel;
private Label m_viewUnlockLabel;
private Label m_viewAllLockLabel;
private StringParameter m_sortDirectionParam;
private StringParameter m_sortTypeParam;
private StringParameter m_lockFilterParam;
@ -103,7 +107,7 @@ public class TasksPanel extends CMSContainer {
private Label m_selectorLabel;
//ToDo
// private CreationSelector m_selector;
// private ContentSectionContainer m_sections;
private ContentSectionContainer m_sections;
// ToDo End
private CcmObjectSelectionModel m_sectionSel;
private CcmObjectSelectionModel m_typeSel;
@ -134,7 +138,8 @@ public class TasksPanel extends CMSContainer {
* @pre maxRows != null
*
*/
public TasksPanel(int maxRows, CcmObjectSelectionModel typeModel,
public TasksPanel(int maxRows,
CcmObjectSelectionModel typeModel,
CcmObjectSelectionModel sectionModel) {
super();
@ -192,14 +197,13 @@ public class TasksPanel extends CMSContainer {
// m_selector = new CreationSelector(m_typeSel, m_folderSel);
// m_creationPane.add(m_selector);
//ToDo End
m_creationPane.setClassAttr("itemCreationPane");
add(m_creationPane);
// The section list UIx
//ToDo
// m_sections = new ContentSectionContainer(m_typeSel, m_sectionSel);
// add(m_sections);
m_sections = new ContentSectionContainer(m_typeSel, m_sectionSel);
add(m_sections);
//ToDo End
// When a new type is selected, show the creation UI.
// When the selection is cleared, return to section list
@ -444,8 +448,6 @@ public class TasksPanel extends CMSContainer {
// query.addEqualsFilter("isLocked", "f");
// } // else show all
// }
// private static class RootFolderSelectionModel
// extends FolderSelectionModel {
//
@ -474,7 +476,6 @@ public class TasksPanel extends CMSContainer {
//
// }
//ToDo End
/**
*
*/
@ -512,9 +513,8 @@ public class TasksPanel extends CMSContainer {
//
// return query;
// }
public int size(PageState ps) {
return ((Long) m_taskCount.get(ps)).intValue();
return ((Integer)m_taskCount.get(ps)).intValue();
}
private RequestLocal m_taskCount = new RequestLocal() {
@ -523,7 +523,7 @@ public class TasksPanel extends CMSContainer {
public Object initialValue(PageState state) {
// DataQuery query = makeQuery(state);
// return new Long(query.size());
return null;
return 0;
}
};
@ -536,7 +536,6 @@ return null;
exportAttributes(content);
// DataQuery query = makeQuery(state);
String lockFilterType = getLockFilterType(state);
content.addAttribute("lockFilterType", lockFilterType);
@ -705,6 +704,7 @@ return null;
// link.generateXML(state, content);
// state.clearControlEvent();
// }
}
@Override
@ -776,5 +776,4 @@ return null;
// return PermissionService.getFilterQuery(factory, "itemID", privilege,
// partyOID);
// }
}

View File

@ -3,6 +3,10 @@
*/
package org.librecms;
import com.arsdigita.cms.ContentCenterAppCreator;
import com.arsdigita.cms.ContentCenterServlet;
import com.arsdigita.cms.ContentCenterSetup;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.libreccm.core.CoreConstants;
@ -14,6 +18,7 @@ import org.libreccm.modules.RequiredModule;
import org.libreccm.modules.ShutdownEvent;
import org.libreccm.modules.UnInstallEvent;
import org.libreccm.web.ApplicationType;
import org.libreccm.web.CcmApplication;
import org.librecms.contentsection.ContentSection;
import org.librecms.contentsection.ContentSectionCreator;
import org.librecms.contentsection.ContentSectionSetup;
@ -29,6 +34,13 @@ import java.util.Properties;
@RequiredModule(module = org.libreccm.core.CcmCore.class)
},
applicationTypes = {
@ApplicationType(
name = CmsConstants.CONTENT_CENTER_APP_TYPE,
applicationClass = CcmApplication.class,
descBundle = CmsConstants.CONTENT_CENTER_DESC_BUNDLE,
creator = ContentCenterAppCreator.class,
servlet = ContentCenterServlet.class
),
@ApplicationType(
name = CmsConstants.CONTENT_SECTION_APP_TYPE,
applicationClass = ContentSection.class,
@ -66,6 +78,12 @@ public class Cms implements CcmModule {
ex);
}
LOGGER.info("Setting content center...");
final ContentCenterSetup contentCenterSetup = new ContentCenterSetup(
event);
contentCenterSetup.setup();
LOGGER.info("Setting up content sections...");
final ContentSectionSetup contentSectionSetup = new ContentSectionSetup(
event);
contentSectionSetup.setup();

View File

@ -32,6 +32,7 @@ public class CmsConstants {
public static final String CONTENT_CENTER_APP_TYPE = "com.arsdigita.cms.ContentCenter";
public static final String CONTENT_CENTER_URL = "/content-center/";
public static final String CONTENT_CENTER_DESC_BUNDLE = "org.librecms.contentcenter.ContentCenterResources";
public static final String CONTENT_SECTION_APP_TYPE
= "org.librecms.contentsection.ContentSection";

View File

@ -19,11 +19,14 @@
package org.librecms.contentsection;
import org.libreccm.categorization.Category;
import org.libreccm.workflow.WorkflowTemplate;
import org.librecms.lifecycle.LifecycleDefinition;
import java.util.List;
import java.util.Optional;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
/**
*
@ -32,10 +35,88 @@ import javax.enterprise.context.RequestScoped;
@RequestScoped
public class ContentItemManager {
@Inject
private ContentItemRepository contentItemRepo;
/**
* Creates a new content item in the provided content section and folder
* with the default lifecycle and workflow.
*
* The folder must be a subfolder of the
* {@link ContentSection#rootDocumentsFolder} of the provided content
* section. Otherwise an {@link IllegalArgumentException} is thrown.
*
* @param <T> The type of the content item.
* @param name The name (URL stub) of the new content item.
* @param section The content section in which the item is generated.
* @param folder The folder in which in the item is stored.
* @param type The type of the new content item.
*
* @return The new content item.
*/
public <T extends ContentItem> T createContentItem(
final String name,
final ContentSection section,
final Category folder,
final Class<T> type) {
throw new UnsupportedOperationException();
}
/**
* Creates a new content item in the provided content section and folder
* with the provided lifecycle and workflow.
*
* The folder must be a subfolder of the
* {@link ContentSection#rootDocumentsFolder} of the provided content
* section. Otherwise an {@link IllegalArgumentException} is thrown.
*
* Likewise the provided {@link LifecycleDefinition} and
* {@link WorkflowTemplate} must be defined in the provided content section.
* Otherwise an {@link IllegalArgumentException} is thrown.
*
* @param <T> The type of the content item.
* @param name The name (URL stub) of the new content item.
* @param section The content section in which the item is
* generated.
* @param folder The folder in which in the item is stored.
* @param workflowTemplate
* @param lifecycleDefinition
* @param type The type of the new content item.
*
* @return The new content item.
*/
public <T extends ContentItem> T createContentItem(
final String name,
final ContentSection section,
final Category folder,
final WorkflowTemplate workflowTemplate,
final LifecycleDefinition lifecycleDefinition,
final Class<T> type) {
throw new UnsupportedOperationException();
}
/**
* Moves a content item to another folder in the same content section. This
* only moves the draft version of the item. The live version is moved after
* a the item is republished.
*
* @param item The item to move.
* @param targetFolder The folder to which the item is moved.
*/
public void move(final ContentItem item, final Category targetFolder) {
throw new UnsupportedOperationException();
}
/**
* Creates an copy of the draft version of the item in the provided
* {@code targetFolder}.
*
* @param item The item to copy.
* @param targetFolder The folder in which the copy is created. If the
* target folder is the same folder as the folder of the
* original item an index is appended to the name of the
* item.
*/
public void copy(final ContentItem item, final Category targetFolder) {
throw new UnsupportedOperationException();
}
@ -65,6 +146,7 @@ public class ContentItemManager {
* Determines if a content item has a live version.
*
* @param item The item
*
* @return {@code true} if the content item has a live version,
* {@code false} if not.
*/
@ -75,10 +157,14 @@ public class ContentItemManager {
/**
* Retrieves the live version of the provided content item if any.
*
* @param <T>
* @param item
* @param type
* @return
* @param <T> Type of the content item.
* @param item The item of which the live version should be retrieved.
* @param type Type of the content item.
*
* @return The live version of an item. If the item provided is already the
* live version the provided item is returned, otherwise the live
* version is returned. If there is no live version an empty
* {@link Optional} is returned.
*/
public <T extends ContentItem> Optional<T> getLiveVersion(
final ContentItem item,
@ -86,11 +172,37 @@ public class ContentItemManager {
throw new UnsupportedOperationException();
}
public <T extends ContentItem> List<T> getPendingVersions() {
/**
* Retrieves the pending versions of an item if there are any.
*
* @param <T> Type of the content item to retrieve.
* @param item The item of which the pending versions are retrieved.
* @param type Type of the content item to retrieve.
*
* @return A list of the pending versions of the item.
*/
public <T extends ContentItem> List<T> getPendingVersions(
final ContentItem item,
final Class<T> type) {
throw new UnsupportedOperationException();
}
public <T extends ContentItem> T getDraftVersion(final ContentItem item) {
/**
* Retrieves the draft version
*
* @param <T> Type of the item.
* @param item The item of which the draft version is retrieved.
* @param type Type of the item.
*
* @return The draft version of the provided content item. If the provided
* item is the draft version the provided item is simply returned.
* Otherwise the draft version is retrieved from the database and is
* returned. Each content item has a draft version (otherwise
* something is seriously wrong with the database) this method will
* <b>never</b> return {@code null}.
*/
public <T extends ContentItem> T getDraftVersion(final ContentItem item,
final Class<T> type) {
throw new UnsupportedOperationException();
}

View File

@ -24,17 +24,19 @@ import org.libreccm.core.CcmObject;
import org.libreccm.core.CcmObjectRepository;
import java.util.List;
import java.util.Optional;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
/**
* Repository for content items.
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
@RequestScoped
public class ContentItemRepository
extends AbstractAuditedEntityRepository<Long, ContentItem>{
extends AbstractAuditedEntityRepository<Long, ContentItem> {
@Inject
private CcmObjectRepository ccmObjectRepo;
@ -54,20 +56,47 @@ public class ContentItemRepository
return ccmObjectRepo.isNew(item);
}
public ContentItem findById(final long itemId) {
/**
* Finds a content item by is id.
*
* @param itemId The id of item to retrieve.
*
* @return The content item identified by the provided {@code itemId} or
* nothing if there is such content item.
*/
public Optional<ContentItem> findById(final long itemId) {
final CcmObject result = ccmObjectRepo.findObjectById(itemId);
if (result instanceof ContentItem) {
return (ContentItem) result;
return Optional.of((ContentItem) result);
} else {
return null;
return Optional.empty();
}
}
public <T extends ContentItem> T findById(final long itemId,
/**
* Finds a content item by its ID and ensures that is a the requested type.
*
* @param <T> The type of the content item.
* @param itemId The id of item to retrieve.
* @param type The type of the content item.
*
* @return The content item identified by the provided id or an empty
* {@link Optional} if there is no such item or if it is not of the
* requested type.
*/
public <T extends ContentItem> Optional<T> findById(final long itemId,
final Class<T> type) {
throw new UnsupportedOperationException();
}
/**
* Finds a content item by is UUID.
*
* @param uuid The id of item to retrieve.
*
* @return The content item identified by the provided {@code uuid} or
* nothing if there is such content item.
*/
public ContentItem findByUuid(final String uuid) {
final CcmObject result = ccmObjectRepo.findObjectByUuid(uuid);
if (result instanceof ContentItem) {
@ -77,15 +106,39 @@ public class ContentItemRepository
}
}
/**
* Finds a content item by its UUID and ensures that is a the requested type.
*
* @param <T> The type of the content item.
* @param uuid The UUID of item to retrieve.
* @param type The type of the content item.
*
* @return The content item identified by the provided UUID or an empty
* {@link Optional} if there is no such item or if it is not of the
* requested type.
*/
public <T extends ContentItem> T findByUuid(final String uuid,
final Class<T> type) {
throw new UnsupportedOperationException();
}
/**
* Finds all content items of a specific type.
*
* @param <T> The type of the items.
* @param type The type of the items.
* @return A list of all content items of the requested type.
*/
public <T extends ContentItem> List<T> findByType(final Class<T> type) {
throw new UnsupportedOperationException();
}
/**
* Retrieves all content items in the provided folder.
*
* @param folder The folder.
* @return A list of all items in the provided folder.
*/
public List<ContentItem> findByFolder(final Category folder) {
throw new UnsupportedOperationException();
}

View File

@ -26,7 +26,6 @@ import org.libreccm.security.Role;
import org.libreccm.web.AbstractCcmApplicationSetup;
import org.librecms.CmsConstants;
import java.util.Locale;
import java.util.UUID;
import static org.librecms.CmsConstants.*;
@ -54,8 +53,13 @@ public class ContentSectionSetup extends AbstractCcmApplicationSetup {
if (getIntegrationProps().containsKey(INITIAL_CONTENT_SECTIONS)) {
sectionNames = getIntegrationProps().getProperty(
INITIAL_CONTENT_SECTIONS);
LOGGER.info(
"Found names for initial content sections in integration "
+ "properties: {}", sectionNames);
} else {
sectionNames = "info";
LOGGER.info("No initial content sections definied integration "
+ "properties, using default: {}", sectionNames);
}
for (final String contentSectionName : sectionNames.split(",")) {
@ -64,13 +68,27 @@ public class ContentSectionSetup extends AbstractCcmApplicationSetup {
}
private void createContentSection(final String sectionName) {
LOGGER.debug("Creating content section with section name \"{}\"...",
sectionName);
final ContentSection section = new ContentSection();
section.setUuid(UUID.randomUUID().toString());
section.setApplicationType(CmsConstants.CONTENT_SECTION_APP_TYPE);
section.setPrimaryUrl(sectionName);
section.setPrimaryUrl(String.format("/%s/", sectionName));
section.setDisplayName(sectionName);
section.setLabel(sectionName);
LOGGER.debug("New content section properties: "
+ "uuid = {}; "
+ "applicationType = \"{}\"; "
+ "primaryUrl = \"{}\"; "
+ "displayName = \"{}\"; "
+ "label = \"{}\"",
section.getUuid(),
section.getApplicationType(),
section.getPrimaryUrl(),
section.getDisplayName(),
section.getLabel());
final Category rootFolder = new Category();
rootFolder.setUuid(UUID.randomUUID().toString());
rootFolder.setUniqueId(rootFolder.getUuid());

View File

@ -25,8 +25,8 @@ import static org.librecms.CmsConstants.*;
import org.libreccm.core.CcmObject;
import org.libreccm.l10n.LocalizedString;
import org.libreccm.workflow.Workflow;
import org.librecms.lifecycle.Lifecycle;
import org.libreccm.workflow.WorkflowTemplate;
import org.librecms.lifecycle.LifecycleDefinition;
import java.io.Serializable;
import java.util.Objects;
@ -98,11 +98,11 @@ public class ContentType extends CcmObject implements Serializable {
@ManyToOne
@JoinColumn(name = "DEFAULT_LIFECYCLE_ID")
private Lifecycle defaultLifecycle;
private LifecycleDefinition defaultLifecycle;
@ManyToOne
@JoinColumn(name = "DEFAULT_WORKFLOW")
private Workflow defaultWorkflow;
private WorkflowTemplate defaultWorkflow;
public String getContentItemClass() {
return contentItemClass;
@ -160,19 +160,19 @@ public class ContentType extends CcmObject implements Serializable {
this.mode = mode;
}
public Lifecycle getDefaultLifecycle() {
public LifecycleDefinition getDefaultLifecycle() {
return defaultLifecycle;
}
protected void setDefaultLifecycle(final Lifecycle defaultLifecycle) {
protected void setDefaultLifecycle(final LifecycleDefinition defaultLifecycle) {
this.defaultLifecycle = defaultLifecycle;
}
public Workflow getDefaultWorkflow() {
public WorkflowTemplate getDefaultWorkflow() {
return defaultWorkflow;
}
protected void setDefaultWorkflow(final Workflow defaultWorkflow) {
protected void setDefaultWorkflow(final WorkflowTemplate defaultWorkflow) {
this.defaultWorkflow = defaultWorkflow;
}

View File

@ -0,0 +1,15 @@
alter table CCM_CMS.CONTENT_TYPES
drop constraint FKoqvcvktnvt4ncx5k6daqat4u8;
alter table CCM_CMS.CONTENT_TYPES
drop constraint FKpgeccqsr50xwb268ypmfx0r66;
alter table CCM_CMS.CONTENT_TYPES
add constraint FK8s83we1tuh9r3j57dyos69wfa
foreign key (DEFAULT_LIFECYCLE_ID)
references CCM_CMS.LIFECYLE_DEFINITIONS;
alter table CCM_CMS.CONTENT_TYPES
add constraint FKhnu9oikw8rpf22lt5fmk41t7k
foreign key (DEFAULT_WORKFLOW)
references CCM_CORE.WORKFLOW_TEMPLATES;

View File

@ -0,0 +1,16 @@
alter table CCM_CMS.CONTENT_TYPES
drop constraint FKoqvcvktnvt4ncx5k6daqat4u8;
alter table CCM_CMS.CONTENT_TYPES
drop constraint FKpgeccqsr50xwb268ypmfx0r66;
alter table CCM_CMS.CONTENT_TYPES
add constraint FK8s83we1tuh9r3j57dyos69wfa
foreign key (DEFAULT_LIFECYCLE_ID)
references CCM_CMS.LIFECYLE_DEFINITIONS;
alter table CCM_CMS.CONTENT_TYPES
add constraint FKhnu9oikw8rpf22lt5fmk41t7k
foreign key (DEFAULT_WORKFLOW)
references CCM_CORE.WORKFLOW_TEMPLATES;

View File

@ -0,0 +1,3 @@
application_title=Content Center
application_desc=Content Center application

View File

@ -0,0 +1,3 @@
application_title=Content Center
application_desc=Content Center application

View File

@ -31,7 +31,9 @@ import org.libreccm.tests.categories.UnitTest;
import org.libreccm.testutils.EqualsVerifier;
import org.libreccm.web.CcmApplication;
import org.libreccm.workflow.Workflow;
import org.libreccm.workflow.WorkflowTemplate;
import org.librecms.lifecycle.Lifecycle;
import org.librecms.lifecycle.LifecycleDefinition;
import java.util.Arrays;
import java.util.Collection;
@ -137,17 +139,17 @@ public class EqualsAndHashCodeTest extends EqualsVerifier {
final Resource resource2 = new Resource();
resource2.setDisplayName("Resource 2");
final Lifecycle lifecycle1 = new Lifecycle();
lifecycle1.setFinished(true);
final LifecycleDefinition lifecycleDef1 = new LifecycleDefinition();
lifecycleDef1.setDefinitionId(-100);
final Lifecycle lifecycle2 = new Lifecycle();
lifecycle2.setFinished(false);
final LifecycleDefinition lifecycleDef2 = new LifecycleDefinition();
lifecycleDef2.setDefinitionId(-110);
final Workflow workflow1 = new Workflow();
workflow1.setWorkflowId(-100);
final WorkflowTemplate workflowTemplate1 = new WorkflowTemplate();
workflowTemplate1.setWorkflowId(-200);
final Workflow workflow2 = new Workflow();
workflow2.setWorkflowId(-200);
final WorkflowTemplate workflowTemplate2 = new WorkflowTemplate();
workflowTemplate2.setWorkflowId(-210);
verifier
.withPrefabValues(ContentItem.class, item1, item2)
@ -161,8 +163,12 @@ public class EqualsAndHashCodeTest extends EqualsVerifier {
.withPrefabValues(CcmApplication.class, application1, application2)
.withPrefabValues(Domain.class, domain1, domain2)
.withPrefabValues(Resource.class, resource1, resource2)
.withPrefabValues(Lifecycle.class, lifecycle1, lifecycle2)
.withPrefabValues(Workflow.class, workflow1, workflow2);
.withPrefabValues(LifecycleDefinition.class,
lifecycleDef1,
lifecycleDef2)
.withPrefabValues(WorkflowTemplate.class,
workflowTemplate1,
workflowTemplate2);
}
/**

View File

@ -187,6 +187,11 @@
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.primefaces</groupId>
<artifactId>primefaces</artifactId>
</dependency>
<!-- Export Import Libraries -->
<dependency>

View File

@ -0,0 +1,146 @@
/*
* Copyright (C) 2014 Peter Boy, University of Bremen. All Rights Reserved.
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
package com.arsdigita.bebop;
import static com.arsdigita.bebop.Component.BEBOP_XML_NS;
import com.arsdigita.bebop.event.PrintEvent;
import com.arsdigita.bebop.event.PrintListener;
import com.arsdigita.xml.Element;
/**
* Injects arbitrary content as a String into the xml output. It is not for
* any semantic type of data und it is not localizable. Specifically it is
* meant for data as Javascript and alike.
*
* It generates some fixed string to be included in the XML output.
*
* It resembles the Label methods for String parameters and currently
* generates the same XML attributes in order to avoid any need to modify the
* themes.
*
* @author pb
*/
public class Embedded extends SimpleComponent {
private final String m_content;
/** The setting for output escaping affects how markup in the
* <code>content</code> is handled.
* <UL><LI>If output escaping is in effect (true), &lt;b>example&lt;/b>
* will appear literally.</LI>
* <LI>If output escaping is disabled, &lt;b>example&lt;/b> appears as the
* String "example" in bold (i.e. retaining the markup.</LI></UL>
* Default is false. */
private boolean m_escaping = false; // default for a primitive
private PrintListener m_printListener;
/**
* Default constructor creates a new <code>Embedded</code> with the empty
* content.
*
* @param content
*/
public Embedded() {
m_content = "";
}
/**
* Constructor creates a new <code>Embedded</code> with the specified
* (fixed) content.
*
* @param content
*/
public Embedded(String content) {
m_content = content;
}
/**
* Constructor creates a new <code>Embedded</code> with the specified
* content and output escaping turned on if <code>escaping</code> is
* <code>true</code>.
*
* The setting for output escaping affects how markup in the
* <code>content</code> is handled. For example: <UL><LI>If output escaping
* is in effect, &lt;b>content&lt;/b> will appear literally.</LI> <LI>If
* output escaping is disabled, &lt;b>content&lt;/b> appears as the String
* "context" in bold.</LI></UL>
*
* @param content the content to inject into the output.
* @param escaping <code>true</code> if output escaping will be in effect;
* <code>false</code> if output escaping will be disabled
*/
public Embedded(String content, boolean escaping) {
m_content = content;
m_escaping = escaping;
}
/**
* Generates the (J)DOM fragment for a embedded.
* <p><pre>
* &lt;bebop:link href="..." type="..." %bebopAttr;/>
* </pre>
*
* @param state The current {@link PageState}.
* @param parent The XML element to attach the XML to.
*/
@Override
public void generateXML(PageState state, Element parent) {
if (!isVisible(state)) {
return;
}
Embedded target = firePrintEvent(state);
Element content = parent.newChildElement("bebop:label", BEBOP_XML_NS);
target.exportAttributes(content);
if (!target.m_escaping) {
content.addAttribute("escape", "yes");
} else {
content.addAttribute("escape", "no");
}
content.setText(m_content);
}
/**
*
* @param state
* @return
*/
protected Embedded firePrintEvent(PageState state) {
Embedded e = this;
if (m_printListener != null) {
try {
e = (Embedded) this.clone();
m_printListener.prepare(new PrintEvent(this, state, e));
} catch (CloneNotSupportedException nse) {
throw new RuntimeException(
"Couldn't clone Embedded for PrintListener. "
+ "This probably indicates a serious programming error: "
+ nse.getMessage());
}
}
return e;
}
}

View File

@ -437,7 +437,7 @@ public class CCMDispatcherServlet extends BaseServlet {
m_typeURI = servletAnnotation.urlPatterns()[0];
}
} else {
m_typeURI = "";
m_typeURI = appType.servletPath();
}
}

View File

@ -0,0 +1,53 @@
/*
* 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.admin.ui;
import org.libreccm.web.ApplicationCreator;
import org.libreccm.web.ApplicationRepository;
import org.libreccm.web.ApplicationType;
import org.libreccm.web.CcmApplication;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
/**
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
@RequestScoped
public class AdminJsfApplicationCreator implements ApplicationCreator<CcmApplication>{
@Inject
private ApplicationRepository appRepo;
@Override
public CcmApplication createInstance(final String primaryUrl,
final ApplicationType type) {
if ("org.libreccm.ui.admin.AdminFaces".equals(primaryUrl)) {
throw new IllegalArgumentException(
"CCM Admin Faces is a singleton application"
+ "which is mounted at /admin-jsf");
}
return appRepo.retrieveApplicationForPath(primaryUrl);
}
}

View File

@ -0,0 +1,51 @@
/*
* 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.admin.ui;
import org.libreccm.modules.InstallEvent;
import org.libreccm.web.AbstractCcmApplicationSetup;
import org.libreccm.web.CcmApplication;
import java.util.UUID;
/**
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
public class AdminJsfApplicationSetup extends AbstractCcmApplicationSetup {
public static final String ADMIN_APP_NAME = "CcmAdminJsf";
public AdminJsfApplicationSetup(final InstallEvent event) {
super(event);
}
@Override
public void setup() {
final CcmApplication admin = new CcmApplication();
admin.setUuid(UUID.randomUUID().toString());
admin.setApplicationType("org.libreccm.ui.admin.AdminFaces");
admin.setPrimaryUrl("/admin-jsf/");
getEntityManager().persist(admin);
}
}

View File

@ -30,7 +30,7 @@ import java.util.List;
/**
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
* @author <a href="mailto:tosmers@uni-bremen.de>Tobias Osmers</a>
* @author <a href="mailto:tosmers@uni-bremen.de">Tobias Osmers</a>
* @param <K> Primary key of the entity.
* @param <T> Type of the entity
*/
@ -42,6 +42,7 @@ public abstract class AbstractAuditedEntityRepository<K, T>
public abstract K getEntityId(final T entity);
@SuppressWarnings("unchecked")
public T retrieveRevisionOfEntity(final T entity, final Number revision) {
final AuditQuery query = auditReader.createQuery()
.forEntitiesAtRevision(getEntityClass(), revision);

View File

@ -35,6 +35,8 @@ import javax.persistence.EntityManager;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.libreccm.admin.ui.AdminJsfApplicationCreator;
import org.libreccm.admin.ui.AdminJsfApplicationSetup;
import org.libreccm.modules.CcmModule;
import org.libreccm.modules.InitEvent;
@ -60,7 +62,12 @@ import org.libreccm.web.ApplicationType;
descBundle = "com.arsdigita.ui.admin.AdminResources",
singleton = true,
creator = AdminApplicationCreator.class,
servlet = AdminServlet.class)},
servlet = AdminServlet.class),
@ApplicationType(name = "org.libreccm.ui.admin.AdminFaces",
descBundle = "com.arsdigita.ui.admin.AdminResources",
singleton = true,
creator = AdminJsfApplicationCreator.class,
servletPath = "/admin-jsf/admin.xhtml")},
configurations = {
com.arsdigita.bebop.BebopConfig.class,
com.arsdigita.dispatcher.DispatcherConfig.class,
@ -94,6 +101,11 @@ public class CcmCore implements CcmModule {
= new AdminApplicationSetup(event);
adminSetup.setup();
LOGGER.info("Setting up admin-jsf application (/ccm/admin-jsf/)...");
final AdminJsfApplicationSetup adminJsfSetup
= new AdminJsfApplicationSetup(event);
adminJsfSetup.setup();
LOGGER.info("Setting up login application...");
final LoginApplicationSetup loginSetup
= new LoginApplicationSetup(event);

View File

@ -0,0 +1,129 @@
/*
* 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.ui.admin;
import com.arsdigita.web.BaseServlet;
import com.arsdigita.web.CCMDispatcherServlet;
import com.arsdigita.web.WebConfig;
import org.apache.commons.codec.EncoderException;
import org.apache.commons.codec.net.URLCodec;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import javax.enterprise.context.RequestScoped;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.event.ComponentSystemEvent;
import javax.inject.Inject;
import javax.inject.Named;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
import org.apache.shiro.subject.Subject;
import org.libreccm.configuration.ConfigurationManager;
import org.libreccm.security.PermissionChecker;
/**
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
@RequestScoped
@Named
public class AuthorizationListener {
private static final Logger LOGGER = LogManager.getLogger(
AuthorizationListener.class);
@Inject
private Subject subject;
@Inject
private HttpServletRequest request;
// @Inject
// private HttpServletResponse response;
@Inject
private PermissionChecker permissionChecker;
@Inject
private ConfigurationManager confManager;
public void isPermitted(final ComponentSystemEvent event) {
if (!subject.isAuthenticated()) {
redirectToLogin();
return;
}
final String requiredPrivilege = (String) event.getComponent().
getAttributes().get("requiredPrivilege");
if (!permissionChecker.isPermitted(requiredPrivilege)) {
try {
final FacesContext facesContext = FacesContext.
getCurrentInstance();
final ExternalContext externalContext = facesContext.
getExternalContext();
final HttpServletResponse response
= (HttpServletResponse) externalContext
.getResponse();
response.sendError(HttpServletResponse.SC_FORBIDDEN);
} catch (IOException ex) {
LOGGER.error("Failed to send FORBIDDEN error to client.", ex);
throw new RuntimeException(
"Failed to send FORBIDDEN error to client", ex);
}
}
}
private void redirectToLogin() {
try {
final FacesContext facesContext = FacesContext.getCurrentInstance();
final ExternalContext externalContext = facesContext.
getExternalContext();
final HttpServletResponse response
= (HttpServletResponse) externalContext
.getResponse();
final WebConfig webConfig = confManager.findConfiguration(
WebConfig.class);
final URLCodec urlCodec = new URLCodec("utf-8");
response.sendRedirect(new URI(String.format(
"%s://%s:%d%s%s/register/?return_url=%s",
request.getScheme(),
request.getServerName(),
request.getLocalPort(),
CCMDispatcherServlet.getContextPath(),
webConfig.getDispatcherServletPath(),
urlCodec.encode(request.getAttribute(
BaseServlet.REQUEST_URL_ATTRIBUTE).toString())))
.toString());
} catch (IOException |
URISyntaxException |
EncoderException ex) {
LOGGER.error("Failed to redirect to login.", ex);
throw new RuntimeException("Failed to redirect to login.", ex);
}
}
}

View File

@ -16,18 +16,28 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
package org.librecms;
import org.librecms.contentsection.ContentItem;
package org.libreccm.ui.admin;
/**
* Annotation providing several informations about a content type. A content
* type is provided by a class extending the {@link ContentItem} class.
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
public @interface ContentType {
public class ConfProperty {
//ToDo
private final String name;
private final String value;
public ConfProperty(final String name, final String value) {
this.name = name;
this.value = value;
}
public String getName() {
return name;
}
public String getValue() {
return value;
}
}

View File

@ -0,0 +1,131 @@
/*
* 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.ui.admin;
import org.xml.sax.SAXException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.ResourceBundle;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.enterprise.context.RequestScoped;
import javax.inject.Named;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerFactory;
/**
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
@RequestScoped
@Named
public class ConfigurationController {
public List<ConfProperty> getSystemInformation() {
final Properties properties = new Properties();
try (final InputStream stream = getClass().getResourceAsStream(
"systeminformation.properties")) {
if (stream == null) {
properties.put("version", "");
properties.put("appname", "LibreCCM");
properties.put("apphomepage", "http://www.libreccm.org");
} else {
properties.load(stream);
}
} catch (IOException ex) {
throw new RuntimeException(ex);
}
final List<ConfProperty> sysInfo = new ArrayList<>();
properties.stringPropertyNames().forEach(propName -> sysInfo.add(
new ConfProperty(propName,
properties.getProperty(propName))));
return sysInfo;
}
public List<ConfProperty> getJavaSystemProperties() {
final Properties systemProperties = System.getProperties();
final List<ConfProperty> javaSysProps = new ArrayList<>();
systemProperties.stringPropertyNames().forEach(propName -> javaSysProps
.add(new ConfProperty(propName, systemProperties.getProperty(
propName))));
return javaSysProps;
}
public List<ConfProperty> getXmlConfig() {
final List<ConfProperty> xmlProps = new ArrayList<>();
final ResourceBundle texts = ResourceBundle.getBundle(
"com.arsdigita.ui.admin.AdminResources");
xmlProps.add(new ConfProperty(
texts.getString("ui.admin.sysinfo.xml_transformer_factory"),
TransformerFactory.newInstance().getClass().getName()));
try {
xmlProps.add(new ConfProperty(
texts.getString("ui.admin.sysinfo.xml_transformer"),
TransformerFactory.newInstance().newTransformer().getClass()
.getName()));
} catch (TransformerConfigurationException ex) {
xmlProps.add(new ConfProperty(
texts.getString("ui.admin.sysinfo.xml_transformer"), "???"));
}
xmlProps.add(new ConfProperty(
texts.getString("ui.admin.sysinfo.xml_document_builder_factory"),
DocumentBuilderFactory.newInstance().getClass().getName()));
try {
xmlProps.add(new ConfProperty(
texts.getString("ui.admin.sysinfo.xml_document_builder"),
DocumentBuilderFactory.newInstance().newDocumentBuilder()
.getClass().getName()));
} catch (ParserConfigurationException ex) {
xmlProps.add(new ConfProperty(
texts.getString("ui.admin.sysinfo.xml_document_builder"),
"???"));
}
xmlProps.add(new ConfProperty(
texts.getString("ui.admin.sysinfo.sax_parser_factory"),
SAXParserFactory.newInstance().getClass().getName()));
try {
xmlProps.add(new ConfProperty(
texts.getString("ui.admin.sysinfo.sax_parser"),
SAXParserFactory.newInstance().newSAXParser().getClass()
.getName()));
} catch (ParserConfigurationException | SAXException ex) {
xmlProps.add(new ConfProperty(
texts.getString("ui.admin.sysinfo.sax_parser"), "???"));
}
return xmlProps;
}
}

View File

@ -0,0 +1,66 @@
/*
* 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.ui.admin;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.inject.Named;
import org.apache.shiro.subject.Subject;
import org.libreccm.security.Shiro;
import org.libreccm.security.User;
/**
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
@RequestScoped
@Named
public class UserContextController {
@Inject
private Shiro shiro;
@Inject
private Subject subject;
public boolean isLoggedIn() {
return subject.isAuthenticated();
}
public String getCurrentUserName() {
final User user = shiro.getUser();
if (user == null) {
return "";
} else {
return String.format("%s %s",
user.getGivenName(),
user.getFamilyName());
}
}
public void changePassword() {
}
public void logout() {
subject.logout();
}
}

View File

@ -0,0 +1,124 @@
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:p="http://primefaces.org/ui"
xmlns:f="http://xmlns.jcp.org/jsf/core">
<f:loadBundle basename="com.arsdigita.ui.admin.AdminResources"
var="texts" />
<h:head>
<title>
LibreCCM Admin
</title>
</h:head>
<h:body>
<f:metadata>
<f:event listener="#{authorizationListener.isPermitted}"
type="preRenderView" />
<f:attribute name="requiredPrivilege" value="admin" />
</f:metadata>
<div id="header">
<h:outputStylesheet library="admin-jsf" name="header.css" />
<div id="logo">
<h:graphicImage alt=""
height="70"
library="admin-jsf"
name="libreccm.png" />
<!--<img alt=""
id="logo"
src="/themes/libreccm-default/images/libreccm.png" />-->
</div>
<h:form id="user-widget">
<p:menuButton rendered="#{userContextController.loggedIn}"
value="#{userContextController.currentUserName}">
<p:menuitem action="#{userContextController.changePassword()}"
icon="fa fa-edit"
value="Change password" />
<p:menuitem action="#{userContextController.logout()}"
icon="fa fa-sign-out"
value="Logout" />
</p:menuButton>
</h:form>
</div>
<p:tabView id="admin-tabs" dynamic="true">
<p:tab title="#{texts['ui.admin.tab.applications']}">
<h:outputText value="Applications Placeholder" />
</p:tab>
<p:tab title="#{texts['ui.admin.tab.users_groups_roles.title']}">
<p:tabView id="user-groups-roles-tabs" orientation="left">
<p:tab title="Users">
<h:outputText value="Users Placeholder" />
</p:tab>
<p:tab title="Groups">
<h:outputText value="Groups Placeholder" />
</p:tab>
<p:tab title="Roles">
<h:outputText value="Roles Placeholder" />
</p:tab>
</p:tabView>
</p:tab>
<p:tab title="#{texts['ui.admin.tab.categories.title']}">
<h:outputText value="Categories Placeholder" />
</p:tab>
<p:tab title="#{texts['ui.admin.tab.configuration.title']}">
<h:outputText value="Configuration Placeholder" />
</p:tab>
<p:tab title="#{texts['ui.admin.tab.workflows.title']}">
<h:outputText value="Workflows Placeholder" />
</p:tab>
<p:tab title="#{texts['ui.admin.tab.sysinfo.title']}">
<p:dataTable value="#{configurationController.systemInformation}"
var="prop">
<f:facet name="header">
<h:outputText value="#{texts['ui.admin.sysinfo.appinfo']}" />
</f:facet>
<p:column>
<h:outputText value="#{prop.name}" />
</p:column>
<p:column>
<h:outputText value="#{prop.value}" />
</p:column>
</p:dataTable>
<p:dataTable value="#{configurationController.javaSystemProperties}"
var="prop">
<f:facet name="header">
<h:outputText value="#{texts['ui.admin.sysinfo.java_system_properties']}" />
</f:facet>
<p:column>
<h:outputText value="#{prop.name}" />
</p:column>
<p:column>
<h:outputText value="#{prop.value}" />
</p:column>
</p:dataTable>
<p:dataTable value="#{configurationController.xmlConfig}"
var="prop">
<f:facet name="header">
<h:outputText value="#{texts['ui.admin.sysinfo.xml_config']}" />
</f:facet>
<p:column>
<h:outputText value="#{prop.name}" />
</p:column>
<p:column>
<h:outputText value="#{prop.value}" />
</p:column>
</p:dataTable>
<h:outputText value="Systeminformation Placeholder" />
</p:tab>
</p:tabView>
<h:outputText value="LibreCCM Admin Faces Placeholder" />
</h:body>
</html>

View File

@ -0,0 +1,33 @@
body {
margin: 0;
}
div#header {
background-color: #56a1bd;
background-image: -moz-linear-gradient(top, #56a1bd 5%, #024C68 95%);
background-image: -webkit-linear-gradient(top, #56a1bd 5%, #024C68 95%);
background-image: linear-gradient(top, #56a1bd 5%, #024C68 95%);
display: flex;
height: 70px;
padding: 0 10px;
position: relative;
}
#logo, #user-widget {
flex: 1;
}
#user-widget {
position: absolute;
top: 15px;
right: 10px;
}
.ui-widget, .ui-widget .ui-widget {
font-size: 90% !important;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

View File

@ -0,0 +1,16 @@
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html">
<head>
<title>
JSF Test
</title>
</head>
<body>
<h:outputText value="JSF TEST ccm-core:/resources/"/>
</body>
</html>

View File

@ -0,0 +1,16 @@
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html">
<head>
<title>
JSF Test
</title>
</head>
<body>
<h:outputText value="JSF TEST"/>
</body>
</html>

View File

@ -291,6 +291,12 @@
<version>1.2.5</version>
</dependency>
<!-- PrimeFaces for JSF prototype -->
<dependency>
<groupId>org.primefaces</groupId>
<artifactId>primefaces</artifactId>
<version>6.0</version>
</dependency>
<!--
*********************