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