Package org.geoserver.gwc.dispatch

Source Code of org.geoserver.gwc.dispatch.GwcServiceProxy$BufferedServletOutputStream

/* (c) 2014 Open Source Geospatial Foundation - all rights reserved
* (c) 2001 - 2013 OpenPlans
* This code is licensed under the GPL 2.0 license, available at the root
* application directory.
*/
package org.geoserver.gwc.dispatch;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.Map;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;

import org.geoserver.config.ServiceInfo;
import org.geoserver.config.impl.ServiceInfoImpl;
import org.geoserver.gwc.GWC;
import org.geoserver.gwc.config.GWCServiceEnablementInterceptor;
import org.geoserver.ows.DisabledServiceCheck;
import org.geoserver.ows.Dispatcher;
import org.geoserver.ows.Response;
import org.geoserver.ows.util.KvpUtils;
import org.geoserver.platform.ServiceException;
import org.geoserver.wfs.kvp.BBoxKvpParser;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.geotools.referencing.CRS;
import org.geotools.util.Version;
import org.geowebcache.GeoWebCacheDispatcher;
import org.geowebcache.GeoWebCacheExtensions;

import com.google.common.collect.ImmutableList;

/**
* Service bean used as service implementation for the GeoServer {@link Dispatcher} when processing
* GWC service requests.
* <p>
* See the package documentation for more insights on how these all fit together.
*/
public class GwcServiceProxy {

    private final ServiceInfoImpl serviceInfo;

    private final GeoWebCacheDispatcher gwcDispatcher;

    public GwcServiceProxy() {
        serviceInfo = new ServiceInfoImpl();
        serviceInfo.setId("gwc");
        serviceInfo.setName("gwc");
        serviceInfo.setEnabled(true);
        serviceInfo.setVersions(ImmutableList.of(new Version("1.0.0")));
        gwcDispatcher = GeoWebCacheExtensions.bean(GeoWebCacheDispatcher.class);
    }

    /**
     * This method is here to assist the {@link DisabledServiceCheck} callback, that uses reflection
     * to find such a method and check if the returned service info is
     * {@link ServiceInfo#isEnabled() enabled} (and hence avoid the WARNING message it spits out if
     * this method is not found); not though, that in the interest of keeping a single
     * {@link GwcServiceProxy} to proxy all gwc provided services (wmts, tms, etc), the service info
     * returned here will always be enabled, we already have a GWC
     * {@link GWCServiceEnablementInterceptor service interceptor} aspect that decorates specific
     * gwc services to check for enablement.
     *
     * @return
     */
    public ServiceInfo getServiceInfo() {
        return serviceInfo;
    }

    /**
     * This method is the only operation defined for the {@link org.geoserver.platform.Service} bean
     * descriptor, and is meant to execute all requests to /gwc/service/*, delegating to the
     * {@code GeoWebCacheDispatcher}'s
     * {@link GeoWebCacheDispatcher#handleRequest(HttpServletRequest, HttpServletResponse)
     * handleRequest(HttpServletRequest, HttpServletResponse)} method, and return a response object
     * so that the GeoServer {@link Dispatcher} looks up a {@link Response} that finally writes the
     * result down to the client response stream.
     *
     * @param rawRequest
     * @param rawRespose
     * @return
     * @throws Exception
     * @see GwcOperationProxy
     * @see GwcResponseProxy
     */
    public GwcOperationProxy dispatch(HttpServletRequest rawRequest, HttpServletResponse rawRespose)
            throws Exception {

        ResponseWrapper responseWrapper = new ResponseWrapper(rawRespose);
       
        if (GWC.get().getConfig().isSecurityEnabled()) {
            verifyAccess(rawRequest);
        }

        gwcDispatcher.handleRequest(rawRequest, responseWrapper);

        final String contentType = responseWrapper.getContentType();
        final Map<String, String> headers = responseWrapper.getHeaders();
        final byte[] bytes = responseWrapper.out.getBytes();

        return new GwcOperationProxy(contentType, headers, bytes);
    }
   
    /***
     * Do a security check using the geoserver internal catalog security for a specific gwc request
     * WMS-C requests are handled as regular WMS requests
     *
     * @param rawRequest the request
     * @throws org.geotools.ows.ServiceException
     */
    public void verifyAccess(HttpServletRequest rawRequest) throws org.geotools.ows.ServiceException {    
        Map parameters = KvpUtils.normalize(rawRequest.getParameterMap());           

        if (rawRequest.getPathInfo().toLowerCase().startsWith("/service/wms")) {
           
            //trick geoserver security into thinking this is a regular wms request
            Dispatcher.REQUEST.get().setService("wms");
            Dispatcher.REQUEST.get().setRequest((String) parameters.get("REQUEST"));

            String layerstr = (String) parameters.get("LAYERS");
            String bboxstr = (String) parameters.get("BBOX");
            String srs = (String) parameters.get("SRS");
                       
            if (layerstr != null) {
                ReferencedEnvelope bbox = null;

                try {
                     bbox = (ReferencedEnvelope) new BBoxKvpParser().parse(bboxstr);                           
                } catch (Exception e) {
                    throw new ServiceException("Invalid bbox: " + bboxstr, e, "MissingOrInvalidParameter");
                }
                if (srs != null) {
                    try {
                        bbox = new ReferencedEnvelope(bbox, CRS.decode(srs));
                    } catch (Exception e) {
                        throw new ServiceException("Invalid srs: " + srs, e, "MissingOrInvalidParameter");
                    }
                }
               
                String[] layers = layerstr.split(",");
                for (String layerName: layers) {
                    layerName = layerName.trim();
                    GWC.get().verifyAccessLayer(layerName, bbox);
                }
            }
           
        } else if (rawRequest.getPathInfo().toLowerCase().startsWith("/service/wmts")) {
            String layer = (String) parameters.get("LAYER");
                       
            if (layer != null) {
                GWC.get().verifyAccessLayer(layer, null);
            }
           
        } else if (rawRequest.getPathInfo().toLowerCase().startsWith("/service/tms/1.0.0/")) {
            String layer = rawRequest.getPathInfo().toLowerCase().substring("/service/tms/1.0.0/".length());
            if (layer.indexOf('/') >= 0) {
                layer = layer.substring(0, layer.indexOf('/'));
            }
            if (layer.indexOf('@') >= 0) {
                layer = layer.substring(0, layer.indexOf('@'));
            }
           
            GWC.get().verifyAccessLayer(layer, null);
        } else if (rawRequest.getPathInfo().toLowerCase().startsWith("/service/kml/")) {
            String layer = rawRequest.getPathInfo().toLowerCase().substring("/service/kml/".length());
            if (layer.indexOf('.') >= 0) {
                layer = layer.substring(0, layer.indexOf('.'));
            }
           
            GWC.get().verifyAccessLayer(layer, null);
        } else if (rawRequest.getPathInfo().toLowerCase().startsWith("/service/gmaps") || rawRequest.getPathInfo().toLowerCase().startsWith("/service/ve")) {
            String layerstr = (String) parameters.get("LAYERS");
                       
            if (layerstr != null) {               
                String[] layers = layerstr.split(",");
                for (String layerName: layers) {
                    layerName = layerName.trim();
                    GWC.get().verifyAccessLayer(layerName, null);
                }
            }           
        }
    }

    /**
     *
     *
     */
    private final class ResponseWrapper extends HttpServletResponseWrapper {

        final BufferedServletOutputStream out = new BufferedServletOutputStream();
        Map<String, String> headers = new LinkedHashMap<String, String>();

        private ResponseWrapper(HttpServletResponse response) {
            super(response);
        }

        @Override
        public ServletOutputStream getOutputStream() throws IOException {
            return out;
        }
       
        @Override
        public void setHeader(String name, String value) {
            headers.put(name, value);
        }

        public Map<String, String> getHeaders() {
            return headers;
        }
    }

    private static class BufferedServletOutputStream extends ServletOutputStream {

        ByteArrayOutputStream outputStream = new ByteArrayOutputStream(4096);

        @Override
        public void write(int b) throws IOException {
            outputStream.write(b);
        }

        @Override
        public void write(byte b[], int off, int len) throws IOException {
            outputStream.write(b, off, len);
        }

        public byte[] getBytes() {
            return outputStream.toByteArray();
        }
    }
}
TOP

Related Classes of org.geoserver.gwc.dispatch.GwcServiceProxy$BufferedServletOutputStream

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.