- Cleanup pom.xml files
- UI for import/export


git-svn-id: https://svn.libreccm.org/ccm/ccm_ng@4779 8810af33-2d31-482b-a856-94f89814c4df
pull/2/head
jensp 2017-06-14 12:35:44 +00:00
parent b2b63fcc16
commit 70e99c35a0
32 changed files with 1084 additions and 88 deletions

View File

@ -170,7 +170,7 @@
<plugin>
<groupId>de.jpdigital</groupId>
<artifactId>hibernate5-ddl-maven-plugin</artifactId>
<artifactId>hibernate50-ddl-maven-plugin</artifactId>
<configuration>
<dialects>
<param>h2</param>

View File

@ -178,7 +178,7 @@
<plugin>
<groupId>de.jpdigital</groupId>
<artifactId>hibernate5-ddl-maven-plugin</artifactId>
<artifactId>hibernate50-ddl-maven-plugin</artifactId>
<configuration>
<dialects>
<param>h2</param>

View File

@ -202,7 +202,7 @@
<plugin>
<groupId>de.jpdigital</groupId>
<artifactId>hibernate5-ddl-maven-plugin</artifactId>
<artifactId>hibernate50-ddl-maven-plugin</artifactId>
<configuration>
<dialects>
<param>h2</param>

View File

@ -201,7 +201,7 @@
<plugin>
<groupId>de.jpdigital</groupId>
<artifactId>hibernate5-ddl-maven-plugin</artifactId>
<artifactId>hibernate50-ddl-maven-plugin</artifactId>
<configuration>
<dialects>
<param>h2</param>

View File

@ -202,7 +202,7 @@
<plugin>
<groupId>de.jpdigital</groupId>
<artifactId>hibernate5-ddl-maven-plugin</artifactId>
<artifactId>hibernate50-ddl-maven-plugin</artifactId>
<configuration>
<dialects>
<param>h2</param>

View File

@ -201,7 +201,7 @@
<plugin>
<groupId>de.jpdigital</groupId>
<artifactId>hibernate5-ddl-maven-plugin</artifactId>
<artifactId>hibernate50-ddl-maven-plugin</artifactId>
<configuration>
<dialects>
<param>h2</param>

View File

@ -201,7 +201,7 @@
<plugin>
<groupId>de.jpdigital</groupId>
<artifactId>hibernate5-ddl-maven-plugin</artifactId>
<artifactId>hibernate50-ddl-maven-plugin</artifactId>
<configuration>
<dialects>
<param>h2</param>

View File

@ -201,7 +201,7 @@
<plugin>
<groupId>de.jpdigital</groupId>
<artifactId>hibernate5-ddl-maven-plugin</artifactId>
<artifactId>hibernate50-ddl-maven-plugin</artifactId>
<configuration>
<dialects>
<param>h2</param>

View File

@ -202,7 +202,7 @@
<plugin>
<groupId>de.jpdigital</groupId>
<artifactId>hibernate5-ddl-maven-plugin</artifactId>
<artifactId>hibernate50-ddl-maven-plugin</artifactId>
<configuration>
<dialects>
<param>h2</param>

View File

@ -234,7 +234,7 @@
<plugin>
<groupId>de.jpdigital</groupId>
<artifactId>hibernate5-ddl-maven-plugin</artifactId>
<artifactId>hibernate50-ddl-maven-plugin</artifactId>
<configuration>
<dialects>
<param>h2</param>
@ -417,7 +417,7 @@
<plugins>
<plugin>
<groupId>de.jpdigital</groupId>
<artifactId>hibernate5-ddl-maven-plugin</artifactId>
<artifactId>hibernate50-ddl-maven-plugin</artifactId>
<configuration>
<dialects>
<param>h2</param>
@ -504,7 +504,7 @@
<plugins>
<plugin>
<groupId>de.jpdigital</groupId>
<artifactId>hibernate5-ddl-maven-plugin</artifactId>
<artifactId>hibernate50-ddl-maven-plugin</artifactId>
<configuration>
<dialects>
<param>h2</param>
@ -591,7 +591,7 @@
<plugins>
<plugin>
<groupId>de.jpdigital</groupId>
<artifactId>hibernate5-ddl-maven-plugin</artifactId>
<artifactId>hibernate50-ddl-maven-plugin</artifactId>
<configuration>
<dialects>
<param>h2</param>
@ -678,7 +678,7 @@
<plugins>
<plugin>
<groupId>de.jpdigital</groupId>
<artifactId>hibernate5-ddl-maven-plugin</artifactId>
<artifactId>hibernate50-ddl-maven-plugin</artifactId>
<configuration>
<dialects>
<param>h2</param>

View File

@ -159,6 +159,8 @@ public class ContentItemPage extends CMSPage implements ActionListener {
private final GlobalNavigation m_globalNavigation;
private final ContentItemContextBar m_contextBar;
private final StringParameter selectedLanguageParam;
private class ItemRequestLocal extends ContentItemRequestLocal {
@Override
@ -199,13 +201,13 @@ public class ContentItemPage extends CMSPage implements ActionListener {
itemModel = new ItemSelectionModel(itemId);
// Add the selected item language as parameter
final StringParameter selectedLanguage = new StringParameter(
selectedLanguageParam = new StringParameter(
SELECTED_LANGUAGE);
selectedLanguage.addParameterListener(new NotNullValidationListener(
selectedLanguageParam.addParameterListener(new NotNullValidationListener(
SELECTED_LANGUAGE));
addGlobalStateParam(selectedLanguage);
addGlobalStateParam(selectedLanguageParam);
selectedLanguageModel = new ParameterSingleSelectionModel<>(
selectedLanguage);
selectedLanguageParam);
// Add the content type global state parameter
final LongParameter contentType = new LongParameter(CONTENT_TYPE);

View File

@ -110,7 +110,6 @@
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk16</artifactId>
<version>1.46</version>
</dependency>
<dependency>
@ -343,7 +342,7 @@
</plugin>
<plugin>
<groupId>de.jpdigital</groupId>
<artifactId>hibernate5-ddl-maven-plugin</artifactId>
<artifactId>hibernate50-ddl-maven-plugin</artifactId>
<configuration>
<dialects>
<param>h2</param>
@ -415,7 +414,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.10.3</version>
<version>2.10.4</version>
<configuration>
<detectLinks>true</detectLinks>
<detectJavaApiLinks>true</detectJavaApiLinks>
@ -688,7 +687,7 @@
<plugins>
<plugin>
<groupId>de.jpdigital</groupId>
<artifactId>hibernate5-ddl-maven-plugin</artifactId>
<artifactId>hibernate50-ddl-maven-plugin</artifactId>
<configuration>
<dialects>
<param>h2</param>
@ -771,7 +770,7 @@
<plugins>
<plugin>
<groupId>de.jpdigital</groupId>
<artifactId>hibernate5-ddl-maven-plugin</artifactId>
<artifactId>hibernate50-ddl-maven-plugin</artifactId>
<configuration>
<dialects>
<param>h2</param>
@ -855,7 +854,7 @@
<plugins>
<plugin>
<groupId>de.jpdigital</groupId>
<artifactId>hibernate5-ddl-maven-plugin</artifactId>
<artifactId>hibernate50-ddl-maven-plugin</artifactId>
<configuration>
<dialects>
<param>h2</param>
@ -933,7 +932,7 @@
<plugins>
<plugin>
<groupId>de.jpdigital</groupId>
<artifactId>hibernate5-ddl-maven-plugin</artifactId>
<artifactId>hibernate50-ddl-maven-plugin</artifactId>
<configuration>
<dialects>
<param>h2</param>
@ -1016,7 +1015,7 @@
<plugins>
<plugin>
<groupId>de.jpdigital</groupId>
<artifactId>hibernate5-ddl-maven-plugin</artifactId>
<artifactId>hibernate50-ddl-maven-plugin</artifactId>
<configuration>
<dialects>
<param>h2</param>
@ -1094,7 +1093,7 @@
<plugins>
<plugin>
<groupId>de.jpdigital</groupId>
<artifactId>hibernate5-ddl-maven-plugin</artifactId>
<artifactId>hibernate50-ddl-maven-plugin</artifactId>
<configuration>
<dialects>
<param>h2</param>

View File

@ -73,6 +73,12 @@ public final class KernelConfig {
@Setting
private String defaultLanguage = "en";
@Setting
private String exportPath = "";
@Setting
private String importPath = "";
public static KernelConfig getConfig() {
final ConfigurationManager confManager = CdiUtil.createCdiUtil()
.findBean(ConfigurationManager.class);
@ -212,6 +218,22 @@ public final class KernelConfig {
this.systemEmailAddress = systemEmailAddress;
}
public String getExportPath() {
return exportPath;
}
public void setExportPath(final String exportPath) {
this.exportPath = exportPath;
}
public String getImportPath() {
return importPath;
}
public void setImportPath(final String importPath) {
this.importPath = importPath;
}
@Override
public int hashCode() {
int hash = 7;
@ -225,6 +247,8 @@ public final class KernelConfig {
hash = 61 * hash + Objects.hashCode(supportedLanguages);
hash = 61 * hash + Objects.hashCode(defaultLanguage);
hash = 61 * hash + Objects.hashCode(systemEmailAddress);
hash = 61 * hash + Objects.hashCode(exportPath);
hash = 61 * hash + Objects.hashCode(importPath);
return hash;
}
@ -270,8 +294,17 @@ public final class KernelConfig {
return false;
}
return Objects.equals(systemEmailAddress,
other.getSystemEmailAddress());
if (!Objects.equals(systemEmailAddress,
other.getSystemEmailAddress())) {
return false;
}
if (!Objects.equals(exportPath,
other.getExportPath())) {
return false;
}
return Objects.equals(importPath, other.getImportPath());
}
@Override
@ -295,7 +328,9 @@ public final class KernelConfig {
+ "secureLoginEnabled = %b, "
+ "supportedLanguages = { \"%s\" }, "
+ "defaultLanguage = \"%s\", "
+ "systemEmailAddress = \"%s\""
+ "systemEmailAddress = \"%s\", "
+ "exportPath = \"%s\", "
+ "importPath = \"%s\""
+ " }",
super.toString(),
debugEnabled,
@ -308,7 +343,9 @@ public final class KernelConfig {
//supportedLanguages == null ? "" : supportedLanguages.stream().collect(Collectors.joining(", ")),
languages,
defaultLanguage,
systemEmailAddress);
systemEmailAddress,
exportPath,
importPath);
}
}

View File

@ -32,6 +32,7 @@ import com.arsdigita.ui.UserBanner;
import com.arsdigita.ui.admin.applications.ApplicationsTab;
import com.arsdigita.ui.admin.categories.CategoriesTab;
import com.arsdigita.ui.admin.configuration.ConfigurationTab;
import com.arsdigita.ui.admin.importexport.ImportExportTab;
import com.arsdigita.web.BaseApplicationServlet;
import com.arsdigita.web.LoginSignal;
import com.arsdigita.xml.Document;
@ -139,13 +140,19 @@ public class AdminServlet extends BaseApplicationServlet {
ADMIN_BUNDLE)),
new WorkflowAdminTab());
tabbedPane.addTab(
new Label(new GlobalizedMessage("ui.admin.tab.importexport.title",
ADMIN_BUNDLE)),
new ImportExportTab());
tabbedPane.addTab(
new Label(new GlobalizedMessage("ui.admin.tab.sysinfo.title",
ADMIN_BUNDLE)),
new SystemInformationTab());
final ServletContext servletContext = getServletContext();
final String develMode = servletContext.getInitParameter("ccm.develmode");
final String develMode = servletContext
.getInitParameter("ccm.develmode");
if (develMode != null && "true".equals(develMode.toLowerCase())) {
}

View File

@ -0,0 +1,182 @@
/*
* 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 com.arsdigita.ui.admin.importexport;
import com.arsdigita.bebop.BoxPanel;
import com.arsdigita.bebop.Form;
import com.arsdigita.bebop.FormProcessException;
import com.arsdigita.bebop.Label;
import com.arsdigita.bebop.PageState;
import com.arsdigita.bebop.SaveCancelSection;
import com.arsdigita.bebop.Text;
import com.arsdigita.bebop.event.FormProcessListener;
import com.arsdigita.bebop.event.FormSectionEvent;
import com.arsdigita.bebop.form.Submit;
import com.arsdigita.globalization.GlobalizedMessage;
import com.arsdigita.ui.admin.AdminUiConstants;
import org.libreccm.cdi.utils.CdiUtil;
import java.util.ArrayList;
/**
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
public class ExportSection extends BoxPanel {
public ExportSection() {
super(BoxPanel.VERTICAL);
add(new ExportForm());
add(new StatusLabel());
add(new ReportForm());
}
private class ExportForm extends Form implements FormProcessListener {
private final SaveCancelSection saveCancelSection;
public ExportForm() {
super("exportForm");
// This placeholder will be replaced with a list of the available
// exporters and checkboxes to select the exporters to use.
add(new Text("export section placeholder"));
saveCancelSection = new SaveCancelSection();
saveCancelSection.getSaveButton().setButtonLabel(
new GlobalizedMessage("ui.admin.importexport.export.start",
AdminUiConstants.ADMIN_BUNDLE));
add(saveCancelSection);
addProcessListener(this);
}
@Override
public boolean isVisible(final PageState state) {
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final ImportExportMonitor monitor = cdiUtil
.findBean(ImportExportMonitor.class);
return !monitor.isLocked();
}
@Override
public void process(final FormSectionEvent event)
throws FormProcessException {
final PageState state = event.getPageState();
if (saveCancelSection.getSaveButton().isSelected(state)) {
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final ImportExportController controller = cdiUtil
.findBean(ImportExportController.class);
controller.export(new ArrayList<>());
}
}
}
private class StatusLabel extends Label {
public StatusLabel() {
super(event -> {
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final ImportExportMonitor monitor = cdiUtil
.findBean(ImportExportMonitor.class);
final Label target = (Label) event.getTarget();
if (monitor.isExportActive()) {
target.setLabel(new GlobalizedMessage(
"ui.admin.importexport.export.status.export_active",
AdminUiConstants.ADMIN_BUNDLE));
} else if (monitor.isImportActive()) {
target.setLabel(new GlobalizedMessage(
"ui.admin.importexport.export.status.import_active",
AdminUiConstants.ADMIN_BUNDLE));
} else {
target.setLabel(new GlobalizedMessage(
"ui.admin.importexport.export.status.locked",
AdminUiConstants.ADMIN_BUNDLE));
}
});
}
@Override
public boolean isVisible(final PageState state) {
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final ImportExportMonitor monitor = cdiUtil
.findBean(ImportExportMonitor.class);
return monitor.isLocked();
}
}
private class ReportForm extends Form {
public ReportForm() {
super("exportReportForm", new BoxPanel(BoxPanel.VERTICAL));
final Label title = new Label(event -> {
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final ImportExportMonitor monitor = cdiUtil
.findBean(ImportExportMonitor.class);
final Label target = (Label) event.getTarget();
if (monitor.isExportActive()) {
target.setLabel(new GlobalizedMessage(
"ui.admin.importexport.export.current_status",
AdminUiConstants.ADMIN_BUNDLE));
} else if (monitor.isExportReportAvailable()) {
target.setLabel(new GlobalizedMessage(
"ui.admin.importexport.export.report",
AdminUiConstants.ADMIN_BUNDLE));
}
});
add(title);
final Text text = new Text(event -> {
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final ImportExportMonitor monitor = cdiUtil
.findBean(ImportExportMonitor.class);
final Text target = (Text) event.getTarget();
target.setText(monitor.getReport().toString());
});
text.setClassAttr("preformatted-text");
add(text);
add(new Submit(new GlobalizedMessage(
"ui.admin.importexport.report.update",
AdminUiConstants.ADMIN_BUNDLE)));
}
@Override
public boolean isVisible(final PageState state) {
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final ImportExportMonitor monitor = cdiUtil
.findBean(ImportExportMonitor.class);
return monitor.isExportActive()
|| monitor.isExportReportAvailable();
}
}
}

View File

@ -0,0 +1,113 @@
/*
* 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 com.arsdigita.ui.admin.importexport;
import com.arsdigita.kernel.KernelConfig;
import org.libreccm.configuration.ConfigurationManager;
import org.libreccm.core.UnexpectedErrorException;
import org.libreccm.files.CcmFiles;
import org.libreccm.files.FileAccessException;
import org.libreccm.files.FileDoesNotExistException;
import org.libreccm.files.InsufficientPermissionsException;
import java.util.Date;
import java.util.List;
import javax.ejb.Asynchronous;
import javax.ejb.Stateless;
import javax.inject.Inject;
/**
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
@Stateless
public class ImportExportController {
@Inject
private ConfigurationManager confManager;
@Inject
private ImportExportMonitor monitor;
@Inject
private CcmFiles ccmFiles;
/**
* Return the fully qualified class names for all available exporters.
*
* @return
*/
public List<String> getAvailableExporters() {
// Note: Return value may needs to be adjusted. Possibly we need a
// data structure which contains some more information like a
// localised label for the exporters etc.
throw new UnsupportedOperationException("Not implemented yet.");
}
/**
* Create an export into the directory configured by
* {@link KernelConfig#exportPath} using the provided exporters.
*
* @param exporters The exporters to use.
*/
@Asynchronous
public void export(final List<String> exporters) {
monitor.startExport();
final long start = System.currentTimeMillis();
while (System.currentTimeMillis() < start + 60 * 1000) {
try {
Thread.sleep(3 * 1000);
} catch (InterruptedException ex) {
throw new UnexpectedErrorException(ex);
}
monitor.getReport().append(String.format("...%tF %<tT%n",
new Date()));
}
monitor.finishExport();
}
public List<String> getAvailableImportFiles() {
final KernelConfig kernelConfig = confManager
.findConfiguration(KernelConfig.class);
final String importPath = kernelConfig.getImportPath();
try {
return ccmFiles.listFiles(importPath);
} catch (FileAccessException
| FileDoesNotExistException
| InsufficientPermissionsException ex) {
throw new UnexpectedErrorException(ex);
}
}
public void importFiles(final List<String> filesToImport) {
monitor.startImport();
// ToDol Import code here
monitor.finishImport();
}
}

View File

@ -0,0 +1,155 @@
/*
* 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 com.arsdigita.ui.admin.importexport;
import java.util.Date;
import java.util.UUID;
import javax.enterprise.context.ApplicationScoped;
/**
*
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
@ApplicationScoped
public class ImportExportMonitor {
/**
* Indicates that an export process is running.
*/
private boolean exportActive = false;
/**
* Indicates that an import process is running.
*/
private boolean importActive = false;
private boolean exportReportAvailable = false;
private boolean importReportAvailable = false;
/**
* A UUID to identify to the import/export process.
*/
private String importExportProcessUuid;
/**
* A {@link StringBuffer} for creating a report of the import/export
* process. The report of the last import/export process will be stored
* until another import/export process is started or the application is
* restarted.
*/
private StringBuffer report;
public boolean isExportActive() {
return exportActive;
}
public boolean isImportActive() {
return importActive;
}
/**
* Returns {@code true} if either an import process or an export process is
* active.
*
* @return {@code true} if an import or export process is active.
*/
public boolean isLocked() {
return exportActive || importActive;
}
public boolean isExportReportAvailable() {
return exportReportAvailable;
}
public boolean isImportReportAvailable() {
return importReportAvailable;
}
public void startExport() {
if (exportActive) {
throw new IllegalStateException(
"Can't start a new export process "
+ "because there is already an export process running");
}
if (importActive) {
throw new IllegalStateException(
"Can't start a export process "
+ "because there is already an import process running");
}
exportActive = true;
importExportProcessUuid = UUID.randomUUID().toString();
report = new StringBuffer();
report.append(String
.format("Lock for export process %s accquired at %tF %<tT%n",
importExportProcessUuid,
new Date()));
}
public void finishExport() {
exportActive = false;
report.append(String
.format("Lock for export process %s released at %tF %<tT%n",
importExportProcessUuid,
new Date()));
importExportProcessUuid = null;
exportReportAvailable = true;
}
public void startImport() {
if (exportActive) {
throw new IllegalStateException(
"Can't start a new import process "
+ "because there is already an export process running");
}
if (importActive) {
throw new IllegalStateException(
"Can't start a new import process "
+ "because there is already an import process running");
}
importActive = true;
importExportProcessUuid = UUID.randomUUID().toString();
report = new StringBuffer();
report.append(String
.format("Lock for import process %s released at %tF %<tT%n",
importExportProcessUuid,
new Date()));
}
public void finishImport() {
importActive = false;
report.append(String
.format("Lock for import process %s released at %tF %<tT%n",
importExportProcessUuid,
new Date()));
importExportProcessUuid = null;
importReportAvailable = true;
}
public StringBuffer getReport() {
return report;
}
}

View File

@ -0,0 +1,182 @@
/*
* 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 com.arsdigita.ui.admin.importexport;
import com.arsdigita.bebop.BoxPanel;
import com.arsdigita.bebop.Component;
import com.arsdigita.bebop.Label;
import com.arsdigita.bebop.List;
import com.arsdigita.bebop.Page;
import com.arsdigita.bebop.PageState;
import com.arsdigita.bebop.Resettable;
import com.arsdigita.bebop.list.ListModel;
import com.arsdigita.bebop.list.ListModelBuilder;
import com.arsdigita.globalization.GlobalizedMessage;
import com.arsdigita.toolbox.ui.LayoutPanel;
import com.arsdigita.ui.admin.AdminUiConstants;
import com.arsdigita.util.Assert;
import com.arsdigita.util.LockableImpl;
import java.util.ArrayList;
/**
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
public class ImportExportTab extends LayoutPanel {
private List sections;
private final java.util.List<Component> components = new ArrayList<>();
private final java.util.List<Label> keys = new ArrayList<>();
public ImportExportTab() {
super();
setClassAttr("sidebarNavPanel");
sections = new List(new SectionsListModelBuilder());
sections.addChangeListener(event -> {
final PageState state = event.getPageState();
final int selectedIndex = Integer
.parseInt((String) sections.getSelectedKey(state));
setSection(selectedIndex, state);
});
sections.setClassAttr("navbar");
final BoxPanel body = new BoxPanel(BoxPanel.VERTICAL);
addSection(
new Label(
new GlobalizedMessage("ui.admin.importexport.export.title",
AdminUiConstants.ADMIN_BUNDLE)),
new ExportSection(),
body);
addSection(
new Label(
new GlobalizedMessage("ui.admin.importexport.import.title",
AdminUiConstants.ADMIN_BUNDLE)),
new ImportSection(),
body);
setLeft(sections);
setBody(body);
}
/**
* Helper method for adding a section
*
* @param label The label of the section.
* @param component The component which provides the section.
* @param panel The panel to which the component is added.
*/
private void addSection(final Label label,
final Component component,
final BoxPanel panel) {
Assert.isUnlocked(this);
components.add(component);
component.setClassAttr("main");
panel.add(component);
keys.add(label);
}
/**
* Register the components in the page
*
* @param page The Admin UI page.
*/
@Override
public void register(final Page page) {
Assert.isUnlocked(this);
components.forEach(c -> page.setVisibleDefault(c, false));
}
/**
* Sets the current section.
*
* @param index The index of the section.
* @param state The page state.
*/
public void setSection(final int index, final PageState state) {
sections.setSelectedKey(state, String.valueOf(index));
for (int i = 0; i < components.size(); i++) {
if (i == index) {
final Component component = components.get(i);
component.setVisible(state, true);
if (component instanceof Resettable) {
final Resettable resettable = (Resettable) component;
resettable.reset(state);
}
} else {
components.get(i).setVisible(state, false);
}
}
}
/**
* Model Builder for the section list.
*/
private class SectionsListModelBuilder extends LockableImpl
implements ListModelBuilder {
@Override
public ListModel makeModel(final List list,
final PageState state) {
if (sections.getSelectedKey(state) == null) {
sections.setSelectedKey(state, String.valueOf(0));
}
return new SectionsListModel(state);
}
}
/**
* Model for the section list.
*/
private class SectionsListModel implements ListModel {
private int index = -1;
private final PageState state;
public SectionsListModel(final PageState state) {
this.state = state;
}
@Override
public boolean next() {
final boolean result = (index < keys.size() - 1);
index++;
return result;
}
@Override
public Object getElement() {
return keys.get(index).getLabel(state);
}
@Override
public String getKey() {
return String.valueOf(index);
}
}
}

View File

@ -0,0 +1,213 @@
/*
* 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 com.arsdigita.ui.admin.importexport;
import com.arsdigita.bebop.BoxPanel;
import com.arsdigita.bebop.Form;
import com.arsdigita.bebop.FormProcessException;
import com.arsdigita.bebop.Label;
import com.arsdigita.bebop.PageState;
import com.arsdigita.bebop.SaveCancelSection;
import com.arsdigita.bebop.Text;
import com.arsdigita.bebop.event.FormProcessListener;
import com.arsdigita.bebop.event.FormSectionEvent;
import com.arsdigita.bebop.form.CheckboxGroup;
import com.arsdigita.bebop.form.Option;
import com.arsdigita.bebop.form.Submit;
import com.arsdigita.bebop.parameters.ArrayParameter;
import com.arsdigita.globalization.GlobalizedMessage;
import com.arsdigita.ui.admin.AdminUiConstants;
import org.libreccm.cdi.utils.CdiUtil;
import org.libreccm.core.UnexpectedErrorException;
import java.util.Arrays;
import java.util.List;
import java.util.TooManyListenersException;
/**
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
public class ImportSection extends BoxPanel {
public ImportSection() {
super(BoxPanel.VERTICAL);
add(new ImportForm());
add(new StatusLabel());
add(new ReportForm());
}
private class ImportForm extends Form implements FormProcessListener {
private static final String SELECTED_IMPORTS_PARAM
= "selectedImportsParam";
private final CheckboxGroup importsSelector;
private final SaveCancelSection saveCancelSection;
public ImportForm() {
super("importForm", new BoxPanel(BoxPanel.VERTICAL));
add(new Label(new GlobalizedMessage(
"ui.admin.importexport.import.select_files_to_import",
AdminUiConstants.ADMIN_BUNDLE)));
importsSelector = new CheckboxGroup(SELECTED_IMPORTS_PARAM);
try {
importsSelector.addPrintListener(event -> {
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final ImportExportController controller = cdiUtil
.findBean(ImportExportController.class);
final CheckboxGroup target = (CheckboxGroup) event
.getTarget();
final List<String> importFiles = controller
.getAvailableImportFiles();
importFiles.forEach(file -> {
target.addOption(new Option(file, new Text(file)));
});
});
} catch (TooManyListenersException ex) {
throw new UnexpectedErrorException(ex);
}
add(importsSelector);
saveCancelSection = new SaveCancelSection();
saveCancelSection
.getSaveButton()
.setButtonLabel(new GlobalizedMessage(
"ui.admin.importexport.import.execute",
AdminUiConstants.ADMIN_BUNDLE));
add(saveCancelSection);
}
@Override
public boolean isVisible(final PageState state) {
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final ImportExportMonitor monitor = cdiUtil
.findBean(ImportExportMonitor.class);
return !monitor.isLocked();
}
@Override
public void process(final FormSectionEvent event)
throws FormProcessException {
final PageState state = event.getPageState();
if (saveCancelSection.getSaveButton().isSelected(state)) {
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final ImportExportController controller = cdiUtil
.findBean(ImportExportController.class);
final String[] selectedFiles = (String[]) importsSelector
.getValue(state);
controller.importFiles(Arrays.asList(selectedFiles));
}
}
}
private class StatusLabel extends Label {
public StatusLabel() {
super(event -> {
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final ImportExportMonitor monitor = cdiUtil
.findBean(ImportExportMonitor.class);
final Label target = (Label) event.getTarget();
if (monitor.isExportActive()) {
target.setLabel(new GlobalizedMessage(
"ui.admin.importexport.import.status.export_active",
AdminUiConstants.ADMIN_BUNDLE));
} else if (monitor.isImportActive()) {
target.setLabel(new GlobalizedMessage(
"ui.admin.importexport.import.status.import_active",
AdminUiConstants.ADMIN_BUNDLE));
} else {
target.setLabel(new GlobalizedMessage(
"ui.admin.importexport.import.status.locked",
AdminUiConstants.ADMIN_BUNDLE));
}
});
}
@Override
public boolean isVisible(final PageState state) {
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final ImportExportMonitor monitor = cdiUtil
.findBean(ImportExportMonitor.class);
return monitor.isLocked();
}
}
private class ReportForm extends Form {
public ReportForm() {
super("importReportForm", new BoxPanel(BoxPanel.VERTICAL));
final Label title = new Label(event -> {
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final ImportExportMonitor monitor = cdiUtil
.findBean(ImportExportMonitor.class);
final Label target = (Label) event.getTarget();
if (monitor.isExportActive()) {
target.setLabel(new GlobalizedMessage(
"ui.admin.importexport.import.current_status",
AdminUiConstants.ADMIN_BUNDLE));
} else if (monitor.isExportReportAvailable()) {
target.setLabel(new GlobalizedMessage(
"ui.admin.importexport.import.report",
AdminUiConstants.ADMIN_BUNDLE));
}
});
add(title);
final Text text = new Text(event -> {
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final ImportExportMonitor monitor = cdiUtil
.findBean(ImportExportMonitor.class);
final Text target = (Text) event.getTarget();
target.setText(monitor.getReport().toString());
});
text.setClassAttr("preformatted-text");
add(text);
add(new Submit(new GlobalizedMessage(
"ui.admin.importexport.report.update",
AdminUiConstants.ADMIN_BUNDLE)));
}
@Override
public boolean isVisible(final PageState state) {
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final ImportExportMonitor monitor = cdiUtil
.findBean(ImportExportMonitor.class);
return monitor.isImportActive()
|| monitor.isImportReportAvailable();
}
}
}

View File

@ -70,13 +70,16 @@ public class GroupsTable extends Grid<Group> {
.setCaption("Name");
addColumn(user -> bundle.getString("ui.admin.groups.table.edit"),
new ButtonRenderer<>(event -> {
final GroupEditor groupEditor = new GroupEditor(
// final GroupEditor groupEditor = new GroupEditor(
final GroupDetails groupDetails = new GroupDetails(
event.getItem(),
usersGroupsRoles,
view.getGroupRepository(),
view.getGroupManager());
groupEditor.center();
UI.getCurrent().addWindow(groupEditor);
groupDetails.center();
groupDetails.setWidth("50%");
groupDetails.setHeight("100%");
UI.getCurrent().addWindow(groupDetails);
}))
.setId(COL_EDIT);
addColumn(user -> bundle.getString("ui.admin.groups.table.delete"),

View File

@ -83,6 +83,7 @@ import org.libreccm.web.ApplicationType;
com.arsdigita.xml.XmlConfig.class,
com.arsdigita.xml.formatters.DateFormatterConfig.class,
org.libreccm.configuration.ExampleConfiguration.class,
org.libreccm.files.CcmFilesConfiguration.class,
org.libreccm.search.SearchConfig.class,
org.libreccm.security.EmailTemplates.class,
org.libreccm.security.OneTimeAuthConfig.class,})

View File

@ -109,6 +109,11 @@ import static org.libreccm.core.CoreConstants.DB_SCHEMA;
+ " u.familyName, "
+ " u.givenName, "
+ " u.primaryEmailAddress.address")
,
@NamedQuery(name = "User.findByGroup",
query = "SELECT u FROM User u "
+ "JOIN u.groupMemberships m "
+ "WHERE m.group = :group")
})
@NamedEntityGraphs({
@NamedEntityGraph(

View File

@ -78,7 +78,8 @@ public class UserRepository extends AbstractEntityRepository<Long, User> {
* user matching the user name (should be possible) the first one is
* returned. If there is no matching user {@code null} is returned.
*/
public Optional<User> findByName(final String name, final String entityGraphName) {
public Optional<User> findByName(final String name,
final String entityGraphName) {
@SuppressWarnings("unchecked")
final EntityGraph<User> entityGraph
= (EntityGraph<User>) getEntityManager()
@ -166,6 +167,14 @@ public class UserRepository extends AbstractEntityRepository<Long, User> {
return query.getResultList();
}
public List<User> findByGroup(final Group group) {
final TypedQuery<User> query = getEntityManager()
.createNamedQuery("User.findByGroup", User.class);
query.setParameter("group", group);
return query.getResultList();
}
@AuthorizationRequired
@RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN)
@Transactional(Transactional.TxType.REQUIRED)

View File

@ -592,3 +592,21 @@ ui.admin.role_edit.roledescription.label=Description
ui.admin.role.createpanel.header=Create new role
ui.admin.role_edit.discard_confirm=Are you sure to discard all changes made to this role?
ui.admin.role_edit.rolename.error.notempty=The name of a role can't be empty.
ui.groups.members.remove=Remove
ui.admin.importexport.export.title=Export
ui.admin.importexport.import.title=Import
ui.admin.tab.importexport.title=Import/Export
ui.admin.importexport.export.status.export_active=An export process is active...
ui.admin.importexport.export.status.import_active=An import process is active. Check the import section for its status.
ui.admin.importexport.export.status.locked=This should not happen...
ui.admin.importexport.export.current_status=Status of active export process
ui.admin.importexport.export.report=Report from last export
ui.admin.importexport.report.update=Update
ui.admin.importexport.export.start=Start export
ui.admin.importexport.import.select_files_to_import=Select files to import
ui.admin.importexport.import.execute=Import selected files
ui.admin.importexport.import.status.export_active=An export process is running at them moment.
ui.admin.importexport.import.status.import_active=An import process is active.
ui.admin.importexport.import.status.locked=This should not happen.
ui.admin.importexport.import.current_status=Import current status
ui.admin.importexport.import.report=Report from last import process

View File

@ -596,3 +596,21 @@ ui.admin.role_edit.roledescription.label=Beschreibung
ui.admin.role.createpanel.header=Neue Rolle anlegen
ui.admin.role_edit.discard_confirm=Sind Sie sicher, dass Sie alle an dieser Rolle vorgenommenden \u00c4nderungen verwerfen wollen?
ui.admin.role_edit.rolename.error.notempty=Der Name einer Rolle kann nicht leer sein.
ui.groups.members.remove=Entfernen
ui.admin.importexport.export.title=Export
ui.admin.importexport.import.title=Import
ui.admin.tab.importexport.title=Import/Export
ui.admin.importexport.export.status.export_active=Ein Export-Prozess ist aktiv...
ui.admin.importexport.export.status.import_active=Ein Import-Prozess ist aktiv. F\u00fcr den Status siehe Import-Sektion.
ui.admin.importexport.export.status.locked=This should not happen...
ui.admin.importexport.export.current_status=Status des aktiven Export-Prozesses
ui.admin.importexport.export.report=Bericht des letzten Export-Vorgangs
ui.admin.importexport.report.update=Aktualisieren
ui.admin.importexport.export.start=Export starten
ui.admin.importexport.import.select_files_to_import=W\u00e4hlen sie die zu importierenden Dateien aus
ui.admin.importexport.import.execute=Ausgew\u00e4hlte Dateien importieren
ui.admin.importexport.import.status.export_active=Derzeit ist ein Export-Prozess aktiv.
ui.admin.importexport.import.status.import_active=Ein Import-Prozess ist bereits aktiv.
ui.admin.importexport.import.status.locked=This should not happen.
ui.admin.importexport.import.current_status=Aktueller Status des Import-Prozesses
ui.admin.importexport.import.report=Bericht des letzten Import-Prozesses

View File

@ -589,3 +589,21 @@ ui.admin.role_edit.roledescription.label=Description
ui.admin.role.createpanel.header=Create new role
ui.admin.role_edit.discard_confirm=Are you sure to discard all changes made to this role?
ui.admin.role_edit.rolename.error.notempty=The name of a role can't be empty.
ui.groups.members.remove=Remove
ui.admin.importexport.export.title=Export
ui.admin.importexport.import.title=Import
ui.admin.tab.importexport.title=Import/Export
ui.admin.importexport.export.status.export_active=An export process is active...
ui.admin.importexport.export.status.import_active=An import process is active. Check the import section for its status.
ui.admin.importexport.export.status.locked=This should not happen...
ui.admin.importexport.export.current_status=Status of active export process
ui.admin.importexport.export.report=Report from last export
ui.admin.importexport.report.update=Update
ui.admin.importexport.export.start=Start export
ui.admin.importexport.import.select_files_to_import=Select files to import
ui.admin.importexport.import.execute=Import selected files
ui.admin.importexport.import.status.export_active=An export process is running at them moment.
ui.admin.importexport.import.status.import_active=An import process is active.
ui.admin.importexport.import.status.locked=This should not happen.
ui.admin.importexport.import.current_status=Import current status
ui.admin.importexport.import.report=Report from last import process

View File

@ -580,3 +580,21 @@ ui.admin.role_edit.roledescription.label=Description
ui.admin.role.createpanel.header=Create new role
ui.admin.role_edit.discard_confirm=Are you sure to discard all changes made to this role?
ui.admin.role_edit.rolename.error.notempty=The name of a role can't be empty.
ui.groups.members.remove=Remove
ui.admin.importexport.export.title=Export
ui.admin.importexport.import.title=Import
ui.admin.tab.importexport.title=Import/Export
ui.admin.importexport.export.status.export_active=An export process is active...
ui.admin.importexport.export.status.import_active=An import process is active. Check the import section for its status.
ui.admin.importexport.export.status.locked=This should not happen...
ui.admin.importexport.export.current_status=Status of active export process
ui.admin.importexport.export.report=Report from last export
ui.admin.importexport.report.update=Update
ui.admin.importexport.export.start=Start export
ui.admin.importexport.import.select_files_to_import=Select files to import
ui.admin.importexport.import.execute=Import selected files
ui.admin.importexport.import.status.export_active=An export process is running at them moment.
ui.admin.importexport.import.status.import_active=An import process is active.
ui.admin.importexport.import.status.locked=This should not happen.
ui.admin.importexport.import.current_status=Import current status
ui.admin.importexport.import.report=Report from last import process

View File

@ -194,7 +194,7 @@
</plugin>
<plugin>
<groupId>de.jpdigital</groupId>
<artifactId>hibernate5-ddl-maven-plugin</artifactId>
<artifactId>hibernate50-ddl-maven-plugin</artifactId>
<configuration>
<dialects>
<param>h2</param>
@ -377,7 +377,7 @@
<plugins>
<plugin>
<groupId>de.jpdigital</groupId>
<artifactId>hibernate5-ddl-maven-plugin</artifactId>
<artifactId>hibernate50-ddl-maven-plugin</artifactId>
<configuration>
<dialects>
<param>h2</param>
@ -459,7 +459,7 @@
<plugins>
<plugin>
<groupId>de.jpdigital</groupId>
<artifactId>hibernate5-ddl-maven-plugin</artifactId>
<artifactId>hibernate50-ddl-maven-plugin</artifactId>
<configuration>
<dialects>
<param>h2</param>
@ -541,7 +541,7 @@
<plugins>
<plugin>
<groupId>de.jpdigital</groupId>
<artifactId>hibernate5-ddl-maven-plugin</artifactId>
<artifactId>hibernate50-ddl-maven-plugin</artifactId>
<configuration>
<dialects>
<param>h2</param>
@ -623,7 +623,7 @@
<plugins>
<plugin>
<groupId>de.jpdigital</groupId>
<artifactId>hibernate5-ddl-maven-plugin</artifactId>
<artifactId>hibernate50-ddl-maven-plugin</artifactId>
<configuration>
<dialects>
<param>h2</param>

View File

@ -226,7 +226,7 @@
</plugin>
<plugin>
<groupId>de.jpdigital</groupId>
<artifactId>hibernate5-ddl-maven-plugin</artifactId>
<artifactId>hibernate50-ddl-maven-plugin</artifactId>
<configuration>
<dialects>
<param>h2</param>
@ -413,7 +413,7 @@
<plugins>
<plugin>
<groupId>de.jpdigital</groupId>
<artifactId>hibernate5-ddl-maven-plugin</artifactId>
<artifactId>hibernate50-ddl-maven-plugin</artifactId>
<configuration>
<dialects>
<param>h2</param>
@ -500,7 +500,7 @@
<plugins>
<plugin>
<groupId>de.jpdigital</groupId>
<artifactId>hibernate5-ddl-maven-plugin</artifactId>
<artifactId>hibernate50-ddl-maven-plugin</artifactId>
<configuration>
<dialects>
<param>h2</param>
@ -590,7 +590,7 @@
<plugins>
<plugin>
<groupId>de.jpdigital</groupId>
<artifactId>hibernate5-ddl-maven-plugin</artifactId>
<artifactId>hibernate50-ddl-maven-plugin</artifactId>
<configuration>
<dialects>
<param>h2</param>
@ -677,7 +677,7 @@
<plugins>
<plugin>
<groupId>de.jpdigital</groupId>
<artifactId>hibernate5-ddl-maven-plugin</artifactId>
<artifactId>hibernate50-ddl-maven-plugin</artifactId>
<configuration>
<dialects>
<param>h2</param>

View File

@ -107,16 +107,16 @@ public class DatasetsVerifier {
//try-with-resources block to ensure that the connection is closed.
final StringBuffer buffer = new StringBuffer("jdbc:h2:mem:testdatabase");
//Create schema if necssary
if (getSchemas().length > 0) {
buffer.append(";INIT=");
for (final String schema : getSchemas()) {
if (buffer.length() > 0) {
buffer.append("\\;");
}
buffer.append(String.format("CREATE SCHEMA IF NOT EXISTS %s",
schema));
}
}
// if (getSchemas().length > 0) {
// buffer.append(";INIT=");
// for (final String schema : getSchemas()) {
// if (buffer.length() > 0) {
// buffer.append("\\;");
// }
// buffer.append(String.format("CREATE SCHEMA IF NOT EXISTS %s",
// schema));
// }
// }
final String connectionStr = buffer.toString();
try (final Connection connection = DriverManager.getConnection(
connectionStr, "sa", "")) {

View File

@ -1946,3 +1946,7 @@ span#quickLinksCascade {
text-align: left;
}
.preformatted-text {
white-space: pre;
}

16
pom.xml
View File

@ -193,8 +193,8 @@
</plugin>
<plugin>
<groupId>de.jpdigital</groupId>
<artifactId>hibernate5-ddl-maven-plugin</artifactId>
<version>1.0.1-hibernate-5.2.4.Final</version>
<artifactId>hibernate50-ddl-maven-plugin</artifactId>
<version>2.0.2-SNAPSHOT</version>
</plugin>
<plugin>
<groupId>org.jacoco</groupId>
@ -221,6 +221,12 @@
<artifactId>vaadin-maven-plugin</artifactId>
<version>8.0.5</version>
</plugin>
<!-- Reporting plugins -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.10.4</version>
</plugin>
</plugins>
</pluginManagement>
@ -494,6 +500,12 @@
<version>2.0.8</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk16</artifactId>
<version>1.46</version>
</dependency>
<dependency>
<groupId>poi</groupId>
<artifactId>poi-2.5-final</artifactId>