• 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了。如何生成呢?伤脑筋那。

  • 相关阅读:
    JavaScript 字符串常用操作
    Redis分布式锁
    CSS布局之-水平垂直居中
    vuejs学习笔记(1)--属性,事件绑定,ajax
    Angular.js学习笔记 (一)
    几年前写的一个支持多数据库切换的设计
    bundle中vim相关快捷键的使用
    使用Bundle进行VIM插件的管理
    javascript代码在线测试
    线程池的创建
  • 原文地址:https://www.cnblogs.com/ayanmw/p/2538783.html
Copyright © 2020-2023  润新知