org.fabric3.introspection.impl.contract.DefaultContractProcessor Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of fabric3-introspection Show documentation
Show all versions of fabric3-introspection Show documentation
Fabric3 Introspection Implementation.
/*
* 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.fabric3.introspection.impl.contract;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import javax.xml.namespace.QName;
import org.osoa.sca.Constants;
import org.osoa.sca.annotations.Callback;
import org.osoa.sca.annotations.Conversational;
import org.osoa.sca.annotations.EndsConversation;
import org.osoa.sca.annotations.OneWay;
import org.osoa.sca.annotations.Remotable;
import org.osoa.sca.annotations.Reference;
import org.fabric3.introspection.contract.ContractProcessor;
import org.fabric3.introspection.contract.InvalidServiceContractException;
import org.fabric3.introspection.IntrospectionHelper;
import org.fabric3.introspection.TypeMapping;
import org.fabric3.scdl.DataType;
import org.fabric3.scdl.Operation;
import static org.fabric3.scdl.Operation.CONVERSATION_END;
import static org.fabric3.scdl.Operation.NO_CONVERSATION;
/**
* Default implementation of a ContractProcessor for Java interfaces.
*
* @version $Rev: 3105 $ $Date: 2008-03-15 16:47:31 +0000 (Sat, 15 Mar 2008) $
*/
public class DefaultContractProcessor implements ContractProcessor {
public static final String IDL_INPUT = "idl:input";
public static final QName ONEWAY_INTENT = new QName(Constants.SCA_NS, "oneWay");
private final IntrospectionHelper helper;
public DefaultContractProcessor(@Reference IntrospectionHelper helper) {
this.helper = helper;
}
public JavaServiceContract introspect(TypeMapping typeMapping, Type type) throws InvalidServiceContractException {
if (type instanceof Class) {
return introspect(typeMapping, (Class>) type);
} else {
throw new UnsupportedOperationException("Interface introspection is only supported for classes");
}
}
public JavaServiceContract introspect(TypeMapping typeMapping, Class> interfaze) throws InvalidServiceContractException {
JavaServiceContract contract = introspectInterface(typeMapping, interfaze);
Callback callback = interfaze.getAnnotation(Callback.class);
if (callback != null) {
Class> callbackClass = callback.value();
if (Void.class.equals(callbackClass)) {
throw new MissingCallbackException(interfaze.getName());
}
JavaServiceContract callbackContract = introspectInterface(typeMapping, callbackClass);
contract.setCallbackContract(callbackContract);
}
return contract;
}
/**
* Introspects a class, returning its service contract.
*
* @param interfaze the interface to introspect
* @return the service contract
* @throws InvalidServiceContractException
* if the class is an invalid service inteface or contains invalid service meatadata
*/
private JavaServiceContract introspectInterface(TypeMapping typeMapping, Class> interfaze) throws InvalidServiceContractException {
JavaServiceContract contract = new JavaServiceContract(interfaze);
contract.setInterfaceName(interfaze.getSimpleName());
// TODO this should be refactored to its own processor
boolean remotable = interfaze.isAnnotationPresent(Remotable.class);
contract.setRemotable(remotable);
// TODO this should be refactored to its own processor
boolean conversational = helper.isAnnotationPresent(interfaze, Conversational.class);
contract.setConversational(conversational);
contract.setOperations(getOperations(typeMapping, interfaze, remotable, conversational));
return contract;
}
private List> getOperations(TypeMapping typeMapping,
Class type,
boolean remotable,
boolean conversational)
throws InvalidServiceContractException {
Method[] methods = type.getMethods();
List> operations = new ArrayList>(methods.length);
for (Method method : methods) {
String name = method.getName();
if (remotable) {
for (Operation operation : operations) {
if (operation.getName().equals(name)) {
throw new OverloadedOperationException(method);
}
}
}
Class> returnType = method.getReturnType();
Class>[] paramTypes = method.getParameterTypes();
Class>[] faultTypes = method.getExceptionTypes();
int conversationSequence = NO_CONVERSATION;
if (method.isAnnotationPresent(EndsConversation.class)) {
if (!conversational) {
throw new InvalidConversationalOperationException(
"Method is marked as end conversation but contract is not conversational",
method.getDeclaringClass().getName(),
method);
}
conversationSequence = CONVERSATION_END;
} else if (conversational) {
conversationSequence = Operation.CONVERSATION_CONTINUE;
}
Type actualReturnType = typeMapping.getActualType(returnType);
DataType returnDataType = new DataType(actualReturnType, actualReturnType);
List> paramDataTypes = new ArrayList>(paramTypes.length);
for (Type paramType : paramTypes) {
Type actualType = typeMapping.getActualType(paramType);
paramDataTypes.add(new DataType(actualType, actualType));
}
List> faultDataTypes = new ArrayList>(faultTypes.length);
for (Type faultType : faultTypes) {
Type actualType = typeMapping.getActualType(faultType);
faultDataTypes.add(new DataType(actualType, actualType));
}
DataType>> inputType =
new DataType>>(Object[].class, paramDataTypes);
Operation operation = new Operation(name,
inputType,
returnDataType,
faultDataTypes,
conversationSequence);
// TODO this should be refactored to its own processor
if (method.isAnnotationPresent(OneWay.class)) {
operation.addIntent(ONEWAY_INTENT);
}
operations.add(operation);
}
return operations;
}
}