001: /*
002: * All content copyright (c) 2003-2007 Terracotta, Inc., except as may otherwise be noted in a separate copyright
003: * notice. All rights reserved.
004: */
005: package com.tctest;
006:
007: import com.tc.object.config.ConfigVisitor;
008: import com.tc.object.config.DSOClientConfigHelper;
009: import com.tc.object.config.DistributedMethodSpec;
010: import com.tc.object.config.TransparencyClassSpec;
011: import com.tc.simulator.app.ApplicationConfig;
012: import com.tc.simulator.listener.ListenerProvider;
013: import com.tc.util.Assert;
014: import com.tctest.runner.AbstractTransparentApp;
015:
016: import java.lang.annotation.ElementType;
017: import java.lang.annotation.Retention;
018: import java.lang.annotation.RetentionPolicy;
019: import java.lang.annotation.Target;
020: import java.util.ArrayList;
021: import java.util.HashSet;
022: import java.util.List;
023: import java.util.concurrent.CyclicBarrier;
024:
025: /**
026: * @author Eugene Kuleshov
027: */
028: public class AnnotationTestApp extends AbstractTransparentApp {
029:
030: private ClassWithAnnotations value = new ClassWithAnnotations();
031:
032: public AnnotationTestApp(String appId, ApplicationConfig cfg,
033: ListenerProvider listenerProvider) {
034: super (appId, cfg, listenerProvider);
035: }
036:
037: public void run() {
038: testPortableOnAnnotation();
039: testLockOnAnnotation();
040: testDmiOnAnnotation();
041: testRoot();
042: }
043:
044: private void testRoot() {
045: ClassWithAnnotatedRoot o = new ClassWithAnnotatedRoot(
046: getParticipantCount());
047: o.await();
048: }
049:
050: private void testPortableOnAnnotation() {
051: ClassIncludedWithAnnotation o = new ClassIncludedWithAnnotation(
052: "foo");
053: value.setDistributed(o);
054:
055: moveToStageAndWait(0);
056: }
057:
058: // CDV-271: Annotation support for Locks, includes by matching on what ever annotations they want.
059: private void testLockOnAnnotation() {
060: value.setDistributed("foo");
061: junit.framework.Assert.assertEquals("foo", value
062: .getDistributed());
063:
064: moveToStageAndWait(1);
065: }
066:
067: private void testDmiOnAnnotation() {
068: moveToStageAndWait(2);
069:
070: value.processMessage("msg from " + getApplicationId());
071:
072: moveToStageAndWait(3);
073:
074: try {
075: Thread.sleep(1000L * 10);
076: } catch (InterruptedException ex) {
077: // ignore
078: }
079:
080: List<String> messages = value.getMessages();
081: Assert.assertEquals(getParticipantCount(), messages.size());
082: Assert.assertEquals(getParticipantCount(), new HashSet<String>(
083: messages).size());
084: }
085:
086: public static void visitL1DSOConfig(ConfigVisitor visitor,
087: DSOClientConfigHelper config) {
088: TransparencyClassSpec spec = config
089: .getOrCreateSpec(AnnotationTestApp.class.getName());
090: spec.addRoot("value", "value");
091:
092: String testClass = "com.tctest.AnnotationTestApp$ClassWithAnnotations";
093: // config.addIncludePattern(testClass);
094:
095: config
096: .addIncludePattern(ClassWithAnnotatedRoot.class
097: .getName());
098:
099: config.addIncludePattern(
100: "@com.tctest.AnnotationTestApp$Portable *", true);
101:
102: config
103: .addWriteAutolock("@com.tctest.AnnotationTestApp$WriteAutolock * "
104: + testClass + ".*(..)");
105: config
106: .addReadAutolock("@com.tctest.AnnotationTestApp$ReadAutolock * "
107: + testClass + ".*(..)");
108:
109: config.addDistributedMethodCall(new DistributedMethodSpec(
110: "@com.tctest.AnnotationTestApp$DistributedCall * "
111: + testClass + ".*(..)", true));
112:
113: String rootExpr = "@" + Root.class.getName() + " * *";
114: com.tc.object.config.Root root = new com.tc.object.config.Root(
115: rootExpr);
116: config.addRoot(root, false);
117: }
118:
119: @Portable
120: public static class ClassWithAnnotations {
121: private Object distributed;
122:
123: private transient List<String> messages = new ArrayList<String>();
124:
125: @ReadAutolock
126: public Object getDistributed() {
127: synchronized (this ) {
128: return distributed;
129: }
130: }
131:
132: @WriteAutolock
133: public void setDistributed(Object distributed) {
134: synchronized (this ) {
135: this .distributed = distributed;
136: }
137: }
138:
139: @DistributedCall
140: public void processMessage(String message) {
141: if (messages == null) {
142: messages = new ArrayList<String>();
143: }
144: messages.add(message);
145: }
146:
147: public List<String> getMessages() {
148: return messages;
149: }
150:
151: }
152:
153: @Portable
154: public static class ClassIncludedWithAnnotation {
155: private String value;
156:
157: public ClassIncludedWithAnnotation(String value) {
158: this .value = value;
159: }
160:
161: public String getValue() {
162: return value;
163: }
164: }
165:
166: public static class ClassWithAnnotatedRoot {
167: @Root
168: private final CyclicBarrier barrier;
169:
170: public ClassWithAnnotatedRoot(int num) {
171: if (num < 2) {
172: throw new AssertionError();
173: }
174: barrier = new CyclicBarrier(num);
175: }
176:
177: public int await() {
178: // this method will hang if the barrier does not become a root
179:
180: try {
181: return barrier.await();
182: } catch (Exception e) {
183: throw new AssertionError(e);
184: }
185: }
186: }
187:
188: @Target(ElementType.TYPE)
189: @Retention(RetentionPolicy.RUNTIME)
190: public static @interface Portable {
191: //
192: }
193:
194: @Target(ElementType.METHOD)
195: @Retention(RetentionPolicy.RUNTIME)
196: public static @interface WriteAutolock {
197: //
198: }
199:
200: @Target(ElementType.METHOD)
201: @Retention(RetentionPolicy.RUNTIME)
202: public static @interface ReadAutolock {
203: //
204: }
205:
206: @Target(ElementType.METHOD)
207: @Retention(RetentionPolicy.RUNTIME)
208: public static @interface DistributedCall {
209: //
210: }
211:
212: @Target(ElementType.FIELD)
213: @Retention(RetentionPolicy.RUNTIME)
214: public static @interface Root {
215: //
216: }
217:
218: }
|