1 22 package org.jboss.ejb.plugins; 23 24 import java.io.BufferedInputStream ; 25 import java.io.BufferedOutputStream ; 26 import java.io.File ; 27 import java.io.FileInputStream ; 28 import java.io.FileNotFoundException ; 29 import java.io.FileOutputStream ; 30 import java.io.IOException ; 31 import java.rmi.RemoteException ; 32 import java.security.AccessController ; 33 import java.security.PrivilegedAction ; 34 import java.security.PrivilegedActionException ; 35 import java.security.PrivilegedExceptionAction ; 36 37 import javax.ejb.EJBException ; 38 import javax.ejb.RemoveException ; 39 import javax.ejb.SessionBean ; 40 41 import org.jboss.ejb.AllowedOperationsAssociation; 42 import org.jboss.ejb.Container; 43 import org.jboss.ejb.StatefulSessionContainer; 44 import org.jboss.ejb.StatefulSessionEnterpriseContext; 45 import org.jboss.ejb.StatefulSessionPersistenceManager; 46 import org.jboss.system.ServiceMBeanSupport; 47 import org.jboss.system.server.ServerConfigLocator; 48 import org.jboss.util.id.UID; 49 50 69 public class StatefulSessionFilePersistenceManager extends ServiceMBeanSupport 70 implements StatefulSessionPersistenceManager, StatefulSessionFilePersistenceManagerMBean 71 { 72 73 public static final String DEFAULT_STORE_DIRECTORY_NAME = "sessions"; 74 75 76 private StatefulSessionContainer con; 77 78 85 private String storeDirName = DEFAULT_STORE_DIRECTORY_NAME; 86 87 88 private File storeDir; 89 90 94 private boolean purgeEnabled = true; 95 96 102 public void setContainer(final Container con) 103 { 104 this.con = (StatefulSessionContainer) con; 105 } 106 107 112 128 public void setStoreDirectoryName(final String dirName) 129 { 130 this.storeDirName = dirName; 131 } 132 133 143 public String getStoreDirectoryName() 144 { 145 return storeDirName; 146 } 147 148 155 public void setPurgeEnabled(final boolean flag) 156 { 157 this.purgeEnabled = flag; 158 } 159 160 167 public boolean getPurgeEnabled() 168 { 169 return purgeEnabled; 170 } 171 172 179 public File getStoreDirectory() 180 { 181 return storeDir; 182 } 183 184 189 protected void createService() throws Exception 190 { 191 String ejbName = con.getBeanMetaData().getEjbName(); 193 194 File dir = ServerConfigLocator.locate().getServerTempDir(); 196 197 dir = new File (dir, storeDirName); 199 dir = new File (dir, ejbName + "-" + new UID().toString()); 201 storeDir = dir; 202 203 log.debug("Storing sessions for '" + ejbName + "' in: " + storeDir); 204 205 if( !storeDir.exists() ) 207 { 208 if( MkdirsFileAction.mkdirs(storeDir) == false ) 209 { 210 throw new IOException ("Failed to create directory: " + storeDir); 211 } 212 } 213 214 if( !storeDir.isDirectory() ) 216 { 217 throw new IOException ("File exists where directory expected: " + storeDir); 218 } 219 220 if( !storeDir.canWrite() || !storeDir.canRead() ) 222 { 223 throw new IOException ("Directory must be readable and writable: " + storeDir); 224 } 225 226 purgeAllSessionData(); 228 } 229 230 233 private void purgeAllSessionData() 234 { 235 if( !purgeEnabled ) return; 236 237 log.debug("Purging all session data in: " + storeDir); 238 239 File [] sessions = storeDir.listFiles(); 240 for(int i = 0; i < sessions.length; i++) 241 { 242 if( !sessions[i].delete() ) 243 { 244 log.warn("Failed to delete session state file: " + sessions[i]); 245 } 246 else 247 { 248 log.debug("Removed stale session state: " + sessions[i]); 249 } 250 } 251 } 252 253 256 protected void destroyService() throws Exception 257 { 258 purgeAllSessionData(); 260 261 if( purgeEnabled && !storeDir.delete() ) 263 { 264 log.warn("Failed to delete session state storage directory: " + storeDir); 265 } 266 } 267 268 271 private File getFile(final Object id) 272 { 273 278 return new File (storeDir, String.valueOf(id) + ".ser"); 279 } 280 281 284 public Object createId(StatefulSessionEnterpriseContext ctx) 285 throws Exception 286 { 287 return new UID(); 288 } 289 290 293 public void createdSession(StatefulSessionEnterpriseContext ctx) 294 throws Exception 295 { 296 } 298 299 303 public void activateSession(final StatefulSessionEnterpriseContext ctx) 304 throws RemoteException 305 { 306 boolean trace = log.isTraceEnabled(); 307 if (trace) 308 { 309 log.trace("Attempting to activate; ctx=" + ctx); 310 } 311 312 Object id = ctx.getId(); 313 314 File file = getFile(id); 316 if (trace) 317 { 318 log.trace("Reading session state from: " + file); 319 } 320 321 try 322 { 323 FileInputStream fis = FISAction.open(file); 324 SessionObjectInputStream in = new SessionObjectInputStream(ctx, 325 new BufferedInputStream (fis)); 326 327 try 328 { 329 Object obj = in.readObject(); 330 if (trace) 331 { 332 log.trace("Session state: " + obj); 333 } 334 ctx.setInstance(obj); 335 } 336 finally 337 { 338 in.close(); 339 } 340 } 341 catch(Exception e) 342 { 343 throw new EJBException ("Could not activate; failed to " + 344 "restore state", e); 345 } 346 347 removePassivated(id); 348 349 try 350 { 351 AllowedOperationsAssociation.pushInMethodFlag(IN_EJB_ACTIVATE); 353 SessionBean bean = (SessionBean ) ctx.getInstance(); 354 bean.ejbActivate(); 355 } 356 finally 357 { 358 AllowedOperationsAssociation.popInMethodFlag(); 359 } 360 361 if (trace) 362 { 363 log.trace("Activation complete; ctx=" + ctx); 364 } 365 } 366 367 371 public void passivateSession(final StatefulSessionEnterpriseContext ctx) 372 throws RemoteException 373 { 374 boolean trace = log.isTraceEnabled(); 375 if (trace) 376 { 377 log.trace("Attempting to passivate; ctx=" + ctx); 378 } 379 380 try 381 { 382 AllowedOperationsAssociation.pushInMethodFlag(IN_EJB_PASSIVATE); 384 SessionBean bean = (SessionBean ) ctx.getInstance(); 385 bean.ejbPassivate(); 386 } 387 finally 388 { 389 AllowedOperationsAssociation.popInMethodFlag(); 390 } 391 392 394 File file = getFile(ctx.getId()); 395 if (trace) 396 { 397 log.trace("Saving session state to: " + file); 398 } 399 400 try 401 { 402 FileOutputStream fos = FOSAction.open(file); 403 SessionObjectOutputStream out = new SessionObjectOutputStream( 404 new BufferedOutputStream (fos)); 405 406 Object obj = ctx.getInstance(); 407 if (trace) 408 { 409 log.trace("Writing session state: " + obj); 410 } 411 412 try 413 { 414 out.writeObject(obj); 415 } 416 finally 417 { 418 out.close(); 419 } 420 } 421 catch(Exception e) 422 { 423 throw new EJBException ("Could not passivate; failed to save state", e); 424 } 425 426 if (trace) 427 { 428 log.trace("Passivation complete; ctx=" + ctx); 429 } 430 } 431 432 435 public void removeSession(final StatefulSessionEnterpriseContext ctx) 436 throws RemoteException , RemoveException 437 { 438 boolean trace = log.isTraceEnabled(); 439 if (trace) 440 { 441 log.trace("Attempting to remove; ctx=" + ctx); 442 } 443 444 SessionBean bean = (SessionBean ) ctx.getInstance(); 446 bean.ejbRemove(); 447 448 if (trace) 449 { 450 log.trace("Removal complete; ctx=" + ctx); 451 } 452 } 453 454 457 public void removePassivated(final Object id) 458 { 459 boolean trace = log.isTraceEnabled(); 460 461 File file = getFile(id); 462 463 if( file.exists() ) 465 { 466 if (trace) 467 { 468 log.trace("Removing passivated state file: " + file); 469 } 470 471 if( DeleteFileAction.delete(file) == false ) 472 { 473 log.warn("Failed to delete passivated state file: " + file); 474 } 475 } 476 } 477 478 static class DeleteFileAction implements PrivilegedAction 479 { 480 File file; 481 DeleteFileAction(File file) 482 { 483 this.file = file; 484 } 485 public Object run() 486 { 487 boolean deleted = file.delete(); 488 return new Boolean (deleted); 489 } 490 static boolean delete(File file) 491 { 492 DeleteFileAction action = new DeleteFileAction(file); 493 Boolean deleted = (Boolean ) AccessController.doPrivileged(action); 494 return deleted.booleanValue(); 495 } 496 } 497 static class MkdirsFileAction implements PrivilegedAction 498 { 499 File file; 500 MkdirsFileAction(File file) 501 { 502 this.file = file; 503 } 504 public Object run() 505 { 506 boolean ok = file.mkdirs(); 507 return new Boolean (ok); 508 } 509 static boolean mkdirs(File file) 510 { 511 MkdirsFileAction action = new MkdirsFileAction(file); 512 Boolean ok = (Boolean ) AccessController.doPrivileged(action); 513 return ok.booleanValue(); 514 } 515 } 516 517 static class FISAction implements PrivilegedExceptionAction 518 { 519 File file; 520 FISAction(File file) 521 { 522 this.file = file; 523 } 524 public Object run() throws Exception 525 { 526 FileInputStream fis = new FileInputStream (file); 527 return fis; 528 } 529 static FileInputStream open(File file) throws FileNotFoundException 530 { 531 FISAction action = new FISAction(file); 532 FileInputStream fis = null; 533 try 534 { 535 fis = (FileInputStream ) AccessController.doPrivileged(action); 536 } 537 catch(PrivilegedActionException e) 538 { 539 throw (FileNotFoundException ) e.getException(); 540 } 541 542 return fis; 543 } 544 } 545 546 static class FOSAction implements PrivilegedExceptionAction 547 { 548 File file; 549 FOSAction(File file) 550 { 551 this.file = file; 552 } 553 public Object run() throws Exception 554 { 555 FileOutputStream fis = new FileOutputStream (file); 556 return fis; 557 } 558 static FileOutputStream open(File file) throws FileNotFoundException 559 { 560 FOSAction action = new FOSAction(file); 561 FileOutputStream fos = null; 562 try 563 { 564 fos = (FileOutputStream ) AccessController.doPrivileged(action); 565 } 566 catch(PrivilegedActionException e) 567 { 568 throw (FileNotFoundException ) e.getException(); 569 } 570 571 return fos; 572 } 573 } 574 } 575 | Popular Tags |