1 | # Copyright (C) 2007 STFC & NERC (Science and Technology Facilities Council). |
---|
2 | # This software may be distributed under the terms of the |
---|
3 | # Q Public License, version 1.0 or later. |
---|
4 | # http://ndg.nerc.ac.uk/public_docs/QPublic_license.txt |
---|
5 | # |
---|
6 | """ |
---|
7 | Controller for the 'View' tab - allowing the display of WMC map layers |
---|
8 | |
---|
9 | @author C Byrom Feb 08, Modified D Lowe, May 09 |
---|
10 | """ |
---|
11 | |
---|
12 | import logging |
---|
13 | import urllib2 |
---|
14 | import urlparse |
---|
15 | from cStringIO import StringIO |
---|
16 | |
---|
17 | #from ows_server.models import Utilities |
---|
18 | from paste.request import parse_querystring |
---|
19 | import cowsclient.lib.utils as utils |
---|
20 | |
---|
21 | # cowsclient imports |
---|
22 | from cowsclient.model import selectedItem |
---|
23 | from cowsclient.lib.base import BaseController, g, response, config, request, c, session, render, abort |
---|
24 | from cowsclient.lib.wmc_util import GetWebMapContext, GetWebMapCapabilities, GetLegend, openURL, GetResponse, parseEndpointString |
---|
25 | from cowsclient.lib.build_figure import build_figure |
---|
26 | from cowsclient.lib.status_builder import StatusBuilder |
---|
27 | |
---|
28 | from cowsclient.lib.base import request |
---|
29 | |
---|
30 | log = logging.getLogger(__name__) |
---|
31 | |
---|
32 | class WmsvizController(BaseController): |
---|
33 | |
---|
34 | _pilImageFormats = { |
---|
35 | 'image/png': 'PNG', |
---|
36 | 'image/jpg': 'JPEG', |
---|
37 | 'image/jpeg': 'JPEG', |
---|
38 | 'image/gif': 'GIF', |
---|
39 | 'image/tiff': 'TIFF' |
---|
40 | } |
---|
41 | |
---|
42 | def index(self): |
---|
43 | """ |
---|
44 | Default controller method to handle the initial requests to the page |
---|
45 | """ |
---|
46 | log.debug('endtered wmsviz controller index action') |
---|
47 | |
---|
48 | g.helpIcon='layout/icons/help.png' #needs to go in config |
---|
49 | |
---|
50 | self.inputs=dict(parse_querystring(request.environ)) |
---|
51 | log.info(self.inputs) |
---|
52 | c.wmcURL = "" |
---|
53 | |
---|
54 | # check if all we're doing is removing a view item |
---|
55 | if 'removeItem' in self.inputs: |
---|
56 | return self.removeViewItem(self.inputs['removeItem']) |
---|
57 | |
---|
58 | |
---|
59 | # check if we're doing an AJAX callback to get some WMC data |
---|
60 | if 'REQUEST' in self.inputs: |
---|
61 | |
---|
62 | if self.inputs['REQUEST'] == 'GetWebMapContext': |
---|
63 | wmc= GetWebMapContext(self) |
---|
64 | log.debug("finished wmsviz controller index action, req = GetWebMapContext") |
---|
65 | return wmc |
---|
66 | |
---|
67 | if self.inputs['REQUEST'] == 'GetWebMapCapabilities': |
---|
68 | wmcDoc = GetWebMapCapabilities(self.inputs['ENDPOINT']) |
---|
69 | |
---|
70 | response.headers['Content-Type'] = 'text/xml' |
---|
71 | response.write(wmcDoc) |
---|
72 | log.debug("finished wmsviz controller index action, req = GetWebMapCapabilities") |
---|
73 | return |
---|
74 | |
---|
75 | elif self.inputs['REQUEST'] == 'GetLegend': |
---|
76 | resp = GetLegend(self) |
---|
77 | log.debug("finished wmsviz controller index action, req = GetLegend") |
---|
78 | return resp |
---|
79 | |
---|
80 | if self.inputs['REQUEST'] == 'GetDisplayOptions': |
---|
81 | |
---|
82 | jsonTxt = GetResponse(self.inputs['URL']) |
---|
83 | |
---|
84 | response.headers['Content-Type'] = 'application/json' |
---|
85 | response.write(jsonTxt) |
---|
86 | log.debug("finished wmsviz controller index action, req = GetDisplayOptions") |
---|
87 | return |
---|
88 | |
---|
89 | if self.inputs['REQUEST'] == 'GetAxisConfig': |
---|
90 | |
---|
91 | respText = GetResponse(self.inputs['URL']) |
---|
92 | |
---|
93 | response.headers['Content-Type'] = 'text/xml' |
---|
94 | response.write(respText) |
---|
95 | return |
---|
96 | |
---|
97 | |
---|
98 | |
---|
99 | #get server information from config file |
---|
100 | g.server=config['app_conf']['serverurl'] |
---|
101 | |
---|
102 | statusBuilder = StatusBuilder() |
---|
103 | |
---|
104 | status = statusBuilder.getCurrentStatus('wmsviz') |
---|
105 | |
---|
106 | initialSetup = self._buildInitialSetup(self.inputs.get('ENDPOINT')) |
---|
107 | |
---|
108 | #TODO: WORK OUT HOW TO COUPLE THIS TO BROWSE |
---|
109 | # otherwise, we can get here by two routes: |
---|
110 | # i) either by clicking on the WMC icon in the details view - if so, get passed endpoint and add to |
---|
111 | # selected items; |
---|
112 | # ii) or from the selections tab - which will already have set up the correct selected items |
---|
113 | |
---|
114 | # if ENDPOINT specified, we've reached the page via the WMC icon |
---|
115 | |
---|
116 | #This will ensure that NDG security is triggered if a secured dataset is in Endpoint |
---|
117 | if 'ENDPOINT' in self.inputs: |
---|
118 | #clear out old endpoints NOTE. this means only one endpoint at a time can be viewed. May want to |
---|
119 | #rethink this to enable 'shopping cart' type selection. |
---|
120 | # self.removeAllViewItems() |
---|
121 | for endpoint in initialSetup: |
---|
122 | urlstring=endpoint['url']+'?request=GetCapabilities&Service=WMS' |
---|
123 | urlstring = parseEndpointString(endpoint['url'], |
---|
124 | {'REQUEST':'GetCapabilities', 'SERVICE':'WMS'}) |
---|
125 | #urlstring=str(self.inputs['ENDPOINT']) |
---|
126 | req = urllib2.Request(urlstring) |
---|
127 | req.add_header('Cookie', request.headers.get('Cookie', '')) |
---|
128 | try: |
---|
129 | filehandle = openURL(req) |
---|
130 | filehandle.close() |
---|
131 | except urllib2.HTTPError, e: |
---|
132 | log.exception("exception occurred") |
---|
133 | if e.code == 401: |
---|
134 | log.info ('401 unauthorized error in cowsclient') |
---|
135 | return abort(401) #triggers ndg security framework |
---|
136 | elif e.code == 403: #TODO: 403 response is UNTESTED. |
---|
137 | # User is authenticated but doesn't have the required permissions |
---|
138 | # or an error occurred in the authorization process |
---|
139 | # Read response |
---|
140 | xresponse = e.read() |
---|
141 | # Send response to user |
---|
142 | self.start_response("%d %s" % (e.code, e.msg), e.headers.dict.items()) |
---|
143 | |
---|
144 | return xresponse |
---|
145 | |
---|
146 | |
---|
147 | # avoid page crashing if we come here without view items defined |
---|
148 | # if 'viewItems' not in session: |
---|
149 | # h.redirect_to(h.url_for(controller='discovery')) |
---|
150 | |
---|
151 | session.save() |
---|
152 | log.info('SAVED SESSION') |
---|
153 | |
---|
154 | # check if page has been visited before; if not display tab |
---|
155 | # if (Utilities.isTabRequired(c.pageTabs, 'View')): |
---|
156 | # c.pageTabs.append(('View', h.url_for(controller='viewItems',action='index'))) |
---|
157 | |
---|
158 | c.initialSetupJSON = utils.toJSON(initialSetup) |
---|
159 | c.initialStatus = utils.toJSON(status) |
---|
160 | |
---|
161 | |
---|
162 | log.debug("request.params = %s" % (request.params,)) |
---|
163 | log.debug("request.headers = %s" % (request.headers,)) |
---|
164 | |
---|
165 | log.debug("finished wmsviz controller index action") |
---|
166 | |
---|
167 | return render('wmsviz') |
---|
168 | |
---|
169 | def _buildInitialSetup(self, endpointParam): |
---|
170 | initialSetup = [] |
---|
171 | |
---|
172 | if endpointParam != None: |
---|
173 | |
---|
174 | for ep in self.inputs['ENDPOINT'].split(','): |
---|
175 | endpoint = {} |
---|
176 | o = urlparse.urlparse(ep) |
---|
177 | |
---|
178 | if o.path.find(':') > 0: |
---|
179 | path = o.path[:o.path.find(':')] |
---|
180 | |
---|
181 | url = "%(scheme)s://%(hostname)s%(port)s%(path)s" % { |
---|
182 | 'scheme' : o.scheme if o.scheme != None else '', |
---|
183 | 'hostname' : o.hostname if o.hostname != None else '', |
---|
184 | 'port' : ':' + str(o.port) if o.port != None else '', |
---|
185 | 'path': path, |
---|
186 | } |
---|
187 | layers = o.path[o.path.find(':')+1:].split('|') |
---|
188 | |
---|
189 | endpoint['layers'] = layers |
---|
190 | else: |
---|
191 | url = ep |
---|
192 | layers = "" |
---|
193 | |
---|
194 | endpoint['url'] = url |
---|
195 | |
---|
196 | initialSetup.append(endpoint) |
---|
197 | |
---|
198 | return initialSetup |
---|
199 | |
---|
200 | def addViewItem(self,endpoint): |
---|
201 | """ |
---|
202 | Add a selected item to the session |
---|
203 | - if this is the first item, then display the selections tab |
---|
204 | @param endpoint: WMC endpoint |
---|
205 | """ |
---|
206 | |
---|
207 | item = selectedItem.SelectedItem(None, None, None, endpoint) |
---|
208 | |
---|
209 | selections = [item,] |
---|
210 | # avoid duplicates |
---|
211 | if 'viewItems' in session: |
---|
212 | for selection in session['viewItems']: |
---|
213 | if selection.wmcURL != endpoint: |
---|
214 | selections.append(selection) |
---|
215 | |
---|
216 | session['viewItems'] = selections |
---|
217 | session.save() |
---|
218 | |
---|
219 | |
---|
220 | def removeViewItem(self,endpoint): |
---|
221 | """ |
---|
222 | Remove view item from session data |
---|
223 | - NB, do this by rebuilding the session data without the input data included |
---|
224 | @param endpoint: The WMC endpoint of the view item to remove |
---|
225 | """ |
---|
226 | selections = [] |
---|
227 | for selection in session['viewItems']: |
---|
228 | if selection.wmcURL != endpoint: |
---|
229 | selections.append(selection) |
---|
230 | |
---|
231 | # if the new list is empty, remove the session variable |
---|
232 | if len(selections) == 0: |
---|
233 | del session['viewItems'] |
---|
234 | c.UpdatePageTabs=1 |
---|
235 | else: |
---|
236 | session['viewItems'] = selections |
---|
237 | session.save() |
---|
238 | |
---|
239 | def removeAllViewItems(self): |
---|
240 | """ |
---|
241 | Remove all old view items - clears out old endpoints |
---|
242 | """ |
---|
243 | session['viewItems']=[] |
---|
244 | session.save() |
---|
245 | |
---|
246 | |
---|
247 | |
---|
248 | |
---|
249 | def get_figure(self): |
---|
250 | log.debug("running wmsvis.get_figure") |
---|
251 | |
---|
252 | params = request.params |
---|
253 | |
---|
254 | log.debug("params = %s" % (params,)) |
---|
255 | |
---|
256 | format = params.pop('figFormat', 'image/png') |
---|
257 | |
---|
258 | finalImage = build_figure(params) |
---|
259 | |
---|
260 | response.headers['content-type'] = format |
---|
261 | |
---|
262 | buffer = StringIO() |
---|
263 | finalImage.save(buffer, self._pilImageFormats[format]) |
---|
264 | |
---|
265 | response.headers['Content-Type'] = format |
---|
266 | response.write(buffer.getvalue()) |
---|
267 | |
---|
268 | |
---|
269 | |
---|