001/*
002 * (C) Copyright 2014 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 *     bstefanescu
018 *     vpasquier <vpasquier@nuxeo.com>
019 */
020package org.nuxeo.ecm.automation.server.jaxrs;
021
022import java.io.IOException;
023import java.security.Principal;
024import java.util.HashSet;
025import java.util.List;
026
027import javax.mail.MessagingException;
028import javax.servlet.http.HttpServletRequest;
029import javax.servlet.http.HttpServletResponse;
030import javax.ws.rs.GET;
031import javax.ws.rs.POST;
032import javax.ws.rs.Path;
033import javax.ws.rs.PathParam;
034import javax.ws.rs.QueryParam;
035import javax.ws.rs.core.Context;
036import javax.ws.rs.core.Response;
037
038import org.nuxeo.ecm.automation.AutomationService;
039import org.nuxeo.ecm.automation.ConflictOperationException;
040import org.nuxeo.ecm.automation.OperationException;
041import org.nuxeo.ecm.automation.OperationNotFoundException;
042import org.nuxeo.ecm.automation.OperationType;
043import org.nuxeo.ecm.automation.core.Constants;
044import org.nuxeo.ecm.automation.jaxrs.LoginInfo;
045import org.nuxeo.ecm.automation.jaxrs.io.operations.AutomationInfo;
046import org.nuxeo.ecm.core.api.Blob;
047import org.nuxeo.ecm.core.api.CoreSession;
048import org.nuxeo.ecm.core.api.DocumentModel;
049import org.nuxeo.ecm.core.api.IdRef;
050import org.nuxeo.ecm.core.api.NuxeoPrincipal;
051import org.nuxeo.ecm.core.api.PropertyException;
052import org.nuxeo.ecm.platform.web.common.exceptionhandling.ExceptionHelper;
053import org.nuxeo.ecm.webengine.WebException;
054import org.nuxeo.ecm.webengine.jaxrs.session.SessionFactory;
055import org.nuxeo.ecm.webengine.model.WebObject;
056import org.nuxeo.ecm.webengine.model.impl.ModuleRoot;
057import org.nuxeo.runtime.api.Framework;
058
059/**
060 * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a>
061 */
062@Path("/automation")
063@WebObject(type = "automation")
064public class AutomationResource extends ModuleRoot {
065
066    protected AutomationService service;
067
068    public AutomationResource() {
069        this.service = Framework.getLocalService(AutomationService.class);
070    }
071
072    @Path("/doc")
073    public Object getDocPage() {
074        return newObject("doc");
075    }
076
077    @Path("/debug")
078    public Object getDebugPage() {
079        return newObject("debug");
080    }
081
082    /**
083     * Gets the content of the blob or blobs (multipart/mixed) located by the given doc uid and property path.
084     */
085    @SuppressWarnings("unchecked")
086    @GET
087    @Path("/files/{uid}")
088    public Object getFile(@Context HttpServletRequest request, @PathParam("uid") String uid,
089            @QueryParam("path") String path) {
090        try {
091            CoreSession session = SessionFactory.getSession(request);
092            DocumentModel doc = session.getDocument(new IdRef(uid));
093            Object obj = null;
094            try {
095                obj = doc.getPropertyValue(path);
096            } catch (PropertyException e) {
097                return ResponseHelper.notFound();
098            }
099            if (obj == null) {
100                return ResponseHelper.notFound();
101            }
102            if (obj instanceof List<?>) {
103                List<?> list = (List<?>) obj;
104                if (list.isEmpty()) {
105                    return ResponseHelper.notFound();
106                }
107                if (list.get(0) instanceof Blob) { // a list of blobs -> use
108                    // multipart/mixed
109                    return ResponseHelper.blobs((List<Blob>) list);
110                }
111            } else if (obj instanceof Blob) {
112                return ResponseHelper.blob((Blob) obj);
113            }
114            return ResponseHelper.notFound();
115        } catch (MessagingException | IOException e) {
116            throw WebException.newException(e);
117        }
118    }
119
120    @GET
121    public AutomationInfo doGet() throws OperationException {
122        return new AutomationInfo(service);
123    }
124
125    @POST
126    @Path("/login")
127    public Object login(@Context HttpServletRequest request) {
128        Principal p = request.getUserPrincipal();
129        if (p instanceof NuxeoPrincipal) {
130            NuxeoPrincipal np = (NuxeoPrincipal) p;
131            List<String> groups = np.getAllGroups();
132            HashSet<String> set = new HashSet<String>(groups);
133            return new LoginInfo(np.getName(), set, np.isAdministrator());
134        } else {
135            return Response.status(401).build();
136        }
137    }
138
139    @Path("/{oid}")
140    public Object getExecutable(@PathParam("oid") String oid) {
141        if (oid.startsWith(Constants.CHAIN_ID_PREFIX)) {
142            oid = oid.substring(6);
143            return new ChainResource(service, oid);
144        } else {
145            try {
146                OperationType op = service.getOperation(oid);
147                return new OperationResource(service, op);
148            } catch (OperationException cause) {
149                if (cause instanceof ConflictOperationException) {
150                    return WebException.newException("Failed to invoke operation: " + oid, cause,
151                            HttpServletResponse.SC_CONFLICT);
152                } else if (cause instanceof OperationNotFoundException) {
153                    return WebException.newException("Failed to invoke " + "operation: " + oid, cause,
154                            HttpServletResponse.SC_NOT_FOUND);
155                } else {
156                    Throwable unWrapException = ExceptionHelper.unwrapException(cause);
157                    if (unWrapException instanceof RestOperationException) {
158                        int customHttpStatus = ((RestOperationException) unWrapException).getStatus();
159                        throw WebException.newException("Failed to invoke operation: " + oid, cause, customHttpStatus);
160                    }
161                    throw WebException.newException("Failed to invoke operation: " + oid, cause);
162                }
163            }
164        }
165    }
166
167    @Path("/batch")
168    public Object getBatchManager() {
169        return newObject("batch");
170    }
171
172}