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                    String packagePathWithSlashes = StringUtil.replace(
130                            packagePath, CharPool.PERIOD, CharPool.SLASH);
131    
132                    File deployFile = new File(
133                            tempDir + "/" + packagePathWithSlashes + "/deploy.wsdd");
134    
135                    String deployContent = new String(
136                            Files.readAllBytes(deployFile.toPath()));
137    
138                    deployContent = StringUtil.replace(
139                            deployContent, packagePath + "." + serviceName + "SoapBindingImpl",
140                            className);
141    
142                    deployContent = _format(deployContent);
143    
144                    File undeployFile = new File(
145                            tempDir + "/" + packagePathWithSlashes + "/undeploy.wsdd");
146    
147                    String undeployContent = new String(
148                            Files.readAllBytes(undeployFile.toPath()));
149    
150                    undeployContent = _format(undeployContent);
151    
152                    // Delete temp directory
153    
154                    DeleteTask.deleteDirectory(tempDir);
155    
156                    return new String[] {deployContent, undeployContent};
157            }
158    
159            private static void _addElements(
160                    Element element, Map<String, Element> elements) {
161    
162                    for (Map.Entry<String, Element> entry : elements.entrySet()) {
163                            Element childElement = entry.getValue();
164    
165                            element.add(childElement);
166                    }
167            }
168    
169            private static String _format(String content) throws Exception {
170                    content = _stripComments(content);
171    
172                    SAXReader saxReader = new SAXReader();
173    
174                    Document document = saxReader.read(new XMLSafeReader(content));
175    
176                    Element rootElement = document.getRootElement();
177    
178                    Element serviceElement = rootElement.element("service");
179    
180                    Map<String, Element> arrayMappingElements = new TreeMap<>();
181                    Map<String, Element> typeMappingElements = new TreeMap<>();
182                    Map<String, Element> operationElements = new TreeMap<>();
183                    Map<String, Element> parameterElements = new TreeMap<>();
184    
185                    List<Element> elements = serviceElement.elements();
186    
187                    for (Element element : elements) {
188                            String elementName = element.getName();
189    
190                            if (elementName.equals("arrayMapping")) {
191                                    element.detach();
192    
193                                    arrayMappingElements.put(_formattedString(element), element);
194                            }
195                            else if (elementName.equals("operation")) {
196                                    element.detach();
197    
198                                    List<Element> parameters = element.elements("parameter");
199    
200                                    StringBundler sb = new StringBundler(2 * parameters.size() + 2);
201    
202                                    String name = element.attributeValue("name");
203    
204                                    sb.append(name);
205                                    sb.append("_METHOD_");
206    
207                                    for (Element parameterElement : parameters) {
208                                            String type = parameterElement.attributeValue("type");
209    
210                                            sb.append(type);
211                                            sb.append("_PARAMETER_");
212                                    }
213    
214                                    operationElements.put(sb.toString(), element);
215                            }
216                            else if (elementName.equals("parameter")) {
217                                    element.detach();
218    
219                                    String name = element.attributeValue("name");
220    
221                                    if (name.equals("allowedMethods")) {
222                                            Attribute valueAttribute = element.attribute("value");
223    
224                                            String[] values = StringUtil.split(
225                                                    valueAttribute.getValue(), CharPool.SPACE);
226    
227                                            Arrays.sort(values);
228    
229                                            valueAttribute.setValue(
230                                                    StringUtil.merge(values, StringPool.SPACE));
231                                    }
232                                    else if (name.equals("schemaUnqualified")) {
233                                            Attribute valueAttribute = element.attribute("value");
234    
235                                            String[] values = StringUtil.split(
236                                                    valueAttribute.getValue());
237    
238                                            Arrays.sort(values);
239    
240                                            valueAttribute.setValue(StringUtil.merge(values));
241                                    }
242    
243                                    parameterElements.put(name, element);
244                            }
245                            else if (elementName.equals("typeMapping")) {
246                                    element.detach();
247    
248                                    typeMappingElements.put(_formattedString(element), element);
249                            }
250                    }
251    
252                    _addElements(serviceElement, arrayMappingElements);
253                    _addElements(serviceElement, typeMappingElements);
254                    _addElements(serviceElement, operationElements);
255                    _addElements(serviceElement, parameterElements);
256    
257                    content = StringUtil.replace(
258                            _formattedString(document), "\"/>", "\" />");
259    
260                    return content;
261            }
262    
263            private static String _formattedString(Node node) throws Exception {
264                    return Dom4jUtil.toString(node);
265            }
266    
267            private static String _stripComments(String text) {
268                    return StringUtil.stripBetween(text, "<!--", "-->");
269            }
270    
271    }