Adds demo auth method. Tweaks polling & state fields setup.
[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.sp.auth.AuthenticationEntity;\r
44 import com.indexdata.mkjsf.pazpar2.sp.auth.ServiceProxyUser;\r
45 import com.indexdata.mkjsf.utils.Utils;\r
46 \r
47 \r
48 public class ServiceProxyClient implements SearchClient {\r
49     \r
50   private static final long serialVersionUID = -4031644009579840277L;\r
51   private static Logger logger = Logger.getLogger(ServiceProxyClient.class);\r
52   public static final String MODULENAME = "proxyclient";\r
53   public static final String SERVICE_PROXY_URL = "SERVICE_PROXY_URL";\r
54   public static final String SP_INIT_DOC_PATHS = "SP_INIT_DOC_PATHS";\r
55   private String serviceUrl = "undefined";\r
56   private String[] initDocPaths = null;\r
57   private Configuration config = null;\r
58   \r
59   ProxyPz2ResponseHandler handler = new ProxyPz2ResponseHandler();\r
60   private HttpClient client;\r
61   private ServiceProxyUser user;\r
62   private Pazpar2Command checkAuth = null;\r
63 \r
64 \r
65   public ServiceProxyClient () {\r
66     SchemeRegistry schemeRegistry = new SchemeRegistry();\r
67     schemeRegistry.register(new Scheme("http", 80, PlainSocketFactory.getSocketFactory()));\r
68     ClientConnectionManager cm = new PoolingClientConnectionManager(schemeRegistry);\r
69     client = new DefaultHttpClient(cm);   \r
70   }\r
71     \r
72   @Override\r
73   public void configure (ConfigurationReader configReader) {\r
74     logger.info(Utils.objectId(this) + " is configuring using the provided " + Utils.objectId(configReader));\r
75     try {\r
76       config = configReader.getConfiguration(this);      \r
77       serviceUrl = config.getMandatory(SERVICE_PROXY_URL);  \r
78       this.initDocPaths = getMultiProperty(config.get(SP_INIT_DOC_PATHS));\r
79       checkAuth = new Pazpar2Command("auth",null);\r
80       checkAuth.setParameterInState(new CommandParameter("action","=","check"));\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 (AuthenticationEntity user) {\r
97     try {      \r
98       logger.info("Authenticating [" + user.getProperty("name") + "]");\r
99       this.user = (ServiceProxyUser) user;      \r
100       Pazpar2Command auth = new Pazpar2Command("auth",null);\r
101       auth.setParametersInState(new CommandParameter("action","=","login"), \r
102                                 new CommandParameter("username","=",user.getProperty("name")), \r
103                                 new CommandParameter("password","=",user.getProperty("password")));                                \r
104       byte[] response = send(auth);\r
105       String responseStr = new String(response,"UTF-8");\r
106       logger.info(responseStr);      \r
107       if (responseStr.contains("FAIL")) {\r
108         this.user.isAuthenticated(false);\r
109         return false;\r
110       } else {\r
111         this.user.isAuthenticated(true);\r
112         return true;\r
113       }      \r
114     } catch (ClientProtocolException e) {\r
115       // TODO Auto-generated catch block\r
116       e.printStackTrace();\r
117       return false;\r
118     } catch (IOException e) {\r
119       // TODO Auto-generated catch block\r
120       e.printStackTrace();\r
121       return false;\r
122     }        \r
123   }\r
124   \r
125   public boolean checkAuthentication () {    \r
126     try {\r
127       byte[] response = send(checkAuth);\r
128       logger.info(new String(response,"UTF-8"));\r
129       String responseStr = new String(response,"UTF-8");    \r
130       if (responseStr.contains("FAIL")) {\r
131         this.user.isAuthenticated(false);\r
132         return false;\r
133       } else {\r
134         this.user.isAuthenticated(true);\r
135         return true;\r
136       }      \r
137     } catch (ClientProtocolException e) {\r
138       // TODO Auto-generated catch block\r
139       e.printStackTrace();\r
140       return false;\r
141     } catch (IOException e) {\r
142       // TODO Auto-generated catch block\r
143       e.printStackTrace();\r
144       return false;\r
145     }        \r
146   }\r
147   \r
148   public boolean isAuthenticatingClient () {\r
149     return true;\r
150   }\r
151   \r
152   public boolean isAuthenticated () {\r
153     if (user.getProperty("name") != null && user.getProperty("password") != null) {\r
154       return checkAuthentication();\r
155     } else {\r
156       return false;\r
157     }\r
158   }\r
159   \r
160   /**\r
161    * Makes the request\r
162    * @param request\r
163    * @return HTTP response as a String\r
164    * @throws ClientProtocolException\r
165    * @throws IOException\r
166    */\r
167   private byte[] send(Pazpar2Command command) throws ClientProtocolException, IOException {\r
168     String url = serviceUrl + "?" + command.getEncodedQueryString(); \r
169     logger.info("Sending request "+url);    \r
170     HttpGet httpget = new HttpGet(url);     \r
171     byte[] response = client.execute(httpget, handler);    \r
172     return response;\r
173   }\r
174   \r
175   private byte[] send (String queryString) throws ClientProtocolException, IOException {\r
176     String url = serviceUrl + "?" + queryString; \r
177     logger.info("Sending request "+url);    \r
178     HttpGet httpget = new HttpGet(url);     \r
179     byte[] response = client.execute(httpget, handler);    \r
180     return response;\r
181     \r
182   }\r
183   \r
184   public class ProxyPz2ResponseHandler implements ResponseHandler<byte[]> {\r
185     private StatusLine statusLine = null;\r
186     public byte[] handleResponse(HttpResponse response) throws ClientProtocolException, IOException {\r
187       byte[] resp = null;\r
188       HttpEntity entity = response.getEntity();      \r
189       statusLine = response.getStatusLine();\r
190       if (entity != null) {        \r
191         resp = EntityUtils.toByteArray(entity);        \r
192       } \r
193       EntityUtils.consume(entity);\r
194       return resp;\r
195     }\r
196     public int getStatusCode() {\r
197       return statusLine.getStatusCode();\r
198     }    \r
199     public String getReasonPhrase() {\r
200       return statusLine.getReasonPhrase();\r
201     }\r
202   }\r
203 \r
204   public int getStatusCode () {\r
205     return handler.getStatusCode();\r
206   }\r
207   \r
208   public String getReasonPhrase() {\r
209     return handler.getReasonPhrase();\r
210   }\r
211 \r
212   @Override\r
213   public void setSearchCommand(Pazpar2Command command) {\r
214     // Do nothing, Service Proxy is handling this    \r
215   }\r
216 \r
217   @Override\r
218   public CommandResponse executeCommand(Pazpar2Command command,\r
219       ByteArrayOutputStream baos) throws Pazpar2ErrorException, IOException {\r
220     byte[] response = send(command);\r
221     baos.write(response);\r
222     return new ServiceProxyClientCommandResponse(getStatusCode(), new String(response,"UTF-8"));    \r
223   }\r
224 \r
225   public ServiceProxyClient cloneMe() {\r
226     logger.debug("Cloning Pz2Client");\r
227     ServiceProxyClient clone = new ServiceProxyClient();\r
228     clone.client = this.client;\r
229     clone.serviceUrl = this.serviceUrl;\r
230     clone.initDocPaths = this.initDocPaths;\r
231     return clone;\r
232   }\r
233 \r
234   @Override\r
235   public Map<String, String> getDefaults() {    \r
236     return new HashMap<String,String>();\r
237   }\r
238 \r
239   @Override\r
240   public String getModuleName() {\r
241     return MODULENAME;\r
242   }\r
243   \r
244   @Override\r
245   public List<String> documentConfiguration () {\r
246     List<String> doc = new ArrayList<String>();\r
247     doc.add(nl+ MODULENAME + " was configured to access the Pazpar2 service proxy at: " + serviceUrl);\r
248     return null;\r
249   }\r
250   \r
251   public byte[] postInitDoc (String filePath) throws IOException {\r
252     logger.info("Looking to post the file in : [" + filePath +"]");\r
253     HttpPost post = new HttpPost(serviceUrl+"?command=init&includeDebug=yes");\r
254     File initDoc = new File(filePath);\r
255     logger.info("Posting to SP: ");\r
256     if (logger.isDebugEnabled()) {\r
257       BufferedReader reader = new BufferedReader(new FileReader(initDoc));\r
258       String line;\r
259       while ( (line = reader.readLine()) != null) {\r
260         System.out.println(line);\r
261       }\r
262       reader.close();\r
263     }\r
264     post.setEntity(new FileEntity(initDoc));\r
265     byte[] response = client.execute(post, handler);\r
266     logger.debug("Response on POST was: " + new String(response,"UTF-8"));    \r
267     return response;\r
268   }\r
269   \r
270   public String[] getInitDocPaths () {\r
271     logger.debug("Get init doc paths ");\r
272     logger.debug("length: " + initDocPaths.length);\r
273     return initDocPaths;\r
274   }\r
275   \r
276   public byte[] postInitDoc(byte[] initDoc) throws IOException {\r
277     HttpPost post = new HttpPost(serviceUrl+"?command=init&includeDebug=yes");\r
278     post.setEntity(new ByteArrayEntity(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 void setServiceProxyUrl (String url) {\r
285     serviceUrl = url;\r
286   }\r
287   \r
288   public String getServiceProxyUrl () {\r
289     return serviceUrl;\r
290   }\r
291   \r
292   public Configuration getConfiguration () {\r
293     return config;\r
294   }\r
295   \r
296 }\r