summaryrefslogtreecommitdiffstats
path: root/sca-java-2.x/tags/2.0.1-RC1/modules/interface-java/src/test/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaInterfaceUtilDuplicateRemotableTestCase.java
blob: c70bdcaf47bc92db18ddc3a5c0ef894abce2a11c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.tuscany.sca.interfacedef.java.impl;

import static org.junit.Assert.assertEquals;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

import org.apache.tuscany.sca.core.DefaultExtensionPointRegistry;
import org.apache.tuscany.sca.core.ExtensionPointRegistry;
import org.apache.tuscany.sca.interfacedef.DataType;
import org.apache.tuscany.sca.interfacedef.Interface;
import org.apache.tuscany.sca.interfacedef.InvalidInterfaceException;
import org.apache.tuscany.sca.interfacedef.Operation;
import org.apache.tuscany.sca.interfacedef.OverloadedOperationException;
import org.apache.tuscany.sca.interfacedef.impl.DataTypeImpl;
import org.apache.tuscany.sca.interfacedef.impl.InterfaceImpl;
import org.apache.tuscany.sca.interfacedef.impl.OperationImpl;
import org.apache.tuscany.sca.interfacedef.java.DefaultJavaInterfaceFactory;
import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory;
import org.junit.Assert;
import org.junit.Test;
import org.oasisopen.sca.annotation.Remotable;

/**
 * This test case will test that a Component that has multiple Remotable interfaces
 * that contain methods with the same name will correctly select the right method.
 * 
 * @version $Rev$ $Date$
 */
public class JavaInterfaceUtilDuplicateRemotableTestCase {

    /**
     * Test to get the getTime() method from the LocalTimeService
     *
     * @throws Exception Test failed
     */
    @Test
    public void testLocalTimeServiceGetTime() throws Exception {
        doTestLocalTimeServiceGetTime(LocalTimeService.class);
    }

    /**
     * Test to get the getTime() method from the LocalTimeService interface from
     * the specified class
     *
     * @param timeServiceClass The class that implements the LocalTimeService
     * @throws Exception Test failed
     */
    private void doTestLocalTimeServiceGetTime(Class<?> timeServiceClass) throws Exception {
        // Add a getTime() method
        Operation operation = newOperation("getTime", LocalTimeService.class);

        Method method = JavaInterfaceUtil.findMethod(timeServiceClass, operation);
        assertEquals("getTime", method.getName());
        assertEquals(0, method.getParameterTypes().length);
    }

    /**
     * Test to get the getTime(String) method from the WorldTimeService
     *
     * @throws Exception Test failed
     */
    @Test
    public void testWorldTimeServiceGetTime() throws Exception {
        doTestWorldTimeServiceGetTime(WorldTimeService.class);
    }

    /**
     * Test to get the getTime(String) method from the WorldTimeService interface from
     * the specified class
     *
     * @param timeServiceClass The class that implements the WorldTimeService
     * @throws Exception Test failed
     */
    private void doTestWorldTimeServiceGetTime(Class<?> timeServiceClass) throws Exception {
        // Add a getTime(String) method
        Operation operation = newOperation("getTime", WorldTimeService.class, String.class);

        Method method = JavaInterfaceUtil.findMethod(timeServiceClass, operation);
        assertEquals("getTime", method.getName());
        assertEquals(1, method.getParameterTypes().length);
        assertEquals(String.class, method.getParameterTypes()[0]);
    }

    /**
     * Test to get the getTime(int) method from the GMTTimeService
     *
     * @throws Exception Test failed
     */
    @Test
    public void testGMTTimeServiceGetTime() throws Exception {
        doTestGMTTimeServiceGetTime(GMTTimeService.class);
    }

    /**
     * Test to get the getTime(int) method from the GMTTimeService interface from
     * the specified class
     *
    * @param timeServiceClass The class that implements the WorldTimeService
     * @throws Exception Test failed
     */
    private void doTestGMTTimeServiceGetTime(Class<?> timeServiceClass) throws Exception {
        // Add a getTime(String) method
        Operation operation = newOperation("getTime", GMTTimeService.class, Integer.TYPE);

        Method method = JavaInterfaceUtil.findMethod(timeServiceClass, operation);
        assertEquals("getTime", method.getName());
        assertEquals(1, method.getParameterTypes().length);
        assertEquals(Integer.TYPE, method.getParameterTypes()[0]);
    }

    /**
     * Test to get the getTime() method from the LocalTimeService on the
     * TimeServiceImpl class
     *
     * @throws Exception Test failed
     */
    @Test
    public void testLocalTimeServiceGetTimeFromTimeServiceImpl() throws Exception {
        doTestLocalTimeServiceGetTime(TimeServiceImpl.class);
    }

    /**
     * Test to get the getTime(String) method from the WorldTimeService on the
     * TimeServiceImpl class
     *
     * @throws Exception Test failed
     */
    @Test
    public void testWorldTimeServiceGetTimeFromTimeServiceImpl() throws Exception {
        doTestWorldTimeServiceGetTime(TimeServiceImpl.class);
    }

    /**
     * Test to get the getTime(int) method from the GMTTimeService
     *
     * @throws Exception Test failed
     */
    @Test
    public void testGMTTimeServiceGetTimeFromTimeServiceImpl() throws Exception {
        doTestGMTTimeServiceGetTime(TimeServiceImpl.class);
    }

    /**
     * Test case that validates that a @Remotable interface with Overloaded operations
     * is detected.
     * 
     * This test case is for TUSCANY-2194
     */
    @Test
    public void testDuplicateOpeartionOnRemotableInterface()
    {
        ExtensionPointRegistry registry = new DefaultExtensionPointRegistry();
        JavaInterfaceFactory javaFactory = new DefaultJavaInterfaceFactory(registry);
        JavaInterfaceIntrospectorImpl introspector = new JavaInterfaceIntrospectorImpl(javaFactory);
        JavaInterfaceImpl javaInterface = new JavaInterfaceImpl();

        try {
            introspector.introspectInterface(javaInterface, DuplicateMethodOnRemotableInterface.class);
            Assert.fail("Should have thrown an exception as @Remotable interface has overloaded methods");
        } catch (OverloadedOperationException ex) {
            // As expected
            // Make sure that the class and method names are in the exception
            String exMsg = ex.toString();
            Assert.assertTrue("Method name missing from exception", exMsg.indexOf("aDuplicateMethod") != -1);
            Assert.assertTrue("Class name missing from exception", 
                exMsg.indexOf(DuplicateMethodOnRemotableInterface.class.getName()) != -1);
        } catch (InvalidInterfaceException ex) {
            // Should have thrown OverloadedOperationException
            Assert.fail("Should have thrown an OverloadedOperationException but threw " + ex);
        }
    }

    /**
     * Creates a new operation with the specified name and parameter types
     *
     * @param name The name of the operation
     * @param operationInterface The interface to which the operation belongs
     * @param parameterTypes The types of the parameters for this operation
     * @return An operation with the specified name and parameter types
     */
    private static Operation newOperation(String name, Class<?> operationInterface, Class<?>... parameterTypes) {
        // Create and set the operation name
        Operation operation = new OperationImpl();
        operation.setName(name);

        // Make the operation remotable
        Interface iface = new InterfaceImpl();
        iface.setRemotable(true);
        operation.setInterface(iface);

        // Construct the parameters
        List<DataType> types = new ArrayList<DataType>();
        DataType<List<DataType>> inputType = new DataTypeImpl<List<DataType>>(Object[].class, types);
        for (Class<?> parameterType : parameterTypes) {
            DataType type = new DataTypeImpl<Class>(parameterType, Object.class);
            types.add(type);
        }
        operation.setInputType(inputType);

        // Return the created operation
        return operation;
    }
    
    /**
     * Sample @Remotable interface that has an overloaded operation which is not 
     * allowed according to the SCA Assembly Specification.
     */
    @Remotable
    private interface DuplicateMethodOnRemotableInterface {
        void aNonDuplicateMethod();
        void aDuplicateMethod();
        void aDuplicateMethod(String aParam);
    }


    /**
     * Sample interface needed for the unit tests
     */
    @Remotable
    private interface LocalTimeService {

        /**
         * Gets the local time
         *
         * @return The Local Time
         */
        String getTime();
    }

    /**
     * Sample interface needed for the unit tests
     */
    @Remotable
    private interface WorldTimeService {

        /**
         * Gets the time in the specified TimeZone
         *
         * @param timeZone A Time Zone
         *
         * @return The time in the specified TimeZone
         */
        String getTime(String timeZone);
    }

    /**
     * Sample interface needed for the unit tests
     */
    @Remotable
    private interface GMTTimeService {

        /**
         * Gets the time with the specified GMT offset
         *
         * @param gmtOffset A GMT offset in hours
         *
         * @return The time with the specified GMT offset
         */
        String getTime(int gmtOffset);
    }

    /**
     * Sample implementation class that implements the three @Remotable interfaces
     */
    private class TimeServiceImpl implements LocalTimeService, WorldTimeService, GMTTimeService {
        /**
         * Gets the local time
         *
         * @return The Local Time
         */
        public String getTime() {
            return "The current local time";
        }

        /**
         * Gets the time in the specified TimeZone
         *
         * @param timeZone A Time Zone
         *
         * @return The time in the specified TimeZone
         */
        public String getTime(String timeZone) {
            return "The current time in TimeZone " + timeZone;
        }

        /**
         * Gets the time with the specified GMT offset
         *
         * @param gmtOffset A GMT offset in hours
         *
         * @return The time with the specified GMT offset
         */
        public String getTime(int gmtOffset) {
            return "The current time with GMT offset of " + gmtOffset;
        }
    }
}