001/*
002 * (C) Copyright 2018 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 *     pierre
018 */
019package org.nuxeo.ecm.automation.core.operations.services.bulk;
020
021import java.io.IOException;
022
023import javax.servlet.http.HttpServletResponse;
024
025import org.nuxeo.ecm.automation.OperationException;
026import org.nuxeo.ecm.automation.core.Constants;
027import org.nuxeo.ecm.automation.core.annotations.Context;
028import org.nuxeo.ecm.automation.core.annotations.Operation;
029import org.nuxeo.ecm.automation.core.annotations.OperationMethod;
030import org.nuxeo.ecm.automation.core.annotations.Param;
031import org.nuxeo.ecm.automation.core.util.PageProviderHelper;
032import org.nuxeo.ecm.automation.core.util.Properties;
033import org.nuxeo.ecm.automation.core.util.StringList;
034import org.nuxeo.ecm.core.api.CoreSession;
035import org.nuxeo.ecm.core.api.NuxeoException;
036import org.nuxeo.ecm.core.bulk.BulkAdminService;
037import org.nuxeo.ecm.core.bulk.BulkService;
038import org.nuxeo.ecm.core.bulk.io.BulkParameters;
039import org.nuxeo.ecm.core.bulk.message.BulkCommand;
040import org.nuxeo.ecm.core.bulk.message.BulkStatus;
041import org.nuxeo.ecm.platform.query.api.PageProvider;
042import org.nuxeo.ecm.platform.query.api.PageProviderDefinition;
043import org.nuxeo.ecm.platform.query.api.PageProviderService;
044
045/**
046 * Automation operation that can run an http enabled Bulk Action.
047 *
048 * @since 10.2
049 */
050@Operation(id = BulkRunAction.ID, category = Constants.CAT_SERVICES, label = "Run a bulk command", addToStudio = true, description = "Run a bulk action on a set of documents expressed by a NXQL.")
051public class BulkRunAction {
052
053    public static final String ID = "Bulk.RunAction";
054
055    @Context
056    protected BulkService service;
057
058    @Context
059    protected BulkAdminService admin;
060
061    @Context
062    protected CoreSession session;
063
064    @Param(name = "query", required = false)
065    protected String query;
066
067    @Param(name = "providerName", required = false)
068    protected String providerName;
069
070    @Param(name = "queryParams", required = false)
071    protected StringList queryParams;
072
073    @Param(name = PageProviderService.NAMED_PARAMETERS, required = false, description = "Named parameters to pass to the page provider to "
074            + "fill in query variables.")
075    protected Properties namedParameters;
076
077    @Param(name = "quickFilters", required = false, description = "Quick filter " + "properties (separated by comma)")
078    protected StringList quickFilters;
079
080    @Param(name = "action", required = true)
081    protected String action;
082
083    @Param(name = "repositoryName", required = false)
084    protected String repositoryName;
085
086    @Param(name = "bucketSize", required = false)
087    protected int bucketSize;
088
089    @Param(name = "batchSize", required = false)
090    protected int batchSize;
091
092    @Param(name = "parameters", required = false)
093    protected String parametersAsJson;
094
095    @OperationMethod(asyncService = BulkService.class)
096    public BulkStatus run() throws IOException, OperationException {
097
098        if (!admin.getActions().contains(action)) {
099            throw new NuxeoException("Action '" + action + "' not found", HttpServletResponse.SC_NOT_FOUND);
100        }
101        if (!admin.isHttpEnabled(action) && !session.getPrincipal().isAdministrator()) {
102            throw new NuxeoException("Action '" + action + "' denied", HttpServletResponse.SC_FORBIDDEN);
103        }
104
105        if (query == null && providerName == null) {
106            throw new OperationException("Query and ProviderName cannot be both null");
107        }
108
109        PageProviderDefinition def = query != null ? PageProviderHelper.getQueryPageProviderDefinition(query)
110                : PageProviderHelper.getPageProviderDefinition(providerName);
111
112        if (def == null) {
113            throw new OperationException("Could not get Provider Definition from either query or provider name");
114        }
115
116        PageProvider<?> provider = PageProviderHelper.getPageProvider(session, def, namedParameters, null, null, null,
117                null, null, quickFilters, queryParams != null ? queryParams.toArray(new String[0]) : null);
118        query = PageProviderHelper.buildQueryStringWithAggregates(provider);
119
120        if (query.contains("?")) {
121            throw new OperationException("Query parameters could not be parsed");
122        }
123
124        BulkCommand.Builder builder = new BulkCommand.Builder(action, query, session.getPrincipal().getName());
125        try {
126            builder.params(BulkParameters.paramsToMap(parametersAsJson));
127        } catch (IOException e) {
128            throw new OperationException("Could not parse parameters, expecting valid json value", e);
129        }
130
131        if (repositoryName != null) {
132            builder.repository(repositoryName);
133        } else {
134            builder.repository(session.getRepositoryName());
135        }
136        if (bucketSize > 0) {
137            builder.bucket(bucketSize);
138        }
139        if (batchSize > 0) {
140            builder.batch(batchSize);
141        }
142        String commandId = service.submit(builder.build());
143        return service.getStatus(commandId);
144    }
145}