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