/*******************************************************************************
* Copyright (c) 2006-2010 eBay Inc. All Rights Reserved.
* 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
*******************************************************************************/
package org.ebayopensource.turmeric.tools.codegen.builders;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.ebayopensource.turmeric.runtime.common.impl.utils.LogManager;
import org.ebayopensource.turmeric.tools.codegen.CodeGenContext;
import org.ebayopensource.turmeric.tools.codegen.SourceGenerator;
import org.ebayopensource.turmeric.tools.codegen.exception.CodeGenFailedException;
import org.ebayopensource.turmeric.tools.codegen.util.CodeGenUtil;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
public class WSDLSingleSchemaGenerator extends BaseCodeGenerator implements SourceGenerator{
private static final String WSDL_GEN_DIR = "META-INF/soa/services/wsdl";
private final String TARGET_NAMESPACE = "targetNamespace";
private final String TYPES_TAG = "wsdl:types";
private final String SCHEMA_TAG = "schema";
private final String IMPORT_TAG = "import";
private final String NAMESPACE = "namespace";
private final String XMLnamespace = "http://www.w3.org/2001/XMLSchema";
private static Logger s_logger = LogManager.getInstance(WSDLSingleSchemaGenerator.class);
private static WSDLSingleSchemaGenerator s_wsdlGenerator = new WSDLSingleSchemaGenerator();
private WSDLSingleSchemaGenerator() {}
public static WSDLSingleSchemaGenerator getInstance() {
return s_wsdlGenerator;
}
@SuppressWarnings("unused")
private Logger getLogger() {
return s_logger;
}
public boolean continueOnError() {
return true;
}
public void generate(CodeGenContext codeGenCtx)
throws CodeGenFailedException {
// String metaSrcdestLoc = codeGenCtx.getMetaSrcDestLocation();
// String svcName = codeGenCtx.getServiceName();
// String wsdlFilePath = CodeGenUtil.toOSFilePath(destFolderPath(metaSrcdestLoc, svcName)) +
// getWSDLFileName(codeGenCtx.getServiceName());
// parseDocument(codeGenCtx.getInputOptions().getInputFile(), wsdlFilePath);
}
private void parseDocument(String srcFileName, String destFileName) throws CodeGenFailedException {
// parse the wsdl
Document wsdlDocument = null;
DocumentBuilderFactory wsdlDocumentBuilderFactory = DocumentBuilderFactory.newInstance();
try {
DocumentBuilder wsdlDocumentBuilder = wsdlDocumentBuilderFactory.newDocumentBuilder();
wsdlDocument = wsdlDocumentBuilder.parse(new File(srcFileName));
} catch (ParserConfigurationException parserConfigurationException) {
String errMsg = "WSDL parsing failed!";
s_logger.log(Level.SEVERE, errMsg, parserConfigurationException);
throw new CodeGenFailedException(errMsg, parserConfigurationException);
} catch (SAXException saxException) {
String errMsg = "SAXException!";
s_logger.log(Level.SEVERE, errMsg, saxException);
throw new CodeGenFailedException(errMsg, saxException);
} catch (IOException e) {
String errMsg = "SAXException!";
s_logger.log(Level.SEVERE, errMsg, e);
}
Element wsdlDefinition = null;
String wsdlNamespace = null;
NodeList wsdlTypes = null;
NamedNodeMap namespacePrefixes = null;
if(wsdlDocument != null){
wsdlDefinition = wsdlDocument.getDocumentElement();
wsdlNamespace = wsdlDefinition.getAttribute(TARGET_NAMESPACE);
wsdlTypes = wsdlDefinition.getElementsByTagName(TYPES_TAG);
namespacePrefixes = wsdlDefinition.getAttributes();
}
Node targetSingleSchema = null;
List<Node> schemaNodes = new ArrayList<Node>();
List<Node> importNodes = new ArrayList<Node>();
//getting all the schemas available in the wsdl and populating them into a list
NodeList schemaTypes = null;
if(wsdlTypes != null && wsdlTypes.getLength() > 0)
schemaTypes = wsdlTypes.item(0).getChildNodes();
for (int j = 0; j < schemaTypes.getLength(); j++) {
if(schemaTypes.item(j).getNodeName().contains(SCHEMA_TAG)){
schemaNodes.add(schemaTypes.item(j));
}
}
List<Node> namespaceNodes = new ArrayList<Node>();
/*
* Adding the import tags in each schema into a list
*/
List<String> importNamespace = new ArrayList<String>();
for (Node schemaNode : schemaNodes) {
if(schemaNode.getAttributes() != null)
if(schemaNode.getAttributes().getNamedItem(TARGET_NAMESPACE) != null)
importNamespace.add(schemaNode.getAttributes().getNamedItem(TARGET_NAMESPACE).getNodeValue());
NamedNodeMap xmlnsNamespace = schemaNode.getAttributes();
for(int j=0; j < xmlnsNamespace.getLength() ; j++){
Node currAttribute = xmlnsNamespace.item(j);
String prefix = currAttribute.getNodeName();
if(currAttribute.getNodeValue().equalsIgnoreCase(XMLnamespace) &&
prefix != null && prefix.indexOf(":") != -1)
namespaceNodes.add(currAttribute);
}
NodeList tempImportList = schemaNode.getChildNodes();
for(int k = 0; k < tempImportList.getLength(); k++){
if(tempImportList.item(k).getNodeName().contains(IMPORT_TAG)){
importNodes.add(tempImportList.item(k));
}
}
}
/*
* Creating a map of namespace and their prefix, which is made use of while replacing the prefixes
*/
Map<String, String> nameSpacePrefixMap = new HashMap<String, String>();
List<String> prefixList = new ArrayList<String>();
for(int j=0; j < namespacePrefixes.getLength() ; j++){
Node currAttribute = namespacePrefixes.item(j);
nameSpacePrefixMap.put(currAttribute.getNodeValue(), currAttribute.getNodeName());
}
int numberOfImports = 0;
if(importNodes != null)
numberOfImports = importNodes.size();
List<Node> requiredImportList = new ArrayList<Node>();
/*
* Creating a list of required namespace that are to be imported
*/
for(int k = 0; k < numberOfImports; k++){
Node parent = importNodes.get(0).getParentNode();
if(importNamespace.contains(importNodes.get(0).getAttributes().getNamedItem(NAMESPACE).getNodeValue()))
parent.removeChild(importNodes.remove(0));
else{
requiredImportList.add(importNodes.get(0).cloneNode(true));
parent.removeChild(importNodes.remove(0));
}
}
if (schemaNodes != null && schemaNodes.size() > 0) {
/*
* Cloning the schema node which has the same targetnamespace as that of the wsdl
*/
for (Node schemaNode : schemaNodes) {
String schemaNamespace = null;
if(schemaNode.getAttributes().getNamedItem(TARGET_NAMESPACE) != null)
schemaNamespace = schemaNode.getAttributes().getNamedItem(TARGET_NAMESPACE).getNodeValue();
if(schemaNamespace != null && wsdlNamespace != null && wsdlNamespace.equalsIgnoreCase(schemaNamespace)){
targetSingleSchema = schemaNode.cloneNode(true);
wsdlTypes.item(0).removeChild(schemaNode);
schemaNodes.remove(schemaNode);
break;
}
}
/*
* Adding the child nodes of each schema to the cloned schema and removing the current schema
*/
for (Node schemaNode : schemaNodes) {
String currSchemaNS = schemaNode.getAttributes().getNamedItem(TARGET_NAMESPACE).getNodeValue();
NodeList currLeftOverSchema = schemaNode.getChildNodes();
String prefix = nameSpacePrefixMap.get(currSchemaNS);
for (int j = 0; j < currLeftOverSchema.getLength(); j++) {
Node newDescendants = currLeftOverSchema.item(j).cloneNode(true);
targetSingleSchema.appendChild(newDescendants);
}
if(nameSpacePrefixMap.get(currSchemaNS)!= null && !(nameSpacePrefixMap.get(currSchemaNS).equals("xmlns")))
if(prefix != null && prefix.indexOf(":") != -1)
prefixList.add(prefix.substring(prefix.indexOf(":") + 1));
wsdlTypes.item(0).removeChild(schemaNode);
}
}
/*
* If each schema uses seperate prefix then that prefix must be added to the wsdl definition as an attribute.
*/
for (Node namespaceNode : namespaceNodes) {
Attr attributeNode = wsdlDocument.createAttribute(namespaceNode.getNodeName());
attributeNode.setNodeValue(namespaceNode.getNodeValue());
if(wsdlDefinition != null)
wsdlDefinition.setAttributeNode(attributeNode);
}
if(requiredImportList != null && requiredImportList.size() > 0)
for (Node node : requiredImportList) {
targetSingleSchema.insertBefore(node, targetSingleSchema.getFirstChild());
}
/*
* After all the schemas are removed, the cloned schema node is added to wsdl element
* and then the prefixes are modified in order not to get any issues and then written into another file
*/
if(wsdlTypes != null && wsdlTypes.getLength() > 0)
wsdlTypes.item(0).appendChild(targetSingleSchema);
writeToFile(wsdlDocument, destFileName);
replacePrefix(prefixList, wsdlNamespace, nameSpacePrefixMap, destFileName);
}
/**
*
* @param document
* @param fileName
* @throws CodeGenFailedException
*/
private void writeToFile(Document document, String fileName) throws CodeGenFailedException{
/*
* Commenting this method .Using restricted apis.
* Not being used currently anywhere else.
* Should not be used.
*/
// OutputFormat outputFormat = new OutputFormat();
// outputFormat.setIndenting(true);
//
// FileWriter fileWriter = null;
// try {
// fileWriter = new FileWriter(fileName);
// DOMSerializer wsdlSerializer = new XMLSerializer(fileWriter, outputFormat);
// wsdlSerializer.serialize(document);
// }catch (Exception exception) {
// String errMsg = "Unknown Exception!";
// s_logger.log(Level.SEVERE, errMsg, exception);
// throw new CodeGenFailedException(errMsg, exception);
// }finally{
// CodeGenUtil.closeQuietly(fileWriter);
// }
}
/**
*
* @param prefixList
* @param wsdlNamespace
* @param nameSpacePrefixMap
* @param fileName
* @throws CodeGenFailedException
*/
private void replacePrefix(List<String> prefixList, String wsdlNamespace,
Map<String, String> nameSpacePrefixMap, String fileName) throws CodeGenFailedException{
BufferedReader fileReader = null;
FileWriter fileWriter = null;
StringBuilder wsdlString = new StringBuilder();
String newPrefix = nameSpacePrefixMap.get(wsdlNamespace).substring(nameSpacePrefixMap.get(wsdlNamespace).indexOf(":") + 1)+":";
try{
fileReader = new BufferedReader(new FileReader(fileName));
String currLine;
while((currLine = fileReader.readLine())!= null){
for (String currPrefix : prefixList)
currLine = currLine.replaceAll(currPrefix+":", newPrefix);
wsdlString.append(currLine).append("\n");
}
fileWriter = new FileWriter(fileName);
fileWriter.write(wsdlString.toString());
}catch (IOException exception) {
String errMsg = "IOException!";
s_logger.log(Level.SEVERE, errMsg, exception);
throw new CodeGenFailedException(errMsg, exception);
}finally{
CodeGenUtil.closeQuietly(fileReader);
CodeGenUtil.closeQuietly(fileWriter);
}
}
private String getWSDLFileName(String svcName) {
return svcName + "SNS.wsdl";
}
private String destFolderPath(String destLoc, String serviceName)
throws CodeGenFailedException {
String destFolderPath = CodeGenUtil.genDestFolderPath(destLoc,
serviceName, WSDL_GEN_DIR);
try {
CodeGenUtil.createDir(destFolderPath);
} catch (IOException ioEx) {
throw new CodeGenFailedException(ioEx.getMessage(), ioEx);
}
return destFolderPath;
}
public String getFilePath(String serviceAdminName, String interfaceName) {
String filePath = CodeGenUtil.toOSFilePath(WSDL_GEN_DIR) + serviceAdminName + File.separatorChar +serviceAdminName + ".wsdl" ;
return filePath;
}
}