1 /* 2 * $Id: ThreadSafeAccess.java 19191 2010-08-25 21:05:23Z tcarlson $ 3 * -------------------------------------------------------------------------------------- 4 * Copyright (c) MuleSoft, Inc. All rights reserved. http://www.mulesoft.com 5 * 6 * The software in this package is published under the terms of the CPAL v1.0 7 * license, a copy of which has been included with this distribution in the 8 * LICENSE.txt file. 9 */ 10 11 package org.mule.api; 12 13 import org.mule.api.config.MuleProperties; 14 15 import org.apache.commons.lang.BooleanUtils; 16 17 18 /** 19 * Interface implemented by message-related objects that avoid exposing mutable data to multiple threads 20 * by providing immutable copies. This interface is optional - it is an implementation detail that is 21 * tested for dynamically and used only if available. 22 * 23 * <p>To avoid "scribbling" where several threads change state within in a single method (typically 24 * in inconsistent ways, causing subtle and intermittent errors) we use the following access policy for 25 * message related objects:</p> 26 * 27 * <ul> 28 * 29 * <li>A new object is "unbound" and "mutable".</li> 30 * 31 * <li>An object is "bound" to the first thread that calls the object after it is created.</li> 32 * 33 * <li>A "mutable" object can be modified only by the thread to which it is bound.</li> 34 * 35 * <li>An object is "sealed" (no longer "mutable") when it is accessed by a thread other than the 36 * thread to which it is "bound". It is an error to attempt to change a "sealed" object.</li> 37 * 38 * </ul> 39 * 40 * <p>In practice this means that objects are initially mutable, but become immutable once they are 41 * shared.</p> 42 */ 43 public interface ThreadSafeAccess 44 { 45 boolean WRITE = true; 46 boolean READ = false; 47 48 /** 49 * This method may be called before data in the object are accessed. It should verify that the 50 * access policy is followed correctly (if not, a runtime exception may be thrown). 51 * 52 * @param write True if the access will mutate values. 53 */ 54 void assertAccess(boolean write); 55 56 /** 57 * This method should ONLY be used in the construction of composite ThreadSafeAccess instances. 58 * For example, a ThreadSafeAccess MuleEvent contains a ThreadSafeAccess MuleMessage. During 59 * the construction of the event, the message may be bound to the contructing thread. 60 * Calling this method releases that binding so that the event as a whole can be passed to a new 61 * thread unbound. 62 */ 63 void resetAccessControl(); 64 65 /** 66 * @return A new instance of the implementing class, unbound to any thread and mutable. 67 */ 68 ThreadSafeAccess newThreadCopy(); 69 70 /** 71 * This helper class can be used by code implementing this interface to determine whether 72 * the thread safety of a message should be enforced or not. 73 */ 74 class AccessControl 75 { 76 private static boolean assertMessageAccess = true; 77 private static boolean failOnMessageScribbling = true; 78 79 static 80 { 81 String propertyValue = System.getProperty(MuleProperties.SYSTEM_PROPERTY_PREFIX + "message.assertAccess"); 82 if (propertyValue != null) 83 { 84 assertMessageAccess = BooleanUtils.toBoolean(propertyValue); 85 } 86 87 propertyValue = System.getProperty(MuleProperties.SYSTEM_PROPERTY_PREFIX + "disable.threadsafemessages"); 88 if (propertyValue != null) 89 { 90 failOnMessageScribbling = !BooleanUtils.toBoolean(propertyValue); 91 } 92 } 93 94 public static boolean isAssertMessageAccess() 95 { 96 return assertMessageAccess; 97 } 98 99 public static void setAssertMessageAccess(boolean flag) 100 { 101 assertMessageAccess = flag; 102 } 103 104 /** 105 * Should we fail when we detect "message scribbling"? 106 * (see AbstractMessageAdapter#checkMutable()) 107 */ 108 public static boolean isFailOnMessageScribbling() 109 { 110 return failOnMessageScribbling; 111 } 112 113 public static void setFailOnMessageScribbling(boolean flag) 114 { 115 failOnMessageScribbling = flag; 116 } 117 } 118 119 }