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 <your ArcGIS install location>/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 远程调用。。。看不出任何 内部细节。只能作罢。
------------------------------------------------------------------------------------------------
一定要专业!本博客定位于 ,C语言,C++语言,Java语言,Android开发和少量的Web开发,之前是做Web开发的,其实就是ASP维护,发现EasyASP这个好框架,对前端后端数据库 都很感觉亲切啊。. linux,总之后台开发多一点。以后也愿意学习 cocos2d-x 游戏客户端的开发。