/src/MapServer/src/mappluginlayer.c
Line | Count | Source (jump to first uncovered line) |
1 | | /****************************************************************************** |
2 | | * $Id$ |
3 | | * |
4 | | * Project: MapServer |
5 | | * Purpose: Implementation of plug-in layer functionality |
6 | | * Author: Jani Averbach, SRC,LLC <javerbach@extendthereach.com> |
7 | | * |
8 | | ****************************************************************************** |
9 | | * Copyright (c) 1996-2005 Regents of the University of Minnesota. |
10 | | * |
11 | | * Permission is hereby granted, free of charge, to any person obtaining a |
12 | | * copy of this software and associated documentation files (the "Software"), |
13 | | * to deal in the Software without restriction, including without limitation |
14 | | * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
15 | | * and/or sell copies of the Software, and to permit persons to whom the |
16 | | * Software is furnished to do so, subject to the following conditions: |
17 | | * |
18 | | * The above copyright notice and this permission notice shall be included in |
19 | | * all copies of this Software or works derived from this Software. |
20 | | * |
21 | | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
22 | | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
23 | | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
24 | | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
25 | | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
26 | | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
27 | | * DEALINGS IN THE SOFTWARE. |
28 | | *****************************************************************************/ |
29 | | |
30 | | #include "mapserver.h" |
31 | | #include "mapthread.h" |
32 | | |
33 | | typedef struct { |
34 | | char *name; |
35 | | layerVTableObj vtable; |
36 | | } VTFactoryItemObj; |
37 | | |
38 | | typedef struct { |
39 | | unsigned int size; |
40 | | unsigned int first_free; |
41 | | VTFactoryItemObj **vtItems; |
42 | | } VTFactoryObj; |
43 | | |
44 | | static VTFactoryObj gVirtualTableFactory = {0, 0, NULL}; |
45 | | |
46 | 0 | static VTFactoryItemObj *createVTFItem(const char *name) { |
47 | 0 | VTFactoryItemObj *pVTFI; |
48 | |
|
49 | 0 | pVTFI = (VTFactoryItemObj *)malloc(sizeof(VTFactoryItemObj)); |
50 | 0 | MS_CHECK_ALLOC(pVTFI, sizeof(VTFactoryItemObj), NULL); |
51 | |
|
52 | 0 | pVTFI->name = msStrdup(name); |
53 | 0 | memset(&pVTFI->vtable, 0, sizeof(layerVTableObj)); |
54 | |
|
55 | 0 | return pVTFI; |
56 | 0 | } |
57 | | |
58 | 0 | static void destroyVTFItem(VTFactoryItemObj **pVTFI) { |
59 | 0 | free((*pVTFI)->name); |
60 | 0 | (*pVTFI)->name = NULL; |
61 | 0 | memset(&(*pVTFI)->vtable, 0, sizeof(layerVTableObj)); |
62 | 0 | free(*pVTFI); |
63 | 0 | *pVTFI = NULL; |
64 | 0 | } |
65 | | |
66 | | static VTFactoryItemObj *lookupVTFItem(VTFactoryObj *VTFactory, |
67 | 171 | const char *key) { |
68 | 171 | unsigned int i; |
69 | 171 | for (i = 0; i < VTFactory->size && VTFactory->vtItems[i]; ++i) { |
70 | 0 | if (0 == strcasecmp(key, VTFactory->vtItems[i]->name)) { |
71 | 0 | return VTFactory->vtItems[i]; |
72 | 0 | } |
73 | 0 | } |
74 | 171 | return NULL; |
75 | 171 | } |
76 | | |
77 | 0 | static int insertNewVTFItem(VTFactoryObj *pVTFactory, VTFactoryItemObj *pVTFI) { |
78 | | /* Ensure there is room for one more item in the array |
79 | | * (safe to use for initial alloc of the array as well) |
80 | | */ |
81 | 0 | if (pVTFactory->first_free == pVTFactory->size) { |
82 | 0 | VTFactoryItemObj **vtItemPtr; |
83 | 0 | vtItemPtr = (VTFactoryItemObj **)realloc( |
84 | 0 | pVTFactory->vtItems, |
85 | 0 | (pVTFactory->size + MS_LAYER_ALLOCSIZE) * sizeof(VTFactoryItemObj *)); |
86 | 0 | MS_CHECK_ALLOC(vtItemPtr, |
87 | 0 | (pVTFactory->size + MS_LAYER_ALLOCSIZE) * |
88 | 0 | sizeof(VTFactoryItemObj *), |
89 | 0 | MS_FAILURE); |
90 | |
|
91 | 0 | pVTFactory->size += MS_LAYER_ALLOCSIZE; |
92 | 0 | pVTFactory->vtItems = vtItemPtr; |
93 | |
|
94 | 0 | for (unsigned i = pVTFactory->first_free; i < pVTFactory->size; i++) |
95 | 0 | pVTFactory->vtItems[i] = NULL; |
96 | 0 | } |
97 | | |
98 | | /* Insert item */ |
99 | 0 | pVTFactory->vtItems[pVTFactory->first_free] = pVTFI; |
100 | 0 | pVTFactory->first_free++; |
101 | |
|
102 | 0 | return MS_SUCCESS; |
103 | 0 | } |
104 | | |
105 | | static VTFactoryItemObj *loadCustomLayerDLL(layerObj *layer, |
106 | 171 | const char *library_path) { |
107 | 171 | int (*pfnPluginInitVTable)(layerVTableObj *, layerObj *); |
108 | | |
109 | 171 | VTFactoryItemObj *pVTFI; |
110 | | |
111 | 171 | pfnPluginInitVTable = |
112 | 171 | msGetSymbol(library_path, "PluginInitializeVirtualTable"); |
113 | 171 | if (!pfnPluginInitVTable) { |
114 | 171 | msSetError(MS_MISCERR, "Failed to load dynamic Layer LIB: %s", |
115 | 171 | "loadCustomLayerDLL", library_path); |
116 | 171 | return NULL; |
117 | 171 | } |
118 | | |
119 | 0 | pVTFI = createVTFItem(library_path); |
120 | 0 | if (!pVTFI) { |
121 | 0 | return NULL; |
122 | 0 | } |
123 | | |
124 | 0 | if (pfnPluginInitVTable(&pVTFI->vtable, layer)) { |
125 | 0 | destroyVTFItem(&pVTFI); |
126 | 0 | msSetError(MS_MISCERR, "Failed to initialize dynamic Layer: %s", |
127 | 0 | "loadCustomLayerDLL", library_path); |
128 | 0 | return NULL; |
129 | 0 | } |
130 | 0 | return pVTFI; |
131 | 0 | } |
132 | | |
133 | | /* |
134 | | * copyVirtualTable |
135 | | * |
136 | | * copy one virtual table from dest to src. Both of dest and src |
137 | | * have to be allocated already. |
138 | | * |
139 | | * If src contains NULL fields, those are NOT copied over. |
140 | | * |
141 | | * Because of that, it is possible for plugin layer to use default |
142 | | * layer API default functions, just leave those function pointers to NULL. |
143 | | */ |
144 | 0 | static void copyVirtualTable(layerVTableObj *dest, const layerVTableObj *src) { |
145 | 0 | dest->LayerTranslateFilter = src->LayerTranslateFilter |
146 | 0 | ? src->LayerTranslateFilter |
147 | 0 | : dest->LayerTranslateFilter; |
148 | 0 | dest->LayerSupportsCommonFilters = src->LayerSupportsCommonFilters |
149 | 0 | ? src->LayerSupportsCommonFilters |
150 | 0 | : dest->LayerSupportsCommonFilters; |
151 | 0 | dest->LayerInitItemInfo = |
152 | 0 | src->LayerInitItemInfo ? src->LayerInitItemInfo : dest->LayerInitItemInfo; |
153 | 0 | dest->LayerFreeItemInfo = |
154 | 0 | src->LayerFreeItemInfo ? src->LayerFreeItemInfo : dest->LayerFreeItemInfo; |
155 | 0 | dest->LayerOpen = src->LayerOpen ? src->LayerOpen : dest->LayerOpen; |
156 | 0 | dest->LayerIsOpen = src->LayerIsOpen ? src->LayerIsOpen : dest->LayerIsOpen; |
157 | 0 | dest->LayerWhichShapes = |
158 | 0 | src->LayerWhichShapes ? src->LayerWhichShapes : dest->LayerWhichShapes; |
159 | 0 | dest->LayerNextShape = |
160 | 0 | src->LayerNextShape ? src->LayerNextShape : dest->LayerNextShape; |
161 | 0 | dest->LayerGetShape = |
162 | 0 | src->LayerGetShape ? src->LayerGetShape : dest->LayerGetShape; |
163 | | /* dest->LayerResultsGetShape = src->LayerResultsGetShape ? |
164 | | * src->LayerResultsGetShape : dest->LayerResultsGetShape; */ |
165 | 0 | dest->LayerGetShapeCount = src->LayerGetShapeCount ? src->LayerGetShapeCount |
166 | 0 | : dest->LayerGetShapeCount; |
167 | 0 | dest->LayerClose = src->LayerClose ? src->LayerClose : dest->LayerClose; |
168 | 0 | dest->LayerGetItems = |
169 | 0 | src->LayerGetItems ? src->LayerGetItems : dest->LayerGetItems; |
170 | 0 | dest->LayerGetExtent = |
171 | 0 | src->LayerGetExtent ? src->LayerGetExtent : dest->LayerGetExtent; |
172 | 0 | dest->LayerGetAutoStyle = |
173 | 0 | src->LayerGetAutoStyle ? src->LayerGetAutoStyle : dest->LayerGetAutoStyle; |
174 | 0 | dest->LayerCloseConnection = src->LayerCloseConnection |
175 | 0 | ? src->LayerCloseConnection |
176 | 0 | : dest->LayerCloseConnection; |
177 | 0 | dest->LayerSetTimeFilter = src->LayerSetTimeFilter ? src->LayerSetTimeFilter |
178 | 0 | : dest->LayerSetTimeFilter; |
179 | 0 | dest->LayerApplyFilterToLayer = src->LayerApplyFilterToLayer |
180 | 0 | ? src->LayerApplyFilterToLayer |
181 | 0 | : dest->LayerApplyFilterToLayer; |
182 | 0 | dest->LayerCreateItems = |
183 | 0 | src->LayerCreateItems ? src->LayerCreateItems : dest->LayerCreateItems; |
184 | 0 | dest->LayerGetNumFeatures = src->LayerGetNumFeatures |
185 | 0 | ? src->LayerGetNumFeatures |
186 | 0 | : dest->LayerGetNumFeatures; |
187 | 0 | dest->LayerGetAutoProjection = src->LayerGetAutoProjection |
188 | 0 | ? src->LayerGetAutoProjection |
189 | 0 | : dest->LayerGetAutoProjection; |
190 | 0 | dest->LayerEscapeSQLParam = src->LayerEscapeSQLParam |
191 | 0 | ? src->LayerEscapeSQLParam |
192 | 0 | : dest->LayerEscapeSQLParam; |
193 | 0 | dest->LayerEscapePropertyName = src->LayerEscapePropertyName |
194 | 0 | ? src->LayerEscapePropertyName |
195 | 0 | : dest->LayerEscapePropertyName; |
196 | 0 | dest->LayerEscapeSQLParam = src->LayerEscapeSQLParam |
197 | 0 | ? src->LayerEscapeSQLParam |
198 | 0 | : dest->LayerEscapeSQLParam; |
199 | 0 | dest->LayerEnablePaging = |
200 | 0 | src->LayerEnablePaging ? src->LayerEnablePaging : dest->LayerEnablePaging; |
201 | 0 | dest->LayerGetPaging = |
202 | 0 | src->LayerGetPaging ? src->LayerGetPaging : dest->LayerGetPaging; |
203 | 0 | } |
204 | | |
205 | 285 | int msPluginLayerInitializeVirtualTable(layerObj *layer) { |
206 | 285 | VTFactoryItemObj *pVTFI; |
207 | | |
208 | 285 | if (!layer->plugin_library) { |
209 | 114 | return MS_FAILURE; |
210 | 114 | } |
211 | | |
212 | 171 | msAcquireLock(TLOCK_LAYER_VTABLE); |
213 | | |
214 | 171 | pVTFI = lookupVTFItem(&gVirtualTableFactory, layer->plugin_library); |
215 | 171 | if (!pVTFI) { |
216 | 171 | pVTFI = loadCustomLayerDLL(layer, layer->plugin_library); |
217 | 171 | if (!pVTFI) { |
218 | 171 | msReleaseLock(TLOCK_LAYER_VTABLE); |
219 | 171 | return MS_FAILURE; |
220 | 171 | } |
221 | 0 | if (insertNewVTFItem(&gVirtualTableFactory, pVTFI) != MS_SUCCESS) { |
222 | 0 | destroyVTFItem(&pVTFI); |
223 | 0 | msReleaseLock(TLOCK_LAYER_VTABLE); |
224 | 0 | return MS_FAILURE; |
225 | 0 | } |
226 | 0 | } |
227 | 0 | msReleaseLock(TLOCK_LAYER_VTABLE); |
228 | |
|
229 | 0 | copyVirtualTable(layer->vtable, &pVTFI->vtable); |
230 | 0 | return MS_SUCCESS; |
231 | 171 | } |
232 | | |
233 | | /* msPluginFreeVirtualTableFactory() |
234 | | ** Called by msCleanup() to free the virtual table factory |
235 | | */ |
236 | 0 | void msPluginFreeVirtualTableFactory() { |
237 | 0 | msAcquireLock(TLOCK_LAYER_VTABLE); |
238 | |
|
239 | 0 | for (unsigned i = 0; i < gVirtualTableFactory.size; i++) { |
240 | 0 | if (gVirtualTableFactory.vtItems[i]) |
241 | 0 | destroyVTFItem(&(gVirtualTableFactory.vtItems[i])); |
242 | 0 | } |
243 | 0 | free(gVirtualTableFactory.vtItems); |
244 | 0 | gVirtualTableFactory.vtItems = NULL; |
245 | 0 | gVirtualTableFactory.size = 0; |
246 | 0 | gVirtualTableFactory.first_free = 0; |
247 | |
|
248 | 0 | msReleaseLock(TLOCK_LAYER_VTABLE); |
249 | 0 | } |