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