001    /**
002     * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.util.ant;
016    
017    import com.liferay.portal.kernel.util.CharPool;
018    import com.liferay.portal.kernel.util.StringBundler;
019    import com.liferay.portal.kernel.util.StringPool;
020    import com.liferay.portal.kernel.util.StringUtil;
021    import com.liferay.portal.kernel.util.SystemProperties;
022    import com.liferay.portal.kernel.util.Validator;
023    import com.liferay.util.xml.Dom4jUtil;
024    import com.liferay.util.xml.XMLSafeReader;
025    
026    import java.io.File;
027    
028    import java.nio.file.Files;
029    import java.nio.file.Paths;
030    
031    import java.util.Arrays;
032    import java.util.List;
033    import java.util.Map;
034    import java.util.TreeMap;
035    
036    import org.apache.axis.tools.ant.wsdl.Java2WsdlAntTask;
037    import org.apache.axis.tools.ant.wsdl.NamespaceMapping;
038    import org.apache.axis.tools.ant.wsdl.Wsdl2javaAntTask;
039    import org.apache.tools.ant.Project;
040    import org.apache.tools.ant.types.Path;
041    
042    import org.dom4j.Attribute;
043    import org.dom4j.Document;
044    import org.dom4j.Element;
045    import org.dom4j.Node;
046    import org.dom4j.io.SAXReader;
047    
048    /**
049     * @author Brian Wing Shun Chan
050     */
051    public class Java2WsddTask {
052    
053            public static String[] generateWsdd(
054                            String className, String classPath, String serviceName)
055                    throws Exception {
056    
057                    // Create temp directory
058    
059                    java.nio.file.Path tempDirPath = Files.createTempDirectory(
060                            Paths.get(SystemProperties.get(SystemProperties.TMP_DIR)), null);
061    
062                    File tempDir = tempDirPath.toFile();
063    
064                    tempDir.mkdir();
065    
066                    // axis-java2wsdl
067    
068                    String wsdlFileName = tempDir + "/service.wsdl";
069    
070                    int pos = className.lastIndexOf(".");
071    
072                    String packagePath = className.substring(0, pos);
073    
074                    String[] packagePaths = StringUtil.split(packagePath, '.');
075    
076                    String namespace = "urn:";
077    
078                    for (int i = packagePaths.length - 1; i >= 0; i--) {
079                            namespace += packagePaths[i];
080    
081                            if (i > 0) {
082                                    namespace += ".";
083                            }
084                    }
085    
086                    String location = "http://localhost/services/" + serviceName;
087    
088                    String mappingPackage = packagePath.substring(
089                            0, packagePath.lastIndexOf(".")) + ".ws";
090    
091                    Project project = AntUtil.getProject();
092    
093                    Java2WsdlAntTask java2Wsdl = new Java2WsdlAntTask();
094    
095                    NamespaceMapping mapping = new NamespaceMapping();
096    
097                    mapping.setNamespace(namespace);
098                    mapping.setPackage(mappingPackage);
099    
100                    java2Wsdl.setProject(project);
101                    java2Wsdl.setClassName(className);
102    
103                    if (Validator.isNotNull(classPath)) {
104                            java2Wsdl.setClasspath(new Path(project, classPath));
105                    }
106    
107                    java2Wsdl.setOutput(new File(wsdlFileName));
108                    java2Wsdl.setLocation(location);
109                    java2Wsdl.setNamespace(namespace);
110                    java2Wsdl.addMapping(mapping);
111    
112                    java2Wsdl.execute();
113    
114                    // axis-wsdl2java
115    
116                    Wsdl2javaAntTask wsdl2Java = new Wsdl2javaAntTask();
117    
118                    wsdl2Java.setProject(project);
119                    wsdl2Java.setURL(wsdlFileName);
120                    wsdl2Java.setOutput(tempDir);
121                    wsdl2Java.setServerSide(true);
122                    wsdl2Java.setTestCase(false);
123                    wsdl2Java.setVerbose(false);
124    
125                    wsdl2Java.execute();
126    
127                    // Get content
128    
129                    File deployFile = new File(
130                            tempDir + "/" + StringUtil.replace(packagePath, ".", "/") +
131                                    "/deploy.wsdd");
132    
133                    String deployContent = new String(
134                            Files.readAllBytes(deployFile.toPath()));
135    
136                    deployContent = StringUtil.replace(
137                            deployContent, packagePath + "." + serviceName + "SoapBindingImpl",
138                            className);
139    
140                    deployContent = _format(deployContent);
141    
142                    File undeployFile = new File(
143                            tempDir + "/" + StringUtil.replace(packagePath, ".", "/") +
144                                    "/undeploy.wsdd");
145    
146                    String undeployContent = new String(
147                            Files.readAllBytes(undeployFile.toPath()));
148    
149                    undeployContent = _format(undeployContent);
150    
151                    // Delete temp directory
152    
153                    DeleteTask.deleteDirectory(tempDir);
154    
155                    return new String[] {deployContent, undeployContent};
156            }
157    
158            private static void _addElements(
159                    Element element, Map<String, Element> elements) {
160    
161                    for (Map.Entry<String, Element> entry : elements.entrySet()) {
162                            Element childElement = entry.getValue();
163    
164                            element.add(childElement);
165                    }
166            }
167    
168            private static String _format(String content) throws Exception {
169                    content = _stripComments(content);
170    
171                    SAXReader saxReader = new SAXReader();
172    
173                    Document document = saxReader.read(new XMLSafeReader(content));
174    
175                    Element rootElement = document.getRootElement();
176    
177                    Element serviceElement = rootElement.element("service");
178    
179                    Map<String, Element> arrayMappingElements = new TreeMap<>();
180                    Map<String, Element> typeMappingElements = new TreeMap<>();
181                    Map<String, Element> operationElements = new TreeMap<>();
182                    Map<String, Element> parameterElements = new TreeMap<>();
183    
184                    List<Element> elements = serviceElement.elements();
185    
186                    for (Element element : elements) {
187                            String elementName = element.getName();
188    
189                            if (elementName.equals("arrayMapping")) {
190                                    element.detach();
191    
192                                    arrayMappingElements.put(_formattedString(element), element);
193                            }
194                            else if (elementName.equals("operation")) {
195                                    element.detach();
196    
197                                    List<Element> parameters = element.elements("parameter");
198    
199                                    StringBundler sb = new StringBundler(2 * parameters.size() + 2);
200    
201                                    String name = element.attributeValue("name");
202    
203                                    sb.append(name);
204                                    sb.append("_METHOD_");
205    
206                                    for (Element parameterElement : parameters) {
207                                            String type = parameterElement.attributeValue("type");
208    
209                                            sb.append(type);
210                                            sb.append("_PARAMETER_");
211                                    }
212    
213                                    operationElements.put(sb.toString(), element);
214                            }
215                            else if (elementName.equals("parameter")) {
216                                    element.detach();
217    
218                                    String name = element.attributeValue("name");
219    
220                                    if (name.equals("allowedMethods")) {
221                                            Attribute valueAttribute = element.attribute("value");
222    
223                                            String[] values = StringUtil.split(
224                                                    valueAttribute.getValue(), CharPool.SPACE);
225    
226                                            Arrays.sort(values);
227    
228                                            valueAttribute.setValue(
229                                                    StringUtil.merge(values, StringPool.SPACE));
230                                    }
231                                    else if (name.equals("schemaUnqualified")) {
232                                            Attribute valueAttribute = element.attribute("value");
233    
234                                            String[] values = StringUtil.split(
235                                                    valueAttribute.getValue());
236    
237                                            Arrays.sort(values);
238    
239                                            valueAttribute.setValue(StringUtil.merge(values));
240                                    }
241    
242                                    parameterElements.put(name, element);
243                            }
244                            else if (elementName.equals("typeMapping")) {
245                                    element.detach();
246    
247                                    typeMappingElements.put(_formattedString(element), element);
248                            }
249                    }
250    
251                    _addElements(serviceElement, arrayMappingElements);
252                    _addElements(serviceElement, typeMappingElements);
253                    _addElements(serviceElement, operationElements);
254                    _addElements(serviceElement, parameterElements);
255    
256                    content = StringUtil.replace(
257                            _formattedString(document), "\"/>", "\" />");
258    
259                    return content;
260            }
261    
262            private static String _formattedString(Node node) throws Exception {
263                    return Dom4jUtil.toString(node);
264            }
265    
266            private static String _stripComments(String text) {
267                    return StringUtil.stripBetween(text, "<!--", "-->");
268            }
269    
270    }