Revision 2067
Added by Matt Jones about 20 years ago
QuerySpecification.java | ||
---|---|---|
30 | 30 |
|
31 | 31 |
package edu.ucsb.nceas.metacat; |
32 | 32 |
|
33 |
import edu.ucsb.nceas.dbadapter.*; |
|
34 |
|
|
35 |
import java.io.*; |
|
33 |
import java.io.File; |
|
34 |
import java.io.FileReader; |
|
35 |
import java.io.IOException; |
|
36 |
import java.io.Reader; |
|
37 |
import java.io.StringReader; |
|
38 |
import java.util.Enumeration; |
|
36 | 39 |
import java.util.Hashtable; |
37 | 40 |
import java.util.Stack; |
38 | 41 |
import java.util.Vector; |
39 |
import java.util.Enumeration; |
|
40 | 42 |
|
43 |
import edu.ucsb.nceas.dbadapter.AbstractDatabase; |
|
44 |
|
|
41 | 45 |
import org.xml.sax.Attributes; |
42 | 46 |
import org.xml.sax.InputSource; |
43 | 47 |
import org.xml.sax.SAXException; |
44 |
import org.xml.sax.SAXParseException; |
|
45 | 48 |
import org.xml.sax.XMLReader; |
49 |
import org.xml.sax.helpers.DefaultHandler; |
|
46 | 50 |
import org.xml.sax.helpers.XMLReaderFactory; |
47 |
import org.xml.sax.helpers.DefaultHandler; |
|
48 | 51 |
|
49 | 52 |
/** |
50 |
* A Class that represents a structured query, and can be |
|
51 |
* constructed from an XML serialization conforming to @see pathquery.dtd. |
|
52 |
* The printSQL() method can be used to print a SQL serialization of the query. |
|
53 |
* A Class that represents a structured query, and can be constructed from an |
|
54 |
* XML serialization conforming to |
|
55 |
* |
|
56 |
* @see pathquery.dtd. The printSQL() method can be used to print a SQL |
|
57 |
* serialization of the query. |
|
53 | 58 |
*/ |
54 |
public class QuerySpecification extends DefaultHandler { |
|
55 |
|
|
56 |
/** flag determining whether extended query terms are present */ |
|
57 |
private boolean containsExtendedSQL=false; |
|
58 |
/** Identifier for this query document */ |
|
59 |
private String meta_file_id; |
|
60 |
/** Title of this query */ |
|
61 |
private String queryTitle; |
|
62 |
/** List of document types to be returned using package back tracing */ |
|
63 |
private Vector returnDocList; |
|
64 |
/** List of document types to be searched */ |
|
65 |
private Vector filterDocList; |
|
66 |
/** List of fields to be returned in result set */ |
|
67 |
private Vector returnFieldList; |
|
68 |
/** List of users owning documents to be searched */ |
|
69 |
private Vector ownerList; |
|
70 |
/** List of sites/scopes used to constrain search */ |
|
71 |
private Vector siteList; |
|
72 |
/** The root query group that contains the recursive query constraints */ |
|
73 |
private QueryGroup query = null; |
|
74 |
|
|
75 |
// Query data structures used temporarily during XML parsing |
|
76 |
private Stack elementStack; |
|
77 |
private Stack queryStack; |
|
78 |
private String currentValue; |
|
79 |
private String currentPathexpr; |
|
80 |
private String parserName = null; |
|
81 |
private String accNumberSeparator = null; |
|
82 |
private static final AbstractDatabase dbAdapter = MetaCatUtil.dbAdapter; |
|
83 |
|
|
59 |
public class QuerySpecification extends DefaultHandler |
|
60 |
{ |
|
84 | 61 |
|
85 |
private boolean percentageSearch = false; |
|
86 |
|
|
87 |
private String userName = null; |
|
88 |
private static final String PUBLIC = "public"; |
|
89 |
private String [] group = null; |
|
62 |
/** flag determining whether extended query terms are present */ |
|
63 |
private boolean containsExtendedSQL = false; |
|
90 | 64 |
|
91 |
public static final String ATTRIBUTESYMBOL = "@"; |
|
92 |
private boolean hasAttributeReturnField = false; |
|
93 |
private Hashtable attributeReturnList = new Hashtable(); |
|
94 |
private int countAttributeReturnField = 0; |
|
95 |
/** |
|
96 |
* construct an instance of the QuerySpecification class |
|
97 |
* |
|
98 |
* @param queryspec the XML representation of the query (should conform |
|
99 |
* to pathquery.dtd) as a Reader |
|
100 |
* @param parserName the fully qualified name of a Java Class implementing |
|
101 |
* the org.xml.sax.XMLReader interface |
|
102 |
*/ |
|
103 |
public QuerySpecification( Reader queryspec, String parserName, |
|
104 |
String accNumberSeparator ) throws IOException { |
|
105 |
super(); |
|
106 |
|
|
107 |
// Initialize the class variables |
|
108 |
returnDocList = new Vector(); |
|
109 |
filterDocList = new Vector(); |
|
110 |
elementStack = new Stack(); |
|
111 |
queryStack = new Stack(); |
|
112 |
returnFieldList = new Vector(); |
|
113 |
ownerList = new Vector(); |
|
114 |
siteList = new Vector(); |
|
115 |
this.parserName = parserName; |
|
116 |
this.accNumberSeparator = accNumberSeparator; |
|
65 |
/** Identifier for this query document */ |
|
66 |
private String meta_file_id; |
|
117 | 67 |
|
118 |
// Initialize the parser and read the queryspec |
|
119 |
XMLReader parser = initializeParser(); |
|
120 |
if (parser == null) { |
|
121 |
System.err.println("SAX parser not instantiated properly."); |
|
68 |
/** Title of this query */ |
|
69 |
private String queryTitle; |
|
70 |
|
|
71 |
/** List of document types to be returned using package back tracing */ |
|
72 |
private Vector returnDocList; |
|
73 |
|
|
74 |
/** List of document types to be searched */ |
|
75 |
private Vector filterDocList; |
|
76 |
|
|
77 |
/** List of fields to be returned in result set */ |
|
78 |
private Vector returnFieldList; |
|
79 |
|
|
80 |
/** List of users owning documents to be searched */ |
|
81 |
private Vector ownerList; |
|
82 |
|
|
83 |
/** List of sites/scopes used to constrain search */ |
|
84 |
private Vector siteList; |
|
85 |
|
|
86 |
/** The root query group that contains the recursive query constraints */ |
|
87 |
private QueryGroup query = null; |
|
88 |
|
|
89 |
// Query data structures used temporarily during XML parsing |
|
90 |
private Stack elementStack; |
|
91 |
|
|
92 |
private Stack queryStack; |
|
93 |
|
|
94 |
private String currentValue; |
|
95 |
|
|
96 |
private String currentPathexpr; |
|
97 |
|
|
98 |
private String parserName = null; |
|
99 |
|
|
100 |
private String accNumberSeparator = null; |
|
101 |
|
|
102 |
private static final AbstractDatabase dbAdapter = MetaCatUtil.dbAdapter; |
|
103 |
|
|
104 |
private boolean percentageSearch = false; |
|
105 |
|
|
106 |
private String userName = null; |
|
107 |
|
|
108 |
private static final String PUBLIC = "public"; |
|
109 |
|
|
110 |
private String[] group = null; |
|
111 |
|
|
112 |
public static final String ATTRIBUTESYMBOL = "@"; |
|
113 |
|
|
114 |
private boolean hasAttributeReturnField = false; |
|
115 |
|
|
116 |
private Hashtable attributeReturnList = new Hashtable(); |
|
117 |
|
|
118 |
private int countAttributeReturnField = 0; |
|
119 |
|
|
120 |
/** |
|
121 |
* construct an instance of the QuerySpecification class |
|
122 |
* |
|
123 |
* @param queryspec |
|
124 |
* the XML representation of the query (should conform to |
|
125 |
* pathquery.dtd) as a Reader |
|
126 |
* @param parserName |
|
127 |
* the fully qualified name of a Java Class implementing the |
|
128 |
* org.xml.sax.XMLReader interface |
|
129 |
*/ |
|
130 |
public QuerySpecification(Reader queryspec, String parserName, |
|
131 |
String accNumberSeparator) throws IOException |
|
132 |
{ |
|
133 |
super(); |
|
134 |
|
|
135 |
// Initialize the class variables |
|
136 |
returnDocList = new Vector(); |
|
137 |
filterDocList = new Vector(); |
|
138 |
elementStack = new Stack(); |
|
139 |
queryStack = new Stack(); |
|
140 |
returnFieldList = new Vector(); |
|
141 |
ownerList = new Vector(); |
|
142 |
siteList = new Vector(); |
|
143 |
this.parserName = parserName; |
|
144 |
this.accNumberSeparator = accNumberSeparator; |
|
145 |
|
|
146 |
// Initialize the parser and read the queryspec |
|
147 |
XMLReader parser = initializeParser(); |
|
148 |
if (parser == null) { |
|
149 |
System.err.println("SAX parser not instantiated properly."); |
|
150 |
} |
|
151 |
try { |
|
152 |
parser.parse(new InputSource(queryspec)); |
|
153 |
} catch (SAXException e) { |
|
154 |
System.err.println("error parsing data in " |
|
155 |
+ "QuerySpecification.QuerySpecification"); |
|
156 |
System.err.println(e.getMessage()); |
|
157 |
} |
|
122 | 158 |
} |
123 |
try { |
|
124 |
parser.parse(new InputSource(queryspec)); |
|
125 |
} catch (SAXException e) { |
|
126 |
System.err.println("error parsing data in " + |
|
127 |
"QuerySpecification.QuerySpecification"); |
|
128 |
System.err.println(e.getMessage()); |
|
159 |
|
|
160 |
/** |
|
161 |
* construct an instance of the QuerySpecification class |
|
162 |
* |
|
163 |
* @param queryspec |
|
164 |
* the XML representation of the query (should conform to |
|
165 |
* pathquery.dtd) as a String |
|
166 |
* @param parserName |
|
167 |
* the fully qualified name of a Java Class implementing the |
|
168 |
* org.xml.sax.Parser interface |
|
169 |
*/ |
|
170 |
public QuerySpecification(String queryspec, String parserName, |
|
171 |
String accNumberSeparator) throws IOException |
|
172 |
{ |
|
173 |
this(new StringReader(queryspec), parserName, accNumberSeparator); |
|
129 | 174 |
} |
130 |
} |
|
131 | 175 |
|
132 |
/** |
|
133 |
* construct an instance of the QuerySpecification class |
|
134 |
* |
|
135 |
* @param queryspec the XML representation of the query (should conform |
|
136 |
* to pathquery.dtd) as a String |
|
137 |
* @param parserName the fully qualified name of a Java Class implementing |
|
138 |
* the org.xml.sax.Parser interface |
|
139 |
*/ |
|
140 |
public QuerySpecification( String queryspec, String parserName, |
|
141 |
String accNumberSeparator) throws IOException { |
|
142 |
this(new StringReader(queryspec), parserName, accNumberSeparator); |
|
143 |
} |
|
144 |
|
|
145 |
/** |
|
146 |
* construct an instance of the QuerySpecification class which don't need |
|
147 |
* to parser a xml document |
|
148 |
* @param accNumberSeparator the separator between doc version |
|
149 |
*/ |
|
150 |
public QuerySpecification(String accNumberSeparator ) throws IOException |
|
151 |
{ |
|
152 |
// Initialize the class variables |
|
153 |
returnDocList = new Vector(); |
|
154 |
filterDocList = new Vector(); |
|
155 |
elementStack = new Stack(); |
|
156 |
queryStack = new Stack(); |
|
157 |
returnFieldList = new Vector(); |
|
158 |
ownerList = new Vector(); |
|
159 |
siteList = new Vector(); |
|
160 |
this.accNumberSeparator = accNumberSeparator; |
|
161 |
} |
|
162 |
|
|
163 |
|
|
164 |
/** |
|
165 |
* Method to set user name |
|
166 |
* |
|
167 |
* @param myName the user name |
|
168 |
*/ |
|
169 |
public void setUserName(String myName) |
|
170 |
{ |
|
171 |
//to lower case |
|
172 |
if (myName != null) |
|
176 |
/** |
|
177 |
* construct an instance of the QuerySpecification class which don't need |
|
178 |
* to parser a xml document |
|
179 |
* |
|
180 |
* @param accNumberSeparator |
|
181 |
* the separator between doc version |
|
182 |
*/ |
|
183 |
public QuerySpecification(String accNumberSeparator) throws IOException |
|
173 | 184 |
{ |
174 |
this.userName = myName.toLowerCase(); |
|
185 |
// Initialize the class variables |
|
186 |
returnDocList = new Vector(); |
|
187 |
filterDocList = new Vector(); |
|
188 |
elementStack = new Stack(); |
|
189 |
queryStack = new Stack(); |
|
190 |
returnFieldList = new Vector(); |
|
191 |
ownerList = new Vector(); |
|
192 |
siteList = new Vector(); |
|
193 |
this.accNumberSeparator = accNumberSeparator; |
|
175 | 194 |
} |
176 |
else |
|
195 |
|
|
196 |
/** |
|
197 |
* Method to set user name |
|
198 |
* |
|
199 |
* @param myName |
|
200 |
* the user name |
|
201 |
*/ |
|
202 |
public void setUserName(String myName) |
|
177 | 203 |
{ |
178 |
this.userName = myName; |
|
204 |
//to lower case |
|
205 |
if (myName != null) { |
|
206 |
this.userName = myName.toLowerCase(); |
|
207 |
} else { |
|
208 |
this.userName = myName; |
|
209 |
} |
|
179 | 210 |
} |
180 |
} |
|
181 |
|
|
182 |
/** |
|
183 |
* Method to set user group |
|
184 |
* |
|
185 |
* @param myGroup the user group |
|
186 |
*/ |
|
187 |
public void setGroup(String [] myGroup) |
|
188 |
{ |
|
189 |
this.group = myGroup; |
|
190 |
} |
|
191 |
/** |
|
192 |
* Method to indicate this query is a percentage search |
|
193 |
*/ |
|
194 |
public boolean isPercentageSearch() |
|
195 |
{ |
|
196 |
return percentageSearch; |
|
197 |
} |
|
198 |
/* |
|
199 |
* Method to get owner query. If it is owner it has all permission |
|
200 |
*/ |
|
201 |
private String createOwerQuery() |
|
202 |
{ |
|
203 |
String ownerQuery = null; |
|
204 |
ownerQuery = "SELECT docid FROM xml_documents WHERE "; |
|
205 |
if (userName != null && !userName.equals("")) |
|
211 |
|
|
212 |
/** |
|
213 |
* Method to set user group |
|
214 |
* |
|
215 |
* @param myGroup |
|
216 |
* the user group |
|
217 |
*/ |
|
218 |
public void setGroup(String[] myGroup) |
|
206 | 219 |
{ |
207 |
ownerQuery = ownerQuery + "lower(user_owner) ='"+ userName +"'";
|
|
220 |
this.group = myGroup;
|
|
208 | 221 |
} |
209 |
|
|
210 |
MetaCatUtil.debugMessage("OwnerQuery: "+ownerQuery, 30); |
|
211 |
return ownerQuery; |
|
212 |
} |
|
213 |
|
|
214 |
/* |
|
215 |
* Method to create query for xml_access, this part is to get docid list which |
|
216 |
* have a allow rule for a given user |
|
217 |
*/ |
|
218 |
private String createAllowRuleQuery() |
|
219 |
{ |
|
220 |
String allowQuery = null; |
|
221 |
String allowString = constructAllowString(); |
|
222 |
allowQuery ="SELECT docid from xml_access WHERE( "+allowString; |
|
223 |
allowQuery = allowQuery +") AND subtreeid IS NULL"; |
|
224 |
MetaCatUtil.debugMessage("allow query is: "+ allowQuery, 30); |
|
225 |
return allowQuery; |
|
226 |
|
|
227 |
|
|
228 |
} |
|
229 |
|
|
230 |
/* Method to construct a allow rule string */ |
|
231 |
private String constructAllowString() |
|
232 |
{ |
|
233 |
String allowQuery =""; |
|
234 |
// add allow rule for user name |
|
235 |
if (userName != null && !userName.equals("")) |
|
222 |
|
|
223 |
/** |
|
224 |
* Method to indicate this query is a percentage search |
|
225 |
*/ |
|
226 |
public boolean isPercentageSearch() |
|
236 | 227 |
{ |
237 |
allowQuery = allowQuery +"(lower(principal_name) = '" + userName |
|
238 |
+"' AND perm_type = 'allow'" |
|
239 |
+" AND (permission='4' OR permission='7'))"; |
|
228 |
return percentageSearch; |
|
240 | 229 |
} |
241 |
// add allow rule for public |
|
242 |
allowQuery = allowQuery +"OR (lower(principal_name) = '" + PUBLIC |
|
243 |
+"' AND perm_type = 'allow'" |
|
244 |
+" AND (permission='4' OR permission='7'))"; |
|
245 |
|
|
246 |
// add allow rule for group |
|
247 |
if (group != null) |
|
230 |
|
|
231 |
/* |
|
232 |
* Method to get owner query. If it is owner it has all permission |
|
233 |
*/ |
|
234 |
private String createOwerQuery() |
|
248 | 235 |
{ |
249 |
for (int i = 0; i< group.length; i++) |
|
250 |
{ |
|
251 |
String groupUint = group[i]; |
|
252 |
if (groupUint != null && !groupUint.equals("")) |
|
253 |
{ |
|
254 |
groupUint = groupUint.toLowerCase(); |
|
255 |
allowQuery = allowQuery +" OR (lower(principal_name) = '" + groupUint |
|
256 |
+"' AND perm_type = 'allow'" |
|
257 |
+" AND (permission='4' OR permission='7'))"; |
|
258 |
}//if |
|
259 |
}//for |
|
260 |
}//if |
|
261 |
MetaCatUtil.debugMessage("allow string is: "+ allowQuery, 40); |
|
262 |
return allowQuery; |
|
263 |
} |
|
236 |
String ownerQuery = null; |
|
237 |
ownerQuery = "SELECT docid FROM xml_documents WHERE "; |
|
238 |
if (userName != null && !userName.equals("")) { |
|
239 |
ownerQuery = ownerQuery + "lower(user_owner) ='" + userName + "'"; |
|
240 |
} |
|
264 | 241 |
|
265 |
/* |
|
266 |
* Method to create query for xml_access, this part is to get docid list which |
|
267 |
* have a deny rule and perm_order is allowFirst for a given user. This means |
|
268 |
* the user will be denied to read |
|
269 |
*/ |
|
270 |
private String createDenyRuleQuery() |
|
271 |
{ |
|
272 |
String denyQuery = null; |
|
273 |
String denyString = constructDenyString(); |
|
274 |
denyQuery ="SELECT docid from xml_access WHERE( " + denyString; |
|
275 |
denyQuery = denyQuery + ") AND subtreeid IS NULL "; |
|
276 |
MetaCatUtil.debugMessage("denyquery is: "+ denyQuery, 30); |
|
277 |
return denyQuery; |
|
278 |
|
|
279 |
} |
|
280 |
/* Construct deny string */ |
|
281 |
private String constructDenyString() |
|
282 |
{ |
|
283 |
String denyQuery =""; |
|
284 |
// add deny rule for user name |
|
285 |
if (userName != null && !userName.equals("")) |
|
242 |
MetaCatUtil.debugMessage("OwnerQuery: " + ownerQuery, 30); |
|
243 |
return ownerQuery; |
|
244 |
} |
|
245 |
|
|
246 |
/* |
|
247 |
* Method to create query for xml_access, this part is to get docid list |
|
248 |
* which have a allow rule for a given user |
|
249 |
*/ |
|
250 |
private String createAllowRuleQuery() |
|
286 | 251 |
{ |
287 |
denyQuery = denyQuery +"(lower(principal_name) = '" + userName |
|
288 |
+"' AND perm_type = 'deny' " |
|
289 |
+"AND perm_order ='allowFirst'" |
|
290 |
+" AND (permission='4' OR permission='7'))"; |
|
252 |
String allowQuery = null; |
|
253 |
String allowString = constructAllowString(); |
|
254 |
allowQuery = "SELECT docid from xml_access WHERE( " + allowString; |
|
255 |
allowQuery = allowQuery + ") AND subtreeid IS NULL"; |
|
256 |
MetaCatUtil.debugMessage("allow query is: " + allowQuery, 30); |
|
257 |
return allowQuery; |
|
258 |
|
|
291 | 259 |
} |
292 |
// add deny rule for public |
|
293 |
denyQuery = denyQuery +"OR (lower(principal_name) = '" + PUBLIC |
|
294 |
+"' AND perm_type = 'deny' " |
|
295 |
+"AND perm_order ='allowFirst'" |
|
296 |
+" AND (permission='4' OR permission='7'))"; |
|
297 |
|
|
298 |
// add allow rule for group |
|
299 |
if (group != null) |
|
260 |
|
|
261 |
/* Method to construct a allow rule string */ |
|
262 |
private String constructAllowString() |
|
300 | 263 |
{ |
301 |
for (int i = 0; i< group.length; i++) |
|
302 |
{ |
|
303 |
String groupUint = group[i]; |
|
304 |
if (groupUint != null && !groupUint.equals("")) |
|
305 |
{ |
|
306 |
groupUint = groupUint.toLowerCase(); |
|
307 |
denyQuery = denyQuery +" OR (lower(principal_name) = '" + groupUint |
|
308 |
+"' AND perm_type = 'deny' " |
|
309 |
+"AND perm_order ='allowFirst'" |
|
310 |
+" AND (permission='4' OR permission='7'))"; |
|
264 |
String allowQuery = ""; |
|
265 |
// add allow rule for user name |
|
266 |
if (userName != null && !userName.equals("")) { |
|
267 |
allowQuery = allowQuery + "(lower(principal_name) = '" + userName |
|
268 |
+ "' AND perm_type = 'allow'" |
|
269 |
+ " AND (permission='4' OR permission='7'))"; |
|
270 |
} |
|
271 |
// add allow rule for public |
|
272 |
allowQuery = allowQuery + "OR (lower(principal_name) = '" + PUBLIC |
|
273 |
+ "' AND perm_type = 'allow'" |
|
274 |
+ " AND (permission='4' OR permission='7'))"; |
|
275 |
|
|
276 |
// add allow rule for group |
|
277 |
if (group != null) { |
|
278 |
for (int i = 0; i < group.length; i++) { |
|
279 |
String groupUint = group[i]; |
|
280 |
if (groupUint != null && !groupUint.equals("")) { |
|
281 |
groupUint = groupUint.toLowerCase(); |
|
282 |
allowQuery = allowQuery + " OR (lower(principal_name) = '" |
|
283 |
+ groupUint + "' AND perm_type = 'allow'" |
|
284 |
+ " AND (permission='4' OR permission='7'))"; |
|
285 |
}//if |
|
286 |
}//for |
|
311 | 287 |
}//if |
312 |
}//for |
|
313 |
}//if |
|
314 |
return denyQuery; |
|
315 |
} |
|
316 |
|
|
317 |
/** |
|
318 |
* Method to append a access control query to SQL. So in DBQuery class, we can |
|
319 |
* get docid from both user specified query and access control query. We don't |
|
320 |
* need to checking permission after we get the doclist. It will be good to |
|
321 |
* performance |
|
322 |
* |
|
323 |
*/ |
|
324 |
public String getAccessQuery() |
|
325 |
{ |
|
326 |
String accessQuery = null; |
|
327 |
String onwer = createOwerQuery(); |
|
328 |
String allow = createAllowRuleQuery(); |
|
329 |
String deny = createDenyRuleQuery(); |
|
330 |
accessQuery = " AND (docid IN("+ onwer + ")"; |
|
331 |
accessQuery = accessQuery + " OR (docid IN (" + allow + ")" |
|
332 |
+ " AND docid NOT IN ("+ deny + ")))"; |
|
333 |
MetaCatUtil.debugMessage("accessquery is: "+ accessQuery, 30); |
|
334 |
return accessQuery; |
|
335 |
} |
|
336 |
|
|
337 |
/** Main routine for testing */ |
|
338 |
static public void main(String[] args) { |
|
288 |
MetaCatUtil.debugMessage("allow string is: " + allowQuery, 40); |
|
289 |
return allowQuery; |
|
290 |
} |
|
339 | 291 |
|
340 |
if (args.length < 1) { |
|
341 |
System.err.println("Wrong number of arguments!!!"); |
|
342 |
System.err.println("USAGE: java QuerySpecification <xmlfile>"); |
|
343 |
return; |
|
344 |
} else { |
|
345 |
int i = 0; |
|
346 |
boolean useXMLIndex = true; |
|
347 |
if ( args[i].equals( "-noindex" ) ) { |
|
348 |
useXMLIndex = false; |
|
349 |
i++; |
|
350 |
} |
|
351 |
String xmlfile = args[i]; |
|
292 |
/* |
|
293 |
* Method to create query for xml_access, this part is to get docid list |
|
294 |
* which have a deny rule and perm_order is allowFirst for a given user. |
|
295 |
* This means the user will be denied to read |
|
296 |
*/ |
|
297 |
private String createDenyRuleQuery() |
|
298 |
{ |
|
299 |
String denyQuery = null; |
|
300 |
String denyString = constructDenyString(); |
|
301 |
denyQuery = "SELECT docid from xml_access WHERE( " + denyString; |
|
302 |
denyQuery = denyQuery + ") AND subtreeid IS NULL "; |
|
303 |
MetaCatUtil.debugMessage("denyquery is: " + denyQuery, 30); |
|
304 |
return denyQuery; |
|
352 | 305 |
|
353 |
try { |
|
354 |
MetaCatUtil util = new MetaCatUtil(); |
|
355 |
FileReader xml = new FileReader(new File(xmlfile)); |
|
356 |
QuerySpecification qspec = |
|
357 |
new QuerySpecification(xml, util.getOption("saxparser"), |
|
358 |
util.getOption("accNumberSeparator")); |
|
359 |
System.out.println(qspec.printSQL(useXMLIndex)); |
|
306 |
} |
|
360 | 307 |
|
361 |
} catch (IOException e) { |
|
362 |
System.err.println(e.getMessage()); |
|
363 |
} |
|
364 |
|
|
365 |
} |
|
366 |
} |
|
367 |
|
|
368 |
/** |
|
369 |
* Returns true if the parsed query contains and extended xml query |
|
370 |
* (i.e. there is at least one <returnfield> in the pathquery document) |
|
371 |
*/ |
|
372 |
public boolean containsExtendedSQL() |
|
373 |
{ |
|
374 |
if(containsExtendedSQL) |
|
308 |
/* Construct deny string */ |
|
309 |
private String constructDenyString() |
|
375 | 310 |
{ |
376 |
return true; |
|
311 |
String denyQuery = ""; |
|
312 |
// add deny rule for user name |
|
313 |
if (userName != null && !userName.equals("")) { |
|
314 |
denyQuery = denyQuery + "(lower(principal_name) = '" + userName |
|
315 |
+ "' AND perm_type = 'deny' " |
|
316 |
+ "AND perm_order ='allowFirst'" |
|
317 |
+ " AND (permission='4' OR permission='7'))"; |
|
318 |
} |
|
319 |
// add deny rule for public |
|
320 |
denyQuery = denyQuery + "OR (lower(principal_name) = '" + PUBLIC |
|
321 |
+ "' AND perm_type = 'deny' " + "AND perm_order ='allowFirst'" |
|
322 |
+ " AND (permission='4' OR permission='7'))"; |
|
323 |
|
|
324 |
// add allow rule for group |
|
325 |
if (group != null) { |
|
326 |
for (int i = 0; i < group.length; i++) { |
|
327 |
String groupUint = group[i]; |
|
328 |
if (groupUint != null && !groupUint.equals("")) { |
|
329 |
groupUint = groupUint.toLowerCase(); |
|
330 |
denyQuery = denyQuery + " OR (lower(principal_name) = '" |
|
331 |
+ groupUint + "' AND perm_type = 'deny' " |
|
332 |
+ "AND perm_order ='allowFirst'" |
|
333 |
+ " AND (permission='4' OR permission='7'))"; |
|
334 |
}//if |
|
335 |
}//for |
|
336 |
}//if |
|
337 |
return denyQuery; |
|
377 | 338 |
} |
378 |
else |
|
339 |
|
|
340 |
/** |
|
341 |
* Method to append a access control query to SQL. So in DBQuery class, we |
|
342 |
* can get docid from both user specified query and access control query. |
|
343 |
* We don't need to checking permission after we get the doclist. It will |
|
344 |
* be good to performance |
|
345 |
* |
|
346 |
*/ |
|
347 |
public String getAccessQuery() |
|
379 | 348 |
{ |
380 |
return false; |
|
349 |
String accessQuery = null; |
|
350 |
String onwer = createOwerQuery(); |
|
351 |
String allow = createAllowRuleQuery(); |
|
352 |
String deny = createDenyRuleQuery(); |
|
353 |
accessQuery = " AND (docid IN(" + onwer + ")"; |
|
354 |
accessQuery = accessQuery + " OR (docid IN (" + allow + ")" |
|
355 |
+ " AND docid NOT IN (" + deny + ")))"; |
|
356 |
MetaCatUtil.debugMessage("accessquery is: " + accessQuery, 30); |
|
357 |
return accessQuery; |
|
381 | 358 |
} |
382 |
} |
|
383 |
|
|
384 |
/** |
|
385 |
* A method to get if the query has an attribute return field |
|
386 |
*/ |
|
387 |
public boolean containAttributeReturnField() |
|
388 |
{ |
|
389 |
return hasAttributeReturnField; |
|
390 |
} |
|
391 |
|
|
392 |
/** |
|
393 |
* Accessor method to return the identifier of this Query |
|
394 |
*/ |
|
395 |
public String getIdentifier() |
|
396 |
{ |
|
397 |
return meta_file_id; |
|
398 |
} |
|
399 | 359 |
|
400 |
/** |
|
401 |
* method to set the identifier of this query |
|
402 |
*/ |
|
403 |
public void setIdentifier(String id) { |
|
404 |
this.meta_file_id = id; |
|
405 |
} |
|
360 |
/** Main routine for testing */ |
|
361 |
static public void main(String[] args) |
|
362 |
{ |
|
406 | 363 |
|
407 |
/** |
|
408 |
* Accessor method to return the title of this Query |
|
409 |
*/ |
|
410 |
public String getQueryTitle() |
|
411 |
{ |
|
412 |
return queryTitle; |
|
413 |
} |
|
364 |
if (args.length < 1) { |
|
365 |
System.err.println("Wrong number of arguments!!!"); |
|
366 |
System.err.println("USAGE: java QuerySpecification <xmlfile>"); |
|
367 |
return; |
|
368 |
} else { |
|
369 |
int i = 0; |
|
370 |
boolean useXMLIndex = true; |
|
371 |
if (args[i].equals("-noindex")) { |
|
372 |
useXMLIndex = false; |
|
373 |
i++; |
|
374 |
} |
|
375 |
String xmlfile = args[i]; |
|
414 | 376 |
|
415 |
/**
|
|
416 |
* method to set the title of this query
|
|
417 |
*/
|
|
418 |
public void setQueryTitle(String title)
|
|
419 |
{
|
|
420 |
this.queryTitle = title;
|
|
421 |
}
|
|
377 |
try {
|
|
378 |
MetaCatUtil util = new MetaCatUtil();
|
|
379 |
FileReader xml = new FileReader(new File(xmlfile));
|
|
380 |
QuerySpecification qspec = new QuerySpecification(xml, util
|
|
381 |
.getOption("saxparser"), util
|
|
382 |
.getOption("accNumberSeparator"));
|
|
383 |
System.out.println(qspec.printSQL(useXMLIndex));
|
|
422 | 384 |
|
423 |
/** |
|
424 |
* Accessor method to return a vector of the return document types as |
|
425 |
* defined in the <returndoctype> tag in the pathquery dtd. |
|
426 |
*/ |
|
427 |
public Vector getReturnDocList() |
|
428 |
{ |
|
429 |
return this.returnDocList; |
|
430 |
} |
|
385 |
} catch (IOException e) { |
|
386 |
System.err.println(e.getMessage()); |
|
387 |
} |
|
431 | 388 |
|
432 |
/** |
|
433 |
* method to set the list of return docs of this query |
|
434 |
*/ |
|
435 |
public void setReturnDocList(Vector returnDocList) |
|
436 |
{ |
|
437 |
this.returnDocList = returnDocList; |
|
438 |
} |
|
389 |
} |
|
390 |
} |
|
439 | 391 |
|
440 |
/** |
|
441 |
* Accessor method to return a vector of the filter doc types as |
|
442 |
* defined in the <filterdoctype> tag in the pathquery dtd. |
|
443 |
*/ |
|
444 |
public Vector getFilterDocList() |
|
445 |
{ |
|
446 |
return this.filterDocList; |
|
447 |
} |
|
392 |
/** |
|
393 |
* Returns true if the parsed query contains and extended xml query (i.e. |
|
394 |
* there is at least one <returnfield> in the pathquery document) |
|
395 |
*/ |
|
396 |
public boolean containsExtendedSQL() |
|
397 |
{ |
|
398 |
if (containsExtendedSQL) { |
|
399 |
return true; |
|
400 |
} else { |
|
401 |
return false; |
|
402 |
} |
|
403 |
} |
|
448 | 404 |
|
449 |
/** |
|
450 |
* method to set the list of filter docs of this query
|
|
451 |
*/ |
|
452 |
public void setFilterDocList(Vector filterDocList)
|
|
453 |
{ |
|
454 |
this.filterDocList = filterDocList;
|
|
455 |
} |
|
405 |
/**
|
|
406 |
* A method to get if the query has an attribute return field
|
|
407 |
*/
|
|
408 |
public boolean containAttributeReturnField()
|
|
409 |
{
|
|
410 |
return hasAttributeReturnField;
|
|
411 |
}
|
|
456 | 412 |
|
457 |
/** |
|
458 |
* Accessor method to return a vector of the extended return fields as |
|
459 |
* defined in the <returnfield> tag in the pathquery dtd. |
|
460 |
*/ |
|
461 |
public Vector getReturnFieldList() |
|
462 |
{ |
|
463 |
return this.returnFieldList; |
|
464 |
} |
|
413 |
/** |
|
414 |
* Accessor method to return the identifier of this Query |
|
415 |
*/ |
|
416 |
public String getIdentifier() |
|
417 |
{ |
|
418 |
return meta_file_id; |
|
419 |
} |
|
465 | 420 |
|
466 |
/** |
|
467 |
* method to set the list of fields to be returned by this query
|
|
468 |
*/ |
|
469 |
public void setReturnFieldList(Vector returnFieldList)
|
|
470 |
{ |
|
471 |
this.returnFieldList = returnFieldList;
|
|
472 |
} |
|
421 |
/**
|
|
422 |
* method to set the identifier of this query
|
|
423 |
*/
|
|
424 |
public void setIdentifier(String id)
|
|
425 |
{
|
|
426 |
this.meta_file_id = id;
|
|
427 |
}
|
|
473 | 428 |
|
474 |
/** |
|
475 |
* Accessor method to return a vector of the owner fields as |
|
476 |
* defined in the <owner> tag in the pathquery dtd. |
|
477 |
*/ |
|
478 |
public Vector getOwnerList() |
|
479 |
{ |
|
480 |
return this.ownerList; |
|
481 |
} |
|
429 |
/** |
|
430 |
* Accessor method to return the title of this Query |
|
431 |
*/ |
|
432 |
public String getQueryTitle() |
|
433 |
{ |
|
434 |
return queryTitle; |
|
435 |
} |
|
482 | 436 |
|
483 |
/** |
|
484 |
* method to set the list of owners used to constrain this query
|
|
485 |
*/ |
|
486 |
public void setOwnerList(Vector ownerList)
|
|
487 |
{ |
|
488 |
this.ownerList = ownerList;
|
|
489 |
} |
|
437 |
/**
|
|
438 |
* method to set the title of this query
|
|
439 |
*/
|
|
440 |
public void setQueryTitle(String title)
|
|
441 |
{
|
|
442 |
this.queryTitle = title;
|
|
443 |
}
|
|
490 | 444 |
|
491 |
/** |
|
492 |
* Accessor method to return a vector of the site fields as
|
|
493 |
* defined in the <site> tag in the pathquery dtd.
|
|
494 |
*/ |
|
495 |
public Vector getSiteList()
|
|
496 |
{ |
|
497 |
return this.siteList;
|
|
498 |
} |
|
445 |
/**
|
|
446 |
* Accessor method to return a vector of the return document types as
|
|
447 |
* defined in the <returndoctype> tag in the pathquery dtd.
|
|
448 |
*/
|
|
449 |
public Vector getReturnDocList()
|
|
450 |
{
|
|
451 |
return this.returnDocList;
|
|
452 |
}
|
|
499 | 453 |
|
500 |
/** |
|
501 |
* method to set the list of sites used to constrain this query
|
|
502 |
*/ |
|
503 |
public void setSiteList(Vector siteList)
|
|
504 |
{ |
|
505 |
this.siteList = siteList;
|
|
506 |
} |
|
454 |
/**
|
|
455 |
* method to set the list of return docs of this query
|
|
456 |
*/
|
|
457 |
public void setReturnDocList(Vector returnDocList)
|
|
458 |
{
|
|
459 |
this.returnDocList = returnDocList;
|
|
460 |
}
|
|
507 | 461 |
|
508 |
/** |
|
509 |
* get the QueryGroup used to express query constraints |
|
510 |
*/ |
|
511 |
public QueryGroup getQueryGroup() |
|
512 |
{ |
|
513 |
return query; |
|
514 |
} |
|
515 |
|
|
516 |
/** |
|
517 |
* set the querygroup |
|
518 |
*/ |
|
519 |
public void setQueryGroup(QueryGroup group) |
|
520 |
{ |
|
521 |
query = group; |
|
522 |
} |
|
523 |
|
|
524 |
/** |
|
525 |
* set if this query sepcification has extendQuery(has return doc type or not) |
|
526 |
*/ |
|
527 |
public void setContainsExtenedSQL(boolean hasExtenedQuery) |
|
528 |
{ |
|
529 |
containsExtendedSQL = hasExtenedQuery; |
|
530 |
} |
|
531 |
|
|
532 |
/** |
|
533 |
* Set up the SAX parser for reading the XML serialized query |
|
534 |
*/ |
|
535 |
private XMLReader initializeParser() { |
|
536 |
XMLReader parser = null; |
|
462 |
/** |
|
463 |
* Accessor method to return a vector of the filter doc types as defined in |
|
464 |
* the <filterdoctype> tag in the pathquery dtd. |
|
465 |
*/ |
|
466 |
public Vector getFilterDocList() |
|
467 |
{ |
|
468 |
return this.filterDocList; |
|
469 |
} |
|
537 | 470 |
|
538 |
// Set up the SAX document handlers for parsing |
|
539 |
try { |
|
471 |
/** |
|
472 |
* method to set the list of filter docs of this query |
|
473 |
*/ |
|
474 |
public void setFilterDocList(Vector filterDocList) |
|
475 |
{ |
|
476 |
this.filterDocList = filterDocList; |
|
477 |
} |
|
540 | 478 |
|
541 |
// Get an instance of the parser |
|
542 |
parser = XMLReaderFactory.createXMLReader(parserName); |
|
479 |
/** |
|
480 |
* Accessor method to return a vector of the extended return fields as |
|
481 |
* defined in the <returnfield> tag in the pathquery dtd. |
|
482 |
*/ |
|
483 |
public Vector getReturnFieldList() |
|
484 |
{ |
|
485 |
return this.returnFieldList; |
|
486 |
} |
|
543 | 487 |
|
544 |
// Set the ContentHandler to this instance |
|
545 |
parser.setContentHandler(this); |
|
488 |
/** |
|
489 |
* method to set the list of fields to be returned by this query |
|
490 |
*/ |
|
491 |
public void setReturnFieldList(Vector returnFieldList) |
|
492 |
{ |
|
493 |
this.returnFieldList = returnFieldList; |
|
494 |
} |
|
546 | 495 |
|
547 |
// Set the error Handler to this instance |
|
548 |
parser.setErrorHandler(this); |
|
496 |
/** |
|
497 |
* Accessor method to return a vector of the owner fields as defined in the |
|
498 |
* <owner> tag in the pathquery dtd. |
|
499 |
*/ |
|
500 |
public Vector getOwnerList() |
|
501 |
{ |
|
502 |
return this.ownerList; |
|
503 |
} |
|
549 | 504 |
|
550 |
} catch (Exception e) { |
|
551 |
System.err.println("Error in QuerySpcecification.initializeParser " + |
|
552 |
e.toString()); |
|
505 |
/** |
|
506 |
* method to set the list of owners used to constrain this query |
|
507 |
*/ |
|
508 |
public void setOwnerList(Vector ownerList) |
|
509 |
{ |
|
510 |
this.ownerList = ownerList; |
|
553 | 511 |
} |
554 | 512 |
|
555 |
return parser; |
|
556 |
} |
|
513 |
/** |
|
514 |
* Accessor method to return a vector of the site fields as defined in the |
|
515 |
* <site> tag in the pathquery dtd. |
|
516 |
*/ |
|
517 |
public Vector getSiteList() |
|
518 |
{ |
|
519 |
return this.siteList; |
|
520 |
} |
|
557 | 521 |
|
558 |
/** |
|
559 |
* callback method used by the SAX Parser when the start tag of an |
|
560 |
* element is detected. Used in this context to parse and store |
|
561 |
* the query information in class variables. |
|
562 |
*/ |
|
563 |
public void startElement (String uri, String localName, |
|
564 |
String qName, Attributes atts) |
|
565 |
throws SAXException { |
|
566 |
BasicNode currentNode = new BasicNode(localName); |
|
567 |
// add attributes to BasicNode here |
|
568 |
if (atts != null) { |
|
569 |
int len = atts.getLength(); |
|
570 |
for (int i = 0; i < len; i++) { |
|
571 |
currentNode.setAttribute(atts.getLocalName(i), atts.getValue(i)); |
|
572 |
} |
|
522 |
/** |
|
523 |
* method to set the list of sites used to constrain this query |
|
524 |
*/ |
|
525 |
public void setSiteList(Vector siteList) |
|
526 |
{ |
|
527 |
this.siteList = siteList; |
|
573 | 528 |
} |
574 | 529 |
|
575 |
elementStack.push(currentNode); |
|
576 |
if (currentNode.getTagName().equals("querygroup")) { |
|
577 |
QueryGroup currentGroup = new QueryGroup( |
|
578 |
currentNode.getAttribute("operator")); |
|
579 |
if (query == null) { |
|
580 |
query = currentGroup; |
|
581 |
} else { |
|
582 |
QueryGroup parentGroup = (QueryGroup)queryStack.peek(); |
|
583 |
parentGroup.addChild(currentGroup); |
|
584 |
} |
|
585 |
queryStack.push(currentGroup); |
|
530 |
/** |
|
531 |
* get the QueryGroup used to express query constraints |
|
532 |
*/ |
|
533 |
public QueryGroup getQueryGroup() |
|
534 |
{ |
|
535 |
return query; |
|
586 | 536 |
} |
587 |
} |
|
588 | 537 |
|
589 |
/** |
|
590 |
* callback method used by the SAX Parser when the end tag of an |
|
591 |
* element is detected. Used in this context to parse and store |
|
592 |
* the query information in class variables. |
|
593 |
*/ |
|
594 |
public void endElement (String uri, String localName, |
|
595 |
String qName) throws SAXException { |
|
596 |
BasicNode leaving = (BasicNode)elementStack.pop(); |
|
597 |
if (leaving.getTagName().equals("queryterm")) { |
|
598 |
boolean isCaseSensitive = (new Boolean( |
|
599 |
leaving.getAttribute("casesensitive"))).booleanValue(); |
|
600 |
QueryTerm currentTerm = null; |
|
601 |
if (currentPathexpr == null) { |
|
602 |
currentTerm = new QueryTerm(isCaseSensitive, |
|
603 |
leaving.getAttribute("searchmode"),currentValue); |
|
604 |
} else { |
|
605 |
currentTerm = new QueryTerm(isCaseSensitive, |
|
606 |
leaving.getAttribute("searchmode"),currentValue, |
|
607 |
currentPathexpr); |
|
608 |
} |
|
609 |
QueryGroup currentGroup = (QueryGroup)queryStack.peek(); |
|
610 |
currentGroup.addChild(currentTerm); |
|
611 |
currentValue = null; |
|
612 |
currentPathexpr = null; |
|
613 |
} else if (leaving.getTagName().equals("querygroup")) { |
|
614 |
QueryGroup leavingGroup = (QueryGroup)queryStack.pop(); |
|
538 |
/** |
|
539 |
* set the querygroup |
|
540 |
*/ |
|
541 |
public void setQueryGroup(QueryGroup group) |
|
542 |
{ |
|
543 |
query = group; |
|
615 | 544 |
} |
616 |
} |
|
617 | 545 |
|
618 |
/** |
|
619 |
* callback method used by the SAX Parser when the text sequences of an |
|
620 |
* xml stream are detected. Used in this context to parse and store |
|
621 |
* the query information in class variables. |
|
622 |
*/ |
|
623 |
public void characters(char ch[], int start, int length) { |
|
546 |
/** |
|
547 |
* set if this query sepcification has extendQuery(has return doc type or |
|
548 |
* not) |
|
549 |
*/ |
|
550 |
public void setContainsExtenedSQL(boolean hasExtenedQuery) |
|
551 |
{ |
|
552 |
containsExtendedSQL = hasExtenedQuery; |
|
553 |
} |
|
624 | 554 |
|
625 |
String inputString = new String(ch, start, length); |
|
626 |
BasicNode currentNode = (BasicNode)elementStack.peek(); |
|
627 |
String currentTag = currentNode.getTagName(); |
|
628 |
if (currentTag.equals("meta_file_id")) { |
|
629 |
meta_file_id = inputString; |
|
630 |
} else if (currentTag.equals("querytitle")) { |
|
631 |
queryTitle = inputString; |
|
632 |
} else if (currentTag.equals("value")) { |
|
633 |
currentValue = inputString; |
|
634 |
} else if (currentTag.equals("pathexpr")) { |
|
635 |
currentPathexpr = inputString; |
|
636 |
} else if (currentTag.equals("returndoctype")) { |
|
637 |
returnDocList.add(inputString); |
|
638 |
} else if (currentTag.equals("filterdoctype")) { |
|
639 |
filterDocList.add(inputString); |
|
640 |
} else if (currentTag.equals("returnfield")) { |
|
641 |
handleReturnField(inputString); |
|
642 |
} else if (currentTag.equals("filterdoctype")) { |
|
643 |
filterDocList.add(inputString); |
|
644 |
} else if (currentTag.equals("owner")) { |
|
645 |
ownerList.add(inputString); |
|
646 |
} else if (currentTag.equals("site")) { |
|
647 |
siteList.add(inputString); |
|
555 |
/** |
|
556 |
* Set up the SAX parser for reading the XML serialized query |
|
557 |
*/ |
|
558 |
private XMLReader initializeParser() |
|
559 |
{ |
|
560 |
XMLReader parser = null; |
|
561 |
|
|
562 |
// Set up the SAX document handlers for parsing |
|
563 |
try { |
|
564 |
|
|
565 |
// Get an instance of the parser |
|
566 |
parser = XMLReaderFactory.createXMLReader(parserName); |
|
567 |
|
|
568 |
// Set the ContentHandler to this instance |
|
569 |
parser.setContentHandler(this); |
|
570 |
|
|
571 |
// Set the error Handler to this instance |
|
572 |
parser.setErrorHandler(this); |
|
573 |
|
|
574 |
} catch (Exception e) { |
|
575 |
System.err.println("Error in QuerySpcecification.initializeParser " |
|
576 |
+ e.toString()); |
|
577 |
} |
|
578 |
|
|
579 |
return parser; |
|
648 | 580 |
} |
649 |
} |
|
650 |
|
|
651 |
/** |
|
652 |
* Method to transfer string to return field |
|
653 |
*/ |
|
654 |
public void handleReturnField(String inputString) |
|
655 |
{ |
|
656 |
// make sure if return fields has an attribute or not |
|
657 |
if (inputString.indexOf(ATTRIBUTESYMBOL) ==-1) |
|
658 |
{ |
|
659 |
// no attribute value will be returned |
|
660 |
returnFieldList.add(inputString); |
|
661 |
containsExtendedSQL = true; |
|
662 |
} |
|
663 |
else |
|
664 |
{ |
|
665 |
// has a attribute return field |
|
666 |
// divied the return filed into two parts, one is path and the |
|
667 |
// other is attribue name |
|
668 |
String returnPath = newPathExpressionWithOutAttribute(inputString); |
|
669 |
String attributeName = getAttributeName(inputString); |
|
670 |
Vector pathInfo = new Vector(); |
|
671 |
// the vector has the information about return path and attributename |
|
672 |
pathInfo.addElement(returnPath); |
|
673 |
pathInfo.addElement(attributeName); |
|
674 |
// put the vector into a hash table. The reseaon why don't put |
|
675 |
// return path or attributename as a key is because they are not unique |
|
676 |
attributeReturnList.put |
|
677 |
(new Integer(countAttributeReturnField), pathInfo); |
|
678 |
countAttributeReturnField++; |
|
679 |
hasAttributeReturnField = true; |
|
680 |
containsExtendedSQL = true; |
|
681 |
|
|
682 |
} |
|
683 |
} |
|
684 |
/** |
|
685 |
* create a SQL serialization of the query that this instance represents |
|
686 |
*/ |
|
687 |
public String printSQL(boolean useXMLIndex) { |
|
688 |
|
|
689 |
|
|
690 |
StringBuffer self = new StringBuffer(); |
|
691 | 581 |
|
692 |
self.append("SELECT docid,docname,doctype,"); |
|
693 |
self.append("date_created, date_updated, rev "); |
|
694 |
self.append("FROM xml_documents WHERE docid IN ("); |
|
582 |
/** |
|
583 |
* callback method used by the SAX Parser when the start tag of an element |
|
584 |
* is detected. Used in this context to parse and store the query |
|
585 |
* information in class variables. |
|
586 |
*/ |
|
587 |
public void startElement(String uri, String localName, String qName, |
|
588 |
Attributes atts) throws SAXException |
|
589 |
{ |
|
590 |
BasicNode currentNode = new BasicNode(localName); |
|
591 |
// add attributes to BasicNode here |
|
592 |
if (atts != null) { |
|
593 |
int len = atts.getLength(); |
|
594 |
for (int i = 0; i < len; i++) { |
|
595 |
currentNode |
|
596 |
.setAttribute(atts.getLocalName(i), atts.getValue(i)); |
|
597 |
} |
|
598 |
} |
|
695 | 599 |
|
696 |
// This determines the documents that meet the query conditions |
|
697 |
self.append(query.printSQL(useXMLIndex)); |
|
600 |
elementStack.push(currentNode); |
|
601 |
if (currentNode.getTagName().equals("querygroup")) { |
|
602 |
QueryGroup currentGroup = new QueryGroup(currentNode |
|
603 |
.getAttribute("operator")); |
|
604 |
if (query == null) { |
|
605 |
query = currentGroup; |
|
606 |
} else { |
|
607 |
QueryGroup parentGroup = (QueryGroup) queryStack.peek(); |
|
608 |
parentGroup.addChild(currentGroup); |
|
609 |
} |
|
610 |
queryStack.push(currentGroup); |
|
611 |
} |
|
612 |
} |
|
698 | 613 |
|
699 |
self.append(") "); |
|
700 |
|
|
701 |
// Add SQL to filter for doctypes requested in the query |
|
702 |
// This is an implicit OR for the list of doctypes. Only doctypes in this |
|
703 |
// list will be searched if the tag is present |
|
704 |
if (!filterDocList.isEmpty()) { |
|
705 |
boolean firstdoctype = true; |
|
706 |
self.append(" AND ("); |
|
707 |
Enumeration en = filterDocList.elements(); |
|
708 |
while (en.hasMoreElements()) { |
|
709 |
String currentDoctype = (String)en.nextElement(); |
|
710 |
if (firstdoctype) { |
|
711 |
firstdoctype = false; |
|
712 |
self.append(" doctype = '" + currentDoctype + "'"); |
|
713 |
} else { |
|
714 |
self.append(" OR doctype = '" + currentDoctype + "'"); |
|
614 |
/** |
|
615 |
* callback method used by the SAX Parser when the end tag of an element is |
|
616 |
* detected. Used in this context to parse and store the query information |
|
617 |
* in class variables. |
|
618 |
*/ |
|
619 |
public void endElement(String uri, String localName, String qName) |
|
620 |
throws SAXException |
|
621 |
{ |
|
622 |
BasicNode leaving = (BasicNode) elementStack.pop(); |
|
623 |
if (leaving.getTagName().equals("queryterm")) { |
|
624 |
boolean isCaseSensitive = (new Boolean(leaving |
|
625 |
.getAttribute("casesensitive"))).booleanValue(); |
|
626 |
QueryTerm currentTerm = null; |
|
627 |
if (currentPathexpr == null) { |
|
628 |
currentTerm = new QueryTerm(isCaseSensitive, leaving |
|
629 |
.getAttribute("searchmode"), currentValue); |
|
630 |
} else { |
|
631 |
currentTerm = new QueryTerm(isCaseSensitive, leaving |
|
632 |
.getAttribute("searchmode"), currentValue, |
|
633 |
currentPathexpr); |
|
634 |
} |
|
635 |
QueryGroup currentGroup = (QueryGroup) queryStack.peek(); |
|
636 |
currentGroup.addChild(currentTerm); |
|
637 |
currentValue = null; |
|
638 |
currentPathexpr = null; |
|
639 |
} else if (leaving.getTagName().equals("querygroup")) { |
|
640 |
QueryGroup leavingGroup = (QueryGroup) queryStack.pop(); |
|
715 | 641 |
} |
716 |
} |
|
717 |
self.append(") "); |
|
718 | 642 |
} |
719 | 643 |
|
720 |
// Add SQL to filter for owners requested in the query |
|
721 |
// This is an implicit OR for the list of owners |
|
722 |
if (!ownerList.isEmpty()) { |
|
723 |
boolean first = true; |
|
724 |
self.append(" AND ("); |
|
725 |
Enumeration en = ownerList.elements(); |
|
726 |
while (en.hasMoreElements()) { |
|
727 |
String current = (String)en.nextElement(); |
|
728 |
if (current != null) |
|
729 |
{ |
|
730 |
current = current.toLowerCase(); |
|
644 |
/** |
|
645 |
* callback method used by the SAX Parser when the text sequences of an xml |
|
646 |
* stream are detected. Used in this context to parse and store the query |
|
647 |
* information in class variables. |
|
648 |
*/ |
|
649 |
public void characters(char ch[], int start, int length) |
|
650 |
{ |
|
651 |
|
|
652 |
String inputString = new String(ch, start, length); |
|
653 |
BasicNode currentNode = (BasicNode) elementStack.peek(); |
|
654 |
String currentTag = currentNode.getTagName(); |
|
655 |
if (currentTag.equals("meta_file_id")) { |
|
656 |
meta_file_id = inputString; |
|
657 |
} else if (currentTag.equals("querytitle")) { |
|
658 |
queryTitle = inputString; |
|
659 |
} else if (currentTag.equals("value")) { |
|
660 |
currentValue = inputString; |
|
661 |
} else if (currentTag.equals("pathexpr")) { |
|
662 |
currentPathexpr = inputString; |
|
663 |
} else if (currentTag.equals("returndoctype")) { |
|
664 |
returnDocList.add(inputString); |
|
665 |
} else if (currentTag.equals("filterdoctype")) { |
|
666 |
filterDocList.add(inputString); |
|
667 |
} else if (currentTag.equals("returnfield")) { |
|
668 |
handleReturnField(inputString); |
|
669 |
} else if (currentTag.equals("filterdoctype")) { |
|
670 |
filterDocList.add(inputString); |
|
671 |
} else if (currentTag.equals("owner")) { |
|
672 |
ownerList.add(inputString); |
|
673 |
} else if (currentTag.equals("site")) { |
|
674 |
siteList.add(inputString); |
|
731 | 675 |
} |
732 |
if (first) { |
|
733 |
first = false; |
|
734 |
self.append(" lower(user_owner) = '" + current + "'"); |
|
676 |
} |
|
677 |
|
|
678 |
/** |
|
679 |
* Method to transfer string to return field |
|
680 |
*/ |
|
681 |
public void handleReturnField(String inputString) |
|
682 |
{ |
|
683 |
// make sure if return fields has an attribute or not |
|
684 |
if (inputString.indexOf(ATTRIBUTESYMBOL) == -1) { |
|
685 |
// no attribute value will be returned |
|
686 |
returnFieldList.add(inputString); |
|
687 |
containsExtendedSQL = true; |
|
735 | 688 |
} else { |
736 |
self.append(" OR lower(user_owner) = '" + current + "'"); |
|
689 |
// has a attribute return field |
|
690 |
// divied the return filed into two parts, one is path and the |
|
691 |
// other is attribue name |
|
692 |
String returnPath = newPathExpressionWithOutAttribute(inputString); |
|
693 |
String attributeName = getAttributeName(inputString); |
|
694 |
Vector pathInfo = new Vector(); |
|
695 |
// the vector has the information about return path and |
|
696 |
// attributename |
|
697 |
pathInfo.addElement(returnPath); |
|
698 |
pathInfo.addElement(attributeName); |
|
699 |
// put the vector into a hash table. The reseaon why don't put |
|
700 |
// return path or attributename as a key is because they are not |
|
701 |
// unique |
|
702 |
attributeReturnList.put(new Integer(countAttributeReturnField), |
|
703 |
pathInfo); |
|
704 |
countAttributeReturnField++; |
|
705 |
hasAttributeReturnField = true; |
|
706 |
containsExtendedSQL = true; |
|
707 |
|
|
737 | 708 |
} |
738 |
} |
|
739 |
self.append(") "); |
|
740 | 709 |
} |
741 | 710 |
|
742 |
// Add SQL to filter for sites requested in the query |
|
743 |
// This is an implicit OR for the list of sites |
|
744 |
if (!siteList.isEmpty()) { |
|
745 |
boolean first = true; |
|
746 |
self.append(" AND ("); |
|
747 |
Enumeration en = siteList.elements(); |
|
748 |
while (en.hasMoreElements()) { |
|
749 |
String current = (String)en.nextElement(); |
|
750 |
if (first) { |
|
751 |
first = false; |
|
752 |
self.append(" SUBSTR(docid, 1, INSTR(docid, '" + |
|
753 |
accNumberSeparator + "')-1) = '" + current + "'"); |
|
754 |
} else { |
|
755 |
self.append(" OR SUBSTR(docid, 1, INSTR(docid, '" + |
|
756 |
accNumberSeparator + "')-1) = '" + current + "'"); |
|
711 |
/** |
|
712 |
* create a SQL serialization of the query that this instance represents |
|
713 |
*/ |
|
714 |
public String printSQL(boolean useXMLIndex) |
|
715 |
{ |
|
716 |
|
|
717 |
StringBuffer self = new StringBuffer(); |
|
718 |
|
|
719 |
self.append("SELECT docid,docname,doctype,"); |
|
720 |
self.append("date_created, date_updated, rev "); |
|
721 |
self.append("FROM xml_documents WHERE docid IN ("); |
|
722 |
|
|
723 |
// This determines the documents that meet the query conditions |
|
724 |
self.append(query.printSQL(useXMLIndex)); |
|
725 |
|
|
726 |
self.append(") "); |
|
727 |
|
|
728 |
// Add SQL to filter for doctypes requested in the query |
|
729 |
// This is an implicit OR for the list of doctypes. Only doctypes in |
|
730 |
// this |
|
731 |
// list will be searched if the tag is present |
|
732 |
if (!filterDocList.isEmpty()) { |
|
733 |
boolean firstdoctype = true; |
|
734 |
self.append(" AND ("); |
|
735 |
Enumeration en = filterDocList.elements(); |
|
736 |
while (en.hasMoreElements()) { |
|
737 |
String currentDoctype = (String) en.nextElement(); |
|
738 |
if (firstdoctype) { |
|
739 |
firstdoctype = false; |
|
740 |
self.append(" doctype = '" + currentDoctype + "'"); |
|
741 |
} else { |
|
742 |
self.append(" OR doctype = '" + currentDoctype + "'"); |
|
743 |
} |
|
744 |
} |
|
745 |
self.append(") "); |
|
757 | 746 |
} |
758 |
} |
|
759 |
self.append(") "); |
|
747 |
|
|
748 |
// Add SQL to filter for owners requested in the query |
|
749 |
// This is an implicit OR for the list of owners |
|
750 |
if (!ownerList.isEmpty()) { |
|
751 |
boolean first = true; |
|
752 |
self.append(" AND ("); |
|
753 |
Enumeration en = ownerList.elements(); |
|
754 |
while (en.hasMoreElements()) { |
|
755 |
String current = (String) en.nextElement(); |
|
756 |
if (current != null) { |
|
757 |
current = current.toLowerCase(); |
|
758 |
} |
|
759 |
if (first) { |
|
760 |
first = false; |
|
761 |
self.append(" lower(user_owner) = '" + current + "'"); |
|
762 |
} else { |
|
763 |
self.append(" OR lower(user_owner) = '" + current + "'"); |
|
764 |
} |
|
765 |
} |
|
766 |
self.append(") "); |
|
767 |
} |
|
768 |
|
|
769 |
// Add SQL to filter for sites requested in the query |
|
770 |
// This is an implicit OR for the list of sites |
|
771 |
if (!siteList.isEmpty()) { |
|
772 |
boolean first = true; |
|
773 |
self.append(" AND ("); |
|
774 |
Enumeration en = siteList.elements(); |
|
775 |
while (en.hasMoreElements()) { |
|
776 |
String current = (String) en.nextElement(); |
|
777 |
if (first) { |
|
778 |
first = false; |
|
779 |
self.append(" SUBSTR(docid, 1, INSTR(docid, '" |
|
780 |
+ accNumberSeparator + "')-1) = '" + current + "'"); |
|
781 |
} else { |
|
782 |
self.append(" OR SUBSTR(docid, 1, INSTR(docid, '" |
|
783 |
+ accNumberSeparator + "')-1) = '" + current + "'"); |
|
784 |
} |
|
785 |
} |
|
786 |
self.append(") "); |
|
787 |
} |
|
788 |
|
|
789 |
// if there is only one percentage search item, this query is a |
|
790 |
// percentage |
|
791 |
// search query |
|
792 |
MetaCatUtil.debugMessage("percentage number: " |
|
793 |
+ query.getPercentageSymbolCount(), 35); |
|
794 |
if (query.getPercentageSymbolCount() == 1) { |
|
795 |
MetaCatUtil.debugMessage("it is a percentage search", 30); |
|
796 |
percentageSearch = true; |
|
797 |
} |
|
798 |
|
|
799 |
return self.toString(); |
|
760 | 800 |
} |
761 |
|
|
762 |
// if there is only one percentage search item, this query is a percentage
|
|
763 |
// search query
|
|
764 |
MetaCatUtil.debugMessage("percentage number: " +
|
|
765 |
query.getPercentageSymbolCount(), 35);
|
|
766 |
if (query.getPercentageSymbolCount() ==1 )
|
|
801 |
|
|
802 |
/**
|
|
803 |
* This sql command will selecet startnodeid and endnodeid that user can
|
|
804 |
* NOT access
|
|
805 |
*/
|
|
806 |
public String printAccessControlSQLForReturnField(String doclist)
|
|
767 | 807 |
{ |
768 |
MetaCatUtil.debugMessage("it is a percentage search", 30); |
|
769 |
percentageSearch =true; |
|
808 |
StringBuffer sql = new StringBuffer(); |
|
809 |
String allowString = constructAllowString(); |
|
810 |
String denyString = constructDenyString(); |
|
811 |
sql.append("SELECT distinct startnodeid, endnodeid from xml_access "); |
|
812 |
sql.append("WHERE docid in ("); |
|
813 |
sql.append(doclist); |
|
814 |
sql.append(") AND startnodeid IS NOT NULL AND "); |
|
815 |
sql.append("("); |
|
816 |
sql.append("("); |
|
817 |
sql.append("startnodeid NOT IN (SELECT startnodeid from xml_access, xml_documents "); |
|
818 |
sql.append(" WHERE xml_access.docid = xml_documents.docid"); |
|
819 |
sql.append(" AND lower(xml_documents.user_owner) ='"); |
|
820 |
sql.append(userName); |
|
821 |
sql.append("' AND xml_access.startnodeid IS NOT NULL)"); |
|
822 |
sql.append(")"); |
|
823 |
sql.append(" AND "); |
|
824 |
sql.append("("); |
|
825 |
sql.append("(startnodeid NOT IN (SELECT startnodeid from xml_access where( "); |
|
826 |
sql.append(allowString); |
|
827 |
sql.append(") AND (startnodeid IS NOT NULL))"); |
|
828 |
sql.append(")"); |
|
829 |
sql.append(" OR (startnodeid IN (SELECT startnodeid from xml_access where( "); |
|
830 |
sql.append(denyString); |
|
831 |
sql.append(") AND (startnodeid IS NOT NULL))"); |
|
832 |
sql.append(")"); |
|
833 |
sql.append(")"); |
|
834 |
sql.append(")"); |
|
835 |
MetaCatUtil.debugMessage("accessControlSQLForReturnField: " |
|
836 |
+ sql.toString(), 30); |
|
837 |
return sql.toString(); |
|
770 | 838 |
} |
771 |
|
|
772 |
return self.toString(); |
|
773 |
} |
|
774 |
|
|
775 |
/** This sql command will selecet startnodeid and endnodeid that user can NOT |
|
776 |
* access |
|
777 |
*/ |
|
778 |
public String printAccessControlSQLForReturnField(String doclist) |
|
779 |
{ |
|
780 |
StringBuffer sql = new StringBuffer(); |
|
781 |
String allowString = constructAllowString(); |
|
782 |
String denyString = constructDenyString(); |
|
783 |
sql.append("SELECT distinct startnodeid, endnodeid from xml_access "); |
|
784 |
sql.append("WHERE docid in ("); |
|
785 |
sql.append(doclist); |
|
786 |
sql.append(") AND startnodeid IS NOT NULL AND "); |
|
787 |
sql.append("("); |
|
788 |
sql.append("("); |
|
789 |
sql.append("startnodeid NOT IN (SELECT startnodeid from xml_access, xml_documents "); |
|
790 |
sql.append(" WHERE xml_access.docid = xml_documents.docid"); |
|
791 |
sql.append(" AND lower(xml_documents.user_owner) ='"); |
|
792 |
sql.append(userName); |
|
793 |
sql.append("' AND xml_access.startnodeid IS NOT NULL)"); |
|
794 |
sql.append(")"); |
|
795 |
sql.append(" AND "); |
|
796 |
sql.append("("); |
|
797 |
sql.append("(startnodeid NOT IN (SELECT startnodeid from xml_access where( "); |
|
798 |
sql.append(allowString); |
|
799 |
sql.append(") AND (startnodeid IS NOT NULL))"); |
|
800 |
sql.append(")"); |
|
801 |
sql.append(" OR (startnodeid IN (SELECT startnodeid from xml_access where( "); |
|
802 |
sql.append(denyString); |
|
803 |
sql.append(") AND (startnodeid IS NOT NULL))"); |
Also available in: Unified diff
Removed the "getdataguide" action as it was always experimental and is no longer used in metacat or morpho.