Extending Service Provider |
The implementation of the service provider is as follows:
public class SampleProvider implements ProviderContextAware {
...
}
ProviderContextAware is used to get the service provider context, through which the configuration information of the service provider can be got.
For the configuration of the three-layer structure, see iServer Configuration File
The types of service providers already provided by SuperMap iServer include: MapProvider, DataProvider, RealspaceProvider, SpatialAnalystProvider, and TransportationAnalystProvider. SuperMap iServer has implemented these service providers to ensure the sources of GIS capabilities (Refer to Service Providers).
Users can extend service providers to expand the sources of GIS capabilities provided by SuperMap iServer.
Table 1 Interfaces or classes for extending service provider
Type | Classes/Interfaces | RemarkNote |
MapProvider | com.supermap.services.components.spi.MapProvider | All map providers need to implement this interface. The service provider that implements the interface can be used by the map component. |
com.supermap.services.components.spi.AbstractRestMapProvider | Encapsulated the basic functions needed to access REST map service, all the service providers using REST map service can use this class to extend. | |
com.supermap.services.components.spi.RemoteTiledMapProviderBase | RemoteTiledMapProviderBase is an abstract class that used to aggregate the third-party map services. It implements ProviderContextAware and MapProvider. (See: RemoteTiledMapProviderBase_Extension) |
|
com.supermap.services.components.spi.LocalTiledMapProviderBase | LocalTileProviderBase is an abstract class for extending the local map tile service, and the local map tiles are derived from ArcGIS. (See: LocalTiledMapProviderBase_Extension) |
|
Other implementation classes (See: Service Provider Introduction) | ||
DataProvider | com.supermap.services.components.spi.DataProvider | All data providers need to implement this interface. The service provider that implements the interface can be used by the data component. |
Other implementation classes (See: Service Provider Introduction) | ||
SpatialAnalystProvider | com.supermap.services.components.spi.SpatialAnalystProvider | All spatial analysis providers need to implement this interface. The service provider that implements the interface can be used by the spatial analysis component. |
Other implementation classes (See: Service Provider Introduction) | ||
TransportationAnalystProvider | com.supermap.services.providers.spi.TransportationAnalystProvider | All transportation analysis providers need to implement this interface. The service provider that implements the interface can be used by the transportation analysis component. |
Other implementation classes (See: Service Provider Introduction) | ||
RealspaceProvider | com.supermap.services.components.spi.RealspaceProvider | All realspace providers need to implement this interface. The service provider that implements the interface can be used by the realspace component. |
Other implementation classes (See: Service Provider Introduction) |
The restrictions above are not applicable to defining new service provider types to realize functions in a certain domain.
In the service provider implementation class, the service provider context can be obtained through the ProviderContextAware interface, and the service provider configuration information can be obtained through the service provider context.
The configuration information of the service components is in services.xml. Below is the configuration for a service component: The configuration of service provider is as follows:
<provider class="com.supermap.sample.SampleProvider" name="sampleProvider">
<config class="com.supermap.sample.SampleProviderSetting">
<param1>default</param1>
...
</config>
</provider>
Where, SampleProviderSetting is the configuration class of SampleProvider. param1 is the property of SampleProviderSetting. Through SampleProviderSetting, the service providers with different types and sources can be built together in iServer.
In the implementation class of the service provider, the service provider context which enables to get configuration (services.xml) of the service provider can be obtained from the ProviderContextAware interface.
public class SampleProvider implements ProviderContextAware{
...
public void setProviderContext(ProviderContext context) {
SampleProviderSetting sampleProviderSetting = context.getConfig(SampleProviderSetting.class);
...
}
}
Where sampleProviderSetting is the configuration item <config/> of <provider/> in services.xml.
RemoteTiledMapProviderBase is an abstract class that used to aggregate the third-party map services and build online map providers. It implements ProviderContextAware and MapProvider.
The main output method of this class is getTileImageUrl(TileImageParameter tileImageParameter).
You can aggregate a third-party map services by inheriting from the abstract class of RemoteTileProviderBase.
The methods are shown as follows:
Note:
Place the compiled classes files to %SuperMap iServer_HOME%\webap\ iserver\WEB-INF\(classes folder does not exist by default.), or the jar package to %SuperMap iServer_HOME%\webap\ iserver\WEB-INF\lib\. iServer can use extensions of the service provider classes. For configuration, see Configure service provider by XML.
cacheEnabled() returns true or false that can be used to enable or disable using cache.
When MapParameter.cacheEnabled is true, the system uses image cache. The catalog is MapProviderSetting.getOutputPath(), and its path is "cache\MapName_ImageWidthxImageHeight\ScaleReciprocal\ImagexIndex\ImageyIndex.ImageSuffix". Meanwhile, this class also enables to cache the third-party map services, and the path is "cache\http\MapName_ImageWidthxImageHeight\ScaleReciprocal\ImagexIndexImageyIndex.ImageSuffix".
Here you are allowed to extend a map service provider. GoogleMapsMapProvider is inherited from TiledMapProviderBase. You can find the sample code in %SuperMap iServer_HOME%/samples/code/DSSE/GoogleMapsProviderSample.
The code for the implementation of GoogleMapsProvider is as follows:
package com.supermap.sample.serviceprovider; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.URL; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import org.apache.commons.io.IOUtils; import com.supermap.services.components.commontypes.Layer; import com.supermap.services.components.commontypes.MapParameter; import com.supermap.services.components.commontypes.OutputFormat; import com.supermap.services.components.commontypes.Point2D; import com.supermap.services.components.commontypes.PrjCoordSys; import com.supermap.services.components.commontypes.Rectangle; import com.supermap.services.components.commontypes.Rectangle2D; import com.supermap.services.components.commontypes.RectifyType; import com.supermap.services.components.commontypes.Unit; import com.supermap.services.providers.RemoteTileProviderBase; import com.supermap.services.util.TileTool; import com.supermap.services.util.Tool; /** * * Google Maps The map service provider *
* * GoogleMapsMapProvider supports integrating Google Maps, and all the GIS functions related to SuperMap iServer are also included. *
* */ public class GoogleMapsMapProvider extends RemoteTileProviderBase { private static final String GOOGLEMAPSADRESSTEMPLATE = "http://mt1.google.cn/vt/hl=zh-CN&x=%d&y=%d&z=%d"; private static final String MAPNAME = "googlemaps"; private static final long EARTH_RADIUS = 6378137; private static final int LEVEL_COUNT = 18; private static final double GOOGLE_DPI = 96.0; private static final double RESOLUTION_PRECISION = 1E-6; private double[] resolutions; /** * * Google Map tile URL *
* @param tileParam tile parameters */ @Override protected String getTileImageUrl(TileImageParameter tileImageParameter) { int z = getLevelByResolution(tileImageParameter.resolution); String googleImageUrl = String.format(GOOGLEMAPSADRESSTEMPLATE, tileImageParameter.x, tileImageParameter.y, z); return googleImageUrl; } @Override protected boolean cacheEnabled() { return false; } @Override protected Point2D getOrigin(String arg0) { return new Point2D(-20037508.3427892, 20037508.3427892); } /** * * * Return the set of formats supported by the specified map *
* @param mapName * @return * @since 7.1.0 */ @Override public OutputFormat[] getSupportImageFormat(String arg0) { return new OutputFormat[0]; } @Override public double[] getSupportResolutions(String arg0) { if (resolutions == null) { /** * Level 0 Resolution = equator perimeter/256 pixels */ double resolution = 2 * Math.PI * EARTH_RADIUS / 256.0; resolutions = new double[LEVEL_COUNT]; for (int i = 0; i < LEVEL_COUNT; i++) { resolutions[i] = resolution; resolution /= 2.0; } } return resolutions.clone(); } /** * * Initialize default map status. The returned value is a mapping, and the key is the map name, and the value is the map parameter object. *
* * @return map status mapping. The key is the map name, and the value is the map parameter object. */ @Override protected Map<String, MapParameter> initDefaultMapParameter() { String mapName = MAPNAME; MapParameter defaultMapParameter = new MapParameter(); defaultMapParameter.name = mapName; defaultMapParameter.coordUnit = Unit.METER; defaultMapParameter.distanceUnit = Unit.METER; defaultMapParameter.viewer = new Rectangle(0, 0, 256, 256); defaultMapParameter.bounds = new Rectangle2D(-20037508.3427892, -20037508.3427892, 20037508.3427892, 20037508.3427892); defaultMapParameter.viewBounds = new Rectangle2D(defaultMapParameter.bounds); defaultMapParameter.center = defaultMapParameter.viewBounds.center(); defaultMapParameter.customEntireBoundsEnabled = false; defaultMapParameter.description = ""; defaultMapParameter.prjCoordSys = new PrjCoordSys(); defaultMapParameter.prjCoordSys.coordUnit = Unit.METER; defaultMapParameter.prjCoordSys.distanceUnit = Unit.METER; defaultMapParameter.prjCoordSys.epsgCode = 3857; defaultMapParameter.rectifyType = RectifyType.BYCENTERANDMAPSCALE; defaultMapParameter.visibleScalesEnabled = true; defaultMapParameter.visibleScales = getSupportScales(); defaultMapParameter.scale = defaultMapParameter.visibleScales[0]; defaultMapParameter.layers = new ArrayList<Layer>(); GoogleMapLayer layer = new GoogleMapLayer(); layer.name = defaultMapParameter.name; layer.caption = defaultMapParameter.name; layer.bounds = new Rectangle2D(defaultMapParameter.bounds); layer.description = "Google Maps Layer"; layer.visible = true; defaultMapParameter.layers.add(layer); Map<String, MapParameter> result = new HashMap<String, MapParameter>(); result.put(mapName, defaultMapParameter); return result; } /** * Initialize the list of maps supported. * * @return List of map names */ @Override protected List<String> initSupportedMapNames() { List<String> names = new ArrayList<String>(); names.add(MAPNAME); return names; } private int getLevelByResolution(double resolution) { resolutions = getSupportResolutions(MAPNAME); for (int i = 0; i < resolutions.length; i++) { if (Tool.equal(resolution, resolutions[i], RESOLUTION_PRECISION)) { return i; } } return -1; } private double[] getSupportScales() { double[] resolutions = getSupportResolutions(MAPNAME); double[] scales = new double[LEVEL_COUNT]; for (int i = 0; i < LEVEL_COUNT; i++) { scales[i] = TileTool.resolutionToScale(resolutions[i], GOOGLE_DPI, Unit.METER); } return scales; } /** * * Send the request to the remote server according to the parameters *
*/ @Override protected Map<String, Object> sendRequestByHttpURLConnection(String paramString1, String paramString2, InputStream paramInputStream, Map<String, String> paramMap, int paramInt) { InputStream localInputStream = null; HttpURLConnection localHttpURLConnection = null; OutputStream localOutputStream = null; int i = paramInt; HashMap<String, Object> localHashMap = new HashMap<String, Object>(); try { URL localURL = new URL(paramString1); localHttpURLConnection = (HttpURLConnection) localURL.openConnection(); localHttpURLConnection.setRequestMethod(paramString2); if ((paramString2.equals("POST")) || (paramString2.equals("PUT"))) { localHttpURLConnection.setDoOutput(true); } localHttpURLConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8"); localHttpURLConnection.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.116 Safari/537.36"); localHttpURLConnection.setRequestProperty("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"); localHttpURLConnection.setRequestProperty("Accept-Encoding", "gzip,deflate,sdch"); localHttpURLConnection.setRequestProperty("Accept-Language", "zh-CN,zh;q=0.8"); if (paramMap != null) { Iterator<?> localIterator = paramMap.entrySet().iterator(); while (localIterator.hasNext()) { @SuppressWarnings("rawtypes") Map.Entry localEntry = (Map.Entry) localIterator.next(); localHttpURLConnection.setRequestProperty((String) localEntry.getKey(), (String) localEntry.getValue()); } } localHttpURLConnection.setConnectTimeout(40000); localHttpURLConnection.setReadTimeout(20000); if ((paramInputStream != null) && (localHttpURLConnection.getDoOutput())) { localOutputStream = localHttpURLConnection.getOutputStream(); IOUtils.copy(paramInputStream, localOutputStream); localOutputStream.flush(); localOutputStream.close(); paramInputStream.close(); } int responseCode = localHttpURLConnection.getResponseCode(); localHashMap.put("status", Integer.valueOf(responseCode)); if (responseCode < 400) { localInputStream = localHttpURLConnection.getInputStream(); } else { logger.info(message.getMessage("TiledMapProvider.sendRequestByHttpURLConnection.RequestError", new String[] { paramString1, String.valueOf(responseCode) })); } if (localInputStream != null) localHashMap.put("ENTITY", localInputStream); } catch (IOException localIOException) { if (i < 5) { logger.debug(message.getMessage("URL_REQUEST_EXCEPTION", new String[] { paramString1, localIOException.getMessage(), String.valueOf(i) })); return sendRequestByHttpURLConnection(paramString1, paramString2, paramInputStream, ++i); } logger.debug(message.getMessage("URL_REQUEST_FAILED", new String[] { paramString1, String.valueOf(i) })); } return localHashMap; } }
GoogleMapLayer in GoogleMapsMapProvider class represents that the current map uses the Google layer (When extend other provider, you can refer to GoogleMapLayer to define corresponding Layer). The codes of GoogleMapLayer are as follows:
package com.supermap.sample.serviceprovider; import com.supermap.services.components.commontypes.Layer; import com.supermap.services.components.commontypes.LayerType; import com.supermap.services.components.commontypes.Rectangle2D; public class GoogleMapLayer extends Layer { private static final long serialVersionUID = 1L; public GoogleMapLayer() { this.type = LayerType.CUSTOM; } @Override public Layer copy() { GoogleMapLayer googleLayer = new GoogleMapLayer(); googleLayer.name = this.name; googleLayer.type = this.type; googleLayer.bounds = new Rectangle2D(this.bounds); googleLayer.caption = this.caption; googleLayer.visible = this.visible; return googleLayer; } }
Configuration class uses MapProviderSetting, as follows:
<provider class="com.supermap.sample.serviceprovider.GoogleMapsMapProvider" name="mapProvider-GoogleMaps">
<config class="com.supermap.services.components.spi.MapProviderSetting">
</config>
</provider>
Place the Jar package in %SuperMap iServer_HOME%/webapps/iserver/WEB-INF/lib after compiling.
Create a new map component--map-google to publish rest, WMS 1.1.1 services using mapProvider-GoogleMaps.
<component class="com.supermap.services.components.impl.MapImpl" interfaceNames="rest,wms111" name="map-google" providers="mapProvider-GoogleMaps">
<config class="com.supermap.services.components.MapConfig">
</config>
</component>
Access the map REST service with the root URI: http://<host>:<port>/iserver/services/map-google/rest. And access the map with the name googlemaps, which is declared in the implementation class of GoogleMapsMapProvider, through http://<host>:<port>/iserver/services/map-google/rest/maps/googlemaps.ijs. with the result shown as below:
LocalTileProviderBase is used to extend the local map tile service. It implements the ProviderContextAware and MapProvider.
The method used to output map is getTileImage(TiledMapProviderBase.TileImageParameterparamTileImageParameter).
Users can inherit LocalTileProviderBase to extend the local map tile service.
Methods to use:
Note:
Configure and Deploy
Place the compiled classes files to %SuperMap iServer_HOME%\webap\ iserver\WEB-INF\, or the jar package to %SuperMap iServer_HOME%\webap\ iserver\WEB-INF\lib\. iServer can use extensions of the service provider classes. For configuration, see Configure service provider by XML.
About Cache
cacheEnabled() returns true or false which is used to set using cache or not.
rue means to use cache. The image cache directory, namely, the directory of MapProviderSetting.getOutputPath(), is “cache\MapName_ImageWidth x ImageHeight\ScaleReciprocal\Image x Index\Image y Index.ImageSuffix". Meanwhile, this class also caches for the third-party map services, and the path is "cache\http\MapName_ImageWidth x ImageHeight\ScaleReciprocal\Image x Index\Image y Index.ImageSuffix".
The sample takes ArcGISExplodedCacheMapProvider as an example which inherits from the class LocalTileProviderBase to demonstrate how to publish your local ArcGIS Server map tiles to SuperMap services. You can find the sample code in %SuperMap iServer_HOME%/samples/code/DSSE/ArcGISExplodedCacheMapProviderSample.
Notes: When generating ArcGIS Server tiles, choose "Exploded" as the format, and choose from NG8, PNG24, PNG32 as the image format.
ArcGISExplodedCacheMapProvider Sample Code:
ArcGISExplodedCacheMapProvider.java
package com.supermap.sample.serviceprovider; import java.awt.image.BufferedImage; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.imageio.ImageIO; import org.apache.commons.lang3.StringUtils; import com.supermap.services.components.commontypes.Layer; import com.supermap.services.components.commontypes.MapParameter; import com.supermap.services.components.commontypes.OutputFormat; import com.supermap.services.components.commontypes.Point2D; import com.supermap.services.components.commontypes.Rectangle; import com.supermap.services.components.commontypes.Rectangle2D; import com.supermap.services.components.commontypes.RectifyType; import com.supermap.services.components.commontypes.Unit; import com.supermap.services.providers.LocalTileProviderBase; import com.supermap.services.util.PrjCoordSysConversionTool; import com.supermap.services.util.TileTool; /** * * ArcGIS exploded cache.The map service provider. *
* * ArcGISExplodedCacheMapProvider supports integrating ArcGIS Exploded caches, and all the GIS functions related to SuperMap iServer are also included. *
* */ public class ArcGISExplodedCacheMapProvider extends LocalTileProviderBase { private static final String MAPNAME = "arcgismaps"; private double[] scales; private double[] resolutions = null; private Point2D origin; /** * * Get tiles *
* @param tileParam tile parameters * @param x * @param x * @param y * @param resolution Resolution * @return */ @Override protected byte[] getTileImage(TileImageParameter paramTileImageParameter) { ArcGISExplodedCacheMapProviderSetting setting = (ArcGISExplodedCacheMapProviderSetting) this.getMapProviderSetting(); String arcgisMapsAdressTemplate = setting.getCachePath(); arcgisMapsAdressTemplate += "/_alllayers/L%02d/R%08x/C%08x.png"; int z = getLevelByResolution(paramTileImageParameter.resolution); if (z < 0) { return TileTool.getBlankImageByte("",this.tilePixWidth, this.tilePixHeight, paramTileImageParameter.outputOption.transparent); } String arcgisImagePath = String.format(arcgisMapsAdressTemplate, z, paramTileImageParameter.y, paramTileImageParameter.x); if (!new File(arcgisImagePath).exists()) { return TileTool.getBlankImageByte("",this.tilePixWidth, this.tilePixHeight, paramTileImageParameter.outputOption.transparent); } BufferedImage image = null; FileInputStream fs = null; byte[] imagebyte = null; try { fs = new FileInputStream(arcgisImagePath); image = ImageIO.read(fs); imagebyte = TileTool.getBytesFromBufferedImage(image, "PNG"); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { try { fs.close(); } catch (IOException e) { e.printStackTrace(); } } return imagebyte; } /** * * 初始化支持的地图列表。 * * * Initialize the supported map list. * @return * * 地图名列表 * * Map name list * */ @Override protected List<String> initSupportedMapNames() { List<String> names = new ArrayList<String>(); names.add(getMapName()); return names; } /** * * 初始化默认地图状态,返回值为一个映射,键为地图名,值为地图参数对象。 * * * Initialize the default map status. Return value is a mapping. The key is the map name and the value is the map parameter object. * * @return 地图状态映射,键为地图名,值为地图参数对象。 * Map status mapping. The key is the map name, and the value is the parameter object. */ @Override protected Map<String, MapParameter> initDefaultMapParameter() { String mapName = getMapName(); ArcGISExplodedCacheMapProviderSetting setting = (ArcGISExplodedCacheMapProviderSetting) this.getMapProviderSetting(); if (StringUtils.isBlank(setting.getCachePath())) { throw new IllegalArgumentException("cahcePath is null"); } ArcGISXMLParseTool arcgisXmlParseTool = new ArcGISXMLParseTool(getConfXMLPath()); tilePixHeight = arcgisXmlParseTool.getTileRows(); tilePixWidth = arcgisXmlParseTool.getTileCols(); MapParameter defaultMapParameter = new MapParameter(); defaultMapParameter.name = mapName; defaultMapParameter.prjCoordSys = PrjCoordSysConversionTool.getPrjCoordSys(arcgisXmlParseTool.getWkid()); defaultMapParameter.coordUnit = defaultMapParameter.prjCoordSys.coordUnit; defaultMapParameter.distanceUnit = Unit.METER; defaultMapParameter.viewer = new Rectangle(0, 0, arcgisXmlParseTool.getTileCols(), arcgisXmlParseTool.getTileRows()); defaultMapParameter.bounds = arcgisXmlParseTool.getBounds(getConfCDIPath()); defaultMapParameter.center = defaultMapParameter.bounds.center(); double[] resolutionArray = getSupportResolutions(mapName); defaultMapParameter.viewBounds = new Rectangle2D(defaultMapParameter.center.x - arcgisXmlParseTool.getTileCols() * resolutionArray[0] * 0.5, defaultMapParameter.center.y - arcgisXmlParseTool.getTileRows() * resolutionArray[0] * 0.5, defaultMapParameter.center.x + arcgisXmlParseTool.getTileCols() * resolutionArray[0] * 0.5, defaultMapParameter.center.y + arcgisXmlParseTool.getTileRows() * resolutionArray[0] * 0.5); defaultMapParameter.customEntireBoundsEnabled = false; defaultMapParameter.rectifyType = RectifyType.BYCENTERANDMAPSCALE; defaultMapParameter.visibleScalesEnabled = true; defaultMapParameter.visibleScales = getSupportScales(); defaultMapParameter.scale = defaultMapParameter.visibleScales[0]; defaultMapParameter.layers = new ArrayList<Layer>(); ArcGISExplodedCacheMapLayer layer = new ArcGISExplodedCacheMapLayer(); layer.name = defaultMapParameter.name; layer.bounds = new Rectangle2D(defaultMapParameter.bounds); layer.visible = true; defaultMapParameter.layers.add(layer); Map<String, MapParameter> result = new HashMap<String, MapParameter>(); result.put(mapName, defaultMapParameter); return result; } /** * * * 返回指定地图支持的图片格式数组 * * * Return image format array supported by specified map * * @param mapName * @return * @since 7.1.0 */ @Override public OutputFormat[] getSupportImageFormat(String paramString) { return new OutputFormat[0]; } /** * * 获取地图的左上角地理坐标。 * * * Get the geographical coordinates of map top left corner. * * @param 地图名 * * Map name * * @return 地图的左上角地理坐标。 * * The geographical coordinates of map top left corner. * */ @Override protected Point2D getOrigin(String paramString) { ArcGISXMLParseTool arcgisXmlParseTool = new ArcGISXMLParseTool(getConfXMLPath()); if (origin == null) { origin = arcgisXmlParseTool.getTileOrigin(); return origin; } return origin; } @Override protected boolean cacheEnabled() { return false; } /** * * 返回当前服务支持的分辨率 。如果支持所有分辨率,则返回空。 * * * Return the resolutions supported by current services. If all resolutions are supported, return null. * * @param mapName * * @return 分辨率数组 * * Resolution array * */ @Override public double[] getSupportResolutions(String paramString) { ArcGISXMLParseTool arcgisXmlParseTool = new ArcGISXMLParseTool(getConfXMLPath()); if (resolutions == null) { resolutions = arcgisXmlParseTool.getResolutions(); } return resolutions; } private int getLevelByResolution(double resolution) { ArcGISXMLParseTool arcgisXmlParseTool = new ArcGISXMLParseTool(getConfXMLPath()); for (int i = 0; i < arcgisXmlParseTool.getResolutions().length; i++) { if (resolution == arcgisXmlParseTool.getResolutions()[i]) { return i; } } return -1; } private double[] getSupportScales() { ArcGISXMLParseTool arcgisXmlParseTool = new ArcGISXMLParseTool(getConfXMLPath()); if (scales == null) { scales = arcgisXmlParseTool.getScales(); } return scales; } private String getConfXMLPath() { ArcGISExplodedCacheMapProviderSetting setting = (ArcGISExplodedCacheMapProviderSetting) this.getMapProviderSetting(); String path = setting.getCachePath() + "/conf.xml"; return path; } private String getConfCDIPath() { ArcGISExplodedCacheMapProviderSetting setting = (ArcGISExplodedCacheMapProviderSetting) this.getMapProviderSetting(); String path = setting.getCachePath() + "/conf.cdi"; return path; } private String getMapName() { ArcGISExplodedCacheMapProviderSetting setting = (ArcGISExplodedCacheMapProviderSetting) this.getMapProviderSetting(); if (StringUtils.isNotBlank(setting.getMapName())) { return setting.getMapName(); } return MAPNAME; } }
For the class ArcGISExplodedCacheMapProvider, ArcGISExplodedCacheMapLayer means ArcGIS layer is used currently(to extend other map provider, please refer to ArcGISExplodedCacheMapLayer to define the Layer).
ArcGISExplodedCacheMapLayer Sample Code:
ArcGISExplodedCacheMapLayer.java
package com.supermap.sample.serviceprovider; import com.supermap.services.components.commontypes.Layer; import com.supermap.services.components.commontypes.LayerType; import com.supermap.services.components.commontypes.Rectangle2D; public class ArcGISExplodedCacheMapLayer extends Layer { private static final long serialVersionUID = 1L; public ArcGISExplodedCacheMapLayer() { this.type = LayerType.CUSTOM; } @Override public Layer copy() { ArcGISExplodedCacheMapLayer arcgisLayer = new ArcGISExplodedCacheMapLayer(); arcgisLayer.name = this.name; arcgisLayer.type = this.type; arcgisLayer.bounds = new Rectangle2D(this.bounds); arcgisLayer.caption = this.caption; arcgisLayer.visible = this.visible; return arcgisLayer; } }
ArcGISXMLParseTool is used to get the conf.xml file of the ArcGIS Server tile directory and some node values in the conf.cdi file.
conf.xml file is as follows:
conf.cdi file is as follows:
ArcGISXMLParseTool Sample Code:
package com.supermap.sample.serviceprovider; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import com.supermap.services.components.commontypes.Point2D; import com.supermap.services.components.commontypes.Rectangle2D; /** * * The class to read the conf file of ArcGIS Server caches. Get the info of conf.xml and conf.cdi. *
* * ArcGISXMLParseTool provides the function to read the info of the conf.xml and conf.cdi file. *
* */ public class ArcGISXMLParseTool { private static DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); private double[] resolutions; private double[] scales; private int wkid, tileCols, tileRows; private String cachePath; /** * * Construct function with parameters *
* * @param cache map cache directory */ public ArcGISXMLParseTool(String cachePath) { this.cachePath = cachePath; } /** * * Get the set of scales. *
* @return the set of scales */ public double[] getScales() { try { DocumentBuilder db = dbf.newDocumentBuilder(); Document doc = db.parse(cachePath); NodeList scaleDenominatorList = doc.getElementsByTagName("Scale"); scales = new double[scaleDenominatorList.getLength()]; for (int i = 0; i < scaleDenominatorList.getLength(); i++) { Node scaleDenominatorNode = scaleDenominatorList.item(i); scales[i] = 1 / Double.parseDouble(scaleDenominatorNode.getTextContent()); } } catch (Exception e) { e.printStackTrace(); } if (scales == null) { return new double[0]; } return scales; } /** * * Get the set of resolutions *
* @return the set of resolutions */ public double[] getResolutions() { try { DocumentBuilder db = dbf.newDocumentBuilder(); Document doc = db.parse(cachePath); NodeList resolutionList = doc.getElementsByTagName("Resolution"); resolutions = new double[resolutionList.getLength()]; for (int i = 0; i < resolutionList.getLength(); i++) { Node resolutionNode = resolutionList.item(i); resolutions[i] = Double.parseDouble(resolutionNode.getTextContent()); } } catch (Exception e) { e.printStackTrace(); } if (resolutions == null) { return new double[0]; } return resolutions; } /** * * Get map WKID *
* @return map WKID */ public int getWkid() { try { DocumentBuilder db = dbf.newDocumentBuilder(); Document doc = db.parse(cachePath); NodeList wkidList = doc.getElementsByTagName("WKID"); Node wkidNode = wkidList.item(0); wkid = Integer.parseInt(wkidNode.getTextContent()); } catch (Exception e) { e.printStackTrace(); } return wkid; } /** * * Get the width of tile *
* @return the width of tile */ public int getTileCols() { try { DocumentBuilder db = dbf.newDocumentBuilder(); Document doc = db.parse(cachePath); NodeList tileColsList = doc.getElementsByTagName("TileCols"); Node tileColsNode = tileColsList.item(0); tileCols = Integer.parseInt(tileColsNode.getTextContent()); } catch (Exception e) { e.printStackTrace(); } return tileCols; } /** * * Get the height of tile *
* @return the height of tile */ public int getTileRows() { try { DocumentBuilder db = dbf.newDocumentBuilder(); Document doc = db.parse(cachePath); NodeList tileRowsList = doc.getElementsByTagName("TileRows"); Node tileRowsNode = tileRowsList.item(0); tileRows = Integer.parseInt(tileRowsNode.getTextContent()); } catch (Exception e) { e.printStackTrace(); } return tileRows; } /** * * Get the origin of the tile * * @return the origin of the tile */ public Point2D getTileOrigin() { double originX = 0; double originY = 0; try { DocumentBuilder db = dbf.newDocumentBuilder(); Document doc = db.parse(cachePath); NodeList originXList = doc.getElementsByTagName("X"); NodeList originYList = doc.getElementsByTagName("Y"); originX = Double.parseDouble(originXList.item(0).getTextContent()); originY = Double.parseDouble(originYList.item(0).getTextContent()); } catch (Exception e) { e.printStackTrace(); } return new Point2D(originX, originY); } /** * * Get the entire extent * * @return the entire extent */ public Rectangle2D getBounds(String cdiPath) { double leftBottomX = 0; double leftBottomY = 0; double rightTopX = 0; double rightTopY = 0; try { DocumentBuilder db = dbf.newDocumentBuilder(); Document doc = db.parse(cdiPath); NodeList leftBottomXList = doc.getElementsByTagName("XMin"); NodeList leftBottomYList = doc.getElementsByTagName("YMin"); NodeList rightTopXList = doc.getElementsByTagName("XMax"); NodeList rightTopYList = doc.getElementsByTagName("YMax"); leftBottomX = Double.parseDouble(leftBottomXList.item(0).getTextContent()); leftBottomY = Double.parseDouble(leftBottomYList.item(0).getTextContent()); rightTopX = Double.parseDouble(rightTopXList.item(0).getTextContent()); rightTopY = Double.parseDouble(rightTopYList.item(0).getTextContent()); } catch (Exception e) { e.printStackTrace(); } return new Rectangle2D(leftBottomX, leftBottomY, rightTopX, rightTopY); } }
ArcGISExplodedCacheMapProviderSetting inherits from MapProviderSetting. It is used to extend MapProviderSetting to set some specific map parameters. cachePath is the path to store the map caches and mapName is the map name.
ArcGISExplodedCacheMapProviderSetting Sample Code:
ArcGISExplodedCacheMapProviderSetting.java
package com.supermap.sample.serviceprovider; import com.supermap.services.components.spi.MapProviderSetting; public class ArcGISExplodedCacheMapProviderSetting extends MapProviderSetting { private static final long serialVersionUID = 1L; private String cachePath; private String mapName; public String getMapName() { return mapName; } public void setMapName(String mapName) { this.mapName = mapName; } public String getCachePath() { return cachePath; } public void setCachePath(String cachePath) { this.cachePath = cachePath; } }
Use ArcGISExplodedCacheMapProviderSetting that herits from MapProviderSetting to do the settings. You must set the cache path by <cachePath>. Optionally set the map name by <mapName>. If the map name is not set, the default will be used. Here shows how to do the settings:
<provider class="com.supermap.sample.serviceprovider.ArcGISExplodedCacheMapProvider" name="mapProvider-ArcGISExplodedCacheMap">
<config class="com.supermap.sample.serviceprovider.ArcGISExplodedCacheMapProviderSetting">
<cachePath>C:/arcgisserver/arcgiscache/China400/China400</cachePath>
<mapName></mapName>
</config>
</provider>
Place the compiled Jar to %SuperMap iServer_HOME%/webapps/iserver/WEB-INF/lib.
Create a new "map service component" map-arcgis that uses mapProvider-ArcGISMaps, and publish the service as rest, WMS 1.1.1:
<component class="com.supermap.services.components.impl.MapImpl" enabled="true" interfaceNames="wms111,rest" name="map-arcgis" providers="mapProvider-ArcGISExplodedCacheMap">
</component>
Access the map REST functions via URI:http://<host>:<port>/iserver/services/map-arcgis/rest. Access the map via http://<host>:<port>/iserver/services/map-arcgis/rest/maps/arcgismaps.ijs. Arcgismaps is the map name that is declared in ArcGISExplodedCacheMapProvider. The result is as follows: