arcgis sample代码之SOE示例代码PageLayout REST Server Object Extension 的源码分析

0.前言

研究 arcgis object的代码是十分重要的,对于学习arcObject太重要了,因为没有这些代码,学习混乱的arcObject将会更佳的困难。

我的arcgis server 是10.0 for java的,所有核心是arcObjects.jar文件:E:\Program Files\ArcGIS\Server10.0\java\lib\arcobjects.jar

arcObject sample在:E:\Program Files\ArcGIS\DeveloperKit10.0\java\samples\arcobjects

其中ao的javadoc文档在:E:\Program Files\ArcGIS\DeveloperKit10.0\java\docs\eclipse\plugins\com.esri.arcgis.doc\doc.zip

在eclipse中配置arcGIS的javadoc地址为:jar:file:/E:\Program Files\ArcGIS\DeveloperKit10.0\/java/docs/eclipse/plugins/com.esri.arcgis.doc/doc.zip!/api/arcobjects

这样就可以通过eclipse迅速打开 javadoc了。

当然通过:E:\Program Files\ArcGIS\DeveloperKit10.0\java\docs\startJavaHelp.bat 也可以打开单独的eclipse帮助形式的 文档,单独的。这个doc.zip文件解压后很大,所以这种方式很好。

下面我要好好的分析下 sample代码

1.arcgis sample代码之SOE示例代码PageLayout REST Server Object Extension  的分析

在eclipse中创建了arcgis sample代码的pageLayout Rest Server Object Extension。这个SOE的功能是 将地图服务的 layout给画出来并缓存到C:\arcgisserver\arcgisoutput\目录下。

在代码的bitmaps有个图片,是此SOE的示意图。

其中在竹资源下有一个操作(操作就是有参数的rest资源)getPageLayoutBySize  ,还有一个资源: PageLayout1024x768 ,其实本质上一样,这个资源只是指定了三个参数而已。

在src/arcgissample.soe包下 有 PageLayoutImpl.java 和 PageLayoutSOE.java

pageLayoutImpl.java

View Code
/* Copyright 2010 ESRI
* 
* All rights reserved under the copyright laws of the United States
* and applicable international laws, treaties, and conventions.
* 
* You may freely redistribute and use this sample code, with or
* without modification, provided you include the original copyright
* notice and use restrictions.
* 
* See the use restrictions at <your ArcGIS install location>/DeveloperKit10.0/userestrictions.txt.
* 
*/
package arcgissamples.soe;

import java.util.logging.Logger;

import com.esri.arcgis.carto.AlternatingScaleBar;
import com.esri.arcgis.carto.IActiveView;
import com.esri.arcgis.carto.IElement;
import com.esri.arcgis.carto.IFrameElement;
import com.esri.arcgis.carto.IGraphicsContainer;
import com.esri.arcgis.carto.IImageDescription;
import com.esri.arcgis.carto.IImageDisplay;
import com.esri.arcgis.carto.IImageType;
import com.esri.arcgis.carto.ILayoutImage;
import com.esri.arcgis.carto.ILegend;
import com.esri.arcgis.carto.IMap;
import com.esri.arcgis.carto.IMapFrame;
import com.esri.arcgis.carto.IMapServerLayout;
import com.esri.arcgis.carto.IMapServerObjects;
import com.esri.arcgis.carto.IMapSurroundFrame;
import com.esri.arcgis.carto.ImageDescription;
import com.esri.arcgis.carto.ImageDisplay;
import com.esri.arcgis.carto.ImageType;
import com.esri.arcgis.carto.Legend;
import com.esri.arcgis.carto.MapServer;
import com.esri.arcgis.carto.MarkerNorthArrow;
import com.esri.arcgis.carto.PageLayout;
import com.esri.arcgis.carto.TextElement;
import com.esri.arcgis.carto.esriImageFormat;
import com.esri.arcgis.carto.esriImageReturnType;
import com.esri.arcgis.carto.esriViewDrawPhase;
import com.esri.arcgis.geometry.Envelope;
import com.esri.arcgis.geometry.IEnvelope;
import com.esri.arcgis.geometry.IGeometry;
import com.esri.arcgis.geometry.IPoint;
import com.esri.arcgis.geometry.Point;
import com.esri.arcgis.system.IUID;
import com.esri.arcgis.system.UID;

public class PageLayoutImpl
{
    private MapServer serverObject;

    // SOE metadata
    private int width;
    private int height;
    private int dpi;
    
    //Document related metadata
    private String mapName;
    private IMap map;
    private IActiveView activeView;
    private IActiveView pageActiveView; 
    private IMapServerObjects serverObjects;
    private PageLayout pageLayout;    

    // SOE result
    private String outputUrl;
    private static final Logger logger = Logger.getLogger(PageLayoutImpl.class.getName());

    // public constructor.
    public PageLayoutImpl(MapServer serverObject, int width, int height, int dpi)
    {
        this.serverObject = serverObject;
        this.width = width;
        this.height = height;
        this.dpi = dpi;
        this.outputUrl = null;
    }
    
      public void generatePageLayout() throws Exception {
            try {
                
              mapName = serverObject.getDefaultMapName();
              
              map = serverObject.getMap(mapName);
              
              activeView = coerce(map);
              
              serverObjects = coerce(serverObject);
              pageLayout = coerce(serverObjects.getPageLayout());
              
              pageActiveView = coerce(pageLayout);
              
              IGraphicsContainer graphicsContainer = coerce(pageLayout);
              
              graphicsContainer.reset();     
              IFrameElement frameElement = graphicsContainer.findFrame(map);
              IMapFrame mapFrame = coerce(frameElement);
              
              //create a legend
              IUID uid = coerce(new UID());
              uid.setValue(Legend.getClsid());      
              
              IMapSurroundFrame legendFrame = mapFrame.createSurroundFrame(uid, null);
              legendFrame.getMapSurround().setName("Map Legend");
              
              IElement legendElement = coerce(legendFrame);
              legendElement.activate(pageActiveView.getScreenDisplay());
              
              ILegend legend = coerce(legendFrame.getMapSurround());
              
              legend.setTitle("Map Legend.");
              legend.setAutoAdd(true);
              legend.refresh();      
              
              IElement mapElement = coerce(mapFrame);                  
              IEnvelope mainEnvelope = mapElement.getGeometry().getEnvelope();
              IEnvelope elementEnvelope = coerce(new Envelope());
              
              double xmin = mainEnvelope.getXMax() + 2;
              double ymin = mainEnvelope.getYMin() + 0.5;
              double xmax = mainEnvelope.getXMax() - 2;
              double ymax = mainEnvelope.getYMax() - 0.5;
              elementEnvelope.putCoords(xmin, ymin, xmax, ymax);
              
              legendElement.setGeometry((IGeometry)elementEnvelope);
              
              //add it to the graphicsContainer.
              graphicsContainer.addElement(legendElement, 0);
              
              //add a North Arrow
              IUID uidNorth = coerce(new UID());
              uidNorth.setValue(MarkerNorthArrow.getClsid());
              
              IEnvelope northArrowEnvelope = coerce(new Envelope());
              northArrowEnvelope.putCoords(xmin , ymax - 0.5, xmin + 2, ymax + 1);
              
              IMapSurroundFrame northArrowFrame = mapFrame.createSurroundFrame(uidNorth, null);
                    
              IElement northElement = coerce(northArrowFrame);
              northElement.setGeometry(northArrowEnvelope);
              
              graphicsContainer.addElement(northElement, 0);
              
              //add a Title
              TextElement title = new TextElement();
              title.setSize(20);
              title.setText(serverObject.getConfigurationName().toUpperCase());
                          
              IPoint titleGeometry = coerce(new Point());
              
              titleGeometry.setX((ymax - ymin) / 2);
              titleGeometry.setY(((xmin + xmax) / 2) + 2);
              
              IElement titleElement = coerce(title);
              titleElement.setGeometry(titleGeometry);
              
              //title element is always on top
              graphicsContainer.addElement(titleElement, 1);
              
              //Add a ScaleBar
              IUID uidScaleBar = coerce(new UID());
              uidScaleBar.setValue(AlternatingScaleBar.getClsid());
              
              IMapSurroundFrame scaleBarFrame = mapFrame.createSurroundFrame(uidScaleBar, null);
              
              IEnvelope scaleEnvelope = coerce(new Envelope());
              scaleEnvelope.putCoords(1, 1, 3, 1.3);
              
              IElement scaleElement = coerce(scaleBarFrame);
              scaleElement.setGeometry(scaleEnvelope);
              
              //Scale bar on top.
              graphicsContainer.addElement(scaleElement, 1);
              graphicsContainer.reset();
              
              activeView.partialRefresh(esriViewDrawPhase.esriViewGraphics, null, null);
              pageActiveView.partialRefresh(esriViewDrawPhase.esriViewGraphics, null, null);
              
              //Generate Layout
              IMapServerLayout mapLayout = coerce(serverObject);
              IImageDescription imageDesc = coerce(new ImageDescription());
              
              IImageDisplay imageDisplay = coerce(new ImageDisplay());
              imageDisplay.setDeviceResolution(dpi);
              imageDisplay.setWidth(width);
              imageDisplay.setHeight(height);
              
              IImageType iImageType = coerce(new ImageType());
              iImageType.setFormat(esriImageFormat.esriImagePNG24);
              iImageType.setReturnType(esriImageReturnType.esriImageReturnURL);
              
              imageDesc.setDisplay(imageDisplay);
              imageDesc.setType(iImageType);
              
              ILayoutImage outputImage = mapLayout.exportLayout(mapLayout.getDefaultPageDescription(), imageDesc);
              
              //dont persist -> restore back to original state.
              graphicsContainer.deleteElement(legendElement);              
              graphicsContainer.deleteElement(northElement);              
              graphicsContainer.deleteElement(titleElement);
              graphicsContainer.deleteElement(scaleElement);
              
              graphicsContainer.reset();
              
              outputUrl = outputImage.getURL();
              logger.info("Generated Layout : " + outputImage.getURL());
                    
            }catch (Exception e) {
              logger.severe("Error generating page layout : " + e.getMessage());
              throw e;
            }
          }    

    /*public void generatePageLayout()
    {
        try
        {
            Map map = (Map) serverObject.getMap(serverObject.getDefaultMapName());

            PageLayout pageLayout = (PageLayout) map.getPageLayout();
            pageLayout.reset();

            MapFrame mapFrame = (MapFrame) pageLayout.findFrame(map);

            // create a legend
            UID uid = new UID();
            uid.setValue(Legend.getClsid());

            MapSurroundFrame legendFrame = (MapSurroundFrame) mapFrame.createSurroundFrame(uid, null);
            legendFrame.getMapSurround().setName("Map Legend");
            legendFrame.activate(pageLayout.getScreenDisplay());

            Legend legend = (Legend) legendFrame.getMapSurround();
            legend.setTitle("Map Legend.");
            legend.setAutoAdd(true);
            legend.refresh();
            
            legendFrame.setMapSurroundByRef(legend);//added by Ajit

            Envelope mainEnvelope = (Envelope) mapFrame.getGeometry().getEnvelope();
            Envelope elementEnvelope = new Envelope();

            double xmin = mainEnvelope.getXMax() + 2;
            double ymin = mainEnvelope.getYMin() + 0.5;
            double xmax = mainEnvelope.getXMax() - 2;
            double ymax = mainEnvelope.getYMax() - 0.5;
            elementEnvelope.putCoords(xmin, ymin, xmax, ymax);

            legendFrame.setGeometry(elementEnvelope);

            // add it to the pagelayout.
            pageLayout.addElement(legendFrame, 0);

            // add a North Arrow
            UID uidNorth = new UID();
            uidNorth.setValue(MarkerNorthArrow.getClsid());

            Envelope northArrowEnvelope = new Envelope();
            northArrowEnvelope.putCoords(xmin, ymax - 0.5, xmin + 2, ymax + 1);

            MapSurroundFrame northArrowFrame = (MapSurroundFrame) mapFrame.createSurroundFrame(uidNorth, null);
            northArrowFrame.setGeometry(northArrowEnvelope);

            pageLayout.addElement(northArrowFrame, 0);

            // add a Title
            TextElement title = new TextElement();
            title.setSize(20);
            title.setText("USA Map Service.");

            Point titleGeometry = new Point();
            titleGeometry.setX((ymax - ymin) / 2);
            titleGeometry.setY(((xmin + xmax) / 2) + 2);

            title.setGeometry(titleGeometry);

            // title element is always on top
            pageLayout.addElement(title, 1);

            // Add a ScaleBar
            UID uidScaleBar = new UID();
            uidScaleBar.setValue(AlternatingScaleBar.getClsid());

            MapSurroundFrame scaleBarFrame = (MapSurroundFrame) mapFrame.createSurroundFrame(uidScaleBar, null);

            Envelope scaleEnvelope = new Envelope();
            scaleEnvelope.putCoords(1, 1, 3, 1.3);

            scaleBarFrame.setGeometry(scaleEnvelope);

            // Scale bar on top.
            pageLayout.addElement(scaleBarFrame, 1);
            pageLayout.reset();

            map.partialRefresh(esriViewDrawPhase.esriViewGraphics, null, null);
            pageLayout.partialRefresh(esriViewDrawPhase.esriViewGraphics, null, null);

            // Generate Layout
            // IMapServerLayout mapLayout = Macros.coerce(serverObject);
            ImageDescription imageDesc = new ImageDescription();

            ImageDisplay imageDisplay = new ImageDisplay();
            imageDisplay.setDeviceResolution(dpi);
            imageDisplay.setWidth(width);
            imageDisplay.setHeight(height);

            ImageType iImageType = new ImageType();
            iImageType.setFormat(esriImageFormat.esriImagePNG24);
            iImageType.setReturnType(esriImageReturnType.esriImageReturnURL);

            imageDesc.setDisplay(imageDisplay);
            imageDesc.setType(iImageType);

            ILayoutImage outputImage = serverObject.exportLayout(serverObject.getDefaultPageDescription(), imageDesc);

            // dont persist -> restore back to original state.
            pageLayout.deleteElement(legendFrame);
            pageLayout.deleteElement(northArrowFrame);
            pageLayout.deleteElement(title);
            pageLayout.deleteElement(scaleBarFrame);

            pageLayout.reset();

            outputUrl = outputImage.getURL();
            logger.info("Generated Layout : " + outputImage.getURL());
        }
        catch (AutomationException e)
        {
            logger.info("MapLayoutImpl exception: " + e.getMessage() + " - " + e.getDescription());
            e.printStackTrace();
        }
        catch (UnknownHostException e)
        {
            logger.info("MapLayoutImpl exception: " + e.getMessage() + " - " + e.getLocalizedMessage());
            e.printStackTrace();
        }
        catch (IOException e)
        {
            logger.info("MapLayoutImpl exception: " + e.getMessage() + " - " + e.getLocalizedMessage());
            e.printStackTrace();
        }

    }*/

    public String getOutputUrl()
    {
        return outputUrl;
    }
    
    // This method is a convinience method to avoid all those interface type casts.
    @SuppressWarnings("unchecked")
    private <F, T> T coerce(F from)
    {
        return (T) from;
    }

    @SuppressWarnings("unused")
    private boolean isEmpty(String str)
    {
        if (str == null || str.length() == 0)
        {
            return true;
        }
        else
        {
            return false;
        }
    }
}

PageLayoutSOE.java

View Code
/* Copyright 2010 ESRI
* 
* All rights reserved under the copyright laws of the United States
* and applicable international laws, treaties, and conventions.
* 
* You may freely redistribute and use this sample code, with or
* without modification, provided you include the original copyright
* notice and use restrictions.
* 
* See the use restrictions at &lt;your ArcGIS install location&gt;/DeveloperKit10.0/userestrictions.txt.
* 
*/
package arcgissamples.soe;

import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;

import com.esri.arcgis.carto.MapServer;
import com.esri.arcgis.interop.AutomationException;
import com.esri.arcgis.interop.extn.ArcGISExtension;
import com.esri.arcgis.server.IServerObjectExtension;
import com.esri.arcgis.server.IServerObjectHelper;
import com.esri.arcgis.system.ILog;
import com.esri.arcgis.system.ServerUtilities;

import static com.esri.arcgis.system.ServerUtilities.*;
import com.esri.arcgis.interop.extn.ServerObjectExtProperties;
import com.esri.arcgis.system.IRESTRequestHandler;

import com.esri.arcgis.server.json.*;

@ArcGISExtension
@ServerObjectExtProperties(
        displayName = "PageLayout SOE", 
        description = "Presents the pagelayout view of layers in associated map service, alongwith with scale bar, north arrow, legend",
        supportsMSD = true
)        
public class PageLayoutSOE implements IServerObjectExtension, IRESTRequestHandler
{
    private static final long serialVersionUID = 1L;
    private IServerObjectHelper soHelper;
    private ILog serverLog;
    private MapServer mapServer;
    
    public PageLayoutSOE() throws Exception
    {
        super();
    }

    /****************************************************************************************************************************
     * IServerObjectExtension methods: This is a mandatory interface that must be supported by all SOEs. This interface
     * is used by the Server Object to manage the lifetime of the SOE and includes two methods: init() and shutdown().
     * The Server Object cocreates the SOE and calls the init() method handing it a back reference to the Server Object
     * via the Server Object Helper argument. The Server Object Helper implements a weak reference on the Server Object.
     * The extension can keep a strong reference on the Server Object Helper (for example, in a member variable) but
     * should not keep a strong reference on the Server Object. The log entries are merely informative and completely
     * optional.
     ****************************************************************************************************************************/
    /**
     * init() is called once, when the instance of the SOE is created.
     */
    public void init(IServerObjectHelper soh) throws IOException, AutomationException
    {
        /*
         * An SOE should get the Server Object from the Server Object Helper in order to make any method calls on the
         * Server Object and release the reference after making the method calls.
         */
        this.soHelper = soh;
        this.serverLog = getServerLogger();

        // get the Server Object (SO) this SOE is associated with
        this.mapServer = (MapServer) soHelper.getServerObject();
    }

    /**
     * shutdown() is called once when the Server Object's context is being shut down and is about to go away.
     */
    public void shutdown() throws IOException, AutomationException
    {
        /*
         * The SOE should release its reference on the Server Object Helper.
         */
        this.mapServer = null;
        this.soHelper = null;
        this.serverLog = null;
    }

    /****************************************************************************************************************************
     * IRESTRequestHandler methods: This interface indicates that SOE supports REST. It exposes two methods: handleRESTRequest()
     * and getSchema().
     ****************************************************************************************************************************/
    /**
     * Handles REST request
     */    
    public byte[] handleRESTRequest(String capabilities, String resourceName, 
            String operationName, String operationInput, 
            String outputFormat, String requestProperties, 
            String[] responseProperties) throws IOException, AutomationException
    {
        /*
         * This method handles REST requests by determining whether an operation
         * or resource has been invoked and then forwards the request to
         * appropriate methods.
         */

        try
        {
            // if no operationName is specified send description of specified
            // resource
            if (operationName.length() == 0)
            {
                return getResource(resourceName);
            }
            else
            // invoke REST operation on specified resource
            {
                return invokeRESTOperation(capabilities, resourceName, operationName, operationInput, outputFormat,
                        requestProperties, responseProperties);
            }
        }
        catch (Exception e)
        {
            return ServerUtilities.sendError(0, "Exception occurred: " + e.getMessage(), null).getBytes("utf-8");
        }    
    }
    
    /**
     * Returns schema of the REST resource
     */
    public String getSchema() throws IOException, AutomationException
    {
        try
        {
            JSONObject _PageLayoutSOE = createResource(
                    "PageLayoutSOE",
                    "Presents a page layout view of layers in associated map service, alongwith with scale bar, north arrow and legend",
                    false);
            JSONArray _PageLayoutSOE_OpArray = new JSONArray();
            _PageLayoutSOE_OpArray.put(createOperation("getPageLayoutBySize", "width, height, dpi", "json, html"));
            _PageLayoutSOE.put("operations", _PageLayoutSOE_OpArray);
            
            JSONArray _PageLayoutSOE_SubResourceArray = new JSONArray();
            JSONObject layout1024x768 = createResource("PageLayout1024x768", "Page layout view of map of dimensions 1024 x 768", false);
            _PageLayoutSOE_SubResourceArray.put(layout1024x768);
            _PageLayoutSOE.put("resources", _PageLayoutSOE_SubResourceArray);            
            
            return _PageLayoutSOE.toString();
        }
        catch (JSONException e)
        {
            e.printStackTrace();
        }
        return null;

    }

    /****************************************************************************************************************************
     * SOE Util methods.
     ****************************************************************************************************************************/    
    /**
     * Invokes specified REST operation on specified REST resource
     * @param capabilitiesList
     * @param resourceName
     * @param operationName
     * @param operationInput
     * @param outputFormat
     * @param requestProperties
     * @param responseProperties
     * @return
     */
    private byte[] invokeRESTOperation(String capabilitiesList, String resourceName, String operationName,
            String operationInput, String outputFormat, String requestProperties, String[] responseProperties) throws Exception
    {
        byte[] operationOutput = null;

        JSONObject operationInputAsJSON = new JSONObject(operationInput);

        //parse request properties and create a map
        java.util.Map<String, String> requestPropertiesMap = new HashMap<String, String>();
        if (requestProperties != null && requestProperties.length() > 0)
        {
            JSONObject requestPropertiesJSON = new JSONObject(requestProperties);
            Iterator<String> jsonKeys = requestPropertiesJSON.keys();
            while (jsonKeys.hasNext())
            {
                String key = jsonKeys.next();
                requestPropertiesMap.put(key, requestPropertiesJSON.getString(key));
            }
        }

        //create a Map to hold response properties
        java.util.Map<String, String> responsePropertiesMap = new HashMap<String, String>();    
        if (resourceName.equalsIgnoreCase("") || resourceName.length() == 0)
        {                            
            if (operationName.equalsIgnoreCase("getPageLayoutBySize"))
            {
                operationOutput = generateLayoutAndReturnURL(mapServer, operationInputAsJSON).getBytes("utf-8");
            }
            else
            {
                operationOutput = sendError(0, "Operation " + "\"" + operationName + "\" not supported on resource " + resourceName + ".", 
                        new String[]{"No other details", " specified"}).getBytes("utf-8");                    
            }                
        }
        else //if non existent sub-resource specified, report error
        {
            operationOutput = sendError(0, "No sub-resource by name \"" + resourceName + "\" found.", new String[]{""}).getBytes("utf-8");    
        }
        
        //convert response properties to String array
        if (!responsePropertiesMap.isEmpty())
        {
            Set<String> keys = responsePropertiesMap.keySet();
            Iterator<String> keysIterator = keys.iterator();
            int i = 0;
            while (keysIterator.hasNext())
            {
                String key = keysIterator.next();
                String value = responsePropertiesMap.get(key);
                responseProperties[i] = key + "=" + value;
                i++;
            }
        }
        
        return operationOutput;    
    }        
    
    /**
     * Returns description of resource specified by resourceName
     * @param resourceName
     * @return byte[]
     */
    private byte[] getResource(String resourceName)
    {
        try
        {
            if(resourceName.equalsIgnoreCase("") || resourceName.length() == 0)
            {
                //this.serverLog.addMessage(1, 8000, "1");
                return getRootResourceDescription().toString().getBytes();
            }
            if(resourceName.equalsIgnoreCase("PageLayout1024x768"))
            {
                JSONObject json = new JSONObject();
                json.put("height", 1024);
                json.put("width", 768);
                json.put("dpi", 72);
                return generateLayoutAndReturnURL(mapServer, json).getBytes("utf-8");
            }            
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }

        return null;
    }    
    
    /**
     * Returns description of the root resource
     * @return description as a JSONObject
     */
    private JSONObject getRootResourceDescription()
    {
        try
        {
            JSONObject rootResource = new JSONObject();
            rootResource.put("Name", "PageLayout SOE");
            rootResource.put("Description", "Presents a Map's image in page layout format.");
            
            return rootResource;            
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
        
        return null;
    }    
    
    /**
     * Generates PageLayout image and returns URL to the image
     * @param serverObject
     * @param width
     * @param height
     * @param dpi
     * @return Image URL as String
     */
    private String generateLayoutAndReturnURL(MapServer serverObject, JSONObject inputParameters)
    {
        try
        {
            int height = inputParameters.getInt("height");
            int width = inputParameters.getInt("width");
            int dpi = inputParameters.getInt("dpi");
            
            if ((height <= 0) || (width <= 0) || (dpi <= 0))
            {
                return sendError(400, "Invalid Input.", null);
            }
            
            // generate page layout.
            PageLayoutImpl impl = new PageLayoutImpl(mapServer, width, height, dpi);
            impl.generatePageLayout();                            
            this.serverLog.addMessage(1, 8000, "Layout Output : " + impl.getOutputUrl());

            // set response properties
            
            JSONObject response = new JSONObject();
            response.put("outputUrl", impl.getOutputUrl());
            return response.toString();
        }
        catch (Exception e)
        {
            return sendError(1, e.getMessage(), null);            
        }
    }

    /****************************************************************************************************************************
     * General Util methods.
     ****************************************************************************************************************************/
    /**
     * Creates a REST resource based on specified name, description and collection flag
     * @param name
     * @param description
     * @param isCollection
     * @return REST resource as a JSONObject
     */
    private JSONObject createResource(String name, String description, boolean isCollection)
    {
        try
        {
            JSONObject json = new JSONObject();

            if (name.length() > 0 && name != null)
            {
                json.put("name", name);
            }
            else
            {
                throw new Exception("Resource must have a valid name.");
            }

            json.put("description", description);
            json.put("isCollection", isCollection);

            return json;
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }

        return null;
    }

    /**
     * Creates an operation that can be called on a REST resource, using specified name, parameter list and 
     * output formats list
     * @param operationName
     * @param parameterList
     * @param supportedOutputFormatsList
     * @return Operation as a JSONObject
     */
    private JSONObject createOperation(String operationName, String parameterList, String supportedOutputFormatsList)
    {
        try
        {
            JSONObject operation = new JSONObject();

            if (operationName.length() > 0 && operationName != null)
            {
                operation.put("name", operationName);
            }
            else
            {
                throw new Exception("Operation must have a valid name.");
            }

            // parameters
            if (parameterList.length() > 0 && parameterList != null)
            {
                JSONArray operationParamArray = new JSONArray();
                String[] parameters = parameterList.split(",");
                for (String parameter : parameters)
                {
                    operationParamArray.put(parameter.trim());
                }

                operation.put("parameters", operationParamArray);
            }
            else
            {
                throw new Exception(
                        "Operation must have parameters. If your operation does not requires params, then please convert it to a sub-resource.");
            }

            // supported Output formats
            if (supportedOutputFormatsList.length() > 0 && supportedOutputFormatsList != null)
            {
                JSONArray outputFormatsArray = new JSONArray();
                String[] outputFormats = supportedOutputFormatsList.split(",");
                for (String outputFormat : outputFormats)
                {
                    outputFormatsArray.put(outputFormat.trim());
                }

                operation.put("supportedOutputFormats", outputFormatsArray);
            }
            else
            {
                throw new Exception("Operation must have supported output formats specified");
            }

            return operation;
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }

        return null;
    }

    /**
     * Returns a detailed error thats constructed based on specified code, message and details array. 
     * @param code
     * @param message
     * @param details
     * @return error String
     */
    private String sendError(int code, String message, String[] details)
    {
        /*
         * An json error is sent back to client in the following structure.{ "error": { "code": 400, "message":
         * "Cannot perform query. Invalid query parameters.", "details": ["'time' param is invalid"] }}
         */
        try
        {
            JSONObject errorObject = new JSONObject();

            JSONObject error = new JSONObject();
            error.put("code", code);
            error.put("message", message);

            if (details != null)
            {
                JSONArray detailsArray = new JSONArray();
                for (String detail : details)
                {
                    detailsArray.put(detail);
                }

                error.put("details", detailsArray);
            }

            errorObject.put("warning", error);

            return errorObject.toString();
        }
        catch (JSONException e)
        {
            e.printStackTrace();
        }

        return null;
    }

}

其中还有一个 rest 的java客户端,这个是单独运行的,和上面两个没啥关系。上面两个文件发布成 jar文件,放到java/lib/ext文件夹下面后部署SOE成功,并且添加到地图服务的 功能  上就可以使用了。比如http://localhost:8399/arcgis/rest/services/portland/MapServer/exts/PageLayoutSOE就是portland的地图服务下面的扩展功能 SOE 是 PageLayoutSOE 了。其实这个SOE可以放到任何一个地图服务的扩展功能当中。

PageLayoutRESTClient.java

View Code
/* Copyright 2010 ESRI
* 
* All rights reserved under the copyright laws of the United States
* and applicable international laws, treaties, and conventions.
* 
* You may freely redistribute and use this sample code, with or
* without modification, provided you include the original copyright
* notice and use restrictions.
* 
* See the use restrictions at &lt;your ArcGIS install location&gt;/DeveloperKit10.0/userestrictions.txt.
* 
*/
package arcgissamples.soe.restclient;

import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.URL;

import sun.misc.BASE64Encoder;

public class PageLayoutRESTClient
{
    private String serverName = "";
    private String mapServiceName = "";
    private String soeName = "";
    private String userName = "";
    private String password = "";
    
    public PageLayoutRESTClient(String serverName, String mapServiceName, String soeName, String userName, String password)
    {
        this.serverName = serverName;
        this.mapServiceName = mapServiceName;
        this.soeName = soeName;
        this.userName = userName;
        this.password = password;
    }
    
    public static void main(String[] args)
    {
        String serverName = "";
        String mapServiceName = "";
        String soeName = "";
        String userName = "";
        String password = "";
        
        if(args.length == 5)
        {
            serverName = args[0];
            mapServiceName = args[1];
            soeName = args[2];
            userName = args[3];
            password = args[4];
        }
        else
        {
            System.out.println("Wrong Usage. For correct usage, see following: \n"
                    + "\nUsage: PageLayoutRESTClient [server name] [map service name] [soe name] [user name] [password]\n\n"
                    + "[server name] - Specifies name of ArcGIS Server\n"
                    + "[map service name] - Specifies name of map service\n"
                    + "[soe name] - Specifies SOE name\n"
                    + "[username] - Specifies user name\n"
                    + "[password] - Specifies user password\n");
            System.exit(1);
        }
        
        try
        {
            PageLayoutRESTClient client = new PageLayoutRESTClient(serverName, mapServiceName, soeName, userName, password);
            client.consumeRESTSOE();
        }
        catch (MalformedURLException e)
        {
            e.printStackTrace();
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
    }
    
    public void consumeRESTSOE() throws MalformedURLException, IOException
    {
        //get SOE's JSON representation 
        String url = "http://" + this.serverName + ":8399/arcgis/rest/services/" + this.mapServiceName + "/MapServer/exts/" + this.soeName + "?f=json";
        System.out.println("\nSOE's JSON representation: \n" + sendReceive(url));
        
        //invoke sub resource
        url = "http://" + this.serverName + ":8399/arcgis/rest/services/" + this.mapServiceName + "/MapServer/exts/" + this.soeName + "/PageLayout1024x768?f=json";
        System.out.println("\nSub Resource: \n" + sendReceive(url));
        
        //invoke operation
        url = "http://" + this.serverName + ":8399/arcgis/rest/services/" + this.mapServiceName + "/MapServer/exts/" + this.soeName + "/getPageLayoutBySize?" +
                "width=1024&height=800&dpi=72&f=json";
        System.out.println("\nOperation: \n" + sendReceive(url));
    }
    
    private String sendReceive(String urlString) throws MalformedURLException, IOException
    {
        //create HTTP connection
        URL url = new URL(urlString);
        HttpURLConnection httpConnection = getHTTPConnection(url, "GET", this.userName, this.password);
        System.out.println("Header Info: \n");
        printHTTPHeaderInfo(httpConnection);
        
        //send request
        httpConnection.connect();
        
        //get response
        String response = getResponse(httpConnection);
        
        //disconnect
        httpConnection.disconnect();        
        
        return response;
    }    
    
    /**
     * Prints HTTP Header info
     * @param httpConnection
     */
    private void printHTTPHeaderInfo(HttpURLConnection httpConnection)
    {
        // look at headers
        // the 0th header has a null key, and the value is the response line ("HTTP/1.1 200 OK" or whatever)
        String header = null;
        String headerValue = null;
        int index = 0;
        while ((headerValue = httpConnection.getHeaderField(index)) != null)
        {
            header = httpConnection.getHeaderFieldKey(index);
            
            if (header == null)
                System.out.println(headerValue);
            else
                System.out.println(header + ": " + headerValue);
            
            index++;
        }
    }    
    
    /**
     * Returns an HTTPURLConnection object based on specified URL and HTTP method, username and password
     * @param url
     * @param method
     * @return
     */
    private HttpURLConnection getHTTPConnection(URL url, String httpMethod, String userName, String userPassword)
    {
        try
        {
            //boolean quiet, String httpMethod, URL url, String username, String password, InputStream body)
            HttpURLConnection httpConnection = (HttpURLConnection) url.openConnection();
            httpConnection.setRequestMethod(httpMethod);
            
            // write auth header
            BASE64Encoder encoder = new BASE64Encoder();
            String encodedCredential = encoder.encode( (userName + ":" + userPassword).getBytes() );
            httpConnection.setRequestProperty("Authorization", "BASIC " + encodedCredential);
            
            return httpConnection;
        }
        catch (ProtocolException e)
        {
            e.printStackTrace();
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
        
        return null;
    }
    
    /**
     * Returns response from an HTTPConnection object
     * @param httpConnection
     * @return
     */
    private String getResponse(HttpURLConnection httpConnection)
    {
        try
        {
            InputStream responseBodyStream = httpConnection.getInputStream();
            StringBuffer responseBody = new StringBuffer();
            int read = 0;
            byte buffer[] = new byte[8192];
            while ((read = responseBodyStream.read(buffer)) != -1)
            {
                responseBody.append(new String(buffer, 0, read));
            }
            
            responseBody.trimToSize();
            return responseBody.toString();
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
        
        return null;
    }        

}

对于客户端 纯java程序,不解释了。SOE文件,其主要就是实现两个接口的方法: IServerObjectExtension, IRESTRequestHandler的。一个是SOE的主要接口,一个是rest服务的接口,当然后者也可以为soap的服务接口。

arcgis plugin for eclipse的创建SOE扩展的时候有一点需要注意:一定要有一个操作,否则生成的代码有点错误 。关于SOE研究下init shutdown方法和 handleRESTRequest getSchema invokeRESTOperation方法就可以,其他方法都是辅助这些方法的。

此SOE的操作其实是调用了 PageLayoutImpl impl = new PageLayoutImpl(mapServer, width, height, dpi);

impl.generatePageLayout();

impl.getOutputUrl();
三个方法。下面就是关键的PageLayoutImpl.java类了。也主要就是这三个方法。

此方法最重要的是 SOE 传递了MapServer mapServer参数,以及三个选项参数。

此SOE的代码太乱了,我精简下,把那些 什么指南针,图例,legend之类的图片上的文字全部去掉,其代码就是:

      public void generatePageLayout() throws Exception {
            try {
              //Generate Layout
              IMapServerLayout mapLayout = coerce(serverObject);

              IImageDisplay imageDisplay = coerce(new ImageDisplay());
              imageDisplay.setDeviceResolution(dpi);
              imageDisplay.setWidth(width);
              imageDisplay.setHeight(height);

              IImageType iImageType =(new ImageType());//coerce(new ImageType());
              iImageType.setFormat(esriImageFormat.esriImagePNG24);
              iImageType.setReturnType(esriImageReturnType.esriImageReturnURL);

              IImageDescription imageDesc = coerce(new ImageDescription());
              imageDesc.setDisplay(imageDisplay);
              imageDesc.setType(iImageType);
        //核心啊 exportLayout就生成了缓存的图片(此缓存图片会在一定时间后自动删除)
              ILayoutImage outputImage = mapLayout.exportLayout(mapLayout.getDefaultPageDescription(), imageDesc);
        //缓存图片的连接示例为:http://localhost:8399/arcgis/server/arcgisoutput/_ags_map4519e0323d8c4358b05fee14d92669e0.png
              this.outputUrl = outputImage.getURL();
              logger.info("Generated Layout : " + outputImage.getURL());

            }catch (Exception e) {
              logger.severe("Error generating page layout : " + e.getMessage());//这个是SOE的日志
              throw e;
            }
    }

生成的图片干净了许多,但是我现在想要生成 要素 的透明png图片,可不是layout了。如何生成呢?伤脑筋那。

原文地址:https://www.cnblogs.com/ayanmw/p/2538783.html