Adds SP extensions to Pazpar2 commands and parameters
[mkjsf-moved-to-github.git] / src / main / java / com / indexdata / mkjsf / pazpar2 / sp / ServiceProxyClient.java
1 package com.indexdata.mkjsf.pazpar2.sp;\r
2 \r
3 import static com.indexdata.mkjsf.utils.Utils.nl;\r
4 \r
5 import java.io.BufferedReader;\r
6 import java.io.ByteArrayOutputStream;\r
7 import java.io.File;\r
8 import java.io.FileReader;\r
9 import java.io.IOException;\r
10 import java.util.ArrayList;\r
11 import java.util.HashMap;\r
12 import java.util.List;\r
13 import java.util.Map;\r
14 \r
15 import org.apache.http.HttpEntity;\r
16 import org.apache.http.HttpResponse;\r
17 import org.apache.http.StatusLine;\r
18 import org.apache.http.client.ClientProtocolException;\r
19 import org.apache.http.client.HttpClient;\r
20 import org.apache.http.client.ResponseHandler;\r
21 import org.apache.http.client.methods.HttpGet;\r
22 import org.apache.http.client.methods.HttpPost;\r
23 import org.apache.http.conn.ClientConnectionManager;\r
24 import org.apache.http.conn.scheme.PlainSocketFactory;\r
25 import org.apache.http.conn.scheme.Scheme;\r
26 import org.apache.http.conn.scheme.SchemeRegistry;\r
27 import org.apache.http.entity.ByteArrayEntity;\r
28 import org.apache.http.entity.FileEntity;\r
29 import org.apache.http.impl.client.DefaultHttpClient;\r
30 import org.apache.http.impl.conn.PoolingClientConnectionManager;\r
31 import org.apache.http.util.EntityUtils;\r
32 import org.apache.log4j.Logger;\r
33 \r
34 import com.indexdata.masterkey.config.MissingMandatoryParameterException;\r
35 import com.indexdata.masterkey.pazpar2.client.exceptions.Pazpar2ErrorException;\r
36 import com.indexdata.mkjsf.config.Configuration;\r
37 import com.indexdata.mkjsf.config.ConfigurationReader;\r
38 import com.indexdata.mkjsf.errors.ConfigurationException;\r
39 import com.indexdata.mkjsf.pazpar2.CommandResponse;\r
40 import com.indexdata.mkjsf.pazpar2.SearchClient;\r
41 import com.indexdata.mkjsf.pazpar2.commands.CommandParameter;\r
42 import com.indexdata.mkjsf.pazpar2.commands.Pazpar2Command;\r
43 import com.indexdata.mkjsf.pazpar2.commands.sp.AuthCommand;\r
44 import com.indexdata.mkjsf.pazpar2.sp.auth.ServiceProxyUser;\r
45 import com.indexdata.mkjsf.utils.Utils;\r
46 \r
47 public class ServiceProxyClient implements SearchClient {\r
48     \r
49   private static final long serialVersionUID = -4031644009579840277L;\r
50   private static Logger logger = Logger.getLogger(ServiceProxyClient.class);\r
51   public static final String MODULENAME = "proxyclient";\r
52   public static final String SERVICE_PROXY_URL = "SERVICE_PROXY_URL";\r
53   public static final String SP_INIT_DOC_PATHS = "SP_INIT_DOC_PATHS";\r
54   private String serviceUrl = "undefined";\r
55   private String[] initDocPaths = null;\r
56   private Configuration config = null;\r
57   \r
58   ProxyPz2ResponseHandler handler = new ProxyPz2ResponseHandler();\r
59   private transient HttpClient client;  \r
60   private Pazpar2Command checkAuth = null;\r
61   private Pazpar2Command ipAuth = null;\r
62 \r
63   public ServiceProxyClient () {\r
64     SchemeRegistry schemeRegistry = new SchemeRegistry();\r
65     schemeRegistry.register(new Scheme("http", 80, PlainSocketFactory.getSocketFactory()));\r
66     ClientConnectionManager cm = new PoolingClientConnectionManager(schemeRegistry);\r
67     client = new DefaultHttpClient(cm);\r
68   }\r
69     \r
70   @Override\r
71   public void configure (ConfigurationReader configReader) {\r
72     logger.info(Utils.objectId(this) + " is configuring using the provided " + Utils.objectId(configReader));\r
73     try {\r
74       config = configReader.getConfiguration(this);      \r
75       serviceUrl = config.getMandatory(SERVICE_PROXY_URL);  \r
76       this.initDocPaths = getMultiProperty(config.get(SP_INIT_DOC_PATHS));\r
77       checkAuth = new AuthCommand(null);\r
78       checkAuth.setParameterInState(new CommandParameter("action","=","check"));\r
79       ipAuth = new AuthCommand(null);\r
80       ipAuth.setParameterInState(new CommandParameter("action","=","ipauth"));\r
81     } catch (ConfigurationException c) {\r
82       c.printStackTrace();\r
83     } catch (MissingMandatoryParameterException mmp) {\r
84       mmp.printStackTrace();\r
85     }    \r
86   }\r
87   \r
88   private String[] getMultiProperty(String prop) {    \r
89     if (prop != null) {\r
90       return prop.split(",");\r
91     } else {\r
92       return null;\r
93     }\r
94   }\r
95   \r
96   public boolean authenticate (ServiceProxyUser user) {\r
97     try {      \r
98       logger.info("Authenticating [" + user.getProperty("name") + "]");            \r
99       Pazpar2Command auth = new AuthCommand(null);\r
100       auth.setParametersInState(new CommandParameter("action","=","login"), \r
101                                 new CommandParameter("username","=",user.getProperty("name")), \r
102                                 new CommandParameter("password","=",user.getProperty("password")));                                \r
103       byte[] response = send(auth);\r
104       String responseStr = new String(response,"UTF-8");\r
105       logger.info(responseStr);      \r
106       if (responseStr.contains("FAIL")) {\r
107         user.isAuthenticated(false);\r
108         return false;\r
109       } else {\r
110         user.isAuthenticated(true);\r
111         return true;\r
112       }      \r
113     } catch (ClientProtocolException e) {\r
114       // TODO Auto-generated catch block\r
115       e.printStackTrace();\r
116       return false;\r
117     } catch (IOException e) {\r
118       // TODO Auto-generated catch block\r
119       e.printStackTrace();\r
120       return false;\r
121     }        \r
122   }\r
123   \r
124   public boolean checkAuthentication (ServiceProxyUser user) {    \r
125     try {\r
126       byte[] response = send(checkAuth);\r
127       logger.info(new String(response,"UTF-8"));\r
128       String responseStr = new String(response,"UTF-8");    \r
129       if (responseStr.contains("FAIL")) {  \r
130         user.isAuthenticated(false);\r
131         return false;\r
132       } else {        \r
133         user.isAuthenticated(true);\r
134         return true;\r
135       }      \r
136     } catch (ClientProtocolException e) {\r
137       // TODO Auto-generated catch block\r
138       e.printStackTrace();\r
139       return false;\r
140     } catch (IOException e) {\r
141       // TODO Auto-generated catch block\r
142       e.printStackTrace();\r
143       return false;\r
144     }        \r
145   }\r
146   \r
147   public boolean ipAuthenticate (ServiceProxyUser user) {\r
148     try {\r
149       byte[] response = send(ipAuth);\r
150       logger.info(new String(response,"UTF-8"));\r
151       String responseStr = new String(response,"UTF-8");    \r
152       if (responseStr.contains("FAIL")) {\r
153         user.isAuthenticated(false);\r
154         return false;\r
155       } else {\r
156         user.isAuthenticated(true);\r
157         return true;\r
158       }      \r
159     } catch (ClientProtocolException e) {\r
160       // TODO Auto-generated catch block\r
161       e.printStackTrace();\r
162       return false;\r
163     } catch (IOException e) {\r
164       // TODO Auto-generated catch block\r
165       e.printStackTrace();\r
166       return false;\r
167     }        \r
168     \r
169   }\r
170   \r
171   public boolean isAuthenticatingClient () {\r
172     return true;\r
173   }\r
174   \r
175   public boolean isAuthenticated (ServiceProxyUser user) {\r
176     if (user.getProperty("name") != null && user.getProperty("password") != null) {\r
177       return checkAuthentication(user);\r
178     } else {\r
179       return false;\r
180     }\r
181   }\r
182   \r
183   /**\r
184    * Makes the request\r
185    * @param request\r
186    * @return HTTP response as a String\r
187    * @throws ClientProtocolException\r
188    * @throws IOException\r
189    */\r
190   private byte[] send(Pazpar2Command command) throws ClientProtocolException, IOException {\r
191     String url = serviceUrl + "?" + command.getEncodedQueryString(); \r
192     logger.info("Sending request "+url);    \r
193     HttpGet httpget = new HttpGet(url);     \r
194     byte[] response = client.execute(httpget, handler);    \r
195     return response;\r
196   }\r
197   \r
198   public class ProxyPz2ResponseHandler implements ResponseHandler<byte[]> {\r
199     private StatusLine statusLine = null;\r
200     public byte[] handleResponse(HttpResponse response) throws ClientProtocolException, IOException {\r
201       byte[] resp = null;\r
202       HttpEntity entity = response.getEntity();      \r
203       statusLine = response.getStatusLine();\r
204       if (entity != null) {        \r
205         resp = EntityUtils.toByteArray(entity);        \r
206       } \r
207       EntityUtils.consume(entity);\r
208       return resp;\r
209     }\r
210     public int getStatusCode() {\r
211       return statusLine.getStatusCode();\r
212     }    \r
213     public String getReasonPhrase() {\r
214       return statusLine.getReasonPhrase();\r
215     }\r
216   }\r
217 \r
218   public int getStatusCode () {\r
219     return handler.getStatusCode();\r
220   }\r
221   \r
222   public String getReasonPhrase() {\r
223     return handler.getReasonPhrase();\r
224   }\r
225 \r
226   @Override\r
227   public void setSearchCommand(Pazpar2Command command) {\r
228     // Do nothing, Service Proxy is handling this    \r
229   }\r
230 \r
231   @Override\r
232   public CommandResponse executeCommand(Pazpar2Command command,\r
233       ByteArrayOutputStream baos) throws Pazpar2ErrorException, IOException {\r
234     byte[] response = send(command);\r
235     baos.write(response);\r
236     return new ServiceProxyClientCommandResponse(getStatusCode(), new String(response,"UTF-8"));    \r
237   }\r
238 \r
239   public ServiceProxyClient cloneMe() {\r
240     logger.debug("Cloning Pz2Client");\r
241     ServiceProxyClient clone = new ServiceProxyClient();\r
242     clone.client = this.client;\r
243     clone.serviceUrl = this.serviceUrl;\r
244     clone.initDocPaths = this.initDocPaths;\r
245     return clone;\r
246   }\r
247 \r
248   @Override\r
249   public Map<String, String> getDefaults() {    \r
250     return new HashMap<String,String>();\r
251   }\r
252 \r
253   @Override\r
254   public String getModuleName() {\r
255     return MODULENAME;\r
256   }\r
257   \r
258   @Override\r
259   public List<String> documentConfiguration () {\r
260     List<String> doc = new ArrayList<String>();\r
261     doc.add(nl+ MODULENAME + " was configured to access the Pazpar2 service proxy at: " + serviceUrl);\r
262     return null;\r
263   }\r
264   \r
265   public byte[] postInitDoc (String filePath) throws IOException {\r
266     logger.info("Looking to post the file in : [" + filePath +"]");\r
267     HttpPost post = new HttpPost(serviceUrl+"?command=init&includeDebug=yes");\r
268     File initDoc = new File(filePath);\r
269     logger.info("Posting to SP: ");\r
270     if (logger.isDebugEnabled()) {\r
271       BufferedReader reader = new BufferedReader(new FileReader(initDoc));\r
272       String line;\r
273       while ( (line = reader.readLine()) != null) {\r
274         System.out.println(line);\r
275       }\r
276       reader.close();\r
277     }\r
278     post.setEntity(new FileEntity(initDoc));\r
279     byte[] response = client.execute(post, handler);\r
280     logger.debug("Response on POST was: " + new String(response,"UTF-8"));    \r
281     return response;\r
282   }\r
283   \r
284   public String[] getInitDocPaths () {\r
285     logger.debug("Get init doc paths ");\r
286     logger.debug("length: " + initDocPaths.length);\r
287     return initDocPaths;\r
288   }\r
289   \r
290   public byte[] postInitDoc(byte[] initDoc) throws IOException {\r
291     HttpPost post = new HttpPost(serviceUrl+"?command=init&includeDebug=yes");\r
292     post.setEntity(new ByteArrayEntity(initDoc));\r
293     byte[] response = client.execute(post, handler);\r
294     logger.debug("Response on POST was: " + new String(response,"UTF-8"));    \r
295     return response;\r
296   }\r
297   \r
298   public void setServiceProxyUrl (String url) {\r
299     serviceUrl = url;\r
300   }\r
301   \r
302   public String getServiceProxyUrl () {\r
303     return serviceUrl;\r
304   }\r
305   \r
306   public Configuration getConfiguration () {\r
307     return config;\r
308   }\r
309   \r
310 }\r