[ofbiz-plugins] branch trunk updated: Implemented: Add support to read and register resources defined in XML DSL(OFBIZ-11995)

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

[ofbiz-plugins] branch trunk updated: Implemented: Add support to read and register resources defined in XML DSL(OFBIZ-11995)

grv-2
This is an automated email from the ASF dual-hosted git repository.

grv pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/ofbiz-plugins.git


The following commit(s) were added to refs/heads/trunk by this push:
     new 6ac1f28  Implemented: Add support to read and register resources defined in XML DSL(OFBIZ-11995)
6ac1f28 is described below

commit 6ac1f284915ff1de659bda944e26b90bdab2f75c
Author: Girish Vasmatkar <[hidden email]>
AuthorDate: Wed Sep 16 18:21:27 2020 +0530

    Implemented: Add support to read and register resources defined in XML DSL(OFBIZ-11995)
---
 .../apache/ofbiz/ws/rs/core/OFBizApiConfig.java    |  40 ++++
 .../ofbiz/ws/rs/process/RestRequestHandler.java    | 256 +++++++++++++++++++++
 .../ofbiz/ws/rs/process/ServiceRequestHandler.java | 102 ++++++++
 3 files changed, 398 insertions(+)

diff --git a/ofbiz-rest-impl/src/main/java/org/apache/ofbiz/ws/rs/core/OFBizApiConfig.java b/ofbiz-rest-impl/src/main/java/org/apache/ofbiz/ws/rs/core/OFBizApiConfig.java
index 911c880..5a168fe 100644
--- a/ofbiz-rest-impl/src/main/java/org/apache/ofbiz/ws/rs/core/OFBizApiConfig.java
+++ b/ofbiz-rest-impl/src/main/java/org/apache/ofbiz/ws/rs/core/OFBizApiConfig.java
@@ -21,19 +21,29 @@ package org.apache.ofbiz.ws.rs.core;
 import java.io.File;
 import java.util.Collection;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
+import javax.ws.rs.core.MediaType;
+
 import org.apache.ofbiz.base.component.ComponentConfig;
 import org.apache.ofbiz.base.component.ComponentException;
 import org.apache.ofbiz.base.util.Debug;
+import org.apache.ofbiz.base.util.UtilValidate;
 import org.apache.ofbiz.ws.rs.model.ModelApi;
 import org.apache.ofbiz.ws.rs.model.ModelApiReader;
+import org.apache.ofbiz.ws.rs.model.ModelOperation;
+import org.apache.ofbiz.ws.rs.model.ModelResource;
+import org.apache.ofbiz.ws.rs.process.ServiceRequestHandler;
+import org.apache.ofbiz.ws.rs.security.Secured;
 import org.glassfish.jersey.jackson.JacksonFeature;
 import org.glassfish.jersey.logging.LoggingFeature;
 import org.glassfish.jersey.media.multipart.MultiPartFeature;
 import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.model.Resource;
+import org.glassfish.jersey.server.model.ResourceMethod;
 
 public class OFBizApiConfig extends ResourceConfig {
     private static final String MODULE = OFBizApiConfig.class.getName();
@@ -58,6 +68,7 @@ public class OFBizApiConfig extends ResourceConfig {
 
     private void registerDSLResources() {
         loadApiDefinitions();
+        traverseAndRegisterApiDefinitions();
     }
 
     private void loadApiDefinitions() {
@@ -78,4 +89,33 @@ public class OFBizApiConfig extends ResourceConfig {
             }
         });
     }
+
+    private void traverseAndRegisterApiDefinitions() {
+        if (UtilValidate.isEmpty(MICRO_APIS)) {
+            Debug.logInfo("No API defintion to process", MODULE);
+            return;
+        }
+        MICRO_APIS.forEach((k, v) -> {
+            Debug.logInfo("Registring Resource Definitions from API - " + k, MODULE);
+            List<ModelResource> resources = v.getResources();
+            resources.forEach(modelResource -> {
+                Resource.Builder resourceBuilder = Resource.builder(modelResource.getPath()).name(modelResource.getName());
+                for (ModelOperation op : modelResource.getOperations()) {
+                    if (UtilValidate.isEmpty(op.getPath())) { // Add the method to the parent resource
+                        ResourceMethod.Builder methodBuilder = resourceBuilder.addMethod(op.getVerb().toUpperCase());
+                        methodBuilder.produces(MediaType.APPLICATION_JSON).nameBindings(Secured.class);
+                        String serviceName = op.getService();
+                        methodBuilder.handledBy(new ServiceRequestHandler(serviceName));
+                    } else {
+                        Resource.Builder childResourceBuilder = resourceBuilder.addChildResource(op.getPath());
+                        ResourceMethod.Builder childResourceMethodBuilder = childResourceBuilder.addMethod(op.getVerb().toUpperCase());
+                        childResourceMethodBuilder.produces(MediaType.APPLICATION_JSON).nameBindings(Secured.class);
+                        String serviceName = op.getService();
+                        childResourceMethodBuilder.handledBy(new ServiceRequestHandler(serviceName));
+                    }
+                }
+                registerResources(resourceBuilder.build());
+            });
+        });
+    }
 }
diff --git a/ofbiz-rest-impl/src/main/java/org/apache/ofbiz/ws/rs/process/RestRequestHandler.java b/ofbiz-rest-impl/src/main/java/org/apache/ofbiz/ws/rs/process/RestRequestHandler.java
new file mode 100644
index 0000000..0309cdf
--- /dev/null
+++ b/ofbiz-rest-impl/src/main/java/org/apache/ofbiz/ws/rs/process/RestRequestHandler.java
@@ -0,0 +1,256 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *******************************************************************************/
+package org.apache.ofbiz.ws.rs.process;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.inject.Inject;
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.HttpMethod;
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.ResourceInfo;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+
+import org.apache.ofbiz.base.util.UtilValidate;
+import org.glassfish.jersey.message.internal.MediaTypes;
+import org.glassfish.jersey.process.Inflector;
+import org.glassfish.jersey.server.ContainerRequest;
+import org.glassfish.jersey.server.ExtendedUriInfo;
+
+public abstract class RestRequestHandler implements Inflector<ContainerRequestContext, Response> {
+
+    @Inject
+    private HttpHeaders httpHeaders;
+
+    @Inject
+    private UriInfo uriInfo;
+
+    @Inject
+    private ExtendedUriInfo extendedUriInfo;
+
+    @Inject
+    private ResourceInfo resourceInfo;
+
+    @Inject
+    private ServletContext servletContext;
+
+    @Inject
+    private HttpServletRequest httpRequest;
+
+    /**
+     * @return the httpHeaders
+     */
+    protected HttpHeaders getHttpHeaders() {
+        return httpHeaders;
+    }
+
+    /**
+     * @return the uriInfo
+     */
+    protected UriInfo getUriInfo() {
+        return uriInfo;
+    }
+
+    /**
+     * @return the extendedUriInfo
+     */
+    protected ExtendedUriInfo getExtendedUriInfo() {
+        return extendedUriInfo;
+    }
+
+    /**
+     * @return the resourceInfo
+     */
+    protected ResourceInfo getResourceInfo() {
+        return resourceInfo;
+    }
+
+    /**
+     * @return the servletContext
+     */
+    protected ServletContext getServletContext() {
+        return servletContext;
+    }
+
+    /**
+     * @return the httpRequest
+     */
+    protected HttpServletRequest getHttpRequest() {
+        return httpRequest;
+    }
+
+    /**
+     * @param ctx
+     * @return
+     */
+    @Override
+    public Response apply(ContainerRequestContext ctx) {
+        // TODO Auto-generated method stub
+        String method = ctx.getMethod();
+        switch (method) {
+        case HttpMethod.POST:
+            return doPost(ctx);
+        case HttpMethod.GET:
+            return doGet(ctx);
+        case HttpMethod.DELETE:
+            return doDelete(ctx);
+        case HttpMethod.PUT:
+            return doPut(ctx);
+        case HttpMethod.PATCH:
+            return doPatch(ctx);
+        }
+        return null;
+    }
+
+    /**
+     * @param data
+     * @param arguments
+     * @return
+     */
+    protected abstract Response execute(ContainerRequestContext data, Map<String, Object> arguments);
+
+    /**
+     * @param requestContext
+     * @return
+     */
+    @SuppressWarnings("unchecked")
+    protected Map<String, Object> extractRequestBody(ContainerRequestContext requestContext) {
+        if (requestContext instanceof ContainerRequest) {
+            ContainerRequest request = (ContainerRequest) requestContext;
+            if (requestContext.hasEntity()) {
+                request.bufferEntity();
+                if (isJson(requestContext)) {
+                    Map<String, Object> entity = request.readEntity(Map.class);
+                    if (entity == null) {
+                        return Collections.emptyMap();
+                    }
+                    return entity;
+                }
+            }
+        }
+        return Collections.emptyMap();
+    }
+
+    /**
+     * @param requestContext
+     * @return
+     */
+    protected Map<String, Object> extractPathParameters(ContainerRequestContext requestContext) {
+        return extract(requestContext.getUriInfo().getPathParameters());
+    }
+
+    /**
+     * @param requestContext
+     * @return
+     */
+    protected Map<String, Object> extractQueryParameters(ContainerRequestContext requestContext) {
+        return extract(requestContext.getUriInfo().getQueryParameters());
+    }
+
+    /**
+     * @param multivaluedMap
+     * @return
+     */
+    protected Map<String, Object> extract(MultivaluedMap<String, String> multivaluedMap) {
+        Map<String, Object> result = new HashMap<>();
+        multivaluedMap.forEach((name, values) -> {
+            if (UtilValidate.isNotEmpty(values)) {
+                result.put(name, (values.size() != 1) ? values : values.get(0));
+            }
+        });
+        return result;
+    }
+
+    /**
+     * @param requestContext
+     * @return
+     */
+    private boolean isJson(ContainerRequestContext requestContext) {
+        final MediaType mediaType = requestContext.getMediaType();
+        if (UtilValidate.isNotEmpty(mediaType) && MediaTypes.typeEqual(mediaType, MediaType.APPLICATION_JSON_TYPE)) {
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * @param requestContext
+     * @return
+     */
+    private Response doGet(ContainerRequestContext requestContext) {
+        Map<String, Object> arguments = new HashMap<>();
+        arguments.putAll(extractPathParameters(requestContext));
+        arguments.putAll(extractQueryParameters(requestContext));
+        return execute(requestContext, arguments);
+    }
+
+    /**
+     * @param requestContext
+     * @return
+     */
+    private Response doPost(ContainerRequestContext requestContext) {
+        Map<String, Object> arguments = new HashMap<>();
+        arguments.putAll(extractRequestBody(requestContext));
+        arguments.putAll(extractPathParameters(requestContext));
+        arguments.putAll(extractQueryParameters(requestContext));
+        return execute(requestContext, arguments);
+    }
+
+    /**
+     * @param requestContext
+     * @return
+     */
+    private Response doPut(ContainerRequestContext requestContext) {
+        Map<String, Object> arguments = new HashMap<>();
+        arguments.putAll(extractRequestBody(requestContext));
+        arguments.putAll(extractPathParameters(requestContext));
+        arguments.putAll(extractQueryParameters(requestContext));
+        return execute(requestContext, arguments);
+    }
+
+    /**
+     * @param requestContext
+     * @return
+     */
+    private Response doPatch(ContainerRequestContext requestContext) {
+        Map<String, Object> arguments = new HashMap<>();
+        arguments.putAll(extractRequestBody(requestContext));
+        arguments.putAll(extractPathParameters(requestContext));
+        arguments.putAll(extractQueryParameters(requestContext));
+        return execute(requestContext, arguments);
+    }
+
+    /**
+     * @param requestContext
+     * @return
+     */
+    private Response doDelete(ContainerRequestContext requestContext) {
+        Map<String, Object> arguments = new HashMap<>();
+        arguments.putAll(extractPathParameters(requestContext));
+        arguments.putAll(extractQueryParameters(requestContext));
+        return execute(requestContext, arguments);
+    }
+}
diff --git a/ofbiz-rest-impl/src/main/java/org/apache/ofbiz/ws/rs/process/ServiceRequestHandler.java b/ofbiz-rest-impl/src/main/java/org/apache/ofbiz/ws/rs/process/ServiceRequestHandler.java
new file mode 100644
index 0000000..51ce63b
--- /dev/null
+++ b/ofbiz-rest-impl/src/main/java/org/apache/ofbiz/ws/rs/process/ServiceRequestHandler.java
@@ -0,0 +1,102 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *******************************************************************************/
+package org.apache.ofbiz.ws.rs.process;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Set;
+
+import javax.ws.rs.InternalServerErrorException;
+import javax.ws.rs.NotFoundException;
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.core.Response;
+
+import org.apache.ofbiz.base.util.UtilValidate;
+import org.apache.ofbiz.entity.GenericValue;
+import org.apache.ofbiz.service.DispatchContext;
+import org.apache.ofbiz.service.GenericServiceException;
+import org.apache.ofbiz.service.LocalDispatcher;
+import org.apache.ofbiz.service.ModelParam;
+import org.apache.ofbiz.service.ModelService;
+import org.apache.ofbiz.service.ServiceUtil;
+import org.apache.ofbiz.ws.rs.util.RestApiUtil;
+
+public final class ServiceRequestHandler extends RestRequestHandler {
+
+    private String service;
+
+    public ServiceRequestHandler(String service) {
+        this.service = service;
+    }
+
+    /**
+     * @param data
+     * @return
+     * @throws GenericServiceException
+     */
+    @Override
+    protected Response execute(ContainerRequestContext data, Map<String, Object> arguments) {
+        LocalDispatcher dispatcher = (LocalDispatcher) getServletContext().getAttribute("dispatcher");
+        Map<String, Object> serviceContext = null;
+        try {
+            serviceContext = dispatcher.getDispatchContext().makeValidContext(service, ModelService.IN_PARAM,
+                    arguments);
+        } catch (GenericServiceException e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+        }
+        ModelService svc = getModelService(dispatcher.getDispatchContext());
+        GenericValue userLogin = (GenericValue) getHttpRequest().getAttribute("userLogin");
+        serviceContext.put("userLogin", userLogin);
+        Map<String, Object> result = null;
+        try {
+            result = dispatcher.runSync(service, serviceContext);
+        } catch (GenericServiceException e) {
+            throw new InternalServerErrorException(e.getMessage());
+        }
+        Map<String, Object> responseData = new LinkedHashMap<>();
+        if (ServiceUtil.isSuccess(result)) {
+            Set<String> outParams = svc.getOutParamNames();
+            for (String outParamName : outParams) {
+                ModelParam outParam = svc.getParam(outParamName);
+                if (!outParam.isInternal()) {
+                    Object value = result.get(outParamName);
+                    if (UtilValidate.isNotEmpty(value)) {
+                        responseData.put(outParamName, value);
+                    }
+                }
+            }
+            return RestApiUtil.success((String) result.get(ModelService.SUCCESS_MESSAGE), responseData);
+        } else {
+            return RestApiUtil.error(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(),
+                    Response.Status.INTERNAL_SERVER_ERROR.getReasonPhrase(),
+                    (String) result.get(ModelService.ERROR_MESSAGE));
+        }
+    }
+
+    private ModelService getModelService(DispatchContext dispatchContext) {
+        ModelService svc = null;
+        try {
+            svc = dispatchContext.getModelService(service);
+        } catch (GenericServiceException gse) {
+            throw new NotFoundException(gse.getMessage());
+        }
+        return svc;
+    }
+}