arcgis sample代码之SOE示例代码Length Calculator Server Object Extension的源码分析

This Server Object Extension calculates lengths of all street (polyline) features in the associated map service and can be accessed by a client application through DCOM. 

这个服务器对象扩展SOE可以计算在指定的地图服务中的所有街道(折线)的长度,并且可以通过客户端应用程序使用DCOM来访问。

此SOE没有实现rest和soap接口,所以在启用此SOE后,在地图服务的rest网页无法看到这个功能。他只能通过客户端使用DCOM来访问。其功能是 计算Streets地图图层de要素类的长度。默认在portLand地图有此地图图层,其他的地图服务如果没有这个要素类是会报错的。当然也可以更改源码改为其他的地图图层。

下面就是主要的源码:

    MapServer mapServer = null;
        mapServer = (MapServer) soHelper.getServerObject();


    /****************************************************************************************************************************
     * ICalculateLength method: This is a custom interface. It exposes 1 method:
     * calculateLength()
     ****************************************************************************************************************************/
    /**
     * Calculates length of all polylines
     */
    public double calculateLength() throws Exception {
        
        // Get index of layer containing all locations
        Map map = (Map) this.mapServer.getMap("Layers");
        FeatureClass streetsFC = new FeatureClass(this.mapServer.getDataSource(this.mapServer.getDefaultMapName(), getLayerIndex(map, "Streets")));

        // count num of features
        int numFeatures = streetsFC.featureCount(null);
        IFeatureCursor featureCursor = streetsFC.search(null, true);

        // calculate length of each feature and add up
        double totalLength = 0.0;
        for (int i = 0; i < numFeatures; i++) {
            IFeature feature = featureCursor.nextFeature();
            Polyline polyline = (Polyline) feature.getShape();
            totalLength += polyline.getLength();
        }

        return totalLength;
    }

    /************************************************************************
     * Util methods
     ************************************************************************/
    /**
     * Retrieves ID of a layer in MapEJB based on its name
     * 
     * @param mapServer
     * @param layerName
     * @return
     */
    private int getLayerIndex(Map map, String layerName) throws IOException, AutomationException {
        int layerID = -1;

        for (int i = 0; i < map.getLayerCount(); i++) {
            String name = map.getLayer(i).getName();
            if (layerName.equalsIgnoreCase(name)) {
                layerID = i;
                break;
            }
        }

        if (layerID < 0) {
            serverLog.addMessage(4, 8000, "Could not find layer " + layerName + " in " + map.getName());
            throw new RuntimeException("Could not find layer " + layerName + " in " + map.getName());
        }

        return layerID;
    }

通过 soHelper.getServerObject();获得mapserver对象,在通过mapserver的getMap("Layers")获得Map对象,通过Mapserver的getDataSource方法获得一个FeatureClass对象,再根据FeatureClass的一个游标获得feature对象,因而获得polyline feature的length,遍历累计相加,返回结果。

我更感兴趣的是:客户端如何通过DCOM来调用这个Length Calculator Server Object Extension

/* 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.client;


import arcgissamples.soe.ICalculateLength;

import com.esri.arcgis.carto.MapServer;
import com.esri.arcgis.server.IServerObjectExtension;
import com.esri.arcgis.server.IServerObjectExtensionManager;
import com.esri.arcgis.server.ServerConnection;
import com.esri.arcgis.server.ServerContext;
import com.esri.arcgis.server.ServerObjectManager;
import com.esri.arcgis.system.ServerInitializer;

public class LengthCalculatorClient {
    private static String serverName, domainName, userName, password, serviceName;
    private static ServerConnection connection;

    public static void main(String[] args) {
        try {
            if (args.length != 5) {
                System.out.println("Wrong Usage. For correct usage, see following: \n"
                        + "\nUsage: LengthCalculatorClient [server name] [domain name] [user name] [password] [map service name]\n\n"
                    + "[server name]\tSpecifies name of ArcGIS Server\n" + "[domain name]\tSpecifies domain name of user\n"
                    + "[user name]\tSpecifies user name\n" + "[password]\tSpecifies user password\n" 
                    + "[map service name]\tSpecifies name of map service\n");
                
                System.exit(1);
            } else {
                // connect to Server
                serverName = args[0];
                domainName = args[1];
                userName = args[2];
                password = args[3];
                serviceName = args[4];

                ServerInitializer serverInit = new ServerInitializer();
                serverInit.initializeServer(domainName, userName, password);

                System.out.print("Connecting to ArcGIS Server " + serverName + "...");
                connection = new ServerConnection();
                connection.connect(serverName);
                System.out.println("Done.");

                // Retrieve the SOM to get ServerContext and the Map Server Object
                System.out.print("Retrieving Server Object Manager.");
                ServerObjectManager som = new ServerObjectManager(connection.getServerObjectManager());
                System.out.println("Done.");

                System.out.print("Creating Server Context...");
                String soeName = "LengthCalculatorSOE";
                ServerContext serverContext = new ServerContext(som.createServerContext(serviceName, "MapServer"));
                MapServer mapServer = (MapServer) serverContext.getServerObject();
                System.out.println("Done.");

                // Access the soe through the IServerObjectExtensionManager
                System.out.println("Creating instance of SOE..");
                IServerObjectExtensionManager extnMgr = (IServerObjectExtensionManager) mapServer;
                IServerObjectExtension calculatorSOE = extnMgr.findExtensionByTypeName(soeName);
                System.out.println("Done.");

                // Consume the SOE
                System.out.println("\nInvoking SOE's calculateLength() method...");
                ICalculateLength mySOE = (ICalculateLength) calculatorSOE;
                System.out.println("Total Length returned by SOE: " + mySOE.calculateLength());

                // releasing connection
                System.out.print("\nDisconnecting " + serverName + "...");
                connection.release();
                System.out.println("Done.");
            }
        } catch (Exception e) {
            try {
                connection.release();
            } catch (Exception e1) {
                e1.printStackTrace();
            }

            e.printStackTrace();
        }
    }
}

这个java 程序 居然可以不用engine的许可,就调用ao的类。。

传递几个参数:serverName:localhost domainName:127.0.0.1 userName:arcgismanager password:arcgismanager serviceName:portland。username和password貌似没啥必要。不清楚。

通过 new ServerConnection();然后一步一步的获得了Mapserver对象,继而获得SOE对象,最后强制转换为ICalculateLength的SOE对象,直接调用calculatgeLength方法直接得到结果了,貌似跟本地程序一样,这就是 传说中的 DCOM 远程调用。。。看不出任何 内部细节。只能作罢。

 

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