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: 2006-12-11 19:07:09 -0800 (Mon, 11 Dec 2006) $'
8
 *  '$Revision: 3118 $'
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.MetaCatUtil;
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
107
   * and sends it as the servlet response.
108
   *
109
   * @param request Incoming servlet request.
110
   * @param response Servlet response.
111
   */
112
  private void handleGetOrPost(HttpServletRequest request, HttpServletResponse response)
113
  throws ServletException, IOException
114
  {
115
    String dataset = request.getParameter("originalSld"); 
116
    String filename = MetaCatUtil.getOption("certPath") + "data/styles/" + dataset;
117
    try {
118
	String sld = getSld(filename);
119
        System.out.println(sld);
120
	response.setContentType("text/xml");
121
	response.getWriter().write(sld);
122
    } catch (FileNotFoundException fnf) {
123
	fnf.printStackTrace();
124
    } catch (Exception e) {
125
        e.printStackTrace();
126
    }
127
    
128
  }
129
  
130
  /**
131
   * Given a filename of an existing SLD document,
132
   * reads the sld and adds an ogc:Filter to exclude/include
133
   * certain docids based on user's permissions. 
134
   * The sld file is specified without path and 
135
   * must exist within geoserver's styles folder (context/data/styles/*)
136
   * 
137
   * returns SLD document as a String.
138
   * 
139
   * @param filename	Filename of the base sld.
140
   * @todo Implement the doc id list queries for contraints.
141
   */
142
  private String getSld(String filename) throws FileNotFoundException
143
  {
144
	    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
145
	    Vector allowedDocids = new Vector();
146

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

    
167
	    String rulesString = "";
168

    
169
	    try {
170
		    DocumentBuilder builder = factory.newDocumentBuilder();
171
		    document = builder.parse( new File(filename) );	       
172
		    Element root = document.getDocumentElement();
173

    
174
		    NodeList elemList = document.getElementsByTagName("Rule");
175
		    Node ruleNode = elemList.item(0);
176

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

    
186
	    } catch (SAXException sxe) {
187
	       sxe.printStackTrace();
188
	    } catch (ParserConfigurationException pce) {
189
	       pce.printStackTrace();
190
	    } catch (IOException ioe) {
191
	       ioe.printStackTrace();
192
	    } 
193
	    return rulesString;
194
  }
195

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

    
213
		  Element propertyElem = inDoc.createElement("ogc:PropertyName");
214
		  Text propertyText = inDoc.createTextNode("docid");
215
		  propertyElem.appendChild(propertyText);
216
		  
217
		  Element literalElem = inDoc.createElement("ogc:Literal");	  
218

    
219
		  docid = (String)docids.elementAt(i);
220
		  Text literalText = inDoc.createTextNode(docid); 
221
		  literalElem.appendChild(literalText);
222
		  
223
		  opElem.appendChild(propertyElem);
224
		  opElem.appendChild(literalElem);
225

    
226
		  orElem.appendChild(opElem);
227
		  // END LOOP
228
	  }
229
	  
230
	  filterElem.appendChild(orElem);
231
	  return filterElem;	  
232
  }
233
  
234
}
(1-1/8)