001    /******************************************************************************
002     * Copyright (C) MActor Developers. All rights reserved.                        *
003     * ---------------------------------------------------------------------------*
004     * This file is part of MActor.                                               *
005     *                                                                            *
006     * MActor is free software; you can redistribute it and/or modify             *
007     * it under the terms of the GNU General Public License as published by       *
008     * the Free Software Foundation; either version 2 of the License, or          *
009     * (at your option) any later version.                                        *
010     *                                                                            *
011     * MActor is distributed in the hope that it will be useful,                  *
012     * but WITHOUT ANY WARRANTY; without even the implied warranty of             *
013     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the              *
014     * GNU General Public License for more details.                               *
015     *                                                                            *
016     * You should have received a copy of the GNU General Public License          *
017     * along with MActor; if not, write to the Free Software                      *
018     * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA *
019     ******************************************************************************/
020    package org.mactor.ui.gui.actions;
021    
022    import java.awt.BorderLayout;
023    import java.awt.FlowLayout;
024    import java.awt.Frame;
025    import java.io.File;
026    import java.io.FileInputStream;
027    import java.io.FileWriter;
028    import java.io.IOException;
029    import java.io.InputStream;
030    import java.net.MalformedURLException;
031    import java.net.URL;
032    import java.util.LinkedList;
033    import java.util.List;
034    
035    import javax.swing.AbstractAction;
036    import javax.swing.JButton;
037    import javax.swing.JCheckBox;
038    import javax.swing.JDialog;
039    import javax.swing.JLabel;
040    import javax.swing.JPanel;
041    import javax.swing.JTextField;
042    
043    import org.dom4j.Element;
044    import org.mactor.brokers.soap.wsdl.Wsdl;
045    import org.mactor.brokers.soap.wsdl.Wsdl.OperationInfo;
046    import org.mactor.framework.MactorException;
047    import org.mactor.framework.spec.ActionSpec;
048    import org.mactor.framework.spec.MessagePublishSpec;
049    import org.mactor.framework.spec.MessageReceiveSpec;
050    import org.mactor.framework.spec.MessageRespondSpec;
051    import org.mactor.framework.spec.MessageSubscribeSpec;
052    import org.mactor.framework.spec.ProjectContext;
053    import org.mactor.ui.gui.AsyncAction;
054    import org.mactor.ui.gui.GuiUtil;
055    import org.mactor.ui.gui.project.GuiAction;
056    import org.mactor.ui.gui.project.ProjectController;
057    import org.mactor.ui.gui.project.ProjectNodeType;
058    import org.mactor.ui.gui.project.ProjectTreeNode;
059    import org.mactor.ui.gui.project.ProjectTreeNodeBuilder;
060    import org.mactor.ui.gui.project.editors.SimpleFormPanel;
061    
062    public class CreateChannelsFromWsdlAction implements GuiAction {
063            public boolean isPermitted(ProjectTreeNode selectedTreeNode, ProjectController projectController, String[] parameters) {
064                    return selectedTreeNode != null && (selectedTreeNode.getNodeType().equals(ProjectNodeType.MBC_CHANNEL) || selectedTreeNode.getNodeType().equals(ProjectNodeType.MBC_MESSAGE_BROKER));
065            }
066            public void perform(ProjectTreeNode selectedTreeNode, ProjectController projectController, String[] parameters) throws MactorException {
067                    // http://webservices.amazon.com/AWSECommerceService/AWSECommerceService.wsdl
068                    ProjectTreeNode targetNode = null;
069                    if (selectedTreeNode.getNodeType().equals(ProjectNodeType.MBC_CHANNEL))
070                            targetNode = selectedTreeNode.getParentNode();
071                    else if (selectedTreeNode.getNodeType().equals(ProjectNodeType.MBC_MESSAGE_BROKER))
072                            targetNode = selectedTreeNode;
073                    else
074                            throw new MactorException("Invalid request");
075                    new WsdlWizard(projectController.getControllerFrame(), targetNode, projectController).setVisible(true);
076            }
077            public class WsdlWizard extends JDialog {
078                    JCheckBox generateTestsButton = new JCheckBox("Generate Test Stubs");
079                    JCheckBox generateMockBatteryButton = new JCheckBox("Generate Mock Battery (only for incoming)");
080                    ProjectController projectController;
081                    SimpleFormPanel form = new SimpleFormPanel();
082                    JTextField url = new JTextField();
083                    ProjectTreeNode targetNode;
084                    JButton closeButton = new JButton(new AbstractAction("Close") {
085                            public void actionPerformed(java.awt.event.ActionEvent arg0) {
086                                    dispose();
087                            };
088                    });
089                    JButton importIncomingButton = new JButton(new AsyncAction("Create Incoming Channels from WSDL (MActor working as a Server)", false, new AsyncAction.AsyncRunnable() {
090                            public void run() {
091                                    generateChannels(true);
092                            }
093                    }));
094                    JButton importOutgoingButton = new JButton(new AsyncAction("Create Outgoing Channels from WSDL (MActor working as a Client)", false, new AsyncAction.AsyncRunnable() {
095                            public void run() {
096                                    generateChannels(false);
097                            }
098                    }));
099                    String template;
100                    public void generateChannels(boolean incoming) {
101                            if (url.getText() == null || url.getText().trim().length() == 0) {
102                                    GuiUtil.showInfo(this, "URL must be specifed!");
103                                    return;
104                            }
105                            try {
106                                    List<String> tests = new LinkedList<String>();
107                                    File wsdlFile = null;
108                                    URL wsdlUrl = null;
109                                    Wsdl wsdl = null;
110                                    try {
111                                            wsdlUrl = new URL(url.getText().trim());
112                                    } catch (Exception e) {
113                                            wsdlFile = new File(url.getText().trim());
114                                    }
115                                    if (wsdlFile != null)
116                                            wsdl = new Wsdl(wsdlFile);
117                                    else
118                                            wsdl = new Wsdl(wsdlUrl);
119                                    String wsdlFileName = null;
120                                    String name = null;
121                                    if (incoming) {
122                                            if (wsdl.getOperations().size() > 0)
123                                                    name = wsdl.getOperations().get(0).getService();
124                                            else
125                                                    name = System.currentTimeMillis() + "";
126                                            InputStream is = null;
127                                            if (wsdlFile != null)
128                                                    is = new FileInputStream(wsdlFile);
129                                            else
130                                                    is = new URL(url.getText()).openStream();
131                                            wsdlFileName = writeToDisk(is, name);
132                                    }
133                                    template = CreateEntityAction.getTemplateContent("MBC_CHANNEL");
134                                    for (Wsdl.OperationInfo oi : wsdl.getOperations()) {
135                                            ProjectTreeNode node = ProjectTreeNodeBuilder.createNewNode(ProjectNodeType.MBC_CHANNEL, template);
136                                            Element e = (Element) node.getModelObject();
137                                            e.addAttribute("requires_response", true + "");
138                                            String channel = null;
139                                            String uri = null;
140                                            if (incoming) {
141                                                    try {
142                                                            URL u = new URL(oi.getTargetURL());
143                                                            uri = "http://localhost:8877" + u.getPath();
144                                                            if (u.getQuery() != null)
145                                                                    uri = uri + "?" + u.getQuery();
146                                                    } catch (MalformedURLException me) {
147                                                            uri = oi.getTargetURL();
148                                                    }
149                                                    channel = "Incoming" + oi.getTargetMethodName();
150                                                    addValue(e, "WsdlFile", wsdlFileName);
151                                            } else {
152                                                    uri = oi.getTargetURL();
153                                                    channel = "Outgoing" + oi.getTargetMethodName();
154                                            }
155                                            addValue(e, "SoapAction", oi.getSoapActionURI());
156                                            addValue(e, "SoapEndpoint", uri);
157                                            e.attribute("name").setValue(channel);
158                                            node = ProjectTreeNodeBuilder.createNewNode(ProjectNodeType.MBC_CHANNEL, e.asXML());
159                                            projectController.insertNodeIntoNode(targetNode, node);
160                                            if (generateTestsButton.isSelected()) {
161                                                    tests.add(createTest(incoming, channel, name, oi));
162                                            }
163                                    }
164                                    if (incoming && generateMockBatteryButton.isSelected())
165                                            createMockBattery(name, tests);
166                                    projectController.reloadProject();
167                            } catch (Exception e) {
168                                    e.printStackTrace();
169                                    GuiUtil.showGuiError(WsdlWizard.this, e);
170                            }
171                    }
172                    private void addValue(Element e, String name, String value) {
173                            Element v = e.addElement("value");
174                            v.addAttribute("name", name);
175                            v.setText(value);
176                    }
177                    String testTemplate;
178                    private String createTest(boolean incoming, String channelName, String serviceName, OperationInfo oi) throws MactorException, IOException {
179                            if (testTemplate == null)
180                                    testTemplate = CreateEntityAction.getTemplateContent("T_TEST");
181                            ProjectTreeNode test = ProjectTreeNodeBuilder.createNewNode(ProjectNodeType.T_TEST, testTemplate);
182                            String fn = ProjectContext.getGlobalInstance().getNextFilename("Test" + channelName + ".xml", false);
183                            test.rename(fn);
184                            Element testElement = (Element) test.getModelObject();
185                            if (incoming)
186                                    initIncomingTest(testElement, channelName, oi);
187                            else
188                                    initOutgoingTest(testElement, channelName, oi);
189                            test.save();
190                            return fn;
191                    }
192                    private void initIncomingTest(Element testElement, String channel, OperationInfo oi) throws MactorException, IOException {
193                            MessageSubscribeSpec msSpec = new MessageSubscribeSpec();
194                            msSpec.setChannel(channel);
195                            msSpec.setName("SubscribeTo" + channel);
196                            msSpec.getMessageSelector().setCommand("java:org.mactor.extensions.xml.XPathIgnoreNsRegExpMessageSelector");
197                            MessageRespondSpec mrespSpec = new MessageRespondSpec();
198                            mrespSpec.setName("RespondTo" + channel);
199                            mrespSpec.getMessageBuilder().setTemplatePath(createTemplateFile(oi.getService(), oi.getTargetMethodName(), "Response", oi.getNamespaceURI()));
200                            mrespSpec.getMessageBuilder().setCommand("java:org.mactor.extensions.xml.XPathTemplateMessageBuilder");
201                            MessageReceiveSpec mrSpec = new MessageReceiveSpec();
202                            mrSpec.setName("ReceiveFrom" + channel);
203                            mrSpec.setMinMessageCount(1);
204                            mrSpec.setMaxTimeoutSeconds(600000);
205                            mrSpec.setMessageSubscribeNodeName("SubscribeTo" + channel);
206                            mrSpec.addSpecNode(mrespSpec);
207                            ActionSpec aSpec = new ActionSpec();
208                            aSpec.setName("VerifyReceivedMessage");
209                            aSpec.setCommand("java:org.mactor.extensions.xml.XPathIgnoreNsRegExpValidator");
210                            msSpec.addToElement(testElement);
211                            mrSpec.addToElement(testElement);
212                            aSpec.addToElement(testElement);
213                    }
214                    private String createTemplateFile(String service, String messageName, String suffix, String targetNs) throws IOException {
215                            String dirName = service + "_templates";
216                            File dir = ProjectContext.getGlobalInstance().getAbsolutePath(dirName);
217                            if (!dir.exists())
218                                    dir.mkdirs();
219                            String name = dirName + "/" + messageName + suffix + ".xml";
220                            File file = ProjectContext.getGlobalInstance().getAbsolutePath(name);
221                            FileWriter fw = new FileWriter(file);
222                            fw.write("<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns=\"" + targetNs + "\">");
223                            fw.write("\n <soapenv:Body>");
224                            fw.write("\n  <" + messageName + ">");
225                            fw.write("\n\n  <!--insert the message body here -->");
226                            fw.write("\n\n  </" + messageName + ">");
227                            fw.write("\n </soapenv:Body>");
228                            fw.write("\n</soapenv:Envelope>");
229                            //
230                            fw.close();
231                            return name;
232                    }
233                    private void initOutgoingTest(Element testElement, String channel, OperationInfo oi) throws MactorException, IOException {
234                            MessagePublishSpec mpSpec = new MessagePublishSpec();
235                            mpSpec.setName("PublishTo" + channel);
236                            mpSpec.setChannel(channel);
237                            mpSpec.getMessageBuilder().setTemplatePath(createTemplateFile(oi.getService(), oi.getTargetMethodName(), "Request", oi.getNamespaceURI()));
238                            mpSpec.getMessageBuilder().setCommand("java:org.mactor.extensions.xml.XPathTemplateMessageBuilder");
239                            ActionSpec aSpec = new ActionSpec();
240                            aSpec.setName("VerifyReceivedMessage");
241                            aSpec.setCommand("java:org.mactor.extensions.xml.XPathIgnoreNsRegExpValidator");
242                            mpSpec.addToElement(testElement);
243                            aSpec.addToElement(testElement);
244                    }
245                    private void createMockBattery(String serviceName, List<String> tests) throws MactorException {
246                            String template = CreateEntityAction.getTemplateContent("TM_MOCK_BATTERY");
247                            ProjectTreeNode tm = ProjectTreeNodeBuilder.createNewNode(ProjectNodeType.TM_MOCK_BATTERY, template);
248                            Element e = (Element) tm.getModelObject();
249                            for (String t : tests)
250                                    e.addElement("test").addAttribute("name", t);
251                            tm.save();
252                    }
253                    private String writeToDisk(InputStream is, String name) throws MactorException, IOException {
254                            File f = new File(ProjectContext.getGlobalInstance().getProjectConfigDir() + "/" + name + ".wsdl");
255                            FileWriter fw = new FileWriter(f);
256                            for (;;) {
257                                    int val = is.read();
258                                    if (val < 0)
259                                            break;
260                                    fw.write(val);
261                            }
262                            fw.close();
263                            return f.getName();
264                    }
265                    public WsdlWizard(Frame parentFrame, ProjectTreeNode targetNode, ProjectController projectController) {
266                            super(parentFrame, true);
267                            setTitle("Create SOAP Channels From WSDL");
268                            this.targetNode = targetNode;
269                            this.projectController = projectController;
270                            setLayout(new BorderLayout());
271                            form.add(new JLabel("WSDL URI:"));
272                            form.add(url);
273                            JPanel p1 = new JPanel(new FlowLayout());
274                            p1.add(importIncomingButton);
275                            JPanel p2 = new JPanel(new FlowLayout());
276                            p2.add(importOutgoingButton);
277                            form.add(generateTestsButton);
278                            form.add(generateMockBatteryButton);
279                            JPanel bottomPanel = new JPanel(new FlowLayout());
280                            form.add(p1);
281                            form.add(p2);
282                            bottomPanel.add(closeButton);
283                            add(form, BorderLayout.CENTER);
284                            add(bottomPanel, BorderLayout.SOUTH);
285                            pack();
286                    }
287            }
288    }