001/*
002 * (C) Copyright 2019 Nuxeo (http://nuxeo.com/) and others.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 *
016 * Contributors:
017 *     Salem Aouana
018 */
019
020package org.nuxeo.ecm.restapi.server.jaxrs.management;
021
022import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
023import static org.nuxeo.ecm.core.api.security.SecurityConstants.SYSTEM_USERNAME;
024import static org.nuxeo.elasticsearch.bulk.IndexAction.ACTION_NAME;
025import static org.nuxeo.elasticsearch.bulk.IndexAction.INDEX_UPDATE_ALIAS_PARAM;
026
027import javax.ws.rs.POST;
028import javax.ws.rs.Path;
029import javax.ws.rs.PathParam;
030import javax.ws.rs.Produces;
031import javax.ws.rs.QueryParam;
032
033import org.apache.commons.lang3.StringUtils;
034import org.nuxeo.ecm.core.bulk.BulkService;
035import org.nuxeo.ecm.core.bulk.message.BulkCommand;
036import org.nuxeo.ecm.core.bulk.message.BulkStatus;
037import org.nuxeo.ecm.core.query.sql.NXQL;
038import org.nuxeo.ecm.webengine.model.WebObject;
039import org.nuxeo.ecm.webengine.model.impl.AbstractResource;
040import org.nuxeo.ecm.webengine.model.impl.ResourceTypeImpl;
041import org.nuxeo.elasticsearch.api.ElasticSearchAdmin;
042import org.nuxeo.runtime.api.Framework;
043
044/**
045 * Endpoint to manage Elasticsearch.
046 *
047 * @since 11.3
048 */
049@WebObject(type = ManagementObject.MANAGEMENT_OBJECT_PREFIX + "elasticsearch")
050@Produces(APPLICATION_JSON)
051public class ElasticsearchObject extends AbstractResource<ResourceTypeImpl> {
052
053    public static final String GET_ALL_DOCUMENTS_QUERY = "SELECT * from Document";
054
055    /**
056     * Performs an ES indexing on documents matching the optional NXQL query.
057     *
058     * @see #performIndexing(String)
059     */
060    @POST
061    @Path("reindex")
062    public BulkStatus doIndexing(@QueryParam("query") String query) {
063        return performIndexing(query);
064    }
065
066    /**
067     * Performs an ES indexing on the given document and his children.
068     *
069     * @param documentId the id of the document that will be indexed and his children recursively
070     * @see #performIndexing(String)
071     */
072    @POST
073    @Path("{documentId}/reindex")
074    public BulkStatus doIndexingOnDocument(@PathParam("documentId") String documentId) {
075        String query = String.format("Select * From Document where %s = '%s' or %s = '%s'", //
076                NXQL.ECM_UUID, documentId, //
077                NXQL.ECM_ANCESTORID, documentId);
078
079        return performIndexing(query);
080    }
081
082    /**
083     * Executes an ES flush on document index of a given repository.
084     */
085    @POST
086    @Path("flush")
087    public void doFlush() {
088        Framework.doPrivileged(() -> Framework.getService(ElasticSearchAdmin.class)
089                                              .flushRepositoryIndex(ctx.getCoreSession().getRepositoryName()));
090    }
091
092    /**
093     * Executes an ES optimize on document index of a given repository.
094     */
095    @POST
096    @Path("optimize")
097    public void doOptimize() {
098        Framework.doPrivileged(() -> Framework.getService(ElasticSearchAdmin.class)
099                                              .optimizeRepositoryIndex(ctx.getCoreSession().getRepositoryName()));
100    }
101
102    /**
103     * Performs an ES indexing on documents matching the optional NXQL query.
104     *
105     * @param query the NXQL query that documents must match to be indexed, can be {@code null} or {@code empty}, in
106     *            this case all documents of the given repository will be indexed {@link #GET_ALL_DOCUMENTS_QUERY}
107     * @return the {@link BulkStatus} of the ES indexing
108     */
109    protected BulkStatus performIndexing(String query) {
110        String nxql = StringUtils.defaultIfBlank(query, GET_ALL_DOCUMENTS_QUERY);
111        BulkService bulkService = Framework.getService(BulkService.class);
112        String commandId = bulkService.submit(
113                new BulkCommand.Builder(ACTION_NAME, nxql, SYSTEM_USERNAME)
114                                                                           .repository(ctx.getCoreSession()
115                                                                                          .getRepositoryName())
116                                                                           .param(INDEX_UPDATE_ALIAS_PARAM, true)
117                                                                           .build());
118        return bulkService.getStatus(commandId);
119    }
120}