1 18 19 20 package sync4j.transport.http.server; 21 22 import java.io.*; 23 import java.net.InetAddress ; 24 import java.net.UnknownHostException ; 25 import java.util.Enumeration ; 26 import java.util.HashMap ; 27 import java.util.Map ; 28 import java.util.logging.Logger ; 29 import java.util.logging.Level ; 30 31 import javax.naming.*; 32 import javax.servlet.*; 33 import javax.servlet.http.*; 34 35 import sync4j.framework.core.*; 36 import sync4j.framework.logging.Sync4jLogger; 37 import sync4j.framework.server.*; 38 import sync4j.framework.tools.Base64; 39 import sync4j.framework.transport.http.SyncHolder; 40 import sync4j.framework.transport.http.SyncHolderCache; 41 import sync4j.framework.protocol.ProtocolException; 42 43 import sync4j.server.config.Configuration; 44 45 import org.apache.commons.lang.StringUtils; 46 47 import org.jibx.runtime.*; 48 import org.jibx.runtime.impl.*; 49 50 77 public final class Sync4jServlet 78 extends HttpServlet 79 implements Constants { 80 81 83 85 private Logger log = Sync4jLogger.getLogger(LOG_NAME); 86 87 private static String syncHolderClass = null; 88 private static SyncHolderCache holderCache = null; 89 90 private boolean initialized = false; 94 private static final String PATH_STATUS = "/sync4j/sync/status"; 95 96 private static final int SIZE_INPUT_BUFFER = 4096; 97 99 public void init() throws ServletException { 100 initialized = false; 101 String value; 102 long timeToLive = 0; 103 104 if (log.isLoggable(Level.INFO)) { 105 System.getProperties().list(System.out); 106 } 107 108 ServletConfig config = getServletConfig(); 109 110 value = config.getInitParameter(PARAM_SYNCHOLDER_CLASS); 111 112 if (StringUtils.isEmpty(value)) { 113 String msg = "The servlet configuration parameter " 114 + PARAM_SYNCHOLDER_CLASS 115 + " cannot be empty (" 116 + value 117 + ")" 118 ; 119 log(msg); 120 throw new ServletException(msg); 121 } 122 syncHolderClass = value; 123 124 value = config.getInitParameter(PARAM_SESSION_TTL); 125 if (!StringUtils.isEmpty(value)) { 126 try { 127 timeToLive = Long.parseLong(value); 128 } catch (NumberFormatException e) { 129 String msg = "The servlet configuration parameter " 130 + PARAM_SESSION_TTL 131 + " is not an integer number (" 132 + value 133 + ")" 134 ; 135 log.severe(msg); 136 throw new ServletException(msg); 137 } 138 } 139 140 holderCache = new SyncHolderCache(timeToLive); 141 142 bootstrap(); 146 147 initialized = true; 151 } 152 153 154 public void doPost(final HttpServletRequest httpRequest , 155 final HttpServletResponse httpResponse) 156 throws ServletException, IOException { 157 158 if (log.isLoggable(Level.FINEST)) { 159 showHeaders(httpRequest); 160 } 161 162 if (log.isLoggable(Level.INFO)) { 163 StringBuffer sb = new StringBuffer ("Handling incoming request "); 164 sb.append(httpRequest.getContextPath()) 165 .append(httpRequest.getServletPath()); 166 if (httpRequest.getPathInfo() != null) { 167 sb.append(httpRequest.getPathInfo()); 168 } 169 170 if (httpRequest.getQueryString() != null) { 171 sb.append('?').append(httpRequest.getQueryString()); 172 } 173 sb.append('.'); 174 175 log.info(sb.toString()); 176 } 177 178 final String contentType = httpRequest.getContentType().split(";")[0]; 179 final int contentLength = httpRequest.getContentLength(); 180 181 if (log.isLoggable(Level.FINEST)) { 182 log.finest("contentType: " + contentType); 183 log.finest("contentLength: " + contentLength); 184 } 185 186 187 Map params = getRequestParameters(httpRequest); 188 Map headers = getRequestHeaders (httpRequest); 189 190 byte[] requestData = null; 191 InputStream in = httpRequest.getInputStream(); 192 193 try{ 194 requestData = readContent(in); 195 } catch (Exception e) { 196 handleError(httpRequest, httpResponse, "Error reading the request", e); 197 return; 198 } finally { 199 200 try { 201 if (in != null) { 202 in.close(); 203 } 204 } catch (Exception ex) { 205 handleError(httpRequest, httpResponse, ex.getClass().getName(), ex); 206 return; 207 } 208 in = null; 209 } 210 211 SyncHolder holder = null; 217 try { 218 holder = createHolder(httpRequest); 219 } catch (Exception e) { 220 handleError(httpRequest, httpResponse, "Error creating SyncBean", e); 221 return; 222 } 223 224 SyncResponse resp = null; 225 try { 226 if (sync4j.framework.core.Constants.MIMETYPE_SYNCMLDS_WBXML.equals(contentType)) { 227 resp = holder.processWBXMLMessage(requestData, params, headers); 228 } else if (sync4j.framework.core.Constants.MIMETYPE_SYNCMLDS_XML.equals(contentType)) { 229 resp = holder.processXMLMessage(requestData, params, headers); 230 } else { 231 throw new ProtocolException( "Mime type " 232 + contentType 233 + " nor supported or unknown" ); 234 } 235 } catch (Exception e) { 236 Throwable cause = e.getCause(); 237 238 if ( (cause != null) 239 && ( (cause instanceof ProtocolException) 240 || (cause instanceof Sync4jException ) 241 ) 242 ) { 243 handleError(httpRequest, httpResponse, "Protocol error", cause); 244 return; 245 } else { 246 throw new ServletException(e); 247 } 248 } 249 250 OutputStream out = null; 251 try { 252 out = httpResponse.getOutputStream(); 253 httpResponse.setContentType(contentType); 254 255 byte[] response = resp.getMessage(); 256 257 if (log.isLoggable(Level.FINEST)) { 258 log.finest("Outgoing message length: " + response.length); 259 } 260 261 httpResponse.setContentLength(response.length); 262 out.write(response); 263 out.flush(); 264 265 } finally { 266 if (out != null) { 267 out.close(); 268 } 269 if (log.isLoggable(Level.FINEST)) { 270 log.finest("Finally"); 271 } 272 } 273 274 if (resp.isCompleted()) { 279 releaseHolder(holder); 280 } 281 } 282 283 public void doGet(final HttpServletRequest httpRequest , 284 final HttpServletResponse httpResponse) 285 throws ServletException, IOException { 286 287 String requestURI = httpRequest.getRequestURI(); 288 289 if (log.isLoggable(Level.FINEST)) { 290 log.finest("requestURI: " + requestURI); 291 } 292 if (requestURI.equals(PATH_STATUS)) { 293 if (initialized) { 294 httpResponse.setStatus(httpResponse.SC_OK); 298 if (log.isLoggable(Level.FINEST)) { 299 log.finest("Request succeeded normally"); 300 } 301 } else { 302 httpResponse.setStatus(httpResponse.SC_SERVICE_UNAVAILABLE); 306 if (log.isLoggable(Level.FINEST)) { 307 log.finest("The HTTP server is unable to handle the request"); 308 } 309 } 310 } 311 } 312 313 321 protected byte[] readContent(final InputStream in) throws IOException { 322 ByteArrayOutputStream bout = new ByteArrayOutputStream(); 323 byte[] buf = new byte[SIZE_INPUT_BUFFER]; 324 325 int c = 0; 326 int b = 0; 327 while ((c < buf.length) && (b = in.read(buf, c, buf.length-c)) >= 0) { 328 c+=b; 329 if (c == SIZE_INPUT_BUFFER) { 330 bout.write(buf); 331 buf = new byte[SIZE_INPUT_BUFFER]; 332 c = 0; 333 } 334 } 335 if (c != 0) { 336 bout.write(buf, 0, c); 337 } 338 return bout.toByteArray(); 339 } 340 341 353 private SyncHolder createHolder(HttpServletRequest request) 354 throws Exception { 355 String sessionId = request.getParameter(PARAM_SESSION_ID); 356 357 SyncHolder holder = null; 358 359 if (log.isLoggable(Level.FINEST)) { 360 log.finest("cache: " + holderCache); 361 } 362 363 if (!StringUtils.isEmpty(sessionId)) { 364 holder = (SyncHolder)holderCache.get(sessionId); 365 } 366 367 if (holder == null) { 368 holder = (SyncHolder)getClass().forName(syncHolderClass).newInstance(); 369 370 sessionId = createSessionId(request); 371 holder.setSessionId(sessionId); 372 holderCache.put(holder); 373 } 374 375 return holder; 376 } 377 378 383 private void releaseHolder(SyncHolder holder) { 384 try { 385 holder.close(); 386 } catch (Exception e) { 387 log.severe(e.getMessage()); 388 log.throwing(getClass().getName(), "releaseHolder", e.getCause()); 389 } 390 holderCache.remove(holder.getSessionId()); 391 } 392 393 402 private void handleError(final HttpServletRequest request , 403 final HttpServletResponse response, 404 String msg , 405 final Throwable t ) { 406 407 if (msg == null) { 408 msg = ""; 409 } 410 411 if (t == null) { 412 log.severe(msg); 413 } else { 414 log.severe(msg); 415 log.throwing(getClass().getName(), "unknown", t); 416 } 417 try { 418 response.sendError(response.SC_BAD_REQUEST, msg); 419 } catch (IOException e) { 420 log.severe(e.getMessage()); 421 log.throwing(getClass().getName(), "unknown", t); 422 } 423 } 424 425 432 private String createSessionId(HttpServletRequest request) { 433 String clientIP = request.getRemoteAddr() ; 434 long timestamp = System.currentTimeMillis(); 435 436 StringBuffer sb = new StringBuffer (); 437 438 byte[] ip = null; 439 440 try { 441 ip = InetAddress.getByName(clientIP).getAddress(); 442 } catch (UnknownHostException e) { 443 ip = new byte[] {0, 0, 0, 0}; 444 } 445 446 sb.append(ip).append('-').append(timestamp); 447 448 String stringSessionId = new String (Base64.encode(sb.toString().getBytes())); 449 450 int i = stringSessionId.lastIndexOf('='); 454 455 return ((i>0) ? stringSessionId.substring(0, i-1) : stringSessionId); 456 } 457 458 463 private Map getRequestParameters(HttpServletRequest request) { 464 Map params = new HashMap (); 465 466 String paramName = null; 467 for (Enumeration e=request.getParameterNames(); e.hasMoreElements(); ) { 468 paramName = (String )e.nextElement(); 469 470 params.put(paramName, request.getParameter(paramName)); 471 } 472 473 return params; 474 } 475 476 481 private Map getRequestHeaders(HttpServletRequest request) { 482 Map headers = new HashMap (); 483 484 String headerName = null; 485 for (Enumeration e=request.getHeaderNames(); e.hasMoreElements(); ) { 486 headerName = (String )e.nextElement(); 487 488 headers.put(headerName.toLowerCase(), request.getHeader(headerName)); 489 } 490 491 return headers; 492 } 493 494 503 private void handleError(final HttpServletRequest request, 504 final HttpServletResponse response, 505 final String msg) { 506 this.handleError(request, response, msg, null); 507 } 508 509 513 private void bootstrap() { 514 Configuration c = null; 515 516 c = Configuration.getConfiguration(); 517 518 String msg1 = "================================================================================"; 519 String sp = "\n\n"; 520 String msg2 = "SyncServer v. " 521 + c.getServerConfig().getServerInfo().getSwV() 522 + " engine started.\nConfiguration object found." 523 ; 524 525 System.out.println(msg1); 530 System.out.println(sp); 531 System.out.println(msg2); 532 System.out.println(sp); 533 System.getProperties().list(System.out); 534 System.out.println(sp); 535 System.out.println(msg1); 536 537 if (log.isLoggable(Level.INFO)) { 538 log.info(msg1+sp); 539 log.info(msg2+sp); 540 log.info(System.getProperties().toString()+sp); 541 log.info(msg1); 542 } 543 544 if (log.isLoggable(Level.FINEST)) { 545 log.finest("Engine configuration:"); 546 log.finest(" - store: " 547 + c.getServerConfig().getEngineConfiguration().getStore() 548 + " (" + c.getStore() + ")" 549 ); 550 log.finest(" - officer: " 551 + c.getServerConfig().getEngineConfiguration().getOfficer() 552 + " (" + c.getOfficer() + ")" 553 ); 554 log.finest(" - strategy: " 555 + c.getServerConfig().getEngineConfiguration().getStrategy() 556 + " (" + c.getStrategy() + ")" 557 ); 558 559 log.finest("Default encoding: " 560 + (new OutputStreamWriter(new ByteArrayOutputStream())). 561 getEncoding() 562 ); 563 564 } 565 } 566 567 571 private void showHeaders(HttpServletRequest request) { 572 Enumeration enumHeaders = request.getHeaderNames(); 573 String headerName = null; 574 log.finest("Http header: "); 575 while (enumHeaders.hasMoreElements()) { 576 headerName = (String )enumHeaders.nextElement(); 577 log.finest(headerName + ": " + request.getHeader(headerName)); 578 } 579 } 580 } 581 | Popular Tags |