You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@netbeans.apache.org by GitBox <gi...@apache.org> on 2018/01/16 07:26:05 UTC

[GitHub] JaroslavTulach closed pull request #370: Support for Multi os engine in Wizard

JaroslavTulach closed pull request #370: Support for Multi os engine in Wizard
URL: https://github.com/apache/incubator-netbeans/pull/370
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/maven.htmlui/manifest.mf b/maven.htmlui/manifest.mf
index 245e4a092..6c6bde388 100644
--- a/maven.htmlui/manifest.mf
+++ b/maven.htmlui/manifest.mf
@@ -5,4 +5,4 @@ OpenIDE-Module-Provides: org.netbeans.modules.maven.archetype
 OpenIDE-Module-Requires: org.netbeans.api.templates.wizard
 OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/maven/htmlui/Bundle.properties
 OpenIDE-Module-Needs: org.netbeans.api.templates.wizard, javax.script.ScriptEngine.freemarker
-OpenIDE-Module-Specification-Version: 1.0
+OpenIDE-Module-Specification-Version: 1.1
diff --git a/maven.htmlui/nbproject/project.properties b/maven.htmlui/nbproject/project.properties
index 0d8a21c9c..e24d9b9b9 100644
--- a/maven.htmlui/nbproject/project.properties
+++ b/maven.htmlui/nbproject/project.properties
@@ -14,6 +14,6 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-javac.source=1.7
+javac.source=1.8
 javac.compilerargs=-Xlint -Xlint:-serial
 is.autoload=true
diff --git a/maven.htmlui/nbproject/project.xml b/maven.htmlui/nbproject/project.xml
index 4a9d4b350..c53fa1660 100644
--- a/maven.htmlui/nbproject/project.xml
+++ b/maven.htmlui/nbproject/project.xml
@@ -57,6 +57,15 @@
                     <code-name-base>org.netbeans.html.ko4j</code-name-base>
                     <run-dependency/>
                 </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.modules.extexecution.base</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>2</release-version>
+                        <specification-version>1.5</specification-version>
+                    </run-dependency>
+                </dependency>
                 <dependency>
                     <code-name-base>org.netbeans.modules.maven</code-name-base>
                     <build-prerequisite/>
@@ -82,7 +91,29 @@
                         <specification-version>9.8</specification-version>
                     </run-dependency>
                 </dependency>
+                <dependency>
+                    <code-name-base>org.openide.util.lookup</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>8.34</specification-version>
+                    </run-dependency>
+                </dependency>
             </module-dependencies>
+            <test-dependencies>
+                <test-type>
+                    <name>unit</name>
+                    <test-dependency>
+                        <code-name-base>org.netbeans.libs.junit4</code-name-base>
+                        <compile-dependency/>
+                    </test-dependency>
+                    <test-dependency>
+                        <code-name-base>org.netbeans.modules.nbjunit</code-name-base>
+                        <recursive/>
+                        <compile-dependency/>
+                    </test-dependency>
+                </test-type>
+            </test-dependencies>
             <public-packages/>
         </data>
     </configuration>
diff --git a/maven.htmlui/src/org/netbeans/modules/maven/htmlui/DeviceType.java b/maven.htmlui/src/org/netbeans/modules/maven/htmlui/DeviceType.java
new file mode 100644
index 000000000..510d2b10f
--- /dev/null
+++ b/maven.htmlui/src/org/netbeans/modules/maven/htmlui/DeviceType.java
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.netbeans.modules.maven.htmlui;
+
+import java.util.List;
+
+enum DeviceType {
+    DEVICE, SIMULATOR;
+
+    public static void listDevices(List<Device> collectTo) {
+        MacUtilities.listDevices(collectTo);
+    }
+}
diff --git a/maven.htmlui/src/org/netbeans/modules/maven/htmlui/DukeScriptWizard.java b/maven.htmlui/src/org/netbeans/modules/maven/htmlui/DukeScriptWizard.java
index da2b2e087..23084247d 100644
--- a/maven.htmlui/src/org/netbeans/modules/maven/htmlui/DukeScriptWizard.java
+++ b/maven.htmlui/src/org/netbeans/modules/maven/htmlui/DukeScriptWizard.java
@@ -20,6 +20,7 @@
 
 import java.awt.EventQueue;
 import java.io.File;
+import java.util.Iterator;
 import java.util.List;
 import javax.swing.JFileChooser;
 import org.netbeans.api.templates.TemplateRegistration;
@@ -32,15 +33,20 @@
 import net.java.html.json.OnPropertyChange;
 import net.java.html.json.OnReceive;
 import org.openide.filesystems.FileChooserBuilder;
+import org.openide.util.RequestProcessor;
 
 @Model(className = "WizardData", properties = {
     @Property(name = "current", type = String.class),
     @Property(name = "ok", type = boolean.class),
-    @Property(name = "msg", type = String.class),
+    @Property(name = "warning", type = String.class),
     @Property(name = "archetype", type = ArchetypeData.class),
     @Property(name = "archetypes", type = ArchetypeData.class, array = true),
     @Property(name = "android", type = boolean.class),
     @Property(name = "ios", type = boolean.class),
+    @Property(name = "iosMoe", type = boolean.class),
+    @Property(name = "iosRoboVM", type = boolean.class),
+    @Property(name = "availableSimulators", type = Device.class, array = true),
+    @Property(name = "selectedSimulator", type = Device.class),
     @Property(name = "web", type = boolean.class),
     @Property(name = "netbeans", type = boolean.class),
     @Property(name = "installExample", type = boolean.class),
@@ -85,25 +91,26 @@ static void init(WizardData data,
         File nbHome = new File(System.getProperty("netbeans.home"));
         data.setNbhome(nbHome.getParent());
 
-        final ArchetypeData crudArch = new ArchetypeData(
-                "crud4j-archetype",
-                "com.dukescript.archetype",
-                false,
-                "0.17",
-                "DukeScript CRUD Template", "Client-Server Application demonstrating communication and reuse of DataModels",
-                null
-        );
-        data.getArchetypes().add(crudArch);
         final ArchetypeData koArch = new ArchetypeData(
                 "knockout4j-archetype",
                 "com.dukescript.archetype",
                 true,
-                "0.17",
+                "0.20",
                 "Basic DukeScript Template", "Default skeletal application",
                 null
         );
         data.setArchetype(koArch);
         data.getArchetypes().add(koArch);
+        final ArchetypeData crudArch = new ArchetypeData(
+                "crud4j-archetype",
+                "com.dukescript.archetype",
+                false,
+                "0.20",
+                "DukeScript CRUD Template", "Client-Server Application demonstrating communication and reuse of DataModels",
+                null
+        );
+        data.getArchetypes().add(crudArch);
+        data.setIosMoe(true);
         String srvPath = Boolean.getBoolean("staging.archetypes") ? "stage" : "archetypes";
         data.loadArchetypes(srvPath);
         data.setAndroidSdkPath(MavenUtilities.getDefault().readAndroidSdkPath());
@@ -149,8 +156,13 @@ static String androidpath(boolean android) {
     }
 
     @ComputedProperty
-    static String iospath(boolean ios) {
-        return ios ? "client-ios" : null;
+    static String iospath(boolean iosRoboVM) {
+        return iosRoboVM ? "client-ios" : null;
+    }
+
+    @ComputedProperty
+    static String moepath(boolean iosMoe) {
+        return iosMoe ? "client-moe" : null;
     }
 
     @ComputedProperty
@@ -160,7 +172,7 @@ static String netbeanspath(boolean netbeans) {
 
     @ComputedProperty
     static String example(boolean installExample) {
-        return Boolean.valueOf(installExample).toString();
+        return Boolean.toString(installExample);
     }
 
     @ComputedProperty
@@ -169,7 +181,10 @@ static int errorCode(
             boolean android,
             String androidSdkPath,
             boolean netbeans,
-            boolean nbInstallationDefined
+            boolean nbInstallationDefined,
+            boolean ios, boolean iosMoe, boolean iosRoboVM,
+            Device selectedSimulator,
+            String warning
     ) {
         if (android && "platforms".equals(current)) { // NOI18N
             if (androidSdkPath == null) {
@@ -184,9 +199,25 @@ static int errorCode(
                 return 8;
             }
         }
+        if (warning != null) {
+            return 6;
+        }
+        if (ios) {
+            if (!iosMoe && !iosRoboVM) {
+                return 3;
+            }
+            if (selectedSimulator == null || MavenUtilities.getDefault().readMoeDevice() == null) {
+                return 4;
+            }
+        }
         return 0;
     }
 
+    @Function
+    static void cleanWarning(WizardData data) {
+        data.setWarning(null);
+    }
+
     @Function
     static void chooseAndroidSDK(final WizardData data) {
         EventQueue.invokeLater(new Runnable() {
@@ -227,6 +258,39 @@ static void verifyNbInstallationDefined(WizardData data) {
         data.setNbInstallationDefined(ok);
     }
 
+    @OnPropertyChange(value = "selectedSimulator")
+    static void deviceSelected(WizardData data) {
+        if (data.getSelectedSimulator() != null) {
+            MavenUtilities.getDefault().writeMoeDevice(data.getSelectedSimulator().getId());
+            String name = data.getSelectedSimulator().getName().replaceAll("\\(.*\\)", "").trim();
+            MavenUtilities.getDefault().writeRobovmDeviceName(name);
+        }
+    }
+    
+    private static final RequestProcessor DEVICES = new RequestProcessor("List iOS Devices");
+    @OnPropertyChange(value = "ios")
+    static void verifySimulator(WizardData data) {
+        final List<Device> arr = data.getAvailableSimulators();
+        DEVICES.post(() -> {
+            DeviceType.listDevices(arr);
+            String selectedDevice = MavenUtilities.getDefault().readMoeDevice();
+            Iterator<Device> it = arr.iterator();
+            while (it.hasNext()) {
+                Device d = it.next();
+                if (d.getType() != DeviceType.SIMULATOR) {
+                    if (d.getType() == null) {
+                        data.setWarning(d.getInfo());
+                    }
+                    it.remove();
+                    continue;
+                }
+                if (selectedDevice != null && selectedDevice.equals(d.getId())) {
+                    data.setSelectedSimulator(d);
+                }
+            }
+        });
+    }
+
     @Function
     static void defineNbInstallation(final WizardData data) {
         EventQueue.invokeLater(new Runnable() {
@@ -260,12 +324,15 @@ public boolean approve(File[] files) {
         });
     }
 
+    @Messages({
+        "ERR_NoData=Loaded data are corrupted!"
+    })
     @OnReceive(url = "http://dukescript.com/presenters/{path}", onError = "loadError")
     static void loadArchetypes(WizardData model, List<ArchetypeData> found) {
         if (!found.isEmpty()) {
             final ArchetypeData first = found.get(0);
             if (first == null || first.getName() == null) {
-                model.setMsg("Loaded data are corrupted");
+                model.setWarning(Bundle.ERR_NoData());
                 return;
             }
             model.getArchetypes().clear();
@@ -274,8 +341,12 @@ static void loadArchetypes(WizardData model, List<ArchetypeData> found) {
         }
     }
 
+    @Messages({
+        "ERR_NoNetwork=Warning: No network connection. This wizard is based on Maven.\n" +
+        "To work properly it needs a network connection. Please check your network settings: {0}\n",
+    })
     static void loadError(WizardData model, Throwable t) {
-        model.setMsg(t.getLocalizedMessage());
+        model.setWarning(Bundle.ERR_NoNetwork(t.getLocalizedMessage()));
     }
 
 }
diff --git a/maven.htmlui/src/org/netbeans/modules/maven/htmlui/MacUtilities.java b/maven.htmlui/src/org/netbeans/modules/maven/htmlui/MacUtilities.java
new file mode 100644
index 000000000..31d64f9b9
--- /dev/null
+++ b/maven.htmlui/src/org/netbeans/modules/maven/htmlui/MacUtilities.java
@@ -0,0 +1,129 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.netbeans.modules.maven.htmlui;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.Arrays;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import net.java.html.json.Model;
+import net.java.html.json.Property;
+import org.netbeans.api.extexecution.base.ProcessBuilder;
+import org.openide.util.NbBundle;
+
+@Model(className="Device", builder="assign", properties = {
+    @Property(name = "name", type = String.class),
+    @Property(name = "id", type = String.class),
+    @Property(name = "type", type = DeviceType.class),
+    @Property(name = "info", type = String.class)
+})
+final class MacUtilities {
+    private static final String ID_UNKNOWN = "0000-0000-0000";
+
+    private MacUtilities() {
+    }
+    
+    @NbBundle.Messages({
+        "# {0} - the error",
+        "ERR_CannotExecute=Cannot execute `instruments -s devices`: {0}",
+        "# {0} - the error",
+        "ERR_CannotParse=Unrecognized device: {0}",
+        "MSG_Loading=Loading devices..."
+    })
+    static void listDevices(List<Device> collectTo) {
+        collectTo.clear();
+        Device loading = new Device().assignId(ID_UNKNOWN).
+                assignName(Bundle.MSG_Loading()).
+                assignInfo(Bundle.MSG_Loading());
+        collectTo.add(loading);
+
+        ProcessBuilder pb = ProcessBuilder.getLocal();
+        pb.setExecutable("instruments");
+        pb.setArguments(Arrays.asList("-s", "devices"));
+        pb.setRedirectErrorStream(true);
+        Process p;
+        try {
+            p = pb.call();
+        } catch (IOException ex) {
+            collectTo.clear();
+            collectTo.add(
+                new Device().assignId(ID_UNKNOWN).
+                assignName("unknown").
+                assignInfo(Bundle.ERR_CannotExecute(ex.getLocalizedMessage()))
+            );
+            return;
+        }
+
+        
+        final InputStream is = p.getInputStream();
+        parseDevices(collectTo, is);
+        p.destroy();
+        collectTo.remove(loading);
+    }
+
+    static List<Device> parseDevices(List<Device> collectTo, final InputStream is) {
+        Pattern pattern = Pattern.compile("\\[([0-9A-Fa-f\\-]+)\\]");
+
+        BufferedReader r = new BufferedReader(new InputStreamReader(is));
+        for (int at = collectTo.size();;) {
+            String l;
+            try {
+                l = r.readLine();
+            } catch (IOException ex) {
+                collectTo.add(new Device().assignId(ID_UNKNOWN).
+                        assignName("unknown").
+                        assignInfo(Bundle.ERR_CannotExecute(ex.getLocalizedMessage()))
+                );
+                break;
+            }
+            if (l == null) {
+                break;
+            }
+            if (l.indexOf('[') == -1 || l.indexOf(']') == -1) {
+                continue;
+            }
+            Matcher m = pattern.matcher(l);
+            if (m.find()) {
+                String id = m.group(1);
+                String nameVersion = l.substring(0, m.start()).trim();
+                String rest = l.substring(m.end());
+                Device d = new Device().
+                        assignName(nameVersion).
+                        assignId(id);
+                if (rest.contains("imulator")) {
+                    d.assignType(DeviceType.SIMULATOR);
+                } else {
+                    d.assignType(DeviceType.DEVICE);
+                }
+                collectTo.add(at++, d);
+            } else {
+                Device notRecognized = new Device().
+                        assignId(ID_UNKNOWN).
+                        assignName("broken").
+                        assignInfo(Bundle.ERR_CannotParse(l));
+                collectTo.add(collectTo.size(), notRecognized);
+            }
+        }
+        return collectTo;
+    }
+}
diff --git a/maven.htmlui/src/org/netbeans/modules/maven/htmlui/MavenUtilities.java b/maven.htmlui/src/org/netbeans/modules/maven/htmlui/MavenUtilities.java
index 8efddb744..f7dc44ab0 100644
--- a/maven.htmlui/src/org/netbeans/modules/maven/htmlui/MavenUtilities.java
+++ b/maven.htmlui/src/org/netbeans/modules/maven/htmlui/MavenUtilities.java
@@ -19,6 +19,7 @@
 package org.netbeans.modules.maven.htmlui;
 
 import java.io.File;
+import java.io.FileWriter;
 import java.io.IOException;
 import java.io.StringReader;
 import java.nio.file.NoSuchFileException;
@@ -46,6 +47,8 @@
     private static final Logger LOG = Logger.getLogger(MavenUtilities.class.getName());
     private static final String DEFINITION = "android.sdk.path";
     private static final String NBDEFINITION = "netbeans.installation";
+    private static final String MOEDEFINITION = "moe.launcher.simulators";
+    private static final String ROBOVMDEFINITION = "robovm.iosDeviceName";
 
     static final String HEADER_XML = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
     static final String HEADER_SETTINGS = "<settings xmlns=\"http://maven.apache.org/SETTINGS/1.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"
@@ -64,6 +67,9 @@ String readAndroidSdkPath() {
 
     private String readProperty(final String tag) {
         try {
+            if (!this.settings.isFile()) {
+                return null;
+            }
             DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
             DocumentBuilder dBuilder;
             dBuilder = dbFactory.newDocumentBuilder();
@@ -99,17 +105,27 @@ private void writeProperty(String name, String value) {
                 dBuilder = dbFactory.newDocumentBuilder();
                 Document settingsDoc = dBuilder.parse(this.settings);
                 settingsDoc.getDocumentElement().normalize();
-                NodeList profiles = settingsDoc.getElementsByTagName("profiles");
+                NodeList profilesNode = settingsDoc.getElementsByTagName("profiles");
                 Node parent = null;
-                if (profiles.getLength() > 0) {
-                    parent = profiles.item(0);
+                if (profilesNode.getLength() > 0) {
+                    parent = profilesNode.item(0);
                 } else {
                     parent = settingsDoc.createElement("profiles");
-                    settingsDoc.appendChild(parent);
+                    settingsDoc.getDocumentElement().appendChild(parent);
                 }
 
                 Document doc = parent.getOwnerDocument();
 
+                NodeList profiles = parent.getChildNodes();
+                for (int i = 0; i < profiles.getLength();) {
+                    Node profileNode = profiles.item(i);
+                    if (name.equals(profileId(profileNode))) {
+                        parent.removeChild(profileNode);
+                    } else {
+                        i++;
+                    }
+                }
+
                 Node fragmentNode = DocumentBuilderFactory
                         .newInstance()
                         .newDocumentBuilder().parse(
@@ -131,22 +147,10 @@ private void writeProperty(String name, String value) {
                         + singleProfile(name, value)
                         + "  </profiles>\n"
                         + FOOTER_SETTINGS;
-                Document newDoc = DocumentBuilderFactory
-                        .newInstance()
-                        .newDocumentBuilder().newDocument();
-                Node fragmentNode = DocumentBuilderFactory
-                        .newInstance()
-                        .newDocumentBuilder().parse(
-                                new InputSource(new StringReader(dump)))
-                        .getDocumentElement();
-                newDoc.adoptNode(fragmentNode);
-                                newDoc.getDocumentElement().normalize();
-                TransformerFactory transformerFactory = TransformerFactory.newInstance();
-                Transformer transformer = transformerFactory.newTransformer();
-                DOMSource source = new DOMSource(newDoc);
-                StreamResult result = new StreamResult(settings);
-                transformer.setOutputProperty(OutputKeys.INDENT, "yes");
-                transformer.transform(source, result);
+
+                FileWriter w = new FileWriter(settings);
+                w.write(dump);
+                w.close();
             }
         } catch (IOException ex) {
             LOG.log(Level.INFO, "Cannot modify " + settings, ex);
@@ -179,12 +183,35 @@ private static String singleProfile(String name, String path) {
                 + "    </profile>\n";
     }
 
+    private static String profileId(Node profile) {
+        NodeList children = profile.getChildNodes();
+        for (int i = 0; i < children.getLength(); i++) {
+            Node ch = children.item(i);
+            if (ch.getNodeName().equals("id")) {
+                return ch.getTextContent();
+            }
+        }
+        return null;
+    }
+
     void writeNetBeansInstallation(String path) {
-        writeProperty("netbeans.installation", path);
+        writeProperty(NBDEFINITION, path);
     }
 
     String readNetBeansInstallation() {
         return readProperty(NBDEFINITION);
     }
 
+    void writeMoeDevice(String id) {
+        writeProperty(MOEDEFINITION, id);
+    }
+
+    String readMoeDevice() {
+        return readProperty(MOEDEFINITION);
+    }
+
+    void writeRobovmDeviceName(String name) {
+        writeProperty(ROBOVMDEFINITION, name);
+    }
+
 }
diff --git a/maven.htmlui/src/org/netbeans/modules/maven/htmlui/dukeScriptWizard.html b/maven.htmlui/src/org/netbeans/modules/maven/htmlui/dukeScriptWizard.html
index 192a57f29..8c3724139 100644
--- a/maven.htmlui/src/org/netbeans/modules/maven/htmlui/dukeScriptWizard.html
+++ b/maven.htmlui/src/org/netbeans/modules/maven/htmlui/dukeScriptWizard.html
@@ -33,7 +33,7 @@
 
             #locations{
                 display: table;
-            }       
+            }
 
             .form-field{
                 display: table-row;
@@ -45,6 +45,8 @@
 
             .error{
                 color: red;
+                position: absolute;
+                bottom: 10px;
             }
 
             label.checkbox-label input[type=checkbox]{
@@ -74,14 +76,28 @@
                         <label for="android" >Run on Android devices</label>
                 </div>
                 <div data-bind="if: errorCode()===7">
-                    <label for="androidSdkPath">Running on Android devices requires an Android SDK. Please specify the path to the directory containing the platform-tools folder:</label> 
+                    <label for="androidSdkPath">Running on Android devices requires an Android SDK. Please specify the path to the directory containing the platform-tools folder:</label>
                     <input type="text" class="form-field" id="androidSdkPath" data-bind="textInput: androidSdkPath"/>
                     <button data-bind="click: chooseAndroidSDK">Browse...</button>
                 </div>
                 <div >
-                    <label class="checkbox-label">
-                        <input id="ios" type="checkbox" data-bind="checked: ios"/>
-                        <label for="ios">Run on iOS devices (Requires a Mac)</label> 
+                    <label class="checkbox-label" for="ios">
+                    <input id="ios" type="checkbox" data-bind="checked: ios"/>
+                    Run on iOS devices (Requires a Mac)</label>
+                    <div data-bind="visible: ios" style="position: relative; left: 3em">
+                        <div>
+                            <label class="checkbox-label" for="moe">
+                            <input id="moe" type="checkbox" data-bind="checked: iosMoe"/>
+                            Use Intel's Multi OS Engine</label>
+                        </div>
+                        <div>
+                            <label class="checkbox-label" for="robovm">
+                            <input id="robovm" type="checkbox" data-bind="checked: iosRoboVM"/>
+                            Use Mobidevelop RoboVM</label>
+                        </div>
+                        <select data-bind='options: availableSimulators, optionsText: "name", value: selectedSimulator, optionsCaption: "Choose a device..."'>
+                        </select>
+                    </div>
                 </div>
                 <div >
                     <label class="checkbox-label">
@@ -94,7 +110,7 @@
                         <label for="netbeans">Run as a NetBeans Plugin</label>
                 </div>
                 <div data-bind="if: errorCode()===8">
-                    <label for="defineNbInstallation">Please select your NetBeans Installation Directory: </label> 
+                    <label for="defineNbInstallation">Please select your NetBeans Installation Directory: </label>
                     <input type="text" class="form-field" id="defineNbInstallation" data-bind="textInput: nbhome"/>
                     <button data-bind="click: defineNbInstallation">Browse...</button>
                 </div>
@@ -108,7 +124,7 @@
                         <input type="radio" name="archetype" data-bind="attr: {id: artifactId}, value: $data, checked: $root.archetype" />
                         <label data-bind="attr: {for: artifactId}, text: name"></label>
                         <br>
-                        </div>  
+                        </div>
                         <div data-bind="with: archetype">
                             <h4>Description:</h4>
                             <span data-bind="text: description"></span>
@@ -119,16 +135,10 @@ <h4>Description:</h4>
                             </div>
                         </div>
                         <br><br>
-                        <div data-bind="visible: msg" class="error">
-                            Warning: No network connection.
-                            This wizard is based on Maven. 
-                            To work properly it needs a network connection.
-                            Please check your network settings.
-                        </div>
-                        </section>
+            </section>
 
 
-                        <section data-bind="step: { 'id' : 'summary', text : 'What will be created?' }" >
+            <section data-bind="step: { 'id' : 'summary', text : 'What will be created?' }" >
                             <p>
                                 Let's generate a project from following archetype:
                             </p>
@@ -137,15 +147,23 @@ <h4>Description:</h4>
                                 <li><b>groupId</b>: <span data-bind="text: groupId"></span></li>
                                 <li><b>version</b>: <span data-bind="text: version"></span></li>
                             </ul>
-                        </section>
-                </div>
-                <!-- display the error message -->
-                <div data-bind="visible: errorCode() === 1" style="color: red">
-                    Please, check the OK checkbox!
-                </div>
-                <div data-bind="visible: errorCode() === 2" style="color: red">
-                    Please, fill in the input field!
-                </div>
+            </section>
+
+
+        </div>
+
 
-                </body>
-                </html>
+        <!-- display the error message -->
+        <div data-bind="visible: errorCode() === 3" class="error">
+            Choose at least one: <b>MOE</b> or <b>RoboVM</b>!
+        </div>
+        <div data-bind="visible: errorCode() === 4" class="error">
+            Choose a device to define <b>moe.launcher.simulators</b> property in
+            <code>.m2/settings.xml</code> file.
+        </div>
+        <div data-bind="visible: errorCode() === 6" class="error">
+            <span data-bind="text: warning"></span>
+            <a href="#" data-bind="click: cleanWarning">Dismiss</a>
+        </div>
+    </body>
+</html>
diff --git a/maven.htmlui/src/org/netbeans/modules/maven/htmlui/dukescript.archetype b/maven.htmlui/src/org/netbeans/modules/maven/htmlui/dukescript.archetype
index 285974ebf..19e7bfd93 100644
--- a/maven.htmlui/src/org/netbeans/modules/maven/htmlui/dukescript.archetype
+++ b/maven.htmlui/src/org/netbeans/modules/maven/htmlui/dukescript.archetype
@@ -18,6 +18,6 @@
 
 archetypeArtifactId=knockout4j-archetype
 archetypeGroupId=com.dukescript.archetype
-archetypeVersion=0.17
+archetypeVersion=0.20
 archetypeBuild=true
 archetypeOpen=client/src/main/java/.*/DataModel.java,client/src/main/webapp/pages/index.html
diff --git a/maven.htmlui/test/unit/src/org/netbeans/modules/maven/htmlui/MacUtilitiesTest.java b/maven.htmlui/test/unit/src/org/netbeans/modules/maven/htmlui/MacUtilitiesTest.java
new file mode 100644
index 000000000..69722c1f8
--- /dev/null
+++ b/maven.htmlui/test/unit/src/org/netbeans/modules/maven/htmlui/MacUtilitiesTest.java
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.netbeans.modules.maven.htmlui;
+
+import java.io.ByteArrayInputStream;
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+public class MacUtilitiesTest {
+
+    public MacUtilitiesTest() {
+    }
+
+    @Test
+    public void testListDevices() throws Exception {
+        String output = ""
+                + "Known Devices:\n" +
+"mymac [2012EC47-B54A-9930-A400-C71F0FDF0EF0]\n" +
+"iPhone 6s Plus (11.2) [43641F54-4845-19147CB4FDE2] (Simulator)\n" +
+"iPhone 8 Plus (11.2) + Apple Watch Series 3 - 42mm (4.2) [76199641-279E-411E-8751-EA504D6B4DA3] (Simulator)\n" +
+"";
+        List<Device> result = new ArrayList<>();
+        MacUtilities.parseDevices(result, new ByteArrayInputStream(output.getBytes("UTF-8")));
+        assertEquals("Found three devices", 3, result.size());
+        assertEquals("mymac", result.get(0).getName());
+        assertEquals("iPhone 6s Plus (11.2)", result.get(1).getName());
+        assertEquals("iPhone 8 Plus (11.2) + Apple Watch Series 3 - 42mm (4.2)", result.get(2).getName());
+
+        assertEquals(DeviceType.DEVICE, result.get(0).getType());
+        assertEquals(DeviceType.SIMULATOR, result.get(1).getType());
+        assertEquals(DeviceType.SIMULATOR, result.get(2).getType());
+    }
+
+    @Test
+    public void testError() throws Exception {
+        FilterInputStream is = new FilterInputStream(null) {
+            @Override
+            public int read(byte[] b, int off, int len) throws IOException {
+                throw new IOException("Artificial error");
+            }
+        };
+        List<Device> result = new ArrayList<>();
+        MacUtilities.parseDevices(result, is);
+        assertEquals("One element", 1, result.size());
+        assertEquals("No type signals error", null, result.get(0).getType());
+        assertEquals("Cannot execute `instruments -s devices`: Artificial error", result.get(0).getInfo());
+    }
+}
diff --git a/maven.htmlui/test/unit/src/org/netbeans/modules/maven/htmlui/MavenUtilitiesTest.java b/maven.htmlui/test/unit/src/org/netbeans/modules/maven/htmlui/MavenUtilitiesTest.java
new file mode 100644
index 000000000..9b1647ac7
--- /dev/null
+++ b/maven.htmlui/test/unit/src/org/netbeans/modules/maven/htmlui/MavenUtilitiesTest.java
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.netbeans.modules.maven.htmlui;
+
+import java.io.File;
+import java.io.FileWriter;
+import org.junit.Test;
+import org.netbeans.junit.NbTestCase;
+
+public class MavenUtilitiesTest extends NbTestCase {
+
+    public MavenUtilitiesTest(String n) {
+        super(n);
+    }
+
+    @Test
+    public void testFewAdditionsToSettings() throws Exception {
+        clearWorkDir();
+        File settings = new File(getWorkDir(), "set.xml");
+        assertFalse("settings file doesn't exist yet", settings.isFile());
+
+        MavenUtilities u = new MavenUtilities(settings);
+        assertNull("No moe device", u.readMoeDevice());
+
+        u.writeMoeDevice("3465");
+        assertEquals("3465", u.readMoeDevice());
+
+        u.writeMoeDevice("6543");
+        assertEquals("6543", u.readMoeDevice());
+    }
+
+    @Test
+    public void testStandardContentOfSettings() throws Exception {
+        clearWorkDir();
+        File settings = new File(getWorkDir(), "setts.xml");
+        try (FileWriter w = new FileWriter(settings)) {
+            w.write(
+                "<settings xmlns=\"http://maven.apache.org/SETTINGS/1.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n" +
+                "          xsi:schemaLocation=\"http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd\">\n" +
+                "    <!--proxies>\n" +
+                "        <proxy>\n" +
+                "            <host>my.proxy.host</host>\n" +
+                "        </proxy>\n" +
+                "    </proxies-->\n" +
+                "\n" +
+                "    <!--pluginGroups>\n" +
+                "        <pluginGroup>org.codehaus.mojo</pluginGroup>\n" +
+                "    </pluginGroups-->\n" +
+                "</settings>"
+            );
+        }
+
+        assertTrue("settings file exists", settings.isFile());
+
+        MavenUtilities u = new MavenUtilities(settings);
+        assertNull("No moe device", u.readMoeDevice());
+
+        u.writeMoeDevice("3465");
+        assertEquals("3465", u.readMoeDevice());
+
+        u.writeMoeDevice("6543");
+        assertEquals("6543", u.readMoeDevice());
+    }
+
+}


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@netbeans.apache.org
For additional commands, e-mail: notifications-help@netbeans.apache.org

For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists