This is an automated email from the git hooks/post-receive script. New commit to branch develop in repository coselmar. See http://git.codelutin.com/coselmar.git commit 7ca25de491ca7ea6aa2d8ad9059777b51461880c Author: Yannick Martel <martel@©odelutin.com> Date: Wed Dec 31 18:00:37 2014 +0100 add an admin part to force a refresh on lucene index --- .../coselmar/converter/BeanEntityConverter.java | 2 +- .../coselmar/services/indexation/LuceneUtils.java | 5 ++ .../coselmar/services/v1/AdminWebService.java | 79 ++++++++++++++++++++++ coselmar-rest/src/main/resources/mapping | 2 + coselmar-ui/src/main/webapp/index.html | 1 + .../src/main/webapp/js/coselmar-admin-services.js | 50 ++++++++++++++ .../src/main/webapp/js/coselmar-controllers.js | 24 +++++++ coselmar-ui/src/main/webapp/js/coselmar.js | 5 ++ .../src/main/webapp/views/admin/admintools.html | 55 +++++++++++++++ 9 files changed, 222 insertions(+), 1 deletion(-) diff --git a/coselmar-rest/src/main/java/fr/ifremer/coselmar/converter/BeanEntityConverter.java b/coselmar-rest/src/main/java/fr/ifremer/coselmar/converter/BeanEntityConverter.java index 1192d6e..950ca54 100644 --- a/coselmar-rest/src/main/java/fr/ifremer/coselmar/converter/BeanEntityConverter.java +++ b/coselmar-rest/src/main/java/fr/ifremer/coselmar/converter/BeanEntityConverter.java @@ -251,7 +251,7 @@ public class BeanEntityConverter { Collection<Question> parents = question.getParents(); if (parents != null && !parents.isEmpty()) { for (Question parent : parents) { - QuestionBean questionBean = toBean(idFactory, parent); + QuestionBean questionBean = toLightBean(idFactory, parent); result.addParent(questionBean); } } diff --git a/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/indexation/LuceneUtils.java b/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/indexation/LuceneUtils.java index 5eeff68..19f762e 100644 --- a/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/indexation/LuceneUtils.java +++ b/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/indexation/LuceneUtils.java @@ -48,4 +48,9 @@ public class LuceneUtils { return indexWriter; } + public void clearIndex() throws IOException { + getIndexWriter().deleteAll(); + getIndexWriter().commit(); + } + } diff --git a/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/v1/AdminWebService.java b/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/v1/AdminWebService.java new file mode 100644 index 0000000..57f606e --- /dev/null +++ b/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/v1/AdminWebService.java @@ -0,0 +1,79 @@ +package fr.ifremer.coselmar.services.v1; + +import java.io.IOException; +import java.util.List; + +import fr.ifremer.coselmar.beans.DocumentBean; +import fr.ifremer.coselmar.beans.QuestionBean; +import fr.ifremer.coselmar.beans.UserWebToken; +import fr.ifremer.coselmar.converter.BeanEntityConverter; +import fr.ifremer.coselmar.persistence.entity.CoselmarUserRole; +import fr.ifremer.coselmar.persistence.entity.Document; +import fr.ifremer.coselmar.persistence.entity.Question; +import fr.ifremer.coselmar.services.CoselmarTechnicalException; +import fr.ifremer.coselmar.services.CoselmarWebServiceSupport; +import fr.ifremer.coselmar.services.errors.InvalidCredentialException; +import fr.ifremer.coselmar.services.errors.UnauthorizedException; +import fr.ifremer.coselmar.services.indexation.DocumentsIndexationService; +import fr.ifremer.coselmar.services.indexation.QuestionsIndexationService; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.logging.Log; + +import static org.apache.commons.logging.LogFactory.getLog; + +/** + * @author ymartel <martel@codelutin.com> + */ +public class AdminWebService extends CoselmarWebServiceSupport { + + private static final Log log = getLog(AdminWebService.class); + + public void refreshLuceneIndex() throws UnauthorizedException, InvalidCredentialException { + + // Check authentication + String authorization = getContext().getHeader("Authorization"); + UserWebToken userWebToken = checkAuthentication(authorization); + + // Who is allowed here ? Admin and user himself + if (!StringUtils.equals(userWebToken.getRole(), CoselmarUserRole.ADMIN.name())) { + if (log.isDebugEnabled()) { + String message = String.format("A non admin user try to refresh lucene index."); + log.debug(message); + } + throw new UnauthorizedException("Not allowed to execute operation"); + } + + + DocumentsIndexationService documentsIndexationService = getServicesContext().newService(DocumentsIndexationService.class); + QuestionsIndexationService questionsIndexationService = getServicesContext().newService(QuestionsIndexationService.class); + try { + getServicesContext().getLuceneUtils().clearIndex(); + + // get All documents + List<Document> documents = getDocumentDao().findAll(); + for (Document document : documents) { + String lightId = getPersistenceContext().getTopiaIdFactory().getRandomPart(document.getTopiaId()); + DocumentBean documentBean = BeanEntityConverter.toBean(lightId, document); + documentsIndexationService.indexDocument(documentBean); + } + + // Get all questions + List<Question> questions = getQuestionDao().findAll(); + for (Question question : questions) { + QuestionBean questionBean = BeanEntityConverter.toLightBean(getPersistenceContext().getTopiaIdFactory(), question); + questionsIndexationService.indexQuestion(questionBean); + } + + if (log.isDebugEnabled()) { + String message = String.format("Index was refreshed"); + log.debug(message); + } + } catch (IOException e) { + if (log.isErrorEnabled()) { + log.error("Unable to index new document", e); + } + throw new CoselmarTechnicalException("Error during Index Refresh", e); + } + } + +} diff --git a/coselmar-rest/src/main/resources/mapping b/coselmar-rest/src/main/resources/mapping index 7bd7fe3..a2494e8 100644 --- a/coselmar-rest/src/main/resources/mapping +++ b/coselmar-rest/src/main/resources/mapping @@ -58,3 +58,5 @@ POST /v1/questions/{questionId}/documents QuestionsWebService.addDocuments POST /v1/questions QuestionsWebService.addQuestion DELETE /v1/questions/{questionId} QuestionsWebService.deleteQuestion +# Admin API +POST /v1/admin/lucene/index AdminWebService.refreshLuceneIndex \ No newline at end of file diff --git a/coselmar-ui/src/main/webapp/index.html b/coselmar-ui/src/main/webapp/index.html index 5f08ce1..518ab6e 100644 --- a/coselmar-ui/src/main/webapp/index.html +++ b/coselmar-ui/src/main/webapp/index.html @@ -49,6 +49,7 @@ <script src="js/coselmar-services.js"></script> <script src="js/coselmar-user-services.js"></script> <script src="js/coselmar-questions-services.js"></script> + <script src="js/coselmar-admin-services.js"></script> </head> <body> diff --git a/coselmar-ui/src/main/webapp/js/coselmar-admin-services.js b/coselmar-ui/src/main/webapp/js/coselmar-admin-services.js new file mode 100644 index 0000000..77a8820 --- /dev/null +++ b/coselmar-ui/src/main/webapp/js/coselmar-admin-services.js @@ -0,0 +1,50 @@ +/* + * #%L + * Coselmar :: UI + * $Id:$ + * $HeadURL:$ + * %% + * Copyright (C) 2014 Ifremer, Code Lutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/gpl-3.0.html>. + * #L% + */ +coselmarServices.factory('adminService', ['$resource', 'coselmar-config', function($resource, coselmarConfig){ + return new Admin($resource, coselmarConfig); +}]); + +function Admin(resource, config){ + + + this.resource = resource; + + var baseURL = config.BASE_URL + "/admin"; + + this.refreshIndex = function(successFunction, failFunction){ + + var serviceURL = baseURL + "/lucene/index"; + // Refresh Lucene Index + var adminResource = resource(serviceURL, null, { + 'refresh': { + method: 'POST', + headers : { + 'Content-Type' : 'application/x-www-form-urlencoded' + }, + }}); + + adminResource.save(null, successFunction, failFunction); + } + +}; \ No newline at end of file diff --git a/coselmar-ui/src/main/webapp/js/coselmar-controllers.js b/coselmar-ui/src/main/webapp/js/coselmar-controllers.js index 90be132..d5d2306 100644 --- a/coselmar-ui/src/main/webapp/js/coselmar-controllers.js +++ b/coselmar-ui/src/main/webapp/js/coselmar-controllers.js @@ -863,6 +863,30 @@ coselmarControllers.controller("ReferentialCtrl", ['$scope', '$routeParams', '$l }]); +///////////////////////////////////////////////// +////////////// Admin Part ///////////////////// +///////////////////////////////////////////////// + +// Controller for Admin Page +coselmarControllers.controller("AdminCtrl", ['$scope', '$routeParams', '$location', 'adminService', + function($scope, $routeParams, $location, adminService){ + + $scope.status = { 'indexRefresh' : 'none'}; + + $scope.refreshIndex = function() { + $scope.status.indexRefresh = "inprogress"; + + adminService.refreshIndex(function() { + $scope.status.indexRefresh = "finish"; + + },function(error) { + $scope.status.indexRefresh = "error"; + }); + + }; + +}]); + /** * AngularJS default filter with the following expression: * "person in people | filter: {name: $select.search, age: $select.search}" diff --git a/coselmar-ui/src/main/webapp/js/coselmar.js b/coselmar-ui/src/main/webapp/js/coselmar.js index 3fe1d28..6b91cf6 100644 --- a/coselmar-ui/src/main/webapp/js/coselmar.js +++ b/coselmar-ui/src/main/webapp/js/coselmar.js @@ -69,6 +69,11 @@ coselmarApp.config(['$routeProvider', function($routeProvider) { controller : 'ReferentialCtrl', templateUrl : 'views/referential/referential.html' + // Admin tools + }).when('/admin', { + controller : 'AdminCtrl', + templateUrl : 'views/admin/admintools.html' + // Error pages }).when('/404', { templateUrl : 'views/errors/404.html' diff --git a/coselmar-ui/src/main/webapp/views/admin/admintools.html b/coselmar-ui/src/main/webapp/views/admin/admintools.html new file mode 100644 index 0000000..09779c9 --- /dev/null +++ b/coselmar-ui/src/main/webapp/views/admin/admintools.html @@ -0,0 +1,55 @@ +<!-- + #%L + Coselmar :: UI + $Id:$ + $HeadURL:$ + %% + Copyright (C) 2014 Ifremer, Code Lutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public + License along with this program. If not, see + <http://www.gnu.org/licenses/gpl-3.0.html>. + #L% + --> +<div style="padding: 0px 0px 0px 30px"> + <div class="page-header" style="margin: 0"> + <h1> + <!-- Heading goes here --> + Admin Tools + </h1> + </div> + + <div class="form-group"> + <div class="form-group"> + + <label class="col-md-5 control-label">Refresh Search Index</label> + + <div class="col-md-7 "> + <a class="form-inline btn btn-primary" ng-click="refreshIndex()">Refresh !</a> + </div> + </div> + + <div ng-show="status.indexRefresh != 'none'" > + <div ng-show="status.indexRefresh === 'inprogress'"> + Refresh in progress. + </div> + <div ng-show="status.indexRefresh === 'finish'"> + Search index has been well refreshed ! + </div> + <div ng-show="status.indexRefresh === 'error'"> + Error during search index refresh. Please try again. If problem persist, see server administrator. + </div> + </div> + <br/> + </div> +</div> \ No newline at end of file -- To stop receiving notification emails like this one, please contact codelutin.com SCM administrator <admin+scm@codelutin.com>.