Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
ThreadSafeAccess |
|
| 1.0;1 | ||||
ThreadSafeAccess$AccessControl |
|
| 1.0;1 |
1 | /* | |
2 | * $Id: ThreadSafeAccess.java 12269 2008-07-10 04:19:03Z dfeist $ | |
3 | * -------------------------------------------------------------------------------------- | |
4 | * Copyright (c) MuleSource, Inc. All rights reserved. http://www.mulesource.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.MuleConfiguration; | |
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 MessageAdapter. During | |
59 | * the construction of the event, the message adapter 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 | 0 | class AccessControl |
75 | { | |
76 | 2 | private static boolean assertMessageAccess = true; |
77 | 2 | private static boolean failOnMessageScribbling = true; |
78 | ||
79 | static | |
80 | { | |
81 | 2 | String propertyValue = System.getProperty(MuleConfiguration.SYSTEM_PROPERTY_PREFIX + "message.assertAccess"); |
82 | 2 | if (propertyValue != null) |
83 | { | |
84 | 0 | assertMessageAccess = BooleanUtils.toBoolean(propertyValue); |
85 | } | |
86 | ||
87 | 2 | propertyValue = System.getProperty(MuleConfiguration.SYSTEM_PROPERTY_PREFIX + "disable.threadsafemessages"); |
88 | 2 | if (propertyValue != null) |
89 | { | |
90 | 0 | failOnMessageScribbling = !BooleanUtils.toBoolean(propertyValue); |
91 | } | |
92 | 2 | } |
93 | ||
94 | public static boolean isAssertMessageAccess() | |
95 | { | |
96 | 8098 | return assertMessageAccess; |
97 | } | |
98 | ||
99 | public static void setAssertMessageAccess(boolean flag) | |
100 | { | |
101 | 0 | assertMessageAccess = flag; |
102 | 0 | } |
103 | ||
104 | /** | |
105 | * Should we fail when we detect "message scribbling"? | |
106 | * @see e.g. AbstractMessageAdapter.checkMutable() | |
107 | */ | |
108 | public static boolean isFailOnMessageScribbling() | |
109 | { | |
110 | 34 | return failOnMessageScribbling; |
111 | } | |
112 | ||
113 | public static void setFailOnMessageScribbling(boolean flag) | |
114 | { | |
115 | 4 | failOnMessageScribbling = flag; |
116 | 4 | } |
117 | } | |
118 | ||
119 | } |