1 18 package sync4j.transport.http.server; 19 20 import java.io.*; 21 import java.net.InetAddress ; 22 import java.net.UnknownHostException ; 23 import java.util.Map ; 24 import java.util.HashMap ; 25 import java.util.Enumeration ; 26 import java.util.logging.Logger ; 27 import java.util.logging.Level ; 28 29 import javax.servlet.*; 30 import javax.servlet.http.*; 31 32 import sync4j.framework.core.*; 33 import sync4j.framework.tools.Base64; 34 import sync4j.framework.server.*; 35 import sync4j.framework.tools.WBXMLTools; 36 import sync4j.framework.transport.http.SyncHolder; 37 import sync4j.framework.protocol.ProtocolException; 38 import sync4j.server.config.Configuration; 39 import sync4j.transport.http.server.Constants; 40 41 import org.apache.commons.lang.StringUtils; 42 43 import org.jibx.runtime.*; 44 import org.jibx.runtime.impl.*; 45 46 73 public final class ClusterableSync4jServlet 74 extends HttpServlet 75 implements Constants { 76 private String jndiAddress = DEFAULT_JNDI_ADDRESS; 78 private RemoteHolderCache holderCache = null; 79 80 private Logger log = Logger.getLogger(LOG_NAME); 81 82 private boolean initialized = false; 86 private static final String PATH_STATUS = "/sync4j/sync/status"; 87 88 private static final int SIZE_INPUT_BUFFER = 4096; 89 91 public void init() throws ServletException { 92 initialized = false; 93 String value; 94 95 if (log.isLoggable(Level.INFO)) { 96 System.getProperties().list(System.out); 97 } 98 99 ServletConfig config = getServletConfig(); 100 101 value = config.getInitParameter(PARAM_CHANNEL_PROPERTIES); 102 if (StringUtils.isEmpty(value)) { 103 String msg = "The servlet configuration parameter " 104 + PARAM_CHANNEL_PROPERTIES 105 + " cannot be empty (" 106 + value 107 + ")" 108 ; 109 log.severe(msg); 110 throw new ServletException(msg); 111 } 112 113 value = config.getInitParameter(PARAM_SESSION_TTL); 114 if (!StringUtils.isEmpty(value)) { 115 try { 116 Long.parseLong(value); 117 } catch (NumberFormatException e) { 118 String msg = "The servlet configuration parameter " 119 + PARAM_SESSION_TTL 120 + " is not an integer number (" 121 + value 122 + ")" 123 ; 124 log.severe(msg); 125 throw new ServletException(msg); 126 } 127 } 128 129 value = config.getInitParameter(PARAM_JNDI_ADDRESS); 130 if (StringUtils.isEmpty(value)) { 131 String msg = "Missing optional parameter " 132 + PARAM_JNDI_ADDRESS 133 + ", default value (" 134 + jndiAddress 135 + ") used." 136 ; 137 log.warning(msg); 138 } else { 139 jndiAddress = value; 140 } 141 142 holderCache = new RemoteHolderCache(config); 143 144 bootstrap(); 148 149 initialized = true; 153 } 154 155 public void doPost(final HttpServletRequest request , 156 final HttpServletResponse response) 157 throws ServletException, IOException { 158 if (log.isLoggable(Level.INFO)) { 159 StringBuffer sb = new StringBuffer ("Handling incoming request "); 160 161 sb.append(request.getContextPath()) 162 .append(request.getServletPath()); 163 if (request.getPathInfo() != null) { 164 sb.append(request.getPathInfo()); 165 } 166 167 if (request.getQueryString() != null) { 168 sb.append('?').append(request.getQueryString()); 169 } 170 sb.append('.'); 171 172 log.info(sb.toString()); 173 } 174 175 final String contentType = request.getContentType().split(";")[0]; 176 final int contentLength = request.getContentLength(); 177 178 if (log.isLoggable(Level.FINEST)) { 179 log.finest("contentType: " + contentType); 180 log.finest("contentLength: " + contentLength); 181 } 182 183 if (contentLength < 1) { 184 throw new Error ("Content length < 1 (" + contentLength + ")"); 185 } 186 187 Map params = getRequestParameters(request); 188 Map headers = getRequestHeaders (request); 189 190 byte[] requestData = null; 191 InputStream in = request.getInputStream(); 192 193 try{ 194 requestData = readContent(in); 195 } catch (Exception e) { 196 handleError(request, response, "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(request, response, ex.getClass().getName(), ex); 206 return; 207 } 208 in = null; 209 } 210 211 RemoteEJBSyncHolder holder = null; 217 try { 218 holder = createHolder(request); 219 } catch (Exception e) { 220 handleError(request, response, "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(request, response, "Protocol error", cause); 244 return; 245 } else { 246 throw new ServletException(e); 247 } 248 } finally { 249 if (holder.isNew()) { 255 holderCache.put(holder); 256 } 257 } 258 259 OutputStream out = null; 260 try { 261 out = response.getOutputStream(); 262 response.setContentType(contentType); 263 264 byte[] buf = resp.getMessage(); 265 response.setContentLength(buf.length); 266 out.write(buf); 267 out.flush(); 268 269 } finally { 270 if (log.isLoggable(Level.FINEST)) { 271 log.finest("Finally"); 272 } 273 if (out != null) { 274 out.close(); 275 } 276 } 277 278 if (resp.isCompleted()) { 283 releaseHolder(holder); 284 } 285 } 286 287 public void doGet(final HttpServletRequest request, 288 final HttpServletResponse response) 289 throws ServletException, IOException { 290 if (log.isLoggable(Level.INFO)) { 291 log.info("holderCache: " + holderCache); 292 } 293 super.doGet(request, response); 294 295 String requestURI = request.getRequestURI(); 296 297 if (log.isLoggable(Level.FINEST)) { 298 log.finest("requestURI: " + requestURI); 299 } 300 if (requestURI.equals(PATH_STATUS)) { 301 if (initialized) { 302 response.setStatus(response.SC_OK); 306 if (log.isLoggable(Level.FINEST)) { 307 log.finest("Request succeeded normally"); 308 } 309 } else { 310 response.setStatus(response.SC_SERVICE_UNAVAILABLE); 314 if (log.isLoggable(Level.FINEST)) { 315 log.finest("The HTTP server is unable to handle the request"); 316 } 317 } 318 } 319 } 320 321 329 protected byte[] readContent(final InputStream in) throws IOException { 330 ByteArrayOutputStream bout = new ByteArrayOutputStream(); 331 byte[] buf = new byte[SIZE_INPUT_BUFFER]; 332 333 int c = 0; 334 int b = 0; 335 while ((c < buf.length) && (b = in.read(buf, c, buf.length-c)) >= 0) { 336 c+=b; 337 if (c == SIZE_INPUT_BUFFER) { 338 bout.write(buf); 339 buf = new byte[SIZE_INPUT_BUFFER]; 340 c = 0; 341 } 342 } 343 if (c != 0) { 344 bout.write(buf, 0, c); 345 } 346 return bout.toByteArray(); 347 } 348 349 361 private RemoteEJBSyncHolder createHolder(HttpServletRequest request) 362 throws Exception { 363 String sessionId = request.getParameter(PARAM_SESSION_ID); 364 365 RemoteEJBSyncHolder holder = null; 366 367 if (log.isLoggable(Level.FINEST)) { 368 log.finest("holderCache: " + holderCache); 369 } 370 371 if (!StringUtils.isEmpty(sessionId)) { 372 holder = (RemoteEJBSyncHolder)holderCache.get(sessionId); 373 } 374 375 if (holder == null) { 376 holder = new RemoteEJBSyncHolder(true); 377 378 holder.setSessionId(createSessionId(request)); 379 holder.setJndiAddress(jndiAddress); 380 } 381 382 return holder; 383 } 384 385 390 private void releaseHolder(SyncHolder holder) { 391 try { 392 holder.close(); 393 } catch (Exception e) { 394 log.severe(e.getMessage()); 395 log.throwing(getClass().getName(), "releaseHolder", e.getCause()); 396 } 397 holderCache.remove(holder.getSessionId()); 398 } 399 400 409 private void handleError(final HttpServletRequest request, 410 final HttpServletResponse response, 411 String msg, 412 final Throwable t) { 413 414 if (msg == null) { 415 msg = ""; 416 } 417 418 if (t == null) { 419 log.severe(msg); 420 } else { 421 log.severe(msg); 422 log.throwing(getClass().getName(), "handleError", t); 423 } 424 try { 425 response.sendError(response.SC_BAD_REQUEST, msg); 426 } catch (IOException e) { 427 log.severe(e.getMessage()); 428 log.throwing(getClass().getName(), "handleError", e); 429 } 430 } 431 432 439 private String createSessionId(HttpServletRequest request) { 440 String clientIP = request.getRemoteAddr() ; 441 long timestamp = System.currentTimeMillis(); 442 443 StringBuffer sb = new StringBuffer (); 444 445 byte[] ip = null; 446 447 try { 448 ip = InetAddress.getByName(clientIP).getAddress(); 449 } catch (UnknownHostException e) { 450 ip = new byte[] {0, 0, 0, 0}; 451 } 452 453 sb.append(ip).append('-').append(timestamp); 454 455 String stringSessionId = new String (Base64.encode(sb.toString().getBytes())); 456 457 int i = stringSessionId.lastIndexOf('='); 461 462 return ((i>0) ? stringSessionId.substring(0, i-1) : stringSessionId); 463 } 464 465 470 private Map getRequestParameters(HttpServletRequest request) { 471 Map params = new HashMap (); 472 473 String paramName = null; 474 for (Enumeration e=request.getParameterNames(); e.hasMoreElements(); ) { 475 paramName = (String )e.nextElement(); 476 477 params.put(paramName, request.getParameter(paramName)); 478 } 479 480 return params; 481 } 482 483 488 private Map getRequestHeaders(HttpServletRequest request) { 489 Map headers = new HashMap (); 490 491 String headerName = null; 492 for (Enumeration e=request.getHeaderNames(); e.hasMoreElements(); ) { 493 headerName = (String )e.nextElement(); 494 495 headers.put(headerName, request.getHeader(headerName)); 496 } 497 498 return headers; 499 } 500 501 510 private void handleError(final HttpServletRequest request, 511 final HttpServletResponse response, 512 final String msg) { 513 this.handleError(request, response, msg, null); 514 } 515 516 520 private void bootstrap() { 521 Configuration c = Configuration.getConfiguration(); 522 523 String msg1 = "================================================================================"; 524 String sp = "\n\n"; 525 String msg2 = "SyncServer v. " 526 + c.getServerConfig().getServerInfo().getSwV() 527 + " engine started.\nConfiguration object found." 528 ; 529 530 System.out.println(msg1); 535 System.out.println(sp); 536 System.out.println(msg2); 537 System.out.println(sp); 538 System.getProperties().list(System.out); 539 System.out.println(sp); 540 System.out.println(msg1); 541 542 if (log.isLoggable(Level.INFO)) { 543 log.info(msg1+sp); 544 log.info(msg2+sp); 545 log.info(System.getProperties().toString()+sp); 546 log.info(msg1); 547 } 548 549 if (log.isLoggable(Level.FINEST)) { 550 log.finest("Engine configuration:"); 551 log.finest(" - store: " 552 + c.getServerConfig().getEngineConfiguration().getStore() 553 + " (" + c.getStore() + ")" 554 ); 555 log.finest(" - officer: " 556 + c.getServerConfig().getEngineConfiguration().getOfficer() 557 + " (" + c.getOfficer() + ")" 558 ); 559 log.finest(" - strategy: " 560 + c.getServerConfig().getEngineConfiguration().getStrategy() 561 + " (" + c.getStrategy() + ")" 562 ); 563 } 564 } 565 } | Popular Tags |