001/*
002 * (C) Copyright 2013 Nuxeo SA (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 *     dmetzler
018 */
019package org.nuxeo.ecm.restapi.server.jaxrs.adapters;
020
021import javax.servlet.http.HttpServletRequest;
022import javax.servlet.http.HttpServletResponse;
023import javax.ws.rs.POST;
024import javax.ws.rs.Path;
025import javax.ws.rs.PathParam;
026import javax.ws.rs.Produces;
027import javax.ws.rs.core.Context;
028import javax.ws.rs.core.MediaType;
029import javax.ws.rs.core.Response;
030
031import org.nuxeo.ecm.automation.AutomationService;
032import org.nuxeo.ecm.automation.OperationChain;
033import org.nuxeo.ecm.automation.OperationContext;
034import org.nuxeo.ecm.automation.OperationException;
035import org.nuxeo.ecm.automation.OperationType;
036import org.nuxeo.ecm.automation.core.impl.ChainTypeImpl;
037import org.nuxeo.ecm.automation.core.impl.InvokableMethod;
038import org.nuxeo.ecm.automation.jaxrs.io.operations.ExecutionRequest;
039import org.nuxeo.ecm.automation.server.AutomationServer;
040import org.nuxeo.ecm.automation.server.jaxrs.ResponseHelper;
041import org.nuxeo.ecm.automation.server.jaxrs.RestOperationException;
042import org.nuxeo.ecm.core.api.NuxeoException;
043import org.nuxeo.ecm.platform.web.common.exceptionhandling.ExceptionHelper;
044import org.nuxeo.ecm.webengine.model.WebAdapter;
045import org.nuxeo.ecm.webengine.model.impl.DefaultAdapter;
046import org.nuxeo.runtime.api.Framework;
047
048/**
049 * @since 5.7.2 - Web adapter that expose how to run an operation on a document
050 */
051@WebAdapter(name = OperationAdapter.NAME, type = "OperationService")
052@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_JSON + "+esentity" })
053public class OperationAdapter extends DefaultAdapter {
054
055    public static final String NAME = "op";
056
057    @SuppressWarnings("resource") // ExecutionRequest's OperationContext not owned by us, don't close it
058    @POST
059    @Path("{operationName}")
060    public Response doPost(@PathParam("operationName") String oid, @Context HttpServletRequest request,
061            @Context HttpServletResponse response, ExecutionRequest xreq) {
062        try {
063            AutomationServer srv = Framework.getService(AutomationServer.class);
064            if (!srv.accept(oid, false, request)) {
065                return ResponseHelper.notFound();
066            }
067
068            AutomationService service = Framework.getService(AutomationService.class);
069
070            OperationType operationType = service.getOperation(oid);
071
072            // If chain, taking the first operation to do the input lookup after
073            if (operationType instanceof ChainTypeImpl) {
074                OperationChain chain = ((ChainTypeImpl) operationType).getChain();
075                if (!chain.getOperations().isEmpty()) {
076                    operationType = service.getOperation(chain.getOperations().get(0).id());
077                } else {
078                    throw new NuxeoException("Chain '" + oid + "' doesn't contain any operation");
079                }
080            }
081
082            for (InvokableMethod method : operationType.getMethods()) {
083                if (getTarget().getAdapter(method.getInputType()) != null) {
084                    xreq.setInput(getTarget().getAdapter(method.getInputType()));
085                    break;
086                }
087            }
088
089            // ExecutionRequest's OperationContext not owned by us, don't close it
090            OperationContext ctx = xreq.createContext(request, response, getContext().getCoreSession());
091            Object result = service.run(ctx, oid, xreq.getParams());
092
093            int customHttpStatus = xreq.getRestOperationContext().getHttpStatus();
094            return Response.status(customHttpStatus).entity(result).build();
095        } catch (OperationException cause) {
096            if (ExceptionHelper.unwrapException(cause) instanceof RestOperationException) {
097                int customHttpStatus = ((RestOperationException) ExceptionHelper.unwrapException(cause)).getStatus();
098                throw new NuxeoException("Failed to invoke operation: " + oid, cause, customHttpStatus);
099            }
100            throw new NuxeoException("Failed to invoke operation: " + oid, cause);
101        }
102
103    }
104
105}