| /** |
| * 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.cxf.jaxrs; |
| |
| import java.lang.reflect.Method; |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.concurrent.Executor; |
| |
| import javax.ws.rs.core.Response; |
| import javax.xml.namespace.QName; |
| import javax.xml.transform.Source; |
| |
| import org.apache.cxf.common.util.PackageUtils; |
| import org.apache.cxf.configuration.Configurable; |
| import org.apache.cxf.databinding.DataBinding; |
| import org.apache.cxf.endpoint.Endpoint; |
| import org.apache.cxf.interceptor.AbstractAttributedInterceptorProvider; |
| import org.apache.cxf.jaxrs.model.ClassResourceInfo; |
| import org.apache.cxf.jaxrs.model.OperationResourceInfo; |
| import org.apache.cxf.jaxrs.model.Parameter; |
| import org.apache.cxf.jaxrs.model.ParameterType; |
| import org.apache.cxf.jaxrs.utils.InjectionUtils; |
| import org.apache.cxf.jaxrs.utils.JAXRSUtils; |
| import org.apache.cxf.service.Service; |
| import org.apache.cxf.service.invoker.Invoker; |
| import org.apache.cxf.service.model.EndpointInfo; |
| import org.apache.cxf.service.model.InterfaceInfo; |
| import org.apache.cxf.service.model.MessageInfo; |
| import org.apache.cxf.service.model.MessagePartInfo; |
| import org.apache.cxf.service.model.OperationInfo; |
| import org.apache.cxf.service.model.ServiceInfo; |
| |
| /** |
| * The CXF Service implementation which is used |
| * to register the JAX-RS endpoint with the runtime. |
| */ |
| public class JAXRSServiceImpl extends AbstractAttributedInterceptorProvider implements Service, Configurable { |
| private static final long serialVersionUID = 6765400202555126993L; |
| private List<ClassResourceInfo> classResourceInfos; |
| private DataBinding dataBinding; |
| private Executor executor; |
| private Invoker invoker; |
| private Map<QName, Endpoint> endpoints = new HashMap<>(); |
| private String address; |
| private boolean createServiceModel; |
| private QName serviceName; |
| |
| public JAXRSServiceImpl(String address, QName qname) { |
| this.address = address; |
| this.serviceName = qname; |
| } |
| |
| public JAXRSServiceImpl(List<ClassResourceInfo> cri, QName qname) { |
| this.classResourceInfos = cri; |
| this.serviceName = qname; |
| } |
| |
| public JAXRSServiceImpl(List<ClassResourceInfo> cri) { |
| this(cri, null); |
| } |
| |
| public JAXRSServiceImpl(List<ClassResourceInfo> cri, boolean create) { |
| this(cri, null); |
| createServiceModel = create; |
| } |
| |
| public void setCreateServiceModel(boolean create) { |
| createServiceModel = create; |
| } |
| |
| public String getBeanName() { |
| return getName().toString(); |
| } |
| |
| public QName getName() { |
| if (serviceName != null) { |
| return serviceName; |
| } |
| if (address == null) { |
| Class<?> primaryClass = classResourceInfos.get(0).getServiceClass(); |
| String ns = PackageUtils.getNamespace(PackageUtils.getPackageName(primaryClass)); |
| return new QName(ns, primaryClass.getSimpleName()); |
| } |
| return new QName(address, "WebClient"); |
| } |
| |
| public List<ClassResourceInfo> getClassResourceInfos() { |
| return classResourceInfos; |
| } |
| |
| public List<ServiceInfo> getServiceInfos() { |
| if (!createServiceModel) { |
| return Collections.emptyList(); |
| } |
| // try to convert to WSDL-centric model so that CXF DataBindings can get initialized |
| // might become useful too if we support wsdl2 |
| |
| // make databindings to use databinding-specific information |
| // like @XmlRootElement for ex to select a namespace |
| this.put("org.apache.cxf.databinding.namespace", "true"); |
| |
| List<ServiceInfo> infos = new ArrayList<>(); |
| for (ClassResourceInfo cri : classResourceInfos) { |
| ServiceInfo si = new ServiceInfo(); |
| infos.add(si); |
| QName qname = JAXRSUtils.getClassQName(cri.getServiceClass()); |
| si.setName(qname); |
| InterfaceInfo inf = new InterfaceInfo(si, qname); |
| si.setInterface(inf); |
| for (OperationResourceInfo ori : cri.getMethodDispatcher().getOperationResourceInfos()) { |
| Method m = ori.getMethodToInvoke(); |
| QName oname = new QName(qname.getNamespaceURI(), m.getName()); |
| OperationInfo oi = inf.addOperation(oname); |
| createMessagePartInfo(oi, m.getReturnType(), qname, m, false); |
| for (Parameter pm : ori.getParameters()) { |
| |
| if (pm.getType() == ParameterType.REQUEST_BODY) { |
| createMessagePartInfo(oi, |
| ori.getMethodToInvoke().getParameterTypes()[pm.getIndex()], |
| qname, m, true); |
| } |
| } |
| } |
| |
| } |
| return infos; |
| } |
| |
| private void createMessagePartInfo(OperationInfo oi, Class<?> type, QName qname, Method m, |
| boolean input) { |
| if (type == void.class || Source.class.isAssignableFrom(type)) { |
| return; |
| } |
| if (InjectionUtils.isPrimitive(type) || Response.class == type) { |
| return; |
| } |
| QName mName = new QName(qname.getNamespaceURI(), |
| (input ? "in" : "out") + m.getName()); |
| MessageInfo ms = oi.createMessage(mName, |
| input ? MessageInfo.Type.INPUT : MessageInfo.Type.OUTPUT); |
| if (input) { |
| oi.setInput("in", ms); |
| } else { |
| oi.setOutput("out", ms); |
| } |
| QName mpQName = JAXRSUtils.getClassQName(type); |
| MessagePartInfo mpi = ms.addMessagePart(mpQName); |
| mpi.setConcreteName(mpQName); |
| mpi.setTypeQName(mpQName); |
| mpi.setTypeClass(type); |
| } |
| |
| public EndpointInfo getEndpointInfo(QName endpoint) { |
| // For WSDL-based services, this is to construct an EndpointInfo |
| // (transport, binding, address etc) from WSDL's physical part. |
| // not applicable to JAX-RS services. |
| return null; |
| } |
| |
| public Executor getExecutor() { |
| return executor; |
| } |
| |
| public void setExecutor(Executor executor) { |
| this.executor = executor; |
| } |
| |
| public Invoker getInvoker() { |
| return invoker; |
| } |
| |
| public void setInvoker(Invoker invoker) { |
| this.invoker = invoker; |
| } |
| |
| public DataBinding getDataBinding() { |
| return dataBinding; |
| } |
| |
| public void setDataBinding(DataBinding dataBinding) { |
| this.dataBinding = dataBinding; |
| } |
| |
| public Map<QName, Endpoint> getEndpoints() { |
| return endpoints; |
| } |
| |
| public void setEndpoints(Map<QName, Endpoint> endpoints) { |
| this.endpoints = endpoints; |
| } |
| |
| public void setProperties(Map<String, Object> properties) { |
| this.putAll(properties); |
| } |
| } |