Project

General

Profile

1 7713 tao
/**
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 7728 tao
import java.util.ArrayList;
34
import java.util.HashMap;
35 7713 tao
import java.util.List;
36
import java.util.Map;
37
import java.util.Set;
38 7728 tao
import java.util.Vector;
39 7713 tao
40 7727 tao
import javax.xml.parsers.DocumentBuilder;
41
import javax.xml.parsers.DocumentBuilderFactory;
42
import javax.xml.parsers.ParserConfigurationException;
43
import javax.xml.xpath.XPathConstants;
44 7728 tao
import javax.xml.xpath.XPathExpressionException;
45 7727 tao
import javax.xml.xpath.XPathFactory;
46
47 7719 tao
import org.apache.commons.codec.net.URLCodec;
48 7714 tao
import org.apache.commons.logging.Log;
49
import org.apache.commons.logging.LogFactory;
50 7713 tao
import org.apache.solr.client.solrj.impl.CommonsHttpSolrServer;
51 7716 tao
import org.apache.solr.client.solrj.util.ClientUtils;
52 7714 tao
53 7713 tao
import org.apache.solr.common.params.SolrParams;
54 7728 tao
import org.apache.solr.core.SolrConfig;
55
import org.apache.solr.schema.FieldType;
56
import org.apache.solr.schema.IndexSchema;
57 7713 tao
import org.apache.solr.schema.SchemaField;
58 7728 tao
import org.apache.solr.schema.TextField;
59 7727 tao
import org.dataone.configuration.Settings;
60 7713 tao
import org.dataone.service.exceptions.NotFound;
61
import org.dataone.service.exceptions.NotImplemented;
62
import org.dataone.service.types.v1.Subject;
63 7728 tao
import org.w3c.dom.Attr;
64 7727 tao
import org.w3c.dom.Document;
65 7728 tao
import org.w3c.dom.Element;
66 7727 tao
import org.w3c.dom.Node;
67
import org.w3c.dom.NodeList;
68 7728 tao
import org.xml.sax.Attributes;
69
import org.xml.sax.InputSource;
70 7727 tao
import org.xml.sax.SAXException;
71 7713 tao
72
73 7714 tao
74 7713 tao
/**
75
 * The query service for the http solr server.
76
 * @author tao
77
 *
78
 */
79
public class HttpSolrQueryService extends SolrQueryService {
80 7719 tao
    private static final String SELECTIONPHASE = "/select";
81 7727 tao
    private static final String SOLR_SYSTEMINFO_URLAPPENDIX = "solr.systeminfo.urlappendix";
82
    private static final String SOLR_SCHEMA_URLAPPENDIX = "sorl.schema.urlappendix";
83 7728 tao
    private static final String SOLR_CONFIG_URLAPPENDIX = "solr.config.urlappendix";
84 7731 tao
    private static final String SPEC_PATH = "//str[@name='solr-spec-version']";
85 7728 tao
    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 7713 tao
90
    private String solrServerBaseURL = null;
91
    private CommonsHttpSolrServer httpSolrServer = null;
92 7714 tao
    private static Log log = LogFactory.getLog(HttpSolrQueryService.class);
93 7713 tao
    /**
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 7714 tao
     * 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 7713 tao
     * @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 7719 tao
    /*public InputStream query(String query, Set<Subject>subjects) throws NotFound, IOException {
117 7713 tao
        StringBuffer accessFilter = generateAccessFilterParamsString(subjects);
118
        if(accessFilter != null && accessFilter.length() != 0) {
119
            query = solrServerBaseURL+"/select?"+query+"&"+FILTERQUERY+"="+accessFilter.toString();
120 7716 tao
            query = ClientUtils.escapeQueryChars(query);
121 7713 tao
        } else {
122
            throw new NotFound("0000", "HttpSolrQueryService.query - There is no identity (even user public) for the user who issued the query");
123
        }
124 7714 tao
        log.info("==========HttpSolrQueryService.query - the final url for querying the solr http server is "+query);
125 7713 tao
        URL url = new URL(query);
126 7714 tao
127 7713 tao
        return url.openStream();
128 7719 tao
    }*/
129 7713 tao
130
    /**
131 7719 tao
     * 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 7713 tao
     * @param query the query params.
135 7732 tao
     * @param subjects the user's identity which sent the query. If the Subjects is null, there wouldn't be any access control.
136 7713 tao
     * @return the response
137 7719 tao
     * @throws IOException
138
     * @throws NotFound
139 7713 tao
     * @throws Exception
140
     */
141 7719 tao
    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 7713 tao
    }
164
165
166
167
168
    /**
169
     * Get the fields list of the index schema
170
     * @return
171 7728 tao
     * @throws SAXException
172
     * @throws IOException
173
     * @throws ParserConfigurationException
174
     * @throws MalformedURLException
175 7713 tao
     * @throws Exception
176
     */
177 7728 tao
    public  Map<String, SchemaField> getIndexSchemaFields() throws MalformedURLException, ParserConfigurationException, IOException, SAXException  {
178
        if(fieldMap == null || fieldMap.isEmpty()) {
179
            getIndexSchemaFieldFromServer();
180
        }
181 7731 tao
        //System.out.println("get filed map ==========================");
182 7728 tao
        return fieldMap;
183 7713 tao
    }
184
185 7727 tao
186
187 7713 tao
    /**
188 7727 tao
     * Get the list of the valid field name (moved the fields names of the CopyFieldTarget).
189
     * @return
190 7728 tao
     * @throws SAXException
191
     * @throws IOException
192
     * @throws ParserConfigurationException
193
     * @throws MalformedURLException
194 7727 tao
     */
195 7728 tao
    public List<String> getValidSchemaField() throws MalformedURLException, ParserConfigurationException, IOException, SAXException {
196
        if(fieldMap == null || fieldMap.isEmpty()) {
197
            getIndexSchemaFields();
198
        }
199
        return super.getValidSchemaFields();
200 7727 tao
    }
201
202 7728 tao
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 7731 tao
        //System.out.println("get filed map from server (downloading files) ==========================");
212 7728 tao
        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 7727 tao
    /**
273 7713 tao
     * Get the version of the solr server.
274
     * @return
275
     */
276
    public String getSolrServerVersion() {
277 7727 tao
        if(solrSpecVersion == null) {
278
            getHttpSolrServerVersion();
279 7731 tao
        }
280
        //System.out.println("get spec version  ==========================");
281 7727 tao
        return solrSpecVersion;
282 7713 tao
    }
283 7716 tao
284 7727 tao
285
    /*
286
     * Get the solr server version from the system information url.
287
     */
288
    private void getHttpSolrServerVersion() {
289 7731 tao
        //System.out.println("get spec version from server (downloading files) ==========================");
290 7727 tao
        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 7731 tao
                //System.out.println("nodelist is not null branch");
298 7727 tao
                Node specNode = nodeList.item(0);
299
                solrSpecVersion = specNode.getFirstChild().getNodeValue();
300
            } else {
301 7731 tao
                //System.out.println("nodelist is null branch");
302 7727 tao
                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 7726 tao
    /**
314 7727 tao
     * Generate a Document from the InputStream
315
     * @param input
316 7726 tao
     * @return
317 7727 tao
     * @throws ParserConfigurationException
318
     * @throws SAXException
319
     * @throws IOException
320 7726 tao
     */
321 7727 tao
    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 7726 tao
    }
327 7727 tao
328 7716 tao
329 7713 tao
}