/* Licensed 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.activiti.engine.impl.webservice;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javax.wsdl.Definition;
import javax.wsdl.Types;
import javax.wsdl.WSDLException;
import javax.wsdl.extensions.schema.Schema;
import javax.xml.namespace.QName;
import org.activiti.engine.impl.bpmn.data.SimpleStructureDefinition;
import org.activiti.engine.impl.bpmn.data.StructureDefinition;
import org.activiti.engine.impl.bpmn.parser.BpmnParse;
import org.activiti.engine.impl.bpmn.parser.XMLImporter;
import org.activiti.engine.impl.util.ReflectUtil;
import org.activiti.engine.impl.util.xml.Element;
import org.apache.cxf.Bus;
import org.apache.cxf.BusFactory;
import org.apache.cxf.service.model.EndpointInfo;
import org.apache.cxf.service.model.OperationInfo;
import org.apache.cxf.service.model.ServiceInfo;
import org.apache.cxf.wsdl.WSDLManager;
import org.apache.cxf.wsdl11.WSDLServiceBuilder;
import com.ibm.wsdl.extensions.schema.SchemaImpl;
import com.sun.codemodel.JDefinedClass;
import com.sun.codemodel.JFieldVar;
import com.sun.tools.xjc.ConsoleErrorReporter;
import com.sun.tools.xjc.api.ErrorListener;
import com.sun.tools.xjc.api.Mapping;
import com.sun.tools.xjc.api.S2JJAXBModel;
import com.sun.tools.xjc.api.SchemaCompiler;
import com.sun.tools.xjc.api.XJC;
/**
* @author Esteban Robles Luna
*/
public class CxfWSDLImporter implements XMLImporter {
protected Map<String, WSService> wsServices = new HashMap<String, WSService>();
protected Map<String, WSOperation> wsOperations = new HashMap<String, WSOperation>();
protected Map<String, StructureDefinition> structures = new HashMap<String, StructureDefinition>();
protected String wsdlLocation;
protected String namespace;
public CxfWSDLImporter() {
this.namespace = "";
}
public void importFrom(Element element, BpmnParse parse) {
this.namespace = element.attribute("namespace") == null ? "" : element.attribute("namespace") + ":";
this.importFrom(element.attribute("location"));
this.transferImportsToParse(parse);
}
private void transferImportsToParse(BpmnParse parse) {
if (parse != null) {
for (StructureDefinition structure : this.structures.values()) {
parse.addStructure(structure);
}
for (WSService service : this.wsServices.values()) {
parse.addService(service);
}
for (WSOperation operation : this.wsOperations.values()) {
parse.addOperation(operation);
}
}
}
public void importFrom(String url) {
this.wsServices.clear();
this.wsOperations.clear();
this.structures.clear();
this.wsdlLocation = url;
try {
Bus bus = BusFactory.getDefaultBus();
WSDLManager wsdlManager = bus.getExtension(WSDLManager.class);
Definition def = wsdlManager.getDefinition(url);
WSDLServiceBuilder builder = new WSDLServiceBuilder(bus);
List<ServiceInfo> services = builder.buildServices(def);
for (ServiceInfo service : services) {
WSService wsService = this.importService(service);
this.wsServices.put(this.namespace + wsService.getName(), wsService);
}
this.importTypes(def.getTypes());
} catch (WSDLException e) {
e.printStackTrace();
}
}
private WSService importService(ServiceInfo service) {
String name = service.getName().getLocalPart();
String location = "";
for (EndpointInfo endpoint : service.getEndpoints()) {
location = endpoint.getAddress();
}
WSService wsService = new WSService(this.namespace + name, location, this.wsdlLocation);
for (OperationInfo operation : service.getInterface().getOperations()) {
WSOperation wsOperation = this.importOperation(operation, wsService);
wsService.addOperation(wsOperation);
this.wsOperations.put(this.namespace + operation.getName().getLocalPart(), wsOperation);
}
return wsService;
}
private WSOperation importOperation(OperationInfo operation, WSService service) {
WSOperation wsOperation = new WSOperation(this.namespace + operation.getName().getLocalPart(), operation.getName().getLocalPart(), service);
return wsOperation;
}
private void importTypes(Types types) {
SchemaCompiler compiler = XJC.createSchemaCompiler();
ErrorListener elForRun = new ConsoleErrorReporter();
compiler.setErrorListener(elForRun);
SchemaImpl impl = (SchemaImpl) types.getExtensibilityElements().get(0);
S2JJAXBModel intermediateModel = this.compileModel(types, compiler, impl.getElement());
Collection<? extends Mapping> mappings = intermediateModel.getMappings();
for (Mapping mapping : mappings){
this.importStructure(mapping);
}
}
private void importStructure(Mapping mapping) {
QName qname = mapping.getElement();
JDefinedClass theClass = (JDefinedClass) mapping.getType().getTypeClass();
SimpleStructureDefinition structure = new SimpleStructureDefinition(this.namespace + qname.getLocalPart());
this.structures.put(structure.getId(), structure);
Map<String, JFieldVar> fields = theClass.fields();
int index = 0;
for (Entry<String, JFieldVar> entry : fields.entrySet()) {
Class<?> fieldClass = ReflectUtil.loadClass(entry.getValue().type().boxify().fullName());
structure.setFieldName(index, entry.getKey(), fieldClass);
index++;
}
}
private S2JJAXBModel compileModel(Types types, SchemaCompiler compiler, org.w3c.dom.Element rootTypes) {
Schema schema = (Schema) types.getExtensibilityElements().get(0);
compiler.parseSchema(schema.getDocumentBaseURI() + "#types1", rootTypes);
S2JJAXBModel intermediateModel = compiler.bind();
return intermediateModel;
}
public Collection<StructureDefinition> getStructures() {
return this.structures.values();
}
public Collection<WSService> getServices() {
return this.wsServices.values();
}
public Collection<WSOperation> getOperations() {
return this.wsOperations.values();
}
}