Project

General

Profile

1
/**
2
 *  '$RCSfile$'
3
 *    Purpose: A class that gets Accession Number, check for uniqueness
4
 *             and register it into db
5
 *  Copyright: 2000 Regents of the University of California and the
6
 *             National Center for Ecological Analysis and Synthesis
7
 *    Authors: Jivka Bojilova, Matt Jones
8
 *
9
 *   '$Author: tao $'
10
 *     '$Date: 2013-04-19 17:47:14 -0700 (Fri, 19 Apr 2013) $'
11
 * '$Revision: 7595 $'
12
 *
13
 * This program is free software; you can redistribute it and/or modify
14
 * it under the terms of the GNU General Public License as published by
15
 * the Free Software Foundation; either version 2 of the License, or
16
 * (at your option) any later version.
17
 *
18
 * This program is distributed in the hope that it will be useful,
19
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21
 * GNU General Public License for more details.
22
 *
23
 * You should have received a copy of the GNU General Public License
24
 * along with this program; if not, write to the Free Software
25
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
26
 */
27
package edu.ucsb.nceas.metacat.common.query;
28

    
29
import java.io.IOException;
30
import java.io.InputStream;
31
import java.net.MalformedURLException;
32
import java.net.URL;
33
import java.util.ArrayList;
34
import java.util.HashMap;
35
import java.util.List;
36
import java.util.Map;
37
import java.util.Set;
38
import java.util.Vector;
39

    
40
import javax.xml.parsers.DocumentBuilder;
41
import javax.xml.parsers.DocumentBuilderFactory;
42
import javax.xml.parsers.ParserConfigurationException;
43
import javax.xml.xpath.XPathConstants;
44
import javax.xml.xpath.XPathExpressionException;
45
import javax.xml.xpath.XPathFactory;
46

    
47
import org.apache.commons.codec.net.URLCodec;
48
import org.apache.commons.logging.Log;
49
import org.apache.commons.logging.LogFactory;
50
import org.apache.solr.client.solrj.impl.CommonsHttpSolrServer;
51
import org.apache.solr.client.solrj.util.ClientUtils;
52

    
53
import org.apache.solr.common.params.SolrParams;
54
import org.apache.solr.core.SolrConfig;
55
import org.apache.solr.schema.FieldType;
56
import org.apache.solr.schema.IndexSchema;
57
import org.apache.solr.schema.SchemaField;
58
import org.apache.solr.schema.TextField;
59
import org.dataone.configuration.Settings;
60
import org.dataone.service.exceptions.NotFound;
61
import org.dataone.service.exceptions.NotImplemented;
62
import org.dataone.service.types.v1.Subject;
63
import org.w3c.dom.Attr;
64
import org.w3c.dom.Document;
65
import org.w3c.dom.Element;
66
import org.w3c.dom.Node;
67
import org.w3c.dom.NodeList;
68
import org.xml.sax.Attributes;
69
import org.xml.sax.InputSource;
70
import org.xml.sax.SAXException;
71

    
72

    
73

    
74
/**
75
 * The query service for the http solr server.
76
 * @author tao
77
 *
78
 */
79
public class HttpSolrQueryService extends SolrQueryService {
80
    private static final String SELECTIONPHASE = "/select";
81
    private static final String SOLR_SYSTEMINFO_URLAPPENDIX = "solr.systeminfo.urlappendix";
82
    private static final String SOLR_SCHEMA_URLAPPENDIX = "sorl.schema.urlappendix";
83
    private static final String SOLR_CONFIG_URLAPPENDIX = "solr.config.urlappendix";
84
    private static final String SPEC_PATH = "//str[@name='solr-spec-version']";
85
    private static final String FIELDS_PATH = "//fields//field";
86
    private static final String COPY_FIELDS_PATH = "//copyField";
87
    private static final String DEST = "dest";
88
    private static final String TRUE = "true";
89
    
90
    private String solrServerBaseURL = null;
91
    private CommonsHttpSolrServer httpSolrServer = null;
92
    private static Log log = LogFactory.getLog(HttpSolrQueryService.class);
93
    /**
94
     * Constructor
95
     * @param httpSolrServer
96
     */
97
    public HttpSolrQueryService(CommonsHttpSolrServer httpSolrServer) {
98
        if(httpSolrServer == null) {
99
            throw new NullPointerException("HttpSolrQueryService.constructor - The httpSolrServer parameter can't be null");
100
        }
101
        this.httpSolrServer = httpSolrServer;
102
        this.solrServerBaseURL = httpSolrServer.getBaseURL();
103
    }
104
    
105
    /**
106
     * Query the Solr server with specified query string and the user's identity. This is the for the http solr server.
107
     * It is hard to transform the SolrQueryReponse object to the InputStream object for the HttpSolrServer
108
     * since the transform needs the SolrCore. We have to open the solr url directly to get the InputStream.
109
     * @param query the query string
110
     * @param subjects the user's identity which sent the query
111
     * @return the response
112
     * @throws NotFound 
113
     * @throws IOException 
114
     * @throws Exception
115
     */
116
    /*public InputStream query(String query, Set<Subject>subjects) throws NotFound, IOException {
117
        StringBuffer accessFilter = generateAccessFilterParamsString(subjects);
118
        if(accessFilter != null && accessFilter.length() != 0) {
119
            query = solrServerBaseURL+"/select?"+query+"&"+FILTERQUERY+"="+accessFilter.toString();
120
            query = ClientUtils.escapeQueryChars(query);
121
        } else {
122
            throw new NotFound("0000", "HttpSolrQueryService.query - There is no identity (even user public) for the user who issued the query");
123
        }
124
        log.info("==========HttpSolrQueryService.query - the final url for querying the solr http server is "+query);
125
        URL url = new URL(query);
126
        
127
        return url.openStream();
128
    }*/
129
    
130
    /**
131
     * Query the Solr server with specified query and user's identity. 
132
     * It is hard to transform the SolrQueryReponse object to the InputStream object for the HttpSolrServer
133
     * since the transform needs the SolrCore. We have to open the solr url directly to get the InputStream.
134
     * @param query the query params. 
135
     * @param subjects the user's identity which sent the query. If the Subjects is null, there wouldn't be any access control.
136
     * @return the response
137
     * @throws IOException 
138
     * @throws NotFound 
139
     * @throws Exception
140
     */
141
    public  InputStream query(SolrParams query, Set<Subject>subjects) throws IOException, NotFound {
142
        boolean xmlFormat = false;
143
        String queryString = ClientUtils.toQueryString(query, xmlFormat);
144
        log.info("==========HttpSolrQueryService.query - the query string after transforming from the SolrParams to the string "+queryString);
145
        StringBuffer accessFilter = generateAccessFilterParamsString(subjects);
146
        if(accessFilter != null && accessFilter.length() != 0) {
147
            String accessStr = accessFilter.toString();
148
            log.debug("==========HttpSolrQueryService.query - the access string is "+accessStr);
149
            URLCodec urlCodec = new URLCodec();
150
            accessStr = urlCodec.encode(accessStr, "UTF-8");
151
            log.debug("==========HttpSolrQueryService.query - the access string after escape special characters string "+accessStr);
152
            queryString = queryString+"&"+FILTERQUERY+"="+accessStr;
153
           
154
        }
155
        
156
        
157
        //queryString = ClientUtils.escapeQueryChars(queryString);
158
        queryString = solrServerBaseURL+SELECTIONPHASE+queryString;
159
        log.info("==========HttpSolrQueryService.query - the final url for querying the solr http server is "+queryString);
160
        URL url = new URL(queryString);    
161
        return url.openStream();
162
        //throw new NotImplemented("0000", "HttpSolrQueryService - the method of  query(SolrParams query, Set<Subject>subjects) is not for the HttpSolrQueryService. We donot need to implemente it");
163
    }
164
    
165
    
166
    
167
    
168
    /**
169
     * Get the fields list of the index schema
170
     * @return
171
     * @throws SAXException 
172
     * @throws IOException 
173
     * @throws ParserConfigurationException 
174
     * @throws MalformedURLException 
175
     * @throws Exception
176
     */
177
    public  Map<String, SchemaField> getIndexSchemaFields() throws MalformedURLException, ParserConfigurationException, IOException, SAXException  {
178
        if(fieldMap == null || fieldMap.isEmpty()) {
179
            getIndexSchemaFieldFromServer();
180
        }
181
        //System.out.println("get filed map ==========================");
182
        return fieldMap;
183
    }
184
    
185
   
186
    
187
    /**
188
     * Get the list of the valid field name (moved the fields names of the CopyFieldTarget).
189
     * @return
190
     * @throws SAXException 
191
     * @throws IOException 
192
     * @throws ParserConfigurationException 
193
     * @throws MalformedURLException 
194
     */
195
    public List<String> getValidSchemaField() throws MalformedURLException, ParserConfigurationException, IOException, SAXException {
196
        if(fieldMap == null || fieldMap.isEmpty()) {
197
            getIndexSchemaFields();
198
        }
199
        return super.getValidSchemaFields();
200
    }
201
    
202
   
203
    /*
204
     * Get the fieldMap from the http server. 
205
     * @throws MalformedURLException
206
     * @throws ParserConfigurationException
207
     * @throws IOException
208
     * @throws SAXException
209
     */
210
    private void getIndexSchemaFieldFromServer() throws MalformedURLException, ParserConfigurationException, IOException, SAXException {
211
        //System.out.println("get filed map from server (downloading files) ==========================");
212
        SolrConfig config = new SolrConfig("dataone", new InputSource(getSolrConfig())); 
213
        schema = new IndexSchema(config, "dataone", new InputSource(getSchema()));
214
        fieldMap = schema.getFields();
215
    }
216
    
217
    /*
218
     * Parse the schema.xml and get the validSolrFieldName list
219
     */
220
    /*private void parseSchema() throws MalformedURLException, ParserConfigurationException, SAXException, IOException, XPathExpressionException {
221
        validSolrFieldNames = new ArrayList<String>();
222
        Map<String, SchemaField> fieldMap = new HashMap<String, SchemaField>();
223
        Document schema = transformInputStreamToDoc(getSchema());
224
        Vector<String>copyFieldTargetNames = new Vector<String>();
225
        NodeList copyFields = (NodeList) XPathFactory.newInstance().newXPath()
226
                        .evaluate(COPY_FIELDS_PATH, schema, XPathConstants.NODESET);
227
        if(copyFields != null) {
228
            for(int i=0; i<copyFields.getLength(); i++) {
229
                Element copyField = (Element)copyFields.item(i);
230
                String target = copyField.getAttribute(DEST);
231
                if(target != null && !target.trim().equals("")) {
232
                    copyFieldTargetNames.add(target);
233
                }
234
            }
235
        }
236
        NodeList fields = (NodeList) XPathFactory.newInstance().newXPath()
237
                        .evaluate(FIELDS_PATH, schema, XPathConstants.NODESET);
238
        if(fields!= null) {
239
            for(int i=0; i<fields.getLength(); i++) {
240
                Element fieldElement = (Element) fields.item(i);
241
                String name = fieldElement.getAttribute("name");
242
                if(name != null && !name.trim().equals("")) {
243
                    if(!copyFieldTargetNames.contains(name)) {
244
                        validSolrFieldNames.add(name);
245
                    }
246
                }
247
            }
248
        }
249
    }*/
250
    
251
    
252
    /*
253
     * Get the SolrConfig InputStream.
254
     * @return
255
     * @throws MalformedURLException
256
     * @throws IOException
257
     */
258
    private InputStream getSolrConfig() throws MalformedURLException, IOException {
259
        String solrConfigAppendix = Settings.getConfiguration().getString(SOLR_CONFIG_URLAPPENDIX);
260
        String configURL = solrServerBaseURL+solrConfigAppendix;
261
        return (new URL(configURL)).openStream();
262
    }
263
    /*
264
     * Get the schema InputStream from the url which is specified in the metacat.properties and transform it to a Document.
265
     */
266
    private InputStream getSchema() throws MalformedURLException, IOException {
267
        String schemaURLAppendix = Settings.getConfiguration().getString(SOLR_SCHEMA_URLAPPENDIX);
268
        String schemaURL = solrServerBaseURL+schemaURLAppendix;
269
        return (new URL(schemaURL)).openStream();
270
    }
271
    
272
    /**
273
     * Get the version of the solr server.
274
     * @return
275
     */
276
    public String getSolrServerVersion() {
277
        if(solrSpecVersion == null) {
278
            getHttpSolrServerVersion();
279
        } 
280
        //System.out.println("get spec version  ==========================");
281
        return solrSpecVersion;
282
    }
283
    
284
    
285
    /*
286
     * Get the solr server version from the system information url. 
287
     */
288
    private void getHttpSolrServerVersion() {
289
        //System.out.println("get spec version from server (downloading files) ==========================");
290
        String systemInfoUrlAppendix = Settings.getConfiguration().getString(SOLR_SYSTEMINFO_URLAPPENDIX);
291
        String systemInfoUrl = solrServerBaseURL+systemInfoUrlAppendix;
292
        try {
293
            Document doc = transformInputStreamToDoc((new URL(systemInfoUrl)).openStream());
294
            NodeList nodeList = (NodeList) XPathFactory.newInstance().newXPath()
295
                            .evaluate(SPEC_PATH, doc, XPathConstants.NODESET);
296
            if(nodeList != null && nodeList.getLength() >0) {
297
                //System.out.println("nodelist is not null branch");
298
                Node specNode = nodeList.item(0);
299
                solrSpecVersion = specNode.getFirstChild().getNodeValue();
300
            } else {
301
                //System.out.println("nodelist is null branch");
302
                solrSpecVersion = UNKNOWN;
303
            }
304
            
305
        } catch (Exception e) {
306
            log.error("HttpSolrQueryService.getHttpSolrServerVersion - can't get the solr specification version since "+e.getMessage());
307
            solrSpecVersion = UNKNOWN;
308
        }
309
        
310
        
311
    }
312
    
313
    /**
314
     * Generate a Document from the InputStream
315
     * @param input
316
     * @return
317
     * @throws ParserConfigurationException
318
     * @throws SAXException
319
     * @throws IOException
320
     */
321
    private Document transformInputStreamToDoc(InputStream input) throws ParserConfigurationException, SAXException, IOException {
322
        DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
323
        DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
324
        Document doc = dBuilder.parse(input);
325
        return doc;
326
    }
327
    
328
 
329
}
(2-2/6)