1 package org.kuali.ole.sip2.sip2Server;
2
3 import io.netty.buffer.ByteBuf;
4 import io.netty.buffer.Unpooled;
5 import io.netty.channel.ChannelFuture;
6 import io.netty.channel.ChannelHandlerContext;
7 import io.netty.channel.ChannelInboundHandlerAdapter;
8 import io.netty.util.CharsetUtil;
9 import org.apache.commons.lang3.StringUtils;
10 import org.apache.http.HttpEntity;
11 import org.apache.http.HttpResponse;
12 import org.apache.http.client.ClientProtocolException;
13 import org.apache.http.client.ResponseHandler;
14 import org.apache.http.client.methods.HttpGet;
15 import org.apache.http.impl.client.CloseableHttpClient;
16 import org.apache.http.impl.client.HttpClients;
17 import org.apache.http.util.EntityUtils;
18 import org.apache.log4j.Logger;
19 import org.kuali.ole.sip2.response.*;
20
21 import java.io.FileNotFoundException;
22 import java.io.IOException;
23 import java.io.InputStream;
24 import java.io.UnsupportedEncodingException;
25 import java.net.SocketAddress;
26 import java.net.URLEncoder;
27 import java.util.HashMap;
28 import java.util.Map;
29 import java.util.Properties;
30
31 public class OLENettyServerHandler extends ChannelInboundHandlerAdapter {
32
33 private final static Logger LOG = Logger.getLogger(OLENettyServerHandler.class.getName());
34 private static String INSTITUTION = "OLE";
35 private String serverURL;
36 private String circulationService;
37
38
39
40 private String clientIP;
41 private String loginUserId;
42
43 private Map<String, String> lastResponseSendToClient = new HashMap<String, String>();
44
45 protected Properties properties = new Properties();
46
47 String propertiesFileName = "sip2-config.properties";
48 InputStream inputStream;
49
50 public OLENettyServerHandler() {
51
52 }
53
54 public OLENettyServerHandler(String serverURL, String circulationService) {
55 this.serverURL = serverURL;
56 this.circulationService = circulationService;
57 }
58
59 @Override
60 public void channelRegistered(ChannelHandlerContext channelHandlerContext) throws Exception {
61 super.channelRegistered(channelHandlerContext);
62 SocketAddress address = channelHandlerContext.channel().remoteAddress();
63 clientIP = address.toString();
64 }
65
66 @Override
67 public void channelRead(ChannelHandlerContext channelHandlerContext, Object message) throws Exception {
68
69
70 LOG.info("Entry OLENettyServerHandler.channelRead(channelHandlerContext, message)");
71 ByteBuf byteBuf = (ByteBuf) message;
72 String requestMessage = "";
73 ChannelFuture channelFuture = null;
74 String response = "";
75
76 try {
77
78
79 requestMessage = byteBuf.toString(CharsetUtil.UTF_8);
80
81 if (requestMessage != null && !requestMessage.equalsIgnoreCase("")) {
82 response = this.processRequest(requestMessage);
83 }
84
85 LOG.info("Client IP Address : " + clientIP);
86 LOG.info("Response Message : " + response);
87
88 if (response != null) {
89 String[] responseArray = response.split("\\$|$");
90
91 for (String responseMessage : responseArray) {
92 channelFuture = channelHandlerContext.write(Unpooled.copiedBuffer(responseMessage, CharsetUtil.UTF_8));
93 channelHandlerContext.flush();
94 if (StringUtils.isNotBlank(responseMessage.trim())) {
95 lastResponseSendToClient.put(clientIP, responseMessage);
96 }
97 }
98 }
99
100
101 if (channelFuture == null || !channelFuture.isSuccess()) {
102 LOG.info("Send Failed: " + channelFuture.cause());
103 } else {
104 LOG.info("Send Success ");
105 }
106
107 } catch (Exception e) {
108 LOG.error(e.getMessage(), e);
109 } finally {
110 byteBuf.release();
111 }
112
113 LOG.info("Exit OLENettyServerHandler.channelRead(channelHandlerContext, message)");
114
115 }
116
117
118 public String processRequest(String requestData) {
119 String response = "";
120
121 LOG.info("Client IP Address : " + clientIP);
122 LOG.info("Request Message : " + requestData);
123 inputStream = getClass().getClassLoader().getResourceAsStream("sip2-config.properties");
124
125 try {
126 if (inputStream != null) {
127 properties.load(inputStream);
128 } else {
129 throw new FileNotFoundException("property file '" + propertiesFileName + "' not found in the classpath");
130 }
131 } catch (IOException e) {
132 LOG.error(e.getMessage(), e);
133 }
134
135 if (properties != null) {
136 String code = requestData.substring(0, 2);
137
138 switch (code) {
139 case "99":
140 LOG.info("Request Type : SC Status Request");
141 response = this.sendRequestToOle(requestData, loginUserId);
142 break;
143 case "97":
144
145
146 LOG.info("Request Type : Request ACS Resend");
147
148 if (lastResponseSendToClient.containsKey(clientIP)) {
149
150 response = this.removeSeqNumFromResponse(lastResponseSendToClient.get(clientIP)) + "$|$";
151 if (requestData.length() > 2) {
152 response = response + requestData.replace("97", "96");
153 } else {
154 response = response + "96";
155 }
156 }
157
158 break;
159 case "93":
160
161 LOG.info("Request Type : Login Request");
162 if (properties.getProperty("sip2.service.login").equalsIgnoreCase("yes")) {
163
164 response = this.sendRequestToOle(requestData, loginUserId);
165 if (response.charAt(2) == '1') {
166 this.loginUserId = getLoginUserId(requestData);
167 }
168
169 } else {
170 OLESIP2LoginTurnedOffResponse olesip2LoginTurnedOffResponse = new OLESIP2LoginTurnedOffResponse();
171 response = olesip2LoginTurnedOffResponse.getOLESIP2LoginTurnedOffResponse(requestData);
172
173 }
174
175 break;
176 case "09":
177
178 LOG.info("Request Type : Checkin Request");
179 if (properties.getProperty("sip2.service.checkIn").equalsIgnoreCase("yes")) {
180 response = this.sendRequestToOle(requestData, loginUserId);
181 } else {
182 OLESIP2CheckInTurnedOffResponse olesip2CheckInTurnedOffResponse = new OLESIP2CheckInTurnedOffResponse();
183 response = olesip2CheckInTurnedOffResponse.getOLESIP2CheckInTurnedOffResponse(requestData);
184 }
185 break;
186 case "11":
187
188 LOG.info("Request Type : Checkout Request");
189 if (properties.getProperty("sip2.service.checkOut").equalsIgnoreCase("yes")) {
190 response = this.sendRequestToOle(requestData, loginUserId);
191 } else {
192 OLESIP2CheckOutTurnedOffResponse olesip2CheckOutTurnedOffResponse = new OLESIP2CheckOutTurnedOffResponse();
193 response = olesip2CheckOutTurnedOffResponse.getOLESIP2CheckOutTurnedOffResponse(requestData);
194 }
195
196 break;
197 case "17":
198 LOG.info("Request Type : Item Information");
199 if (properties.getProperty("sip2.service.itemInformation").equalsIgnoreCase("yes")) {
200 response = this.sendRequestToOle(requestData, loginUserId);
201 } else {
202 OLESIP2ItemInfoTurnedOffResponse olesip2ItemInfoTurnedOffResponse = new OLESIP2ItemInfoTurnedOffResponse();
203 response = olesip2ItemInfoTurnedOffResponse.getOLESIP2ItemInfoTurnedOffResponse(requestData);
204 }
205
206 break;
207 case "23":
208 LOG.info("Request Type : Patron Status Request");
209 if (properties.getProperty("sip2.service.patronStatus").equalsIgnoreCase("yes")) {
210 response = this.sendRequestToOle(requestData, loginUserId);
211 } else {
212 OLESIP2PatronStatusTurnedOffResponse patronStatusTurnedOffResponse = new OLESIP2PatronStatusTurnedOffResponse();
213 response = patronStatusTurnedOffResponse.getOLESIP2PatronStatusTurnedOffResponse(requestData, "Patron Status Request");
214 }
215
216 break;
217 case "63":
218 LOG.info("Request Type : Patron Information");
219 if (properties.getProperty("sip2.service.patronInformation").equalsIgnoreCase("yes")) {
220 response = this.sendRequestToOle(requestData, loginUserId);
221 } else {
222 OLESIP2PatronInformationTurnedOffResponse patronInformationTurnedOffResponse = new OLESIP2PatronInformationTurnedOffResponse();
223 response = patronInformationTurnedOffResponse.getOLESIP2PatronInformationTurnedOffResponse(requestData);
224 }
225
226
227 break;
228 case "01":
229 LOG.info("Request Type : Patron Block");
230 if (properties.getProperty("sip2.service.blockPatron").equalsIgnoreCase("yes")) {
231 response = this.sendRequestToOle(requestData, loginUserId);
232 } else {
233 OLESIP2PatronStatusTurnedOffResponse patronStatusTurnedOffResponse = new OLESIP2PatronStatusTurnedOffResponse();
234 response = patronStatusTurnedOffResponse.getOLESIP2PatronStatusTurnedOffResponse(requestData, "Patron Block Request");
235 }
236
237 break;
238
239 case "25":
240
241 LOG.info("Request Type : Patron Enable");
242 if (properties.getProperty("sip2.service.patronEnable").equalsIgnoreCase("yes")) {
243 response = this.sendRequestToOle(requestData, loginUserId);
244 } else {
245 OLESIP2PatronEnableTurnedOffResponse patronEnableTurnedOffResponse = new OLESIP2PatronEnableTurnedOffResponse();
246 response = patronEnableTurnedOffResponse.getOLESIP2PatronEnableTurnedOffResponse(requestData);
247 }
248 break;
249 case "35":
250 LOG.info("Request Type : End Patron Session");
251
252 if (properties.getProperty("sip2.service.endPatronSession").equalsIgnoreCase("yes")) {
253 response = this.sendRequestToOle(requestData, loginUserId);
254 } else {
255 OLESIP2EndPatronSessionTurnedOffResponse endPatronSessionTurnedOffResponse = new OLESIP2EndPatronSessionTurnedOffResponse();
256 response = endPatronSessionTurnedOffResponse.getOLESIP2EndPatronSessionTurnedOffResponse(requestData);
257 }
258 break;
259 case "29":
260
261 LOG.info("Request Type : Renew");
262 if (properties.getProperty("sip2.service.renew").equalsIgnoreCase("yes")) {
263 response = this.sendRequestToOle(requestData, loginUserId);
264 } else {
265 OLESIP2RenewTurnedOffResponse renewTurnedOffResponse = new OLESIP2RenewTurnedOffResponse();
266 response = renewTurnedOffResponse.getOLESIP2RenewTurnedOffResponse(requestData);
267 }
268 break;
269 case "15":
270 LOG.info("Request Type : Hold");
271 if (properties.getProperty("sip2.service.hold").equalsIgnoreCase("yes")) {
272 response = this.sendRequestToOle(requestData, loginUserId);
273 } else {
274 OLESIP2HoldTurnedOffResponse holdTurnedOffResponse = new OLESIP2HoldTurnedOffResponse();
275 response = holdTurnedOffResponse.getOLESIP2HoldTurnedOffResponse(requestData);
276 }
277
278 break;
279 case "37":
280 LOG.info("Request Type : Fee Paid Message");
281 if (properties.getProperty("sip2.service.feePaid").equalsIgnoreCase("yes")) {
282 response = this.sendRequestToOle(requestData, loginUserId);
283 } else {
284 OLESIP2FeePaidTurnedOffResponse olesip2FeePaidTurnedOffResponse = new OLESIP2FeePaidTurnedOffResponse();
285 response = olesip2FeePaidTurnedOffResponse.getOLESIP2FeePaidTurnedOffResponse(requestData);
286 }
287
288 break;
289 case "65":
290
291 LOG.info("Request Type : Renew All");
292 if (properties.getProperty("sip2.service.renewAll").equalsIgnoreCase("yes")) {
293 response = this.sendRequestToOle(requestData, loginUserId);
294
295 } else {
296 OLESIP2RenewAllTurnedOffResponse renewAllTurnedOffResponse = new OLESIP2RenewAllTurnedOffResponse();
297 response = renewAllTurnedOffResponse.getOLESIP2RenewAllTurnedOffResponse(requestData);
298 }
299
300 break;
301 case "19":
302
303 LOG.info("Request Type : Item Status Update");
304 if (properties.getProperty("sip2.service.itemStatusUpdate").equalsIgnoreCase("yes")) {
305 response = this.sendRequestToOle(requestData, loginUserId);
306 } else {
307 OLESIP2ItemStatusUpdateTurnedOffResponse itemStatusUpdateTurnedOffResponse = new OLESIP2ItemStatusUpdateTurnedOffResponse();
308 response = itemStatusUpdateTurnedOffResponse.getOLESIP2ItemStatusUpdateTurnedOffResponse(requestData);
309 }
310
311 break;
312
313
314 default:
315 LOG.info("Request Type : *****Not a valid SIP2 request");
316 new Throwable("Not a valid SIP2 request");
317
318 break;
319 }
320
321
322 }
323
324
325 LOG.info("Exit OLENettyServerHandler.analysisRequestType(String requestData)");
326 return response;
327 }
328
329
330 public String sendRequestToOle(String requestData, String loginUserId) {
331 LOG.info("Entry OLENettyServerHandler.sendRequestToOle(restRequestURL, clientRequest, requestRResponseType)");
332 String url = "";
333 try {
334 if (loginUserId != null && !loginUserId.equalsIgnoreCase("")) {
335 url = serverURL + circulationService + "sipService&requestData=" + URLEncoder.encode(requestData, "UTF-8") + "&loginUser=" + loginUserId;
336 } else {
337 url = serverURL + circulationService + "sipService&requestData=" + URLEncoder.encode(requestData, "UTF-8");
338 }
339 } catch (UnsupportedEncodingException e1) {
340
341 e1.printStackTrace();
342 }
343 ;
344 LOG.info("URL : " + url);
345 String response = "";
346 try {
347 response = this.httpGet(url, requestData);
348 } catch (Exception e) {
349 LOG.error(e.getMessage(), e);
350 }
351 LOG.info("Exit OLENettyServerHandler.sendRequestToOle(restRequestURL, clientRequest, requestRResponseType)");
352 return response;
353
354 }
355
356
357 @Override
358 public void channelReadComplete(ChannelHandlerContext channelHandlerContext) {
359 LOG.info("Entry OLENettyServerHandler.channelReadComplete(channelHandlerContext)");
360 channelHandlerContext.flush();
361 LOG.info("Exit OLENettyServerHandler.channelReadComplete(channelHandlerContext)");
362 }
363
364
365 @Override
366 public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
367 throws Exception {
368 LOG.info("Entry OLENettyServerHandler.exceptionCaught(channelHandlerContext, cause)");
369
370
371 LOG.error("Client (" + clientIP + ") disconnected from server.");
372 LOG.info("Exit OLENettyServerHandler.exceptionCaught(channelHandlerContext, cause)");
373 }
374
375
376 public String httpGet(String url, String requestData) {
377 LOG.info("Entry OLENettyServerHandler.httpGet(url, requestRResponseType)");
378
379
380 String response = null;
381 CloseableHttpClient httpclient = null;
382 HttpGet httpget = null;
383 ResponseHandler<String> responseHandler = null;
384 try {
385
386 httpclient = HttpClients.createDefault();
387
388 httpget = new HttpGet(url);
389 LOG.info("Executing request " + httpget.getRequestLine());
390
391
392 responseHandler = new ResponseHandler<String>() {
393
394 public String handleResponse(
395 final HttpResponse response) throws ClientProtocolException {
396 int status = response.getStatusLine().getStatusCode();
397
398 HttpEntity entity = response.getEntity();
399 try {
400 return entity != null ? EntityUtils.toString(entity) : null;
401 } catch (IOException e) {
402 e.printStackTrace();
403 return null;
404 }
405
406
407
408 }
409 };
410 response = httpclient.execute(httpget, responseHandler);
411 } catch (Exception ex) {
412
413 if (requestData.startsWith("99")) {
414
415 response = this.scStatusNegativeResponse(requestData);
416 } else {
417 ex.printStackTrace();
418 }
419
420 } finally {
421 try {
422 httpclient.close();
423 if (requestData.startsWith("99") && !response.startsWith("98")) {
424
425 response = this.scStatusNegativeResponse(requestData);
426 } else {
427 return response;
428 }
429
430 } catch (Exception ex) {
431 ex.printStackTrace();
432
433 }
434 }
435
436 LOG.info("Exit OLENettyServerHandler.httpGet(url, requestRResponseType)");
437 return response;
438 }
439
440 private String scStatusNegativeResponse(String requestData) {
441
442 LOG.info("Entry OLENettyServerHandler.scStatusNegativeResponse()");
443 requestData = requestData.trim();
444
445 StringBuilder builder = new StringBuilder();
446 builder.append(98);
447 builder.append("N");
448 builder.append("N");
449 builder.append("N");
450 builder.append("N");
451 builder.append("N");
452 builder.append("N");
453 builder.append("010");
454 builder.append("003");
455 builder.append(MessageUtil.getSipDateTime());
456 builder.append("2.00");
457 builder.append("AO");
458 builder.append("InId");
459 builder.append("|AM");
460 builder.append(INSTITUTION);
461
462 if (requestData.length() == 19) {
463 if (requestData.substring(10, 12).equalsIgnoreCase("AY")) {
464 builder.append("|AY");
465 builder.append(requestData.substring(12, 15));
466 builder.append(MessageUtil.computeChecksum(builder.toString()));
467
468 }
469 }
470
471
472 LOG.info("Exit OLENettyServerHandler.scStatusNegativeResponse()");
473 return builder.toString() + '\r';
474 }
475
476
477 private String removeSeqNumFromResponse(String lastResponse) {
478
479 StringBuilder builder = new StringBuilder();
480
481 if (lastResponse.contains("AY")) {
482 int indexOfSeqNum = lastResponse.indexOf("AY");
483 builder.append(MessageUtil.computeChecksum(lastResponse.replace(lastResponse.substring(indexOfSeqNum, indexOfSeqNum + 5), "")));
484 }
485 return builder.toString() + '\r';
486
487 }
488
489 public String getLoginUserId(String requestData) {
490
491 String[] requestDataArray = requestData.split("\\|");
492 String loginUser = "";
493 try {
494 for (String data : requestDataArray) {
495 if (data.startsWith("93")) {
496 loginUser = data.substring(6);
497 break;
498 }
499 }
500
501 } catch (Exception e) {
502 LOG.error(e.getMessage(), e);
503 }
504 return loginUser;
505 }
506
507
508 }