Package org.locationtech.geogig.rest.repository

Source Code of org.locationtech.geogig.rest.repository.CommandResource$StreamWriterRepresentation

/* Copyright (c) 2014 Boundless and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Distribution License v1.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/org/documents/edl-v10.html
*
* Contributors:
* Gabriel Roldan (Boundless) - initial implementation
*/
package org.locationtech.geogig.rest.repository;

import static org.locationtech.geogig.rest.Variants.CSV;
import static org.locationtech.geogig.rest.Variants.CSV_MEDIA_TYPE;
import static org.locationtech.geogig.rest.Variants.JSON;
import static org.locationtech.geogig.rest.Variants.XML;
import static org.locationtech.geogig.rest.Variants.getVariantByExtension;
import static org.locationtech.geogig.rest.repository.RESTUtils.getGeogig;

import java.io.IOException;
import java.io.Writer;
import java.util.List;
import java.util.UUID;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;

import org.codehaus.jettison.mapped.MappedNamespaceConvention;
import org.codehaus.jettison.mapped.MappedXMLStreamWriter;
import org.locationtech.geogig.api.GeoGIG;
import org.locationtech.geogig.rest.RestletException;
import org.locationtech.geogig.rest.WriterRepresentation;
import org.locationtech.geogig.web.api.CommandBuilder;
import org.locationtech.geogig.web.api.CommandContext;
import org.locationtech.geogig.web.api.CommandResponse;
import org.locationtech.geogig.web.api.CommandSpecException;
import org.locationtech.geogig.web.api.ParameterSet;
import org.locationtech.geogig.web.api.ResponseWriter;
import org.locationtech.geogig.web.api.StreamResponse;
import org.locationtech.geogig.web.api.WebAPICommand;
import org.restlet.Context;
import org.restlet.data.Form;
import org.restlet.data.MediaType;
import org.restlet.data.Request;
import org.restlet.data.Response;
import org.restlet.resource.Representation;
import org.restlet.resource.Resource;
import org.restlet.resource.Variant;

import com.google.common.base.Optional;
import com.google.common.base.Preconditions;

/**
*
*/
public class CommandResource extends Resource {

    @Override
    public void init(Context context, Request request, Response response) {
        super.init(context, request, response);
        List<Variant> variants = getVariants();
        variants.add(XML);
        variants.add(JSON);
        variants.add(CSV);
    }

    @Override
    public Variant getPreferredVariant() {
        return getVariantByExtension(getRequest(), getVariants()).or(super.getPreferredVariant());
    }

    @Override
    public Representation getRepresentation(Variant variant) {
        Request request = getRequest();
        Representation representation = runCommand(variant, request);
        return representation;
    }

    private Representation runCommand(Variant variant, Request request) {

        final Optional<GeoGIG> geogig = getGeogig(request);
        Preconditions.checkState(geogig.isPresent());

        Representation rep = null;
        WebAPICommand command = null;
        Form options = getRequest().getResourceRef().getQueryAsForm();
        String commandName = (String) getRequest().getAttributes().get("command");
        MediaType format = resolveFormat(options, variant);
        try {
            ParameterSet params = new FormParams(options);
            command = CommandBuilder.build(commandName, params);
            assert command != null;
        } catch (CommandSpecException ex) {
            rep = formatException(ex, format);
        }
        try {
            if (command != null) {
                RestletContext ctx = new RestletContext(geogig.get());
                command.run(ctx);
                rep = ctx.getRepresentation(format, getJSONPCallback());
            }
        } catch (IllegalArgumentException ex) {
            rep = formatException(ex, format);
        } catch (Exception ex) {
            rep = formatUnexpectedException(ex, format);
        }
        return rep;
    }

    private Representation formatException(IllegalArgumentException ex, MediaType format) {
        Logger logger = getLogger();
        if (logger.isLoggable(Level.FINE)) {
            logger.log(Level.FINE, "CommandSpecException", ex);
        }
        if (format == CSV_MEDIA_TYPE) {
            return new StreamWriterRepresentation(format, StreamResponse.error(ex.getMessage()));
        }
        return new JettisonRepresentation(format, CommandResponse.error(ex.getMessage()),
                getJSONPCallback());

    }

    private Representation formatUnexpectedException(Exception ex, MediaType format) {
        Logger logger = getLogger();
        UUID uuid = UUID.randomUUID();
        String stack = "";
        StackTraceElement[] trace = ex.getStackTrace();
        for (int index = 0; index < 5; index++) {
            if (index < trace.length) {
                stack += trace[index].toString() + '\t';
            } else {
                break;
            }
        }
        logger.log(Level.SEVERE, "Unexpected exception : " + uuid, ex);
        if (format == CSV_MEDIA_TYPE) {
            return new StreamWriterRepresentation(format, StreamResponse.error(stack));
        }
        return new JettisonRepresentation(format, CommandResponse.error(stack), getJSONPCallback());
    }

    private String getJSONPCallback() {
        Form form = getRequest().getResourceRef().getQueryAsForm();
        return form.getFirstValue("callback", null);
    }

    private MediaType resolveFormat(Form options, Variant variant) {
        MediaType retval = variant.getMediaType();
        String requested = options.getFirstValue("output_format");
        if (requested != null) {
            if (requested.equalsIgnoreCase("xml")) {
                retval = MediaType.APPLICATION_XML;
            } else if (requested.equalsIgnoreCase("json")) {
                retval = MediaType.APPLICATION_JSON;
            } else if (requested.equalsIgnoreCase("csv")) {
                retval = CSV_MEDIA_TYPE;
            } else {
                throw new RestletException("Invalid output_format '" + requested + "'",
                        org.restlet.data.Status.CLIENT_ERROR_BAD_REQUEST);
            }
        }
        return retval;
    }

    static class RestletContext implements CommandContext {

        CommandResponse responseContent = null;

        StreamResponse streamContent = null;

        final GeoGIG geogig;

        RestletContext(GeoGIG geogig) {
            this.geogig = geogig;
        }

        @Override
        public GeoGIG getGeoGIG() {
            return geogig;
        }

        Representation getRepresentation(MediaType format, String callback) {
            if (streamContent != null) {
                if (format != CSV_MEDIA_TYPE) {
                    throw new CommandSpecException(
                            "Unsupported Media Type: This response is only compatible with text/csv.");
                }
                return new StreamWriterRepresentation(format, streamContent);
            }
            if (format != MediaType.APPLICATION_JSON && format != MediaType.APPLICATION_XML) {
                throw new CommandSpecException(
                        "Unsupported Media Type: This response is only compatible with application/json and application/xml.");
            }
            return new JettisonRepresentation(format, responseContent, callback);
        }

        @Override
        public void setResponseContent(CommandResponse responseContent) {
            this.responseContent = responseContent;
        }

        @Override
        public void setResponseContent(StreamResponse responseContent) {
            this.streamContent = responseContent;
        }
    }

    public static class JettisonRepresentation extends WriterRepresentation {

        final CommandResponse impl;

        String callback;

        public JettisonRepresentation(MediaType mediaType, CommandResponse impl, String callback) {
            super(mediaType);
            this.impl = impl;
            this.callback = callback;
        }

        private XMLStreamWriter createWriter(Writer writer) {
            final MediaType mediaType = getMediaType();
            XMLStreamWriter xml;
            if (mediaType.getSubType().equalsIgnoreCase("xml")) {
                try {
                    xml = XMLOutputFactory.newFactory().createXMLStreamWriter(writer);
                } catch (XMLStreamException ex) {
                    throw new RuntimeException(ex);
                }
                callback = null; // this doesn't make sense
            } else if (mediaType == MediaType.APPLICATION_JSON) {
                xml = new MappedXMLStreamWriter(new MappedNamespaceConvention(), writer);
            } else {
                throw new RuntimeException("mediatype not handled " + mediaType);
            }
            return xml;
        }

        @Override
        public void write(Writer writer) throws IOException {
            XMLStreamWriter stax = null;
            if (callback != null) {
                writer.write(callback);
                writer.write('(');
            }
            try {
                stax = createWriter(writer);
                impl.write(new ResponseWriter(stax));
                stax.flush();
                stax.close();
            } catch (Exception ex) {
                throw new IOException(ex);
            }
            if (callback != null) {
                writer.write(");");
            }
        }
    }

    static class StreamWriterRepresentation extends WriterRepresentation {

        final StreamResponse impl;

        public StreamWriterRepresentation(MediaType mediaType, StreamResponse impl) {
            super(mediaType);
            this.impl = impl;
        }

        @Override
        public void write(Writer writer) throws IOException {
            try {
                impl.write(writer);
            } catch (Exception e) {
                throw new IOException(e);
            }
        }
    }
}
TOP

Related Classes of org.locationtech.geogig.rest.repository.CommandResource$StreamWriterRepresentation

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.