diff --git a/ccm-core/pom.xml b/ccm-core/pom.xml index 1dde82744..ca94023cc 100644 --- a/ccm-core/pom.xml +++ b/ccm-core/pom.xml @@ -62,6 +62,12 @@ provided + + org.hibernate + hibernate-search + provided + + diff --git a/ccm-core/src/main/java/com/arsdigita/ui/admin/configuration/AbstractSettingFormSingleValue.java b/ccm-core/src/main/java/com/arsdigita/ui/admin/configuration/AbstractSettingFormSingleValue.java index 2bf1c0dff..de0399a83 100644 --- a/ccm-core/src/main/java/com/arsdigita/ui/admin/configuration/AbstractSettingFormSingleValue.java +++ b/ccm-core/src/main/java/com/arsdigita/ui/admin/configuration/AbstractSettingFormSingleValue.java @@ -165,7 +165,11 @@ public abstract class AbstractSettingFormSingleValue extends Form { return; } - valueField.setValue(state, value.toString()); + if (value == null) { + valueField.setValue(state, ""); + } else { + valueField.setValue(state, value.toString()); + } } } diff --git a/ccm-core/src/main/java/org/libreccm/configuration/ConfigurationManager.java b/ccm-core/src/main/java/org/libreccm/configuration/ConfigurationManager.java index 33c17eefe..36d67e916 100644 --- a/ccm-core/src/main/java/org/libreccm/configuration/ConfigurationManager.java +++ b/ccm-core/src/main/java/org/libreccm/configuration/ConfigurationManager.java @@ -302,7 +302,7 @@ public class ConfigurationManager { "New value of setting \"%s#%s\" is: \"%s\"", confClassName, settingName, - value.toString())); + value)); @SuppressWarnings("unchecked") final T settingValue = (T) value; setting.setValue(settingValue); @@ -310,8 +310,7 @@ public class ConfigurationManager { "Value of setting \"%s#%s\" is now: \"%s\"", confClassName, settingName, - setting.getValue().toString() - )); + setting.getValue())); LOGGER.debug("Saving changed setting to DB..."); settingManager.saveSetting(setting); } @@ -355,7 +354,7 @@ public class ConfigurationManager { LOGGER.debug("Setting \"{}#{}\" found. Value: {}", confName, settingName, - setting.getValue().toString()); + setting.getValue()); field.set(conf, setting.getValue()); } catch (IllegalAccessException ex) { LOGGER.warn( diff --git a/ccm-core/src/main/java/org/libreccm/configuration/SettingManager.java b/ccm-core/src/main/java/org/libreccm/configuration/SettingManager.java index 9d342185d..bf2f74566 100644 --- a/ccm-core/src/main/java/org/libreccm/configuration/SettingManager.java +++ b/ccm-core/src/main/java/org/libreccm/configuration/SettingManager.java @@ -176,7 +176,7 @@ public class SettingManager { if (Strings.isBlank(settingAnnotation.descKey())) { settingInfo.setDescKey(String.join(".", field.getName(), - "descripotion")); + "description")); } else { settingInfo.setDescKey(settingAnnotation.descKey()); } diff --git a/ccm-core/src/main/java/org/libreccm/core/CcmCore.java b/ccm-core/src/main/java/org/libreccm/core/CcmCore.java index 071e183df..bc81b8bf0 100644 --- a/ccm-core/src/main/java/org/libreccm/core/CcmCore.java +++ b/ccm-core/src/main/java/org/libreccm/core/CcmCore.java @@ -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.search.SearchConfig.class, org.libreccm.security.EmailTemplates.class, org.libreccm.security.OneTimeAuthConfig.class,}) public class CcmCore implements CcmModule { diff --git a/ccm-core/src/main/java/org/libreccm/modules/CcmIntegrator.java b/ccm-core/src/main/java/org/libreccm/modules/CcmIntegrator.java index 223e31aba..ddd33b7d6 100644 --- a/ccm-core/src/main/java/org/libreccm/modules/CcmIntegrator.java +++ b/ccm-core/src/main/java/org/libreccm/modules/CcmIntegrator.java @@ -24,17 +24,19 @@ import org.flywaydb.core.Flyway; import org.flywaydb.core.api.MigrationInfo; import org.flywaydb.core.internal.util.jdbc.JdbcUtils; import org.hibernate.boot.Metadata; -import org.hibernate.cfg.Configuration; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.integrator.spi.Integrator; import org.hibernate.service.spi.SessionFactoryServiceRegistry; +import org.libreccm.search.SearchConfig; import java.sql.Connection; +import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.List; import java.util.Locale; +import java.util.Optional; import java.util.ServiceLoader; import javax.sql.DataSource; @@ -65,7 +67,7 @@ public class CcmIntegrator implements Integrator { /** * Service loader containing all modules. Initialised by the - * {@link #integrate(Configuration, SessionFactoryImplementor, SessionFactoryServiceRegistry)} + * {@link #integrate(Metadata, SessionFactoryImplementor, SessionFactoryServiceRegistry)} * method. */ private ServiceLoader modules; @@ -132,12 +134,10 @@ public class CcmIntegrator implements Integrator { node.getModuleInfo().getModuleName(), node.getModuleInfo().getModuleVersion()); migrateModule(node.getModule().getClass(), dataSource); - -// for (Class entity : node.getModuleInfo().getModuleEntities()) { -// configuration.addAnnotatedClass(entity); -// } } + configureHibernateSearch(connection, sessionFactory); + } catch (DependencyException | SQLException ex) { throw new IntegrationException("Failed to integrate modules", ex); } finally { @@ -145,6 +145,7 @@ public class CcmIntegrator implements Integrator { } LOGGER.info("All modules integrated successfully."); + } /** @@ -415,4 +416,61 @@ public class CcmIntegrator implements Integrator { } } + private void configureHibernateSearch( + final Connection connection, + final SessionFactoryImplementor sessionFactory) throws SQLException { + + LOGGER.info("Configuring Hibernate Search..."); + + LOGGER.debug( + "Checking for Directory Provider setting in configuration..."); + final Optional directoryProvider = getSetting( + connection, + SearchConfig.class.getName(), + SearchConfig.DIRECTORY_PROVIDER); + if (directoryProvider.isPresent()) { + LOGGER.debug("Found setting for directory provider: {}", + directoryProvider.orElse("")); + sessionFactory.getProperties().setProperty( + "hibernate.search.default.directory_provider", + directoryProvider.get()); + } else { + LOGGER.debug("No setting for directory provider. " + + "Defaulting to RAM directory provider."); + sessionFactory.getProperties().setProperty( + "hibernate.search.default.directory_provider", "ram"); + } + + final Optional indexBase = getSetting( + connection, + SearchConfig.class.getName(), + SearchConfig.INDEX_BASE); + if (indexBase.isPresent()) { + LOGGER.debug("Setting Index Base to \"{}\".", indexBase.get()); + sessionFactory.getProperties().setProperty( + "hibernate.search.default.indexBase", + indexBase.get()); + } + } + + private Optional getSetting(final Connection connection, + final String settingClass, + final String settingName) + throws SQLException { + + try (PreparedStatement statement = connection.prepareStatement( + "SELECT setting_value_string FROM ccm_core.settings " + + "WHERE configuration_class = ? AND name = ?")) { + statement.setString(1, settingClass); + statement.setString(2, settingName); + try (ResultSet resultSet = statement.executeQuery()) { + if (resultSet.next()) { + return Optional.ofNullable(resultSet.getString(1)); + } else { + return Optional.empty(); + } + } + } + } + } diff --git a/ccm-core/src/main/java/org/libreccm/search/SearchConfig.java b/ccm-core/src/main/java/org/libreccm/search/SearchConfig.java new file mode 100644 index 000000000..3006855ca --- /dev/null +++ b/ccm-core/src/main/java/org/libreccm/search/SearchConfig.java @@ -0,0 +1,99 @@ +/* + * 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.search; + +import org.libreccm.configuration.Configuration; +import org.libreccm.configuration.Setting; + +import java.util.Objects; + +/** + * Configuration for Hibernate Search. Some of the options in this configuration + * are directly applied to Hibernate search. Please refer to the Hibernate + * Search documentation for details and valid values. + * + * @author Jens Pelzetter + */ +@Configuration +public final class SearchConfig { + + public static final String DIRECTORY_PROVIDER = "directoryProvider"; + public static final String INDEX_BASE = "indexBase"; + + @Setting + private String directoryProvider; + + @Setting + private String indexBase; + + public String getDirectoryProvider() { + return directoryProvider; + } + + public void setDirectoryProvider(final String directoryProvider) { + this.directoryProvider = directoryProvider; + } + + public String getIndexBase() { + return indexBase; + } + + public void setIndexBase(final String indexBase) { + this.indexBase = indexBase; + } + + @Override + public int hashCode() { + int hash = 7; + hash = 83 * hash + Objects.hashCode(directoryProvider); + hash = 83 * hash + Objects.hashCode(indexBase); + return hash; + } + + @Override + public boolean equals(final Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (!(obj instanceof SearchConfig)) { + return false; + } + final SearchConfig other = (SearchConfig) obj; + if (!Objects.equals(this.directoryProvider, + other.getDirectoryProvider())) { + return false; + } + return Objects.equals(this.indexBase, other.getIndexBase()); + } + + @Override + public String toString() { + return String.format("%s{ " + + "directoryProvider = \"%s\", " + + "indexBase = \"%s\"" + + " }", + super.toString(), + directoryProvider, + indexBase); + } + +} diff --git a/ccm-core/src/main/java/org/libreccm/search/package-info.java b/ccm-core/src/main/java/org/libreccm/search/package-info.java new file mode 100644 index 000000000..c1216c5fc --- /dev/null +++ b/ccm-core/src/main/java/org/libreccm/search/package-info.java @@ -0,0 +1,22 @@ +/* + * 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 + */ +/** + * Provides configuration and other services for accessing Hibernate Search. + */ +package org.libreccm.search; diff --git a/ccm-core/src/main/java/org/libreccm/security/Role.java b/ccm-core/src/main/java/org/libreccm/security/Role.java index e6afa8e10..366a6c39f 100644 --- a/ccm-core/src/main/java/org/libreccm/security/Role.java +++ b/ccm-core/src/main/java/org/libreccm/security/Role.java @@ -262,15 +262,22 @@ public class Role implements Serializable { @Override public String toString() { +// return String.format("%s{ " +// + "roldId = %d, " +// + "name = \"%s\", " +// + "permissions = { %s }" +// + " }", +// super.toString(), +// roleId, +// name, +// Objects.toString(permissions)); return String.format("%s{ " + "roldId = %d, " + "name = \"%s\", " - + "permissions = { %s }" + " }", super.toString(), roleId, - name, - Objects.toString(permissions)); + name); } } diff --git a/ccm-core/src/main/java/org/libreccm/ui/admin/usersgroupsroles/RolesController.java b/ccm-core/src/main/java/org/libreccm/ui/admin/usersgroupsroles/RolesController.java index ec65651c6..2cb5961b1 100644 --- a/ccm-core/src/main/java/org/libreccm/ui/admin/usersgroupsroles/RolesController.java +++ b/ccm-core/src/main/java/org/libreccm/ui/admin/usersgroupsroles/RolesController.java @@ -43,6 +43,8 @@ public class RolesController { private final LazyDataModel tableModel; + private Role selectedRole; + public RolesController() { tableModel = new RolesTableModel(); } @@ -54,6 +56,16 @@ public class RolesController { public List getRoles() { return roleRepo.findAll(); } + + public Role getSelectedRole() { + return selectedRole; + } + + public void setSelectedRole(final Role selectedRole) { + this.selectedRole = selectedRole; + } + + private class RolesTableModel extends LazyDataModel { diff --git a/ccm-core/src/main/resources/META-INF/resources/admin-jsf/admin.xhtml b/ccm-core/src/main/resources/META-INF/resources/admin-jsf/admin.xhtml index 2734b6408..17c008002 100644 --- a/ccm-core/src/main/resources/META-INF/resources/admin-jsf/admin.xhtml +++ b/ccm-core/src/main/resources/META-INF/resources/admin-jsf/admin.xhtml @@ -64,7 +64,7 @@ - + + + + + + + + + + + + + + + + diff --git a/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources.properties b/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources.properties index 6c32b8ade..a1f8e802d 100644 --- a/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources.properties +++ b/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources.properties @@ -546,3 +546,4 @@ ui.admin.applications.new_instance_form.title=Create new instance ui.admin.applications.instance_table.heading=Instances ui.admin.applications.new_instance.primary_url=Primary URL ui.admin.applications.new_instance.primary_url.error.not_empty=The primary URL of an application instance can't be empty. +ui.admin.tab.users_groups_roles.edit=Edit role diff --git a/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_de.properties b/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_de.properties index 618bba6ce..fdb4a3cdb 100644 --- a/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_de.properties +++ b/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_de.properties @@ -550,3 +550,4 @@ ui.admin.applications.new_instance_form.title=Neue Instanz anlegen ui.admin.applications.instance_table.heading=Instanzen ui.admin.applications.new_instance.primary_url=Prim\u00e4re URL ui.admin.applications.new_instance.primary_url.error.not_empty=Die prim\u00e4re URL einer Applikations-Instanz kann nicht leer sein. +ui.admin.tab.users_groups_roles.edit=Rolle bearbeiten diff --git a/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_en.properties b/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_en.properties index f59005dfa..4aa255b0d 100755 --- a/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_en.properties +++ b/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_en.properties @@ -543,3 +543,4 @@ ui.admin.applications.new_instance_form.title=Create new instance ui.admin.applications.instance_table.heading=Instances ui.admin.applications.new_instance.primary_url=Primary URL ui.admin.applications.new_instance.primary_url.error.not_empty=The primary URL of an application instance can't be empty. +ui.admin.tab.users_groups_roles.edit=Edit role diff --git a/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_fr.properties b/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_fr.properties index 5aec9ccba..a2ff3b59a 100755 --- a/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_fr.properties +++ b/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_fr.properties @@ -534,3 +534,4 @@ ui.admin.applications.new_instance_form.title=Create new instance ui.admin.applications.instance_table.heading=Instances ui.admin.applications.new_instance.primary_url=Primary URL ui.admin.applications.new_instance.primary_url.error.not_empty=The primary URL of an application instance can't be empty. +ui.admin.tab.users_groups_roles.edit=Edit role diff --git a/ccm-core/src/main/resources/org/libreccm/search/SearchConfigDescription.properties b/ccm-core/src/main/resources/org/libreccm/search/SearchConfigDescription.properties new file mode 100644 index 000000000..c0886c5ec --- /dev/null +++ b/ccm-core/src/main/resources/org/libreccm/search/SearchConfigDescription.properties @@ -0,0 +1,7 @@ +description = Configuration for Hibernate Search. Some of the options here are directly applied to Hibernate Search. Please refer to the Hibernate Search documentation for details and valid values. Changes to these settings while become effective after a restart of LibreCCM. + +directoryProvider.label = Directory Provider +directoryProvider.description = The Lucene Directory provider used by Hibernate Search to store the search index. + +indexBase.label = Index Base +indexBase.description = Where the index is stored. diff --git a/pom.xml b/pom.xml index 788bc74c9..d644eaa12 100644 --- a/pom.xml +++ b/pom.xml @@ -270,6 +270,16 @@ 5.2.3.Final + + + org.hibernate + hibernate-search + 5.5.4.Final + +