Mapserver Plug-in Infastructure: RFC and PATCH

Jani Averbach javerbach at EXTENDTHEREACH.COM
Wed Aug 17 18:44:44 EDT 2005


Hello,

This proposal (and patch) provides plug-in infrastructure for layers.

The main idea is that we add new connection type "custom" and use
processing with "lib=library_name" to tell which library to load for
this custom layer. Also layerObj will hold a virtual table, which will
contain function pointers to the actual layer functions. The custom
layer library has to implement following function:

   int InitializeLayerVirtualTable(layerVTableObj *vtable, layerObj *layer);

which will populate layer's vtable. After that custom layer functions
will call actually this library's functions via this vtable.

The layer's DLL is loaded and vtable initialized in msCustomLayerOpen,
if it is not yet done.

Detailed list of changes and prototype patch is at the end of this
email. The patch is generated against Mapserver 4.6.0 source code, if
it looks good and general concepts are fine, then I will port it
against CVS source.

The second phase could be that we remove all those switch
statements and use this vtable also for internal layers.

Best Regards,
Jani

ChangeLog:

mapthread.h:
- New lock handle, TLOCK_LAYER_VTABLE
  This is used to protect customlayer virtual table factory/cache.

mapfile.c:
- New connection type: MS_CUSTOM

map.h:
- New enum MS_CUSTOM
- New type layerVTableObj

struct layerVTable {
	int (*fpLayerInitItemInfo)(layerObj *layer);
	void (*fpLayerFreeItemInfo)(layerObj *layer);
	int (*fpLayerOpen)(layerObj *layer);
	int (*fpLayerIsOpen)(layerObj *layer);
	int (*fpLayerWhichShapes)(layerObj *layer, rectObj rect);
	int (*fpLayerNextShape)(layerObj *layer, shapeObj *shape);
	int (*fpLayerGetShape)(layerObj *layer, shapeObj *shape, int tile, long
record);
	int (*fpLayerClose)(layerObj *layer);
	int (*fpLayerGetItems)(layerObj *layer);
	int (*fpLayerGetExtent)(layerObj *layer, rectObj *extent);
	int (*fpLayerGetAutoStyle)(mapObj *map, layerObj *layer, classObj *c, int
tile, long record);
};

- layerObj, added a new field: layerVTableObj *vtable

- New function, msGetSymbol for on demand loading DLLs (taken from GDAL
project)
  void *msGetSymbol(const char *pszLibrary, const char *pszEntryPoint);

- Prototypes for custom layer functions
  MS_DLL_EXPORT int msCustomLayerOpen(layerObj *layer);
  and so on.

mapgetsymbol.c:
- New file, code taken from GDAL project. This will load library file
  for the custom layer.

maplayer.c:
- Added MS_CUSTOM to every switch statement

maplexer.l:
- Added new token "custom"

mapcustomlayer.c:
- New file, All heavy lifting regarding custom layers is handled here.

makefile.in:
- Added mapcustomlayer.c and mapgetsymbol.c to the OBJ list


Index: mapthread.h
===================================================================
--- mapthread.h	(revision 10904)
+++ mapthread.h	(revision 10943)
@@ -66,6 +66,7 @@
 #define TLOCK_PROJ      4
 #define TLOCK_TTF       5
 #define TLOCK_POOL      6
+#define TLOCK_LAYER_VTABLE  7

 #define TLOCK_STATIC_MAX 20
 #define TLOCK_MAX       100
Index: mapfile.c
===================================================================
--- mapfile.c	(revision 10904)
+++ mapfile.c	(revision 10943)
@@ -2256,6 +2256,7 @@

   layer->connection = NULL;
   layer->connectiontype = MS_SHAPEFILE;
+  layer->vtable = NULL;

   layer->layerinfo = NULL;
   layer->ogrlayerinfo = NULL;
@@ -2380,7 +2381,7 @@
       if(getString(&layer->connection) == MS_FAILURE) return(-1);
       break;
     case(CONNECTIONTYPE):
-      if((layer->connectiontype = getSymbol(8, MS_SDE, MS_OGR, MS_POSTGIS,
MS_WMS, MS_ORACLESPATIAL, MS_WFS, MS_GRATICULE, MS_MYGIS)) == -1)
return(-1);
+      if((layer->connectiontype = getSymbol(9, MS_SDE, MS_OGR, MS_POSTGIS,
MS_WMS, MS_ORACLESPATIAL, MS_WFS, MS_GRATICULE, MS_MYGIS, MS_CUSTOM)) == -1)
return(-1);
       break;
     case(DATA):
       if(getString(&layer->data) == MS_FAILURE) return(-1);
Index: map.h
===================================================================
--- map.h	(revision 10904)
+++ map.h	(revision 10943)
@@ -482,7 +482,7 @@
     enum MS_LABEL_POSITIONS {MS_UL, MS_LR, MS_UR, MS_LL, MS_CR, MS_CL,
MS_UC, MS_LC, MS_CC, MS_AUTO, MS_XY}; /* arrangement matters for auto
placement, don't change it */
     enum MS_BITMAP_FONT_SIZES {MS_TINY , MS_SMALL, MS_MEDIUM, MS_LARGE,
MS_GIANT};
     enum MS_QUERYMAP_STYLES {MS_NORMAL, MS_HILITE, MS_SELECTED};
-    enum MS_CONNECTION_TYPE {MS_INLINE, MS_SHAPEFILE, MS_TILED_SHAPEFILE,
MS_SDE, MS_OGR, MS_UNUSED_1, MS_POSTGIS, MS_WMS, MS_ORACLESPATIAL, MS_WFS,
MS_GRATICULE, MS_MYGIS, MS_RASTER };
+    enum MS_CONNECTION_TYPE {MS_INLINE, MS_SHAPEFILE, MS_TILED_SHAPEFILE,
MS_SDE, MS_OGR, MS_UNUSED_1, MS_POSTGIS, MS_WMS, MS_ORACLESPATIAL, MS_WFS,
MS_GRATICULE, MS_MYGIS, MS_RASTER, MS_CUSTOM };
     enum MS_JOIN_CONNECTION_TYPE {MS_DB_XBASE, MS_DB_CSV, MS_DB_MYSQL,
MS_DB_ORACLE, MS_DB_POSTGRES};
     enum MS_JOIN_TYPE {MS_JOIN_ONE_TO_ONE, MS_JOIN_ONE_TO_MANY};

@@ -494,8 +494,10 @@


 #define MS_FILE_DEFAULT MS_FILE_MAP
-

+struct layerVTable;
+typedef struct layerVTable layerVTableObj;
+
 /* FONTSET OBJECT - used to hold aliases for TRUETYPE fonts */
     typedef struct {
 #ifdef SWIG
@@ -1004,6 +1006,7 @@

   char *connection;
   enum MS_CONNECTION_TYPE connectiontype;
+  const layerVTableObj *vtable;

 #ifndef SWIG
   struct layer_obj *sameconnection;
@@ -1211,6 +1214,20 @@
 #endif
 } imageObj;

+/* LAYER_VTABLE, contains function pointers to the layer operations */
+struct layerVTable {
+    int (*fpLayerInitItemInfo)(layerObj *layer);
+    void (*fpLayerFreeItemInfo)(layerObj *layer);
+    int (*fpLayerOpen)(layerObj *layer);
+    int (*fpLayerIsOpen)(layerObj *layer);
+    int (*fpLayerWhichShapes)(layerObj *layer, rectObj rect);
+    int (*fpLayerNextShape)(layerObj *layer, shapeObj *shape);
+    int (*fpLayerGetShape)(layerObj *layer, shapeObj *shape, int tile, long
record);
+    int (*fpLayerClose)(layerObj *layer);
+    int (*fpLayerGetItems)(layerObj *layer);
+    int (*fpLayerGetExtent)(layerObj *layer, rectObj *extent);
+    int (*fpLayerGetAutoStyle)(mapObj *map, layerObj *layer, classObj *c,
int tile, long record);
+};

 /* Function prototypes, wrapable */
 MS_DLL_EXPORT int msSaveImage(mapObj *map, imageObj *img, char *filename);
@@ -1268,6 +1285,7 @@
 pointObj get_metrics(pointObj *p, int position, rectObj rect, int ox, int
oy, double angle, int buffer, shapeObj *poly);
 double dist(pointObj a, pointObj b);

+void *msGetSymbol(const char *pszLibrary, const char *pszEntryPoint);


 /*
@@ -1602,7 +1620,28 @@
 MS_DLL_EXPORT int msRASTERLayerGetExtent(layerObj *layer, rectObj *extent);
 MS_DLL_EXPORT int msRASTERLayerGetItems(layerObj *layer);

+
 /* ==================================================================== */
+/*      Prototypes for functions in mapcustomlayer.c                    */
+/* ==================================================================== */
+MS_DLL_EXPORT int msCustomLayerInitItemInfo(layerObj *layer);
+MS_DLL_EXPORT void msCustomLayerFreeItemInfo(layerObj *layer);
+MS_DLL_EXPORT int msCustomLayerOpen(layerObj *layer);
+MS_DLL_EXPORT int msCustomLayerIsOpen(layerObj *layer);
+MS_DLL_EXPORT int msCustomLayerWhichShapes(layerObj *layer, rectObj rect);
+MS_DLL_EXPORT int msCustomLayerNextShape(layerObj *layer, shapeObj *shape);
+MS_DLL_EXPORT int msCustomLayerGetShape(layerObj *layer, shapeObj *shape,
int tile, long record);
+MS_DLL_EXPORT int msCustomLayerClose(layerObj *layer);
+MS_DLL_EXPORT int msCustomLayerGetItems(layerObj *layer);
+MS_DLL_EXPORT int msCustomLayerGetExtent(layerObj *layer, rectObj *extent);
+MS_DLL_EXPORT int msCustomLayerGetAutoStyle(mapObj *map, layerObj *layer,
classObj *c, int tile, long record);
+/* ==================================================================== */
+/*      End of Prototypes for functions in mapcustomlayer.c             */
+/* ==================================================================== */
+
+
+
+/* ==================================================================== */
 /*      Prototypes for functions in mapdraw.c                           */
 /* ==================================================================== */
 MS_DLL_EXPORT void msClearLayerPenValues(layerObj *layer);
Index: Makefile.in
===================================================================
--- Makefile.in	(revision 10904)
+++ Makefile.in	(revision 10943)
@@ -219,7 +219,7 @@

 RM= /bin/rm -f

-OBJS= maptemplate.o mapbits.o maphash.o mapshape.o mapxbase.o mapparser.o
maplexer.o maptree.o mapsearch.o mapstring.o mapsymbol.o mapfile.o
maplegend.o maputil.o mapscale.o mapquery.o maplabel.o maperror.o
mapprimitive.o mapproject.o mapraster.o mapsde.o mapogr.o mappostgis.o
mapmygis.o maplayer.o mapresample.o mapwms.o mapwmslayer.o
maporaclespatial.o mapgml.o mapprojhack.o mapthread.o mapdraw.o mapgd.o
mapoutput.o mapgdal.o mapswf.o mapimagemap.o mapows.o mapwfs.o mapwfslayer.o
mapcontext.o maphttp.o mapdrawgdal.o mappdf.o mapjoin.o mapgraticule.o
mapcopy.o mapogcfilter.o mapogcsld.o maptime.o mapwcs.o mapcpl.o cgiutil.o
maprasterquery.o mapobject.o mapgeos.o classobject.o layerobject.o mapio.o
mappool.o mapsvg.o mapregex.o $(EPPL_OBJ)
+OBJS= maptemplate.o mapbits.o maphash.o mapshape.o mapxbase.o mapparser.o
maplexer.o maptree.o mapsearch.o mapstring.o mapsymbol.o mapfile.o
maplegend.o maputil.o mapscale.o mapquery.o maplabel.o maperror.o
mapprimitive.o mapproject.o mapraster.o mapsde.o mapogr.o mappostgis.o
mapmygis.o maplayer.o mapresample.o mapwms.o mapwmslayer.o
maporaclespatial.o mapgml.o mapprojhack.o mapthread.o mapdraw.o mapgd.o
mapoutput.o mapgdal.o mapswf.o mapimagemap.o mapows.o mapwfs.o mapwfslayer.o
mapcontext.o maphttp.o mapdrawgdal.o mappdf.o mapjoin.o mapgraticule.o
mapcopy.o mapogcfilter.o mapogcsld.o maptime.o mapwcs.o mapcpl.o cgiutil.o
maprasterquery.o mapobject.o mapgeos.o classobject.o layerobject.o mapio.o
mappool.o mapsvg.o mapregex.o $mapcustomlayer.o mapgetsymbol.o (EPPL_OBJ)

 EXE_LIST = 	shp2img shp2pdf legend mapserv shptree shptreevis \
 		shptreetst scalebar sortshp mapscriptvars tile4ms
Index: mapgetsymbol.c
===================================================================
--- mapgetsymbol.c	(revision 0)
+++ mapgetsymbol.c	(revision 10943)
@@ -0,0 +1,183 @@
+/*
+ * This code has been copied from GDAL project, and it was
+ * originally in file named as port/cplgetsymbol.cpp
+ */
+/**************************************************************************
****
+ * $Id: cplgetsymbol.cpp,v 1.14 2004/11/11 20:40:38 fwarmerdam Exp $
+ *
+ * Project:  Common Portability Library
+ * Purpose:  Fetch a function pointer from a shared library / DLL.
+ * Author:   Frank Warmerdam, warmerda at home.com
+ *
+
****************************************************************************
**
+ * Copyright (c) 1999, Frank Warmerdam
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
"Software"),
+ * to deal in the Software without restriction, including without
limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+
****************************************************************************
**
+ *
+ */
+
+#include "map.h"
+
+MS_CVSID("$Id: cplgetsymbol.cpp,v 1.14 2004/11/11 20:40:38 fwarmerdam Exp
$");
+
+/* ==================================================================== */
+/*                  Unix Implementation                                 */
+/* ==================================================================== */
+#if defined(HAVE_DLFCN_H)
+
+#define GOT_GETSYMBOL
+
+#include <dlfcn.h>
+
+/************************************************************************/
+/*                            msGetSymbol()                            */
+/************************************************************************/
+
+/**
+ * Fetch a function pointer from a shared library / DLL.
+ *
+ * This function is meant to abstract access to shared libraries and
+ * DLLs and performs functions similar to dlopen()/dlsym() on Unix and
+ * LoadLibrary() / GetProcAddress() on Windows.
+ *
+ * If no support for loading entry points from a shared library is
available
+ * this function will always return NULL.   Rules on when this function
+ * issues a CPLError() or not are not currently well defined, and will have
+ * to be resolved in the future.
+ *
+ * Currently msGetSymbol() doesn't try to:
+ * <ul>
+ *  <li> prevent the reference count on the library from going up
+ *    for every request, or given any opportunity to unload
+ *    the library.
+ *  <li> Attempt to look for the library in non-standard
+ *    locations.
+ *  <li> Attempt to try variations on the symbol name, like
+ *    pre-prending or post-pending an underscore.
+ * </ul>
+ *
+ * Some of these issues may be worked on in the future.
+ *
+ * @param pszLibrary the name of the shared library or DLL containing
+ * the function.  May contain path to file.  If not system supplies search
+ * paths will be used.
+ * @param pszSymbolName the name of the function to fetch a pointer to.
+ * @return A pointer to the function if found, or NULL if the function
isn't
+ * found, or the shared library can't be loaded.
+ */
+
+void *msGetSymbol( const char * pszLibrary, const char * pszSymbolName )
+
+{
+    void        *pLibrary;
+    void        *pSymbol;
+
+    pLibrary = dlopen(pszLibrary, RTLD_LAZY);
+    if( pLibrary == NULL )
+    {
+        msSetError(MS_MISCERR, "MapServer: Can't load requested DLL: %s",
"msGetSymbol", pszLibrary);
+        return NULL;
+    }
+
+    pSymbol = dlsym( pLibrary, pszSymbolName );
+
+#if (defined(__APPLE__) && defined(__MACH__))
+    /* On mach-o systems, C symbols have a leading underscore and depending
+     * on how dlcompat is configured it may or may not add the leading
+     * underscore.  So if dlsym() fails add an underscore and try again.
+     */
+    if( pSymbol == NULL )
+    {
+        char withUnder[strlen(pszSymbolName) + 2];
+        withUnder[0] = '_'; withUnder[1] = 0;
+        strcat(withUnder, pszSymbolName);
+        pSymbol = dlsym( pLibrary, withUnder );
+    }
+#endif
+
+    if( pSymbol == NULL )
+    {
+        msSetError(MS_MISCERR, "MapServer: Can't find requested entry
point: %s", "msGetSymbol", pszSymbolName );
+        return NULL;
+    }
+
+    return( pSymbol );
+}
+
+#endif /* def __unix__ && defined(HAVE_DLFCN_H) */
+
+/* ==================================================================== */
+/*                 Windows Implementation                               */
+/* ==================================================================== */
+#ifdef WIN32
+
+#define GOT_GETSYMBOL
+
+#include <windows.h>
+
+/************************************************************************/
+/*                            msGetSymbol()                            */
+/************************************************************************/
+
+void *msGetSymbol( const char * pszLibrary, const char * pszSymbolName )
+
+{
+    void        *pLibrary;
+    void        *pSymbol;
+
+    pLibrary = LoadLibrary(pszLibrary);
+    if( pLibrary == NULL )
+    {
+        msSetError(MS_MISCERR, "MapServer: Can't load requested DLL: %s",
"msGetSymbol", pszLibrary);
+        return NULL;
+    }
+
+    pSymbol = (void *) GetProcAddress( (HINSTANCE) pLibrary,
pszSymbolName );
+
+    if( pSymbol == NULL )
+    {
+        msSetError(MS_MISCERR, "MapServer: Can't find requested entry
point: %s", "msGetSymbol", pszSymbolName );
+        return NULL;
+    }
+
+    return( pSymbol );
+}
+
+#endif /* def _WIN32 */
+
+/* ==================================================================== */
+/*      Dummy implementation.                                           */
+/* ==================================================================== */
+
+#ifndef GOT_GETSYMBOL
+
+/************************************************************************/
+/*                            msGetSymbol()                            */
+/*                                                                      */
+/*      Dummy implementation.                                           */
+/************************************************************************/
+
+void *msGetSymbol(const char *pszLibrary, const char *pszEntryPoint)
+
+{
+    msSetError(MS_MISCERR, "msGetSymbol called.  Failed as this is stub
implementation." );
+    return NULL;
+}
+#endif
Index: maplayer.c
===================================================================
--- maplayer.c	(revision 10904)
+++ maplayer.c	(revision 10943)
@@ -124,6 +124,9 @@
   case(MS_RASTER):
     return(msRASTERLayerInitItemInfo(layer));
     break;
+  case(MS_CUSTOM):
+    return(msCustomLayerInitItemInfo(layer));
+    break;
   default:
     break;
   }
@@ -163,6 +166,9 @@
   case(MS_RASTER):
     msRASTERLayerFreeItemInfo(layer);
     break;
+  case(MS_CUSTOM):
+    msCustomLayerFreeItemInfo(layer);
+    break;
   default:
     break;
   }
@@ -241,6 +247,9 @@
   case(MS_RASTER):
     return(msRASTERLayerOpen(layer));
     break;
+  case(MS_CUSTOM):
+    return(msCustomLayerOpen(layer));
+    break;
   default:
     break;
   }
@@ -292,6 +301,9 @@
   case(MS_RASTER):
     return(msRASTERLayerIsOpen(layer));
     break;
+  case(MS_CUSTOM):
+    return(msCustomLayerIsOpen(layer));
+    break;
   default:
     break;
   }
@@ -374,6 +386,9 @@
   case(MS_RASTER):
     return(msRASTERLayerWhichShapes(layer, rect));
     break;
+  case(MS_CUSTOM):
+    return(msCustomLayerWhichShapes(layer, rect));
+    break;
   default:
     break;
   }
@@ -460,6 +475,9 @@
   case(MS_RASTER):
     return(msRASTERLayerNextShape(layer, shape));
     break;
+  case(MS_CUSTOM):
+    return(msCustomLayerNextShape(layer, shape));
+    break;
   default:
     break;
   }
@@ -531,6 +549,9 @@
   case(MS_RASTER):
     return(msRASTERLayerGetShape(layer, shape, tile, record));
     break;
+  case(MS_CUSTOM):
+    return(msCustomLayerGetShape(layer, shape, tile, record));
+    break;
   default:
     break;
   }
@@ -598,6 +619,9 @@
   case(MS_RASTER):
     msRASTERLayerClose(layer);
     break;
+  case(MS_CUSTOM):
+    msCustomLayerClose(layer);
+    break;
   default:
     break;
   }
@@ -665,6 +689,9 @@
   case(MS_RASTER):
     return(msRASTERLayerGetItems(layer));
     break;
+  case(MS_CUSTOM):
+    return(msCustomLayerGetItems(layer));
+    break;
   default:
     break;
   }
@@ -736,6 +763,9 @@
   case(MS_RASTER):
     status = msRASTERLayerGetExtent(layer, extent);
     break;
+  case(MS_CUSTOM):
+    status = msCustomLayerGetExtent(layer, extent);
+    break;
   default:
     break;
   }
@@ -1078,6 +1108,9 @@
   case(MS_OGR):
     return(msOGRLayerGetAutoStyle(map, layer, c, tile, record));
     break;
+  case(MS_CUSTOM):
+    return(msCustomLayerGetAutoStyle(map, layer, c, tile, record));
+    break;
   case(MS_SHAPEFILE):
   case(MS_TILED_SHAPEFILE):
   case(MS_INLINE):
Index: maplexer.l
===================================================================
--- maplexer.l	(revision 10904)
+++ maplexer.l	(revision 10943)
@@ -289,6 +289,7 @@
 <INITIAL,VALUE_STRING>cc                       { return(MS_CC); }
 <INITIAL,VALUE_STRING>circle                   { return(MS_LAYER_CIRCLE); }
 <INITIAL,VALUE_STRING>cl                       { return(MS_CL); }
+<INITIAL,VALUE_STRING>custom                   { return(MS_CUSTOM); }
 <INITIAL,VALUE_STRING>cr                       { return(MS_CR); }
 <INITIAL,VALUE_STRING>csv                      { return(MS_DB_CSV); }
 <INITIAL,VALUE_STRING>mysql                      { return(MS_DB_MYSQL); }
Index: mapcustomlayer.c
===================================================================
--- mapcustomlayer.c	(revision 0)
+++ mapcustomlayer.c	(revision 10943)
@@ -0,0 +1,242 @@
+/**************************************************************************
****
+ *
+ * Project:  MapServer
+ * Purpose:  Implementation of plug-in custom layer functionality
+ * Author:
+ *
+
****************************************************************************
**
+ * Copyright (c) 1996-2005 Regents of the University of Minnesota.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
"Software"),
+ * to deal in the Software without restriction, including without
limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
in
+ * all copies of this Software or works derived from this Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+
****************************************************************************
**
+ */
+
+#include "map.h"
+#include "mapthread.h"
+
+MS_CVSID("$Id: maplayer.c,v 1.105 2005/06/14 16:03:33 dan Exp $");
+
+typedef struct {
+    char *name;
+    layerVTableObj virtualtable;
+} VTFactoryItemObj;
+
+#define VIRTUAL_TABLE_FACTORY_SIZE 64
+
+typedef struct {
+    unsigned int size;
+    unsigned int first_free;
+    VTFactoryItemObj * vtItems[VIRTUAL_TABLE_FACTORY_SIZE];
+} VTFactoryObj;
+
+static VTFactoryObj gVirtualTableFactory = {VIRTUAL_TABLE_FACTORY_SIZE, 0,
{NULL}};
+
+#undef VIRTUAL_TABLE_FACTORY_SIZE
+
+static void
+virtualTableItemInit(VTFactoryItemObj *VTI, const char *name)
+{
+    VTI->name = strdup(name);
+    memset(&VTI->virtualtable, 0, sizeof(layerVTableObj));
+}
+
+static void
+virtualTableItemDestroy(VTFactoryItemObj *VTI)
+{
+    free(VTI->name);
+    VTI->name = NULL;
+    memset(&VTI->virtualtable, 0, sizeof(layerVTableObj));
+}
+
+
+static VTFactoryItemObj *
+lookupVirtualTable(VTFactoryObj *VTFactory,
+                   const char *key)
+{
+    unsigned int i;
+    for (i=0; i < VTFactory->size && VTFactory->vtItems[i]; ++i) {
+        if (0 == strcasecmp(key, VTFactory->vtItems[i]->name)) {
+            return VTFactory->vtItems[i];
+        }
+    }
+    return NULL;
+}
+
+static int
+insertNewVirtualTable(VTFactoryObj *vtfactory,
+                      VTFactoryItemObj *vtitem)
+{
+    unsigned int first_free = vtfactory->first_free;
+    if (first_free < vtfactory->size) {
+        vtfactory->vtItems[first_free] = vtitem;
+        vtfactory->first_free++;
+        return MS_SUCCESS;
+    }
+    return MS_FAILURE;
+}
+
+static VTFactoryItemObj *
+loadCustomLayerDLL(layerObj *layer, const char *name)
+{
+    int (*fpLayerInitVTable)(layerVTableObj *, layerObj *);
+    VTFactoryItemObj *pVTI;
+    const char *pszLibrary = msLayerGetProcessingKey(layer, "LIB");
+
+    fpLayerInitVTable = msGetSymbol(pszLibrary,
"InitializeLayerVirtualTable");
+    if ( ! fpLayerInitVTable) {
+        msSetError(MS_MISCERR, "Failed to load dynamic Layer LIB: %s",
"loadCustomLayerDLL", pszLibrary);
+        return NULL;
+    }
+
+    pVTI = (VTFactoryItemObj *)malloc(sizeof(VTFactoryItemObj));
+    if ( ! pVTI) {
+        return NULL;
+    }
+    virtualTableItemInit(pVTI, name);
+
+    if (fpLayerInitVTable(&pVTI->virtualtable, layer)) {
+        virtualTableItemDestroy(pVTI);
+        free(pVTI);
+        msSetError(MS_MISCERR, "Failed to initialize dynamic Layer: %s",
"loadCustomLayerDLL", pszLibrary);
+        return NULL;
+    }
+    return pVTI;
+}
+
+static const layerVTableObj *
+getCustomLayerVirtualTable(layerObj *layer)
+{
+    VTFactoryItemObj *pVTableItem;
+    const char *pHashKey;
+
+    pHashKey = msLayerGetProcessingKey(layer, "LIB");
+
+    msAcquireLock(TLOCK_LAYER_VTABLE);
+
+    pVTableItem = lookupVirtualTable(&gVirtualTableFactory, pHashKey);
+    if ( ! pVTableItem) {
+        pVTableItem = loadCustomLayerDLL(layer, pHashKey);
+        if ( ! pVTableItem) {
+            msReleaseLock(TLOCK_LAYER_VTABLE);
+            return NULL;
+        }
+        if (insertNewVirtualTable(&gVirtualTableFactory, pVTableItem)) {
+            virtualTableItemDestroy(pVTableItem);
+            free(pVTableItem);
+            msReleaseLock(TLOCK_LAYER_VTABLE);
+            return NULL;
+        }
+    }
+    msReleaseLock(TLOCK_LAYER_VTABLE);
+    return &pVTableItem->virtualtable;
+}
+
+
+int msCustomLayerOpen(layerObj *layer)
+{
+    if ( ! layer->vtable) {
+        layer->vtable = getCustomLayerVirtualTable(layer);
+    }
+
+    if (layer->vtable && layer->vtable->fpLayerOpen) {
+        return layer->vtable->fpLayerOpen(layer);
+    }
+    return(MS_FAILURE);
+}
+
+int msCustomLayerInitItemInfo(layerObj *layer)
+{
+    if (layer->vtable && layer->vtable->fpLayerInitItemInfo) {
+        return layer->vtable->fpLayerInitItemInfo(layer);
+    }
+    return(MS_FAILURE);
+}
+
+void msCustomLayerFreeItemInfo(layerObj *layer)
+{
+    if (layer->vtable && layer->vtable->fpLayerFreeItemInfo) {
+        layer->vtable->fpLayerFreeItemInfo(layer);
+    }
+}
+
+
+int msCustomLayerIsOpen(layerObj *layer)
+{
+    if (layer->vtable && layer->vtable->fpLayerIsOpen) {
+        return layer->vtable->fpLayerIsOpen(layer);
+    }
+    return MS_FALSE;
+}
+
+int msCustomLayerWhichShapes(layerObj *layer, rectObj rect)
+{
+    if (layer->vtable && layer->vtable->fpLayerWhichShapes) {
+        return layer->vtable->fpLayerWhichShapes(layer, rect);
+    }
+    return(MS_FAILURE);
+}
+
+int msCustomLayerNextShape(layerObj *layer, shapeObj *shape)
+{
+    if (layer->vtable && layer->vtable->fpLayerNextShape) {
+        return layer->vtable->fpLayerNextShape(layer, shape);
+    }
+    return(MS_FAILURE);
+}
+
+int msCustomLayerGetShape(layerObj *layer, shapeObj *shape, int tile, long
record)
+{
+    if (layer->vtable && layer->vtable->fpLayerGetShape) {
+        return layer->vtable->fpLayerGetShape(layer, shape, tile, record);
+    }
+    return(MS_FAILURE);
+}
+
+int msCustomLayerClose(layerObj *layer)
+{
+    int rv;
+    if (layer->vtable && layer->vtable->fpLayerClose) {
+        rv = layer->vtable->fpLayerClose(layer);
+    }
+    layer->vtable = NULL;
+    return(rv);
+}
+int msCustomLayerGetItems(layerObj *layer)
+{
+    if (layer->vtable && layer->vtable->fpLayerGetItems) {
+        return layer->vtable->fpLayerGetItems(layer);
+    }
+    return(MS_FAILURE);
+}
+
+int msCustomLayerGetExtent(layerObj *layer, rectObj *extent)
+{
+    if (layer->vtable && layer->vtable->fpLayerGetExtent) {
+        return layer->vtable->fpLayerGetExtent(layer, extent);
+    }
+    return(MS_FAILURE);
+}
+
+int msCustomLayerGetAutoStyle(mapObj *map, layerObj *layer, classObj *c,
int tile, long record)
+{
+    if (layer->vtable && layer->vtable->fpLayerGetAutoStyle) {
+        return layer->vtable->fpLayerGetAutoStyle(map, layer, c, tile,
record);
+    }
+    return(MS_FAILURE);
+}



More information about the mapserver-dev mailing list