All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.fabric3.management.rest.runtime.MarshallerImpl Maven / Gradle / Ivy

The newest version!
/*
 * Fabric3
 * Copyright (c) 2009-2015 Metaform Systems
 *
 * Licensed 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.fabric3.management.rest.runtime;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;

import org.fabric3.api.annotation.monitor.Monitor;
import org.fabric3.api.host.Fabric3Exception;
import org.fabric3.management.rest.Constants;
import org.fabric3.management.rest.model.HttpStatus;
import org.fabric3.management.rest.model.Resource;
import org.fabric3.management.rest.model.ResourceException;
import org.fabric3.management.rest.model.SelfLink;
import org.fabric3.management.rest.spi.ResourceMapping;
import org.fabric3.management.rest.spi.Verb;
import org.fabric3.spi.transform.Transformer;

/**
 *
 */
public class MarshallerImpl implements Marshaller {
    private ManagementMonitor monitor;

    public MarshallerImpl(@Monitor ManagementMonitor monitor) {
        this.monitor = monitor;
    }

    public Object[] deserialize(Verb verb, HttpServletRequest request, ResourceMapping mapping) throws ResourceException {
        Object[] params = null;
        Class[] types = mapping.getMethod().getParameterTypes();
        if (types.length > 0) {
            // skip deserialization if the method does not take parameters
            if (verb == Verb.GET || verb == Verb.DELETE) {
                params = deserializeUrlParams(request, mapping);
            } else if (verb == Verb.PUT | verb == Verb.POST) {
                params = deserializeInputStream(request, mapping);
            }
        }
        return params;
    }

    public void serialize(Object value, ResourceMapping mapping, HttpServletRequest request, HttpServletResponse response) throws ResourceException {
        ClassLoader loader = mapping.getInstance().getClass().getClassLoader();
        try {
            Resource resource;
            if (value instanceof Resource) {
                resource = (Resource) value;
                if (resource.getSelfLink() == null) {
                    // set the resource self-link if it has not been
                    URL url = new URL(request.getRequestURL().toString());
                    SelfLink link = new SelfLink(url);
                    resource.setSelfLink(link);
                }
            } else {
                URL url = new URL(request.getRequestURL().toString());
                SelfLink link = new SelfLink(url);
                resource = new Resource(link);
                resource.setProperty("value", value);
            }
            byte[] output = mapping.getPair().getSerializer().transform(resource, loader);
            response.getOutputStream().write(output);
        } catch (Fabric3Exception e) {
            Method method = mapping.getMethod();
            monitor.error("Error serializing response for " + method, e);
            throw new ResourceException(HttpStatus.INTERNAL_SERVER_ERROR);
        } catch (MalformedURLException e) {
            monitor.error("Error creating URL for " + request.getRequestURL(), e);
            throw new ResourceException(HttpStatus.INTERNAL_SERVER_ERROR);
        } catch (IOException e) {
            monitor.error("Error opening response output stream", e);
            throw new ResourceException(HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }


    /**
     * Deserializes resource parameters from a request URL.
     *
     * @param mapping the resource mapping
     * @param request the current request
     * @return the deserialized request body
     * @throws ResourceException if an error handling the request occurs
     */
    private Object[] deserializeUrlParams(HttpServletRequest request, ResourceMapping mapping) throws ResourceException {
        Method method = mapping.getMethod();
        Class[] types = method.getParameterTypes();
        if (types.length == 1 && HttpServletRequest.class.isAssignableFrom(types[0])) {
            // if the parameter is HttpServletRequest, short-circuit deserialization
            return new Object[]{request};
        } else if (types.length == 1) {
            // parameters are encoded in the request URL
            StringBuffer requestUrl = request.getRequestURL();
            int pos = requestUrl.lastIndexOf("/");
            if (pos < 0) {
                throw new ResourceException(HttpStatus.BAD_REQUEST, "Expected parameterized URL: " + requestUrl);
            }
            String value = requestUrl.substring(pos + 1);
            if (value.length() == 0) {
                throw new ResourceException(HttpStatus.BAD_REQUEST, "Parameter must be specified: " + requestUrl);
            }
            try {
                Object deserialized = deserialize(value, method);
                return new Object[]{deserialized};
            } catch (IOException e) {
                monitor.error("Error deserializing parameters for " + method, e);
                throw new ResourceException(HttpStatus.BAD_REQUEST, "Invalid or unsupported parameter type");
            }
        } else {
            throw new ResourceException(HttpStatus.BAD_REQUEST, "Multiple parameter types not supported: " + method);
        }
    }

    /**
     * Deserializes resource parameters from a request stream.
     *
     * @param mapping the resource mapping
     * @param request the current request
     * @return the deserialized request body
     * @throws ResourceException if an error handling the request occurs
     */
    private Object[] deserializeInputStream(HttpServletRequest request, ResourceMapping mapping) throws ResourceException {
        Method method = mapping.getMethod();
        Class[] types = method.getParameterTypes();
        if (types.length == 1 && HttpServletRequest.class.isAssignableFrom(types[0])) {
            // if the parameter is HttpServletRequest, short-circuit deserialization
            return new Object[]{request};
        } else if (types.length == 1) {
            Transformer transformer;
            if (Constants.APPLICATION_JSON.equals(request.getContentType())) {
                transformer = mapping.getPair().getDeserializer();
            } else {
                throw new ResourceException(HttpStatus.BAD_REQUEST, "Content type not supported: " + request.getContentType());
            }

            try {
                ClassLoader loader = mapping.getInstance().getClass().getClassLoader();
                ServletInputStream stream = request.getInputStream();
                return new Object[]{transformer.transform(stream, loader)};
            } catch (Fabric3Exception e) {
                monitor.error("Error deserializing parameters for " + method, e);
                throw new ResourceException(HttpStatus.BAD_REQUEST, "Invalid or unsupported parameter type");
            } catch (IOException e) {
                monitor.error("Error opening request input stream", e);
                throw new ResourceException(HttpStatus.INTERNAL_SERVER_ERROR, "Error reading request");
            }
        } else {
            throw new ResourceException(HttpStatus.BAD_REQUEST, "Multiple parameter types not supported: " + method);
        }
    }

    Object deserialize(String value, Method method) throws IOException {
        if (method.getParameterTypes().length != 1) {
            throw new IOException("Invalid number of parameters: " + method);
        }
        Class type = method.getParameterTypes()[0];
        if (String.class.equals(type)) {
            return value;
        } else if (Integer.class.equals(type) || Integer.TYPE.equals(type)) {
            return Integer.parseInt(value);
        } else if (Long.class.equals(type) || Long.TYPE.equals(type)) {
            return Long.parseLong(value);
        } else if (Double.class.equals(type) || Double.TYPE.equals(type)) {
            return Double.parseDouble(value);
        } else if (Short.class.equals(type) || Short.TYPE.equals(type)) {
            return Short.parseShort(value);
        } else if (Float.class.equals(type) || Float.TYPE.equals(type)) {
            return Float.parseFloat(value);
        }
        throw new IOException("Unsupported parameter type: " + method);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy