Project

General

Profile

1
/**
2
 *  '$RCSfile$'
3
 *  Copyright: 2000 Regents of the University of California and the
4
 *  National Center for Ecological Analysis and Synthesis
5
 *
6
 *  Author: Matthew Perry
7
 *  '$Date: 2008-07-28 16:07:10 -0700 (Mon, 28 Jul 2008) $'
8
 *  '$Revision: 4167 $'
9
 *
10
 *  This program is free software; you can redistribute it and/or modify
11
 *  it under the terms of the GNU General Public License as published by
12
 *  the Free Software Foundation; either version 2 of the License, or
13
 *  (at your option) any later version.
14
 *  
15
 *  This program is distributed in the hope that it will be useful,
16
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
 *  GNU General Public License for more details.
19
 *
20
 *  You should have received a copy of the GNU General Public License
21
 *  along with this program; if not, write to the Free Software
22
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23
 *
24
 *  Purpose: Servlet to generate a styled layer descriptor (SLD)
25
 *           with a filter to restrict features on
26
 *           a WMS map to given docids
27
 *
28
 *  Status: Currently this is just a working stub
29
 *          with some hardcoded values. Since this needs to be
30
 *          fired off on every map redraw, we'll need a way to make 
31
 *          the generation of docid list very efficient. 
32
 *
33
 *  Usage: Append the URL as an "SLD" to any WMS GetMap request
34
 *    ex: http://server/context/wms?...&SLD=http://server/context/sldfactory?originalSld=data_points_style
35
 */
36

    
37

    
38
package edu.ucsb.nceas.metacat.spatial;
39

    
40
import edu.ucsb.nceas.utilities.XMLUtilities;
41
import edu.ucsb.nceas.metacat.util.SystemUtil;
42

    
43
import javax.servlet.ServletConfig;
44
import javax.servlet.ServletContext;
45
import javax.servlet.ServletException;
46
import javax.servlet.ServletInputStream;
47
import javax.servlet.http.HttpServlet;
48
import javax.servlet.http.HttpServletRequest;
49
import javax.servlet.http.HttpServletResponse;
50
import javax.servlet.http.HttpSession;
51
import javax.servlet.http.HttpUtils;
52
import javax.servlet.ServletOutputStream;
53

    
54
import javax.xml.parsers.DocumentBuilder; 
55
import javax.xml.parsers.DocumentBuilderFactory;  
56
import javax.xml.parsers.FactoryConfigurationError;  
57
import javax.xml.parsers.ParserConfigurationException;
58

    
59
import org.xml.sax.SAXException;  
60
import org.xml.sax.SAXParseException;
61

    
62
import java.io.File;
63
import java.io.IOException;
64
import java.io.FileNotFoundException;
65

    
66
import java.util.Vector;
67

    
68
import org.w3c.dom.*;
69

    
70
/**
71
 * Class to generate Styled Layer Descriptors allowing geoserver to 
72
 * filter the feature rendering based on various contraints 
73
 * such as permissions, non-spatial queries and skin configuration.
74
 */
75
public class SldFactory extends HttpServlet {
76
  
77
  static Document document;
78
  static String sld;
79
  
80
  /** 
81
   * Handle "GET" method requests from HTTP clients 
82
   *
83
   * @param request Incoming servlet request.
84
   * @param response Servlet response.
85
   */
86
  public void doGet(HttpServletRequest request, HttpServletResponse response)
87
  throws ServletException, IOException
88
  {
89
    handleGetOrPost(request, response);
90
  }
91

    
92
  /** 
93
   * Handle "POST" method requests from HTTP clients 
94
   *
95
   * @param request Incoming servlet request.
96
   * @param response Servlet response.
97
   */
98
  public void doPost(HttpServletRequest request, HttpServletResponse response)
99
  throws ServletException, IOException
100
  {
101
    handleGetOrPost(request, response);
102
  }
103

    
104
  /**
105
	 * Control servlet response depending on the action parameter specified
106
	 * Modifies the original SLD according to various access contraints and
107
	 * sends it as the servlet response.
108
	 * 
109
	 * @param request
110
	 *            Incoming servlet request.
111
	 * @param response
112
	 *            Servlet response.
113
	 */
114
	private void handleGetOrPost(HttpServletRequest request, HttpServletResponse response)
115
			throws ServletException, IOException {
116
		String dataset = request.getParameter("originalSld");
117

    
118
		try {
119
			String certPath = SystemUtil.getContextDir();
120
			String filename = certPath + "/data/styles/" + dataset;
121
			String sld = getSld(filename);
122
			System.out.println(sld);
123
			response.setContentType("text/xml");
124
			response.getWriter().write(sld);
125
		} catch (FileNotFoundException fnf) {
126
			fnf.printStackTrace();
127
		} catch (Exception e) {
128
			e.printStackTrace();
129
		}
130

    
131
	}
132
  
133
  /**
134
	 * Given a filename of an existing SLD document, reads the sld and adds an
135
	 * ogc:Filter to exclude/include certain docids based on user's permissions.
136
	 * The sld file is specified without path and must exist within geoserver's
137
	 * styles folder (context/data/styles/*)
138
	 * 
139
	 * returns SLD document as a String.
140
	 * 
141
	 * @param filename
142
	 *            Filename of the base sld.
143
	 * @todo Implement the doc id list queries for contraints.
144
	 */
145
  private String getSld(String filename) throws FileNotFoundException
146
  {
147
	    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
148
	    Vector allowedDocids = new Vector();
149

    
150
	    /*
151
	     * TODO : 
152
	     *  Get the list of allowable docids due to 
153
	     *    access contraints (based on current logged-in user)
154
	     *    skin filtering (eg organization name) 
155
	     *    existing non-spatial query (eg taxonomic query)
156
	     *
157
	     *  These could ideally be cached as session variables to improve
158
	     *  speed over running expensive SQL queries on 
159
	     *  each map redraw.
160
	     *
161
	     * Combined, these will be a vector of allowed docids that
162
	     * are to be displayed on the map
163
	     *
164
	     * Below is just a hardcoded example of the above...
165
	     *
166
	     */
167
	    allowedDocids.add("nceas.288");
168
	    allowedDocids.add("nrs.720");
169

    
170
	    String rulesString = "";
171

    
172
	    try {
173
		    DocumentBuilder builder = factory.newDocumentBuilder();
174
		    document = builder.parse( new File(filename) );	       
175
		    Element root = document.getDocumentElement();
176

    
177
		    NodeList elemList = document.getElementsByTagName("Rule");
178
		    Node ruleNode = elemList.item(0);
179

    
180
		    // Get the Element/node comprising the ogc:Filter for all of the above
181
		    Element filterElement = getFilterElement(document,allowedDocids);
182
		    
183
		    // Append the Filter to the ruleNode
184
		    ruleNode.appendChild(filterElement);
185
		    
186
		    // Write new DOM as a string
187
		    rulesString = XMLUtilities.getDOMTreeAsString((Node) root, true);
188

    
189
	    } catch (SAXException sxe) {
190
	       sxe.printStackTrace();
191
	    } catch (ParserConfigurationException pce) {
192
	       pce.printStackTrace();
193
	    } catch (IOException ioe) {
194
	       ioe.printStackTrace();
195
	    } 
196
	    return rulesString;
197
  }
198

    
199
  /**
200
   * Given a DOM document and a vector of docids,
201
   * Creates an OGC Filter node
202
   * 
203
   * @param inDoc	DOM document.
204
   * @param docids 	Vector of documents allowed in the map.
205
   */
206
  private Element getFilterElement(Document inDoc, Vector docids) 
207
  {
208
	  Element filterElem = inDoc.createElement("ogc:Filter");
209
	  Element orElem = inDoc.createElement("ogc:Or");
210
	  String docid = "";
211
	  
212
	  // Begin loop thru vector of allowed docids
213
	  for (int i = 0; i < docids.size(); i++) {
214
		  Element opElem = inDoc.createElement("ogc:PropertyIsEqualTo");
215

    
216
		  Element propertyElem = inDoc.createElement("ogc:PropertyName");
217
		  Text propertyText = inDoc.createTextNode("docid");
218
		  propertyElem.appendChild(propertyText);
219
		  
220
		  Element literalElem = inDoc.createElement("ogc:Literal");	  
221

    
222
		  docid = (String)docids.elementAt(i);
223
		  Text literalText = inDoc.createTextNode(docid); 
224
		  literalElem.appendChild(literalText);
225
		  
226
		  opElem.appendChild(propertyElem);
227
		  opElem.appendChild(literalElem);
228

    
229
		  orElem.appendChild(opElem);
230
		  // END LOOP
231
	  }
232
	  
233
	  filterElem.appendChild(orElem);
234
	  return filterElem;	  
235
  }
236
  
237
}
(1-1/8)