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/08/01 18:27:11 UTC

[GitHub] junichi11 closed pull request #644: Merge the 2ndDonation branch into the master branch

junichi11 closed pull request #644: Merge the 2ndDonation branch into the master branch
URL: https://github.com/apache/incubator-netbeans/pull/644
 
 
   

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/api.knockout/apichanges.xml b/api.knockout/apichanges.xml
new file mode 100644
index 0000000000..1a13034c94
--- /dev/null
+++ b/api.knockout/apichanges.xml
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    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.
+
+-->
+<?xml-stylesheet type="text/xml" href="../nbbuild/javadoctools/apichanges.xsl"?>
+<!DOCTYPE apichanges PUBLIC "-//NetBeans//DTD API changes list 1.0//EN" "../nbbuild/javadoctools/apichanges.dtd">
+
+
+<apichanges>
+
+    <!-- First, a list of API names you may use: -->
+<apidefs>
+   <apidef name="ko">Knockout Integration API</apidef>
+</apidefs>
+
+    <!-- ACTUAL CHANGES BEGIN HERE: -->
+
+<changes>
+    <change id="bindings-function">
+        <api name="ko"/>
+        <summary>Introducing Bindings.function(String name)</summary>
+        <version major="1" minor="1" />
+        <date day="20" month="3" year="2015"/>
+        <author login="rsvitanic"/>
+        <compatibility addition="yes" modification="no" semantic="compatible" source="compatible" binary="compatible"/>
+        <description>
+            <p>
+                Added method Bindings.function(String name) which generates an empty function property.
+            </p>
+        </description>
+        <issue number="251075"/>
+    </change>
+    <change id="branding.token">
+        <api name="ko"/>
+        <summary>Introduced</summary>
+        <version major="1" minor="0" />
+        <date day="24" month="12" year="2014"/>
+        <author login="rsvitanic"/>
+        <compatibility addition="yes"/>
+        <description>
+            <p>
+                Initial version of Knockout Integration API published.
+            </p>
+        </description>
+        <issue number="231131"/>
+    </change>
+</changes>
+
+    <htmlcontents>
+    <head>
+      <title>Change History for the NetBeans Knockout Integration API</title>
+      <link rel="stylesheet" href="prose.css" type="text/css"/>
+    </head>
+    <body>
+
+<p class="overviewlink"><a href="overview-summary.html">Overview</a></p>
+
+<h1>Introduction</h1>
+
+<p>This document lists changes made to the <a href="@TOP@/index.html">Knockout Integration</a> API.</p>
+
+<!-- The actual lists of changes, as summaries and details: -->
+      <hr/>
+      <standard-changelists module-code-name="org.netbeans.api.knockout"/>
+
+      <hr/><p>@FOOTER@</p>
+
+    </body>
+  </htmlcontents>
+
+</apichanges>
diff --git a/api.knockout/arch.xml b/api.knockout/arch.xml
new file mode 100644
index 0000000000..0903b52484
--- /dev/null
+++ b/api.knockout/arch.xml
@@ -0,0 +1,1135 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    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.
+
+-->
+<!DOCTYPE api-answers PUBLIC "-//NetBeans//DTD Arch Answers//EN" "../nbbuild/antsrc/org/netbeans/nbbuild/Arch.dtd" [
+  <!ENTITY api-questions SYSTEM "../nbbuild/antsrc/org/netbeans/nbbuild/Arch-api-questions.xml">
+]>
+
+<api-answers
+  question-version="1.29"
+  author="yourname@netbeans.org"
+>
+
+  &api-questions;
+
+
+<!--
+        <question id="arch-overall" when="init">
+            Describe the overall architecture.
+            <hint>
+            What will be API for
+            <a href="http://wiki.netbeans.org/API_Design#Separate_API_for_clients_from_support_API">
+                clients and what support API</a>?
+            What parts will be pluggable?
+            How will plug-ins be registered? Please use <code>&lt;api type="export"/&gt;</code>
+            to describe your general APIs and specify their
+            <a href="http://wiki.netbeans.org/API_Stability#Private">
+            stability categories</a>.
+            If possible please provide simple diagrams.
+            </hint>
+        </question>
+-->
+ <answer id="arch-overall">
+  <p>
+   Java <a href="@TOP@/org/netbeans/spi/knockout/Bindings.html">model class</a>
+   to describe JSON-like Knockout bindings and register
+   <a href="@TOP@/org/netbeans/spi/knockout/BindingsProvider.html">a provider</a>
+   used by the editor infrastructure to query for the model.
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="arch-quality" when="init">
+            How will the <a href="http://www.netbeans.org/community/guidelines/q-evangelism.html">quality</a>
+            of your code be tested and
+            how are future regressions going to be prevented?
+            <hint>
+            What kind of testing do
+            you want to use? How much functionality, in which areas,
+            should be covered by the tests? How you find out that your
+            project was successful?
+            </hint>
+        </question>
+-->
+ <answer id="arch-quality">
+  <p>
+   There are some unit tests. The integration with editor is then tested
+   manually.
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="arch-time" when="init">
+            What are the time estimates of the work?
+            <hint>
+            Please express your estimates of how long the design, implementation,
+            stabilization are likely to last. How many people will be needed to
+            implement this and what is the expected milestone by which the work should be
+            ready?
+            </hint>
+        </question>
+-->
+ <answer id="arch-time">
+  <p>
+   Let's offer this API for 8.1 release.
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="arch-usecases" when="init">
+            <hint>
+                Content of this answer will be displayed as part of page at
+                http://www.netbeans.org/download/dev/javadoc/usecases.html
+                You can use tags &lt;usecase name="name&gt; regular html description &lt;/usecase&gt;
+                and if you want to use an URL you can prefix if with @TOP@ to begin
+                at the root of your javadoc
+            </hint>
+
+            Describe the main <a href="http://wiki.netbeans.org/API_Design#The_Importance_of_Being_Use_Case_Oriented">
+            use cases</a> of the new API. Who will use it under
+            what circumstances? What kind of code would typically need to be written
+            to use the module?
+        </question>
+-->
+ <answer id="arch-usecases">
+     <usecase id="register" name="Register a provider">
+<p>
+This is the code to register a sample <a href="@TOP@/org/netbeans/spi/knockout/BindingsProvider.html">provider</a>:
+</p>
+<pre>
+{@code @}ServiceProvider(service = BindingsProvider.class)
+public class SampleBindingsProvider implements {@link org.netbeans.spi.knockout.BindingsProvider} {
+    {@code @Override}
+    public void findBindings(FileObject htmlFile, Response r) {
+        Bindings tweet = Bindings.create("Tweet").
+                stringProperty("from_user", false).
+                intProperty("from_user_id", false);
+
+        Bindings tweeters = Bindings.create("Tweeters").
+                stringProperty("name", false).
+                stringProperty("userNames", true);
+
+        Bindings twitterClient = Bindings.create("TwitterClient");
+        twitterClient.
+                stringProperty("activeTweetersName", false).
+                stringProperty("activeTweeters", true).
+                stringProperty("userNameToAdd", false).
+                booleanProperty("loading", false).
+                modelProperty("currentTweets", tweet, true).
+                modelProperty("savedLists", tweeters, true);
+
+        r.applyBindings(twitterClient);
+    }
+}
+</pre>
+
+<p>
+This sample has been used when testing the module.
+</p>
+     </usecase>
+ </answer>
+
+
+
+<!--
+        <question id="arch-what" when="init">
+            What is this project good for?
+            <hint>
+            Please provide here a few lines describing the project,
+            what problem it should solve, provide links to documentation,
+            specifications, etc.
+            </hint>
+        </question>
+-->
+ <answer id="arch-what">
+     <api name="api.knockout" category="official" group="java" type="export">
+     API for registering additional <a href="@TOP@/org/netbeans/spi/knockout/BindingsProvider.html">provider</a>s
+     that help the HTML editor to offer better code completion for certain HTML
+     files based on the produced description of a
+     <a href="@TOP@/org/netbeans/spi/knockout/Bindings.html">JSON-like structure</a>.
+     </api>
+ </answer>
+
+
+
+<!--
+        <question id="arch-where" when="impl">
+            Where one can find sources for your module?
+            <hint>
+                Please provide link to the Hg web client at
+                http://hg.netbeans.org/
+                or just use tag defaultanswer generate='here'
+            </hint>
+        </question>
+-->
+ <answer id="arch-where">
+  <defaultanswer generate='here' />
+ </answer>
+
+
+
+<!--
+        <question id="compat-deprecation" when="init">
+            How the introduction of your project influences functionality
+            provided by previous version of the product?
+            <hint>
+            If you are planning to deprecate/remove/change any existing APIs,
+            list them here accompanied with the reason explaining why you
+            are doing so.
+            </hint>
+        </question>
+-->
+ <answer id="compat-deprecation">
+  <p>
+   XXX no answer for compat-deprecation
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="compat-i18n" when="impl">
+            Is your module correctly internationalized?
+            <hint>
+            Correct internationalization means that it obeys instructions
+            at <a href="http://www.netbeans.org/download/dev/javadoc/org-openide-modules/org/openide/modules/doc-files/i18n-branding.html">
+            NetBeans I18N pages</a>.
+            </hint>
+        </question>
+-->
+ <answer id="compat-i18n">
+  <p>
+   XXX no answer for compat-i18n
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="compat-standards" when="init">
+            Does the module implement or define any standards? Is the
+            implementation exact or does it deviate somehow?
+        </question>
+-->
+ <answer id="compat-standards">
+  <p>
+   XXX no answer for compat-standards
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="compat-version" when="impl">
+            Can your module coexist with earlier and future
+            versions of itself? Can you correctly read all old settings? Will future
+            versions be able to read your current settings? Can you read
+            or politely ignore settings stored by a future version?
+
+            <hint>
+            Very helpful for reading settings is to store version number
+            there, so future versions can decide whether how to read/convert
+            the settings and older versions can ignore the new ones.
+            </hint>
+        </question>
+-->
+ <answer id="compat-version">
+  <p>
+   XXX no answer for compat-version
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="dep-jre" when="final">
+            Which version of JRE do you need (1.2, 1.3, 1.4, etc.)?
+            <hint>
+            It is expected that if your module runs on 1.x that it will run
+            on 1.x+1 if no, state that please. Also describe here cases where
+            you run different code on different versions of JRE and why.
+            </hint>
+        </question>
+-->
+ <answer id="dep-jre">
+  <p>
+   XXX no answer for dep-jre
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="dep-jrejdk" when="final">
+            Do you require the JDK or is the JRE enough?
+        </question>
+-->
+ <answer id="dep-jrejdk">
+  <p>
+   XXX no answer for dep-jrejdk
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="dep-nb" when="init">
+            What other NetBeans projects and modules does this one depend on?
+            <hint>
+            Depending on other NetBeans projects influnces the ability of
+            users of your work to customize their own branded version of
+            NetBeans by enabling and disabling some modules. Too
+            much dependencies restrict this kind of customization. If that
+            is your case, then you may want to split your functionality into
+            pieces of autoload, eager and regular modules which can be
+            enabled independently. Usually the answer to this question
+            is generated from your <code>project.xml</code> file, but
+            if it is not guessed correctly, you can suppress it by
+            specifying &lt;defaultanswer generate="none"/&gt; and
+            write here your own. Please describe such projects as imported APIs using
+            the <code>&lt;api name="identification" type="import or export" category="stable" url="where is the description" /&gt;</code>.
+            By doing this information gets listed in the summary page of your
+            javadoc.
+            </hint>
+        </question>
+-->
+ <answer id="dep-nb">
+  <defaultanswer generate='here' />
+ </answer>
+
+
+
+<!--
+        <question id="dep-non-nb" when="init">
+            What other projects outside NetBeans does this one depend on?
+
+            <hint>
+            Depending on 3rd party libraries is always problematic,
+            especially if they are not open source, as that complicates
+            the licensing scheme of NetBeans. Please enumerate your
+            external dependencies here, so it is correctly understood since
+            the begining what are the legal implications of your project.
+            Also please note that
+            some non-NetBeans projects are packaged as NetBeans modules
+            (see <a href="http://libs.netbeans.org/">libraries</a>) and
+            it is preferred to use this approach when more modules may
+            depend and share such third-party libraries.
+            </hint>
+        </question>
+-->
+ <answer id="dep-non-nb">
+  <p>
+   XXX no answer for dep-non-nb
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="dep-platform" when="init">
+            On which platforms does your module run? Does it run in the same
+            way on each?
+            <hint>
+            If you plan any dependency on OS or any usage of native code,
+            please describe why you are doing so and describe how you envision
+            to enforce the portability of your code.
+            Please note that there is a support for <a href="http://www.netbeans.org/download/dev/javadoc/org-openide-modules/org/openide/modules/doc-files/api.html#how-os-specific">OS conditionally
+            enabled modules</a> which together with autoload/eager modules
+            can allow you to enable to provide the best OS aware support
+            on certain OSes while providing compatibility bridge on the not
+            supported ones.
+            Also please list the supported
+            OSes/HW platforms and mentioned the lovest version of JDK required
+            for your project to run on. Also state whether JRE is enough or
+            you really need JDK.
+            </hint>
+        </question>
+-->
+ <answer id="dep-platform">
+  <p>
+   XXX no answer for dep-platform
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="deploy-dependencies" when="final">
+            What do other modules need to do to declare a dependency on this one,
+            in addition to or instead of the normal module dependency declaration
+            (e.g. tokens to require)?
+            <hint>
+                Provide a sample of the actual lines you would add to a module manifest
+                to declare a dependency, for example OpenIDE-Module-Requires: some.token.
+                If other modules should not depend on this module, or should just use a
+                simple regular module dependency, you can just answer "nothing". If you
+                intentionally expose a semistable API to clients using implementation
+                dependencies, you should mention that here (but there is no need to give
+                an example of usage).
+            </hint>
+        </question>
+-->
+ <answer id="deploy-dependencies">
+  <p>
+   XXX no answer for deploy-dependencies
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="deploy-jar" when="impl">
+            Do you deploy just module JAR file(s) or other files as well?
+            <hint>
+            Usually a module consist of one JAR file (perhaps with Class-Path
+            extensions) and also a configuration file that enables it. If you
+            have any other files, use
+            &lt;api group="java.io.File" name="yourname" type="export" category="friend"&gt;...&lt;/api&gt;
+            to define the location, name and stability of your files (of course
+            changing "yourname" and "friend" to suit your needs).
+
+            If it uses more than one JAR, describe where they are located, how
+            they refer to each other.
+            If it consist of module JAR(s) and other files, please describe
+            what is their purpose, why other files are necessary. Please
+            make sure that installation/uninstallation leaves the system
+            in state as it was before installation.
+            </hint>
+        </question>
+-->
+ <answer id="deploy-jar">
+  <p>
+   XXX no answer for deploy-jar
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="deploy-nbm" when="impl">
+            Can you deploy an NBM via the Update Center?
+            <hint>
+            If not why?
+            </hint>
+        </question>
+-->
+ <answer id="deploy-nbm">
+  <p>
+   XXX no answer for deploy-nbm
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="deploy-packages" when="init">
+            Are packages of your module made inaccessible by not declaring them
+            public?
+
+            <hint>
+            By default NetBeans build harness treats all packages are private.
+            If you export some of them - either as public or friend packages,
+            you should have a reason. If the reason is described elsewhere
+            in this document, you can ignore this question.
+            </hint>
+        </question>
+-->
+ <answer id="deploy-packages">
+  <p>
+   XXX no answer for deploy-packages
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="deploy-shared" when="final">
+            Do you need to be installed in the shared location only, or in the user directory only,
+            or can your module be installed anywhere?
+            <hint>
+            Installation location shall not matter, if it does explain why.
+            Consider also whether <code>InstalledFileLocator</code> can help.
+            </hint>
+        </question>
+-->
+ <answer id="deploy-shared">
+  <p>
+   XXX no answer for deploy-shared
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="exec-ant-tasks" when="impl">
+            Do you define or register any ant tasks that other can use?
+
+            <hint>
+            If you provide an ant task that users can use, you need to be very
+            careful about its syntax and behaviour, as it most likely forms an
+	          API for end users and as there is a lot of end users, their reaction
+            when such API gets broken can be pretty strong.
+            </hint>
+        </question>
+-->
+ <answer id="exec-ant-tasks">
+  <p>
+   XXX no answer for exec-ant-tasks
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="exec-classloader" when="impl">
+            Does your code create its own class loader(s)?
+            <hint>
+            A bit unusual. Please explain why and what for.
+            </hint>
+        </question>
+-->
+ <answer id="exec-classloader">
+  <p>
+   XXX no answer for exec-classloader
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="exec-component" when="impl">
+            Is execution of your code influenced by any (string) property
+            of any of your components?
+
+            <hint>
+            Often <code>JComponent.getClientProperty</code>, <code>Action.getValue</code>
+            or <code>PropertyDescriptor.getValue</code>, etc. are used to influence
+            a behavior of some code. This of course forms an interface that should
+            be documented. Also if one depends on some interface that an object
+            implements (<code>component instanceof Runnable</code>) that forms an
+            API as well.
+            </hint>
+        </question>
+-->
+ <answer id="exec-component">
+  <p>
+   XXX no answer for exec-component
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="exec-introspection" when="impl">
+            Does your module use any kind of runtime type information (<code>instanceof</code>,
+            work with <code>java.lang.Class</code>, etc.)?
+            <hint>
+            Check for cases when you have an object of type A and you also
+            expect it to (possibly) be of type B and do some special action. That
+            should be documented. The same applies on operations in meta-level
+            (Class.isInstance(...), Class.isAssignableFrom(...), etc.).
+            </hint>
+        </question>
+-->
+ <answer id="exec-introspection">
+  <p>
+   XXX no answer for exec-introspection
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="exec-privateaccess" when="final">
+            Are you aware of any other parts of the system calling some of
+            your methods by reflection?
+            <hint>
+            If so, describe the "contract" as an API. Likely private or friend one, but
+            still API and consider rewrite of it.
+            </hint>
+        </question>
+-->
+ <answer id="exec-privateaccess">
+  <p>
+   XXX no answer for exec-privateaccess
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="exec-process" when="impl">
+            Do you execute an external process from your module? How do you ensure
+            that the result is the same on different platforms? Do you parse output?
+            Do you depend on result code?
+            <hint>
+            If you feed an input, parse the output please declare that as an API.
+            </hint>
+        </question>
+-->
+ <answer id="exec-process">
+  <p>
+   XXX no answer for exec-process
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="exec-property" when="impl">
+            Is execution of your code influenced by any environment or
+            Java system (<code>System.getProperty</code>) property?
+            On a similar note, is there something interesting that you
+            pass to <code>java.util.logging.Logger</code>? Or do you observe
+            what others log?
+            <hint>
+            If there is a property that can change the behavior of your
+            code, somebody will likely use it. You should describe what it does
+            and the <a href="http://wiki.netbeans.org/API_Stability">stability category</a>
+            of this API. You may use
+            <pre>
+                &lt;api type="export" group="property" name="id" category="private" url="http://..."&gt;
+                    description of the property, where it is used, what it influence, etc.
+                &lt;/api&gt;
+            </pre>
+            </hint>
+        </question>
+-->
+ <answer id="exec-property">
+  <p>
+   XXX no answer for exec-property
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="exec-reflection" when="impl">
+            Does your code use Java Reflection to execute other code?
+            <hint>
+            This usually indicates a missing or insufficient API in the other
+            part of the system. If the other side is not aware of your dependency
+            this contract can be easily broken.
+            </hint>
+        </question>
+-->
+ <answer id="exec-reflection">
+  <p>
+   XXX no answer for exec-reflection
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="exec-threading" when="init">
+            What threading models, if any, does your module adhere to? How the
+            project behaves with respect to threading?
+            <hint>
+                Is your API threadsafe? Can it be accessed from any threads or
+                just from some dedicated ones? Any special relation to AWT and
+                its Event Dispatch thread? Also
+                if your module calls foreign APIs which have a specific threading model,
+                indicate how you comply with the requirements for multithreaded access
+                (synchronization, mutexes, etc.) applicable to those APIs.
+                If your module defines any APIs, or has complex internal structures
+                that might be used from multiple threads, declare how you protect
+                data against concurrent access, race conditions, deadlocks, etc.,
+                and whether such rules are enforced by runtime warnings, errors, assertions, etc.
+                Examples: a class might be non-thread-safe (like Java Collections); might
+                be fully thread-safe (internal locking); might require access through a mutex
+                (and may or may not automatically acquire that mutex on behalf of a client method);
+                might be able to run only in the event queue; etc.
+                Also describe when any events are fired: synchronously, asynchronously, etc.
+                Ideas: <a href="http://core.netbeans.org/proposals/threading/index.html#recommendations">Threading Recommendations</a> (in progress)
+            </hint>
+        </question>
+-->
+ <answer id="exec-threading">
+  <p>
+   XXX no answer for exec-threading
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="format-clipboard" when="impl">
+            Which data flavors (if any) does your code read from or insert to
+            the clipboard (by access to clipboard on means calling methods on <code>java.awt.datatransfer.Transferable</code>?
+
+            <hint>
+            Often Node's deal with clipboard by usage of <code>Node.clipboardCopy, Node.clipboardCut and Node.pasteTypes</code>.
+            Check your code for overriding these methods.
+            </hint>
+        </question>
+-->
+ <answer id="format-clipboard">
+  <p>
+   XXX no answer for format-clipboard
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="format-dnd" when="impl">
+            Which protocols (if any) does your code understand during Drag &amp; Drop?
+            <hint>
+            Often Node's deal with clipboard by usage of <code>Node.drag, Node.getDropType</code>.
+            Check your code for overriding these methods. Btw. if they are not overridden, they
+            by default delegate to <code>Node.clipboardCopy, Node.clipboardCut and Node.pasteTypes</code>.
+            </hint>
+        </question>
+-->
+ <answer id="format-dnd">
+  <p>
+   XXX no answer for format-dnd
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="format-types" when="impl">
+            Which protocols and file formats (if any) does your module read or write on disk,
+            or transmit or receive over the network? Do you generate an ant build script?
+            Can it be edited and modified?
+
+            <hint>
+            <p>
+            Files can be read and written by other programs, modules and users. If they influence
+            your behaviour, make sure you either document the format or claim that it is a private
+            api (using the &lt;api&gt; tag).
+            </p>
+
+            <p>
+            If you generate an ant build file, this is very likely going to be seen by end users and
+            they will be attempted to edit it. You should be ready for that and provide here a link
+            to documentation that you have for such purposes and also describe how you are going to
+            understand such files during next release, when you (very likely) slightly change the
+            format.
+            </p>
+            </hint>
+        </question>
+-->
+ <answer id="format-types">
+  <p>
+   XXX no answer for format-types
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="lookup-lookup" when="init">
+            Does your module use <code>org.openide.util.Lookup</code>
+            or any similar technology to find any components to communicate with? Which ones?
+
+            <hint>
+            NetBeans is build around a generic registry of services called
+            lookup. It is preferable to use it for registration and discovery
+            if possible. See
+            <a href="http://www.netbeans.org/download/dev/javadoc/org-openide-util/org/openide/util/lookup/doc-files/index.html">
+            The Solution to Comunication Between Components
+            </a>. If you do not plan to use lookup and insist usage
+            of other solution, then please describe why it is not working for
+            you.
+            <br/>
+            When filling the final version of your arch document, please
+            describe the interfaces you are searching for, where
+            are defined, whether you are searching for just one or more of them,
+            if the order is important, etc. Also classify the stability of such
+            API contract. Use &lt;api group=&amp;lookup&amp; /&gt; tag, so
+            your information gets listed in the summary page of your javadoc.
+            </hint>
+        </question>
+-->
+ <answer id="lookup-lookup">
+  <p>
+   XXX no answer for lookup-lookup
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="lookup-register" when="final">
+            Do you register anything into lookup for other code to find?
+            <hint>
+            Do you register using layer file or using a declarative annotation such as <code>@ServiceProvider</code>?
+            Who is supposed to find your component?
+            </hint>
+        </question>
+-->
+ <answer id="lookup-register">
+  <p>
+   XXX no answer for lookup-register
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="lookup-remove" when="final">
+            Do you remove entries of other modules from lookup?
+            <hint>
+            Why? Of course, that is possible, but it can be dangerous. Is the module
+            your are masking resource from aware of what you are doing?
+            </hint>
+        </question>
+-->
+ <answer id="lookup-remove">
+  <p>
+   XXX no answer for lookup-remove
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="perf-exit" when="final">
+            Does your module run any code on exit?
+        </question>
+-->
+ <answer id="perf-exit">
+  <p>
+   XXX no answer for perf-exit
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="perf-huge_dialogs" when="final">
+            Does your module contain any dialogs or wizards with a large number of
+            GUI controls such as combo boxes, lists, trees, or text areas?
+        </question>
+-->
+ <answer id="perf-huge_dialogs">
+  <p>
+   XXX no answer for perf-huge_dialogs
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="perf-limit" when="init">
+            Are there any hard-coded or practical limits in the number or size of
+            elements your code can handle?
+            <hint>
+                Most of algorithms have increasing memory and speed complexity
+                with respect to size of data they operate on. What is the critical
+                part of your project that can be seen as a bottleneck with
+                respect to speed or required memory? What are the practical
+                sizes of data you tested your project with? What is your estimate
+                of potential size of data that would cause visible performance
+                problems? Is there some kind of check to detect such situation
+                and prevent "hard" crashes - for example the CloneableEditorSupport
+                checks for size of a file to be opened in editor
+                and if it is larger than 1Mb it shows a dialog giving the
+                user the right to decide - e.g. to cancel or commit suicide.
+            </hint>
+        </question>
+-->
+ <answer id="perf-limit">
+  <p>
+   XXX no answer for perf-limit
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="perf-mem" when="final">
+            How much memory does your component consume? Estimate
+            with a relation to the number of windows, etc.
+        </question>
+-->
+ <answer id="perf-mem">
+  <p>
+   XXX no answer for perf-mem
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="perf-menus" when="final">
+            Does your module use dynamically updated context menus, or
+            context-sensitive actions with complicated and slow enablement logic?
+            <hint>
+                If you do a lot of tricks when adding actions to regular or context menus, you can significantly
+                slow down display of the menu, even when the user is not using your action. Pay attention to
+                actions you add to the main menu bar, and to context menus of foreign nodes or components. If
+                the action is conditionally enabled, or changes its display dynamically, you need to check the
+                impact on performance. In some cases it may be more appropriate to make a simple action that is
+                always enabled but does more detailed checks in a dialog if it is actually run.
+            </hint>
+        </question>
+-->
+ <answer id="perf-menus">
+  <p>
+   XXX no answer for perf-menus
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="perf-progress" when="final">
+            Does your module execute any long-running tasks?
+
+            <hint>Long running tasks should never block
+            AWT thread as it badly hurts the UI
+            <a href="http://performance.netbeans.org/responsiveness/issues.html">
+            responsiveness</a>.
+            Tasks like connecting over
+            network, computing huge amount of data, compilation
+            be done asynchronously (for example
+            using <code>RequestProcessor</code>), definitively it should
+            not block AWT thread.
+            </hint>
+        </question>
+-->
+ <answer id="perf-progress">
+  <p>
+   XXX no answer for perf-progress
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="perf-scale" when="init">
+            Which external criteria influence the performance of your
+            program (size of file in editor, number of files in menu,
+            in source directory, etc.) and how well your code scales?
+            <hint>
+            Please include some estimates, there are other more detailed
+            questions to answer in later phases of implementation.
+            </hint>
+        </question>
+-->
+ <answer id="perf-scale">
+  <p>
+   XXX no answer for perf-scale
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="perf-spi" when="init">
+            How the performance of the plugged in code will be enforced?
+            <hint>
+            If you allow foreign code to be plugged into your own module, how
+            do you enforce that it will behave correctly and quickly and will not
+            negatively influence the performance of your own module?
+            </hint>
+        </question>
+-->
+ <answer id="perf-spi">
+  <p>
+   XXX no answer for perf-spi
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="perf-startup" when="final">
+            Does your module run any code on startup?
+        </question>
+-->
+ <answer id="perf-startup">
+  <p>
+   XXX no answer for perf-startup
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="perf-wakeup" when="final">
+            Does any piece of your code wake up periodically and do something
+            even when the system is otherwise idle (no user interaction)?
+        </question>
+-->
+ <answer id="perf-wakeup">
+  <p>
+   XXX no answer for perf-wakeup
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="resources-file" when="final">
+            Does your module use <code>java.io.File</code> directly?
+
+            <hint>
+            NetBeans provide a logical wrapper over plain files called
+            <code>org.openide.filesystems.FileObject</code> that
+            provides uniform access to such resources and is the preferred
+            way that should be used. But of course there can be situations when
+            this is not suitable.
+            </hint>
+        </question>
+-->
+ <answer id="resources-file">
+  <p>
+   XXX no answer for resources-file
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="resources-layer" when="final">
+            Does your module provide own layer? Does it create any files or
+            folders in it? What it is trying to communicate by that and with which
+            components?
+
+            <hint>
+            NetBeans allows automatic and declarative installation of resources
+            by module layers. Module register files into appropriate places
+            and other components use that information to perform their task
+            (build menu, toolbar, window layout, list of templates, set of
+            options, etc.).
+            </hint>
+        </question>
+-->
+ <answer id="resources-layer">
+  <p>
+   XXX no answer for resources-layer
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="resources-mask" when="final">
+            Does your module mask/hide/override any resources provided by other modules in
+            their layers?
+
+            <hint>
+            If you mask a file provided by another module, you probably depend
+            on that and do not want the other module to (for example) change
+            the file's name. That module shall thus make that file available as an API
+            of some stability category.
+            </hint>
+        </question>
+-->
+ <answer id="resources-mask">
+  <p>
+   XXX no answer for resources-mask
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="resources-preferences" when="final">
+            Does your module uses preferences via Preferences API? Does your module use NbPreferences or
+            or regular JDK Preferences ? Does it read, write or both ?
+            Does it share preferences with other modules ? If so, then why ?
+            <hint>
+                You may use
+                    &lt;api type="export" group="preferences"
+                    name="preference node name" category="private"&gt;
+                    description of individual keys, where it is used, what it
+                    influences, whether the module reads/write it, etc.
+                    &lt;/api&gt;
+                Due to XML ID restrictions, rather than /org/netbeans/modules/foo give the "name" as org.netbeans.modules.foo.
+                Note that if you use NbPreferences this name will then be the same as the code name base of the module.
+            </hint>
+        </question>
+-->
+ <answer id="resources-preferences">
+  <p>
+   XXX no answer for resources-preferences
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="resources-read" when="final">
+            Does your module read any resources from layers? For what purpose?
+
+            <hint>
+            As this is some kind of intermodule dependency, it is a kind of API.
+            Please describe it and classify according to
+            <a href="http://wiki.netbeans.org/API_Design#What_is_an_API.3F">
+            common stability categories</a>.
+            </hint>
+        </question>
+-->
+ <answer id="resources-read">
+  <p>
+   XXX no answer for resources-read
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="security-grant" when="final">
+            Does your code grant additional rights to some other code?
+            <hint>Avoid using a class loader that adds extra
+            permissions to loaded code unless really necessary.
+            Also note that your API implementation
+            can also expose unneeded permissions to enemy code by
+            calling AccessController.doPrivileged().</hint>
+        </question>
+-->
+ <answer id="security-grant">
+  <p>
+   XXX no answer for security-grant
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="security-policy" when="final">
+            Does your functionality require modifications to the standard policy file?
+            <hint>Your code might pass control to third-party code not
+            coming from trusted domains. This could be code downloaded over the
+            network or code coming from libraries that are not bundled
+            with NetBeans. Which permissions need to be granted to which domains?</hint>
+        </question>
+-->
+ <answer id="security-policy">
+  <p>
+   XXX no answer for security-policy
+  </p>
+ </answer>
+
+</api-answers>
diff --git a/api.knockout/build.xml b/api.knockout/build.xml
new file mode 100644
index 0000000000..9ae3d033ee
--- /dev/null
+++ b/api.knockout/build.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    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.
+
+-->
+<project basedir="." default="netbeans" name="api.knockout">
+    <description>Builds, tests, and runs the project org.netbeans.api.knockout</description>
+    <import file="../nbbuild/templates/projectized.xml"/>
+</project>
diff --git a/api.knockout/manifest.mf b/api.knockout/manifest.mf
new file mode 100644
index 0000000000..7aee239c43
--- /dev/null
+++ b/api.knockout/manifest.mf
@@ -0,0 +1,5 @@
+Manifest-Version: 1.0
+OpenIDE-Module: org.netbeans.api.knockout
+OpenIDE-Module-Localizing-Bundle: org/netbeans/spi/knockout/Bundle.properties
+OpenIDE-Module-Specification-Version: 1.4
+AutoUpdate-Show-In-Client: false
diff --git a/api.knockout/nbproject/org-netbeans-api-knockout.sig b/api.knockout/nbproject/org-netbeans-api-knockout.sig
new file mode 100644
index 0000000000..cfcff42cef
--- /dev/null
+++ b/api.knockout/nbproject/org-netbeans-api-knockout.sig
@@ -0,0 +1,40 @@
+#Signature file v4.1
+#Version 1.2.1
+
+CLSS public java.lang.Object
+cons public init()
+meth protected java.lang.Object clone() throws java.lang.CloneNotSupportedException
+meth protected void finalize() throws java.lang.Throwable
+meth public boolean equals(java.lang.Object)
+meth public final java.lang.Class<?> getClass()
+meth public final void notify()
+meth public final void notifyAll()
+meth public final void wait() throws java.lang.InterruptedException
+meth public final void wait(long) throws java.lang.InterruptedException
+meth public final void wait(long,int) throws java.lang.InterruptedException
+meth public int hashCode()
+meth public java.lang.String toString()
+
+CLSS public final org.netbeans.spi.knockout.Bindings
+meth public final org.netbeans.spi.knockout.Bindings booleanProperty(java.lang.String,boolean)
+meth public final org.netbeans.spi.knockout.Bindings doubleProperty(java.lang.String,boolean)
+meth public final org.netbeans.spi.knockout.Bindings function(java.lang.String)
+meth public final org.netbeans.spi.knockout.Bindings intProperty(java.lang.String,boolean)
+meth public final org.netbeans.spi.knockout.Bindings modelProperty(java.lang.String,org.netbeans.spi.knockout.Bindings,boolean)
+meth public final org.netbeans.spi.knockout.Bindings stringProperty(java.lang.String,boolean)
+meth public static java.lang.String findBindings(org.openide.filesystems.FileObject,int)
+meth public static org.netbeans.spi.knockout.Bindings create(java.lang.String)
+supr java.lang.Object
+hfds name,props,subBindings
+
+CLSS public abstract interface org.netbeans.spi.knockout.BindingsProvider
+innr public final static Response
+meth public abstract org.netbeans.spi.knockout.BindingsProvider$Response findBindings(org.openide.filesystems.FileObject)
+
+CLSS public final static org.netbeans.spi.knockout.BindingsProvider$Response
+ outer org.netbeans.spi.knockout.BindingsProvider
+meth public org.netbeans.spi.knockout.BindingsProvider$Response create(org.netbeans.spi.knockout.Bindings,java.lang.String)
+meth public static org.netbeans.spi.knockout.BindingsProvider$Response create(org.netbeans.spi.knockout.Bindings)
+supr java.lang.Object
+hfds bindings,targetId
+
diff --git a/api.knockout/nbproject/project.properties b/api.knockout/nbproject/project.properties
new file mode 100644
index 0000000000..a93b3b9f88
--- /dev/null
+++ b/api.knockout/nbproject/project.properties
@@ -0,0 +1,21 @@
+# 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.
+is.autoload=true
+javac.source=1.7
+javac.compilerargs=-Xlint -Xlint:-serial
+javadoc.arch=${basedir}/arch.xml
+javadoc.apichanges=${basedir}/apichanges.xml
diff --git a/api.knockout/nbproject/project.xml b/api.knockout/nbproject/project.xml
new file mode 100644
index 0000000000..a0d0772ea8
--- /dev/null
+++ b/api.knockout/nbproject/project.xml
@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    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.
+
+-->
+<project xmlns="http://www.netbeans.org/ns/project/1">
+    <type>org.netbeans.modules.apisupport.project</type>
+    <configuration>
+        <data xmlns="http://www.netbeans.org/ns/nb-module-project/3">
+            <code-name-base>org.netbeans.api.knockout</code-name-base>
+            <module-dependencies>
+                <dependency>
+                    <code-name-base>org.netbeans.modules.editor.mimelookup</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>1</release-version>
+                        <specification-version>1.32</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.modules.lexer</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>2</release-version>
+                        <specification-version>1.52</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.modules.parsing.api</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>1</release-version>
+                        <specification-version>9.0</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.filesystems</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>9.0</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.util</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>9.3</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.21</specification-version>
+                    </run-dependency>
+                </dependency>
+            </module-dependencies>
+            <test-dependencies>
+                <test-type>
+                    <name>unit</name>
+                    <test-dependency>
+                        <code-name-base>org.netbeans.libs.testng</code-name-base>
+                        <compile-dependency/>
+                    </test-dependency>
+                </test-type>
+            </test-dependencies>
+            <public-packages>
+                <package>org.netbeans.modules.knockout.impl</package>
+                <package>org.netbeans.spi.knockout</package>
+            </public-packages>
+        </data>
+    </configuration>
+</project>
diff --git a/api.knockout/src/org/netbeans/spi/knockout/Bindings.java b/api.knockout/src/org/netbeans/spi/knockout/Bindings.java
new file mode 100644
index 0000000000..2a04676d0a
--- /dev/null
+++ b/api.knockout/src/org/netbeans/spi/knockout/Bindings.java
@@ -0,0 +1,249 @@
+/*
+ * 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.spi.knockout;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import org.netbeans.spi.knockout.BindingsProvider.Response;
+import org.openide.filesystems.FileObject;
+import org.openide.util.BaseUtilities;
+import org.openide.util.Lookup;
+import org.openide.util.TopologicalSortException;
+
+/**
+ * Allows structural description of a <code>ko.applyBindings</code> parameter.
+ * Register as {@link BindingsProvider}. When called build description of JSON
+ * types using methods like {@link #stringProperty(java.lang.String, boolean)}
+ * and then pass the result into
+ * {@link Response#applyBindings(org.netbeans.spi.knockout.Bindings)} method.
+ *
+ * @author Jaroslav Tulach <jt...@netbeans.org>
+ */
+public final class Bindings {
+
+    private final String name;
+    private final List<Bindings> subBindings = new ArrayList<>();
+    private final List<Object> props = new ArrayList<>();
+
+    private Bindings(String name) {
+        this.name = name;
+    }
+
+    /**
+     * Defines new variable with provided name and assigns a JSON object into
+     * it. The created instance is a builder - continue calling its various
+     * builder methods like {@link #intProperty(java.lang.String, boolean)}.
+     *
+     * @param name name of variable (must be valid JavaScript identifier)
+     * @return empty JSON object ready to be filled using
+     * {@link #doubleProperty(java.lang.String, boolean)}, and other methods
+     */
+    public static Bindings create(String name) {
+        return new Bindings(name);
+    }
+
+    /**
+     * Generates a boolean property (with value <code>true</code>) into the JSON
+     * class.
+     *
+     * @param name name of variable (must be valid JavaScript identifier)
+     * @param array should this property be an array of just a single value
+     * @return this object
+     */
+    public final Bindings booleanProperty(String name, boolean array) {
+        addProp(name, array, "true");
+        return this;
+    }
+
+    /**
+     * Generates a string property (with value <code>''</code>) into the JSON
+     * class.
+     *
+     * @param name name of variable (must be valid JavaScript identifier)
+     * @param array should this property be an array of just a single value
+     * @return this object
+     */
+    public final Bindings stringProperty(String name, boolean array) {
+        addProp(name, array, "''");
+        return this;
+    }
+
+    /**
+     * Generates a integer property (with value <code>0</code>) into the JSON
+     * class.
+     *
+     * @param name name of variable (must be valid JavaScript identifier)
+     * @param array should this property be an array of just a single value
+     * @return this object
+     */
+    public final Bindings intProperty(String name, boolean array) {
+        addProp(name, array, "0");
+        return this;
+    }
+
+    /**
+     * Generates a floating point property (with value <code>0.1</code>) into
+     * the JSON class.
+     *
+     * @param name name of variable (must be valid JavaScript identifier)
+     * @param array should this property be an array of just a single value
+     * @return this object
+     */
+    public final Bindings doubleProperty(String name, boolean array) {
+        addProp(name, array, "0.1");
+        return this;
+    }
+
+    /**
+     * Generates a function (empty) into the JSON class.
+     *
+     * @param name name of variable (must be valid JavaScript identifier)
+     * @return this object
+     *
+     * @since 1.1
+     */
+    public final Bindings function(String name) {
+        addProp(name, false, "function() {}");
+        return this;
+    }
+
+    /**
+     * Generates complex subtype based on another {@link Bindings} class.
+     *
+     * @param name name of variable (must be valid JavaScript identifier)
+     * @param binding another description of a JSON like object
+     * @param array should this property be an array of just a single value
+     * @return this object
+     */
+    public final Bindings modelProperty(String name, Bindings binding, boolean array) {
+        subBindings.add(binding);
+        addProp(name, array, binding);
+        return this;
+    }
+
+    final String generate() {
+        StringBuilder sb = new StringBuilder();
+        //sb.append("(function() {\n");
+        HashSet<Bindings> visited = new HashSet<>();
+        Collection<Bindings> lhs = new LinkedHashSet<>();
+        StringBuilder delayedInit = new StringBuilder();
+        if (!walkBindings(visited, lhs)) {
+            Map<Bindings, List<Bindings>> edges = new HashMap<>();
+            for (Bindings b : lhs) {
+                edges.put(b, b.subBindings);
+            }
+            try {
+                BaseUtilities.topologicalSort(lhs, edges);
+                // There is a cycle, so the resolution should fail
+                throw new IllegalStateException();
+            } catch (TopologicalSortException ex) {
+                lhs = Collections.checkedList(ex.partialSort(), Bindings.class);
+            }
+        }
+        for (Bindings b : lhs) {
+            b.generate(sb, delayedInit, visited);
+            visited.remove(b);
+        }
+        sb.append(delayedInit);
+        sb.append("\nko.applyBindings(").append(name).append(");\n");
+        //sb.append("}());");
+        return sb.toString();
+    }
+
+    private void generate(StringBuilder sb, StringBuilder delayedInit, Set<Bindings> notYetProcessed) {
+        sb.append("var ").append(name).append(" = {");
+        String sep = "\n";
+        for (int i = 0; i < props.size(); i += 3) {
+            String propName = (String)props.get(i);
+            Boolean array = (Boolean)props.get(i + 1);
+            Object value = props.get(i + 2);
+            
+            if (value instanceof Bindings) {
+                Bindings b = (Bindings) value;
+                if (notYetProcessed.contains(b)) {
+                    delayedInit.append("\n").append(this.name).append("[\"").
+                        append(propName).append("\"] = ").append(b.name).
+                        append(";");
+                    continue;
+                }
+                value = b.name;
+            }
+            
+            if (array) {
+                value = "[ " + value + " ]";
+            }
+            sb.append(sep).append("  ").append('\"').append(propName).append("\" : ").append(value);
+            sep = ",\n";
+        }
+        sb.append("\n};\n");
+    }
+
+    private void addProp(String name, boolean array, Object value) {
+        if (name.contains("\"")) {
+            throw new IllegalStateException("Wrong name " + name);
+        }
+        props.add(name);
+        props.add(array);
+        props.add(value);
+    }
+
+    private boolean walkBindings(Set<Bindings> visited, Collection<Bindings> collect) {
+        if (!visited.add(this)) {
+            return false;
+        }
+        boolean ok = true;
+        for (Bindings b : subBindings) {
+            ok &= b.walkBindings(visited, collect);
+        }
+        collect.add(this);
+        return ok;
+    }
+
+    /**
+     * Queries registered providers for additional knockout.js bindings for
+     * given file. Generates a JavaScript code describing JSON-like structures
+     * used by knockout.js that can be used to enhance code-completion for HTML
+     * files using knockout.js bindings.
+     *
+     * @param htmlFile the HTML file opened in editor
+     * @param versionOfFormat the format of the output. Use <code>1</code> for
+     * now.
+     * @return either <code>null</code> if no provider or format has been found
+     * for given file or a JavaScript code formated accordingly
+     */
+    public static String findBindings(FileObject htmlFile, int versionOfFormat) {
+        if (versionOfFormat != 1) {
+            return null;
+        }
+        for (BindingsProvider p : Lookup.getDefault().lookupAll(BindingsProvider.class)) {
+            final Response r = p.findBindings(htmlFile);
+            if (r.bindings != null) {
+                return r.bindings.generate();
+            }
+        }
+        return null;
+    }
+}
diff --git a/api.knockout/src/org/netbeans/spi/knockout/BindingsProvider.java b/api.knockout/src/org/netbeans/spi/knockout/BindingsProvider.java
new file mode 100644
index 0000000000..cd9eba8012
--- /dev/null
+++ b/api.knockout/src/org/netbeans/spi/knockout/BindingsProvider.java
@@ -0,0 +1,89 @@
+/*
+ * 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.spi.knockout;
+
+import org.openide.filesystems.FileObject;
+import org.openide.util.lookup.ServiceProvider;
+
+/**
+ * A provider that knows more about structure of Knockout bindings in an HTML
+ * page. Providers should be registered by {@link ServiceProvider} annotation so
+ * they can be found for a particular HTML file. Their
+ * {@link #findBindings(org.openide.filesystems.FileObject, org.netbeans.spi.knockout.BindingsProvider.Response) findBindings}
+ * method is called when a knockout code completion is about to be shown in the
+ * HTML editor and then can generate a JSON like description of the structure of
+ * knockout context via {@link Bindings} methods.
+ *
+ * @author Jaroslav Tulach <jt...@netbeans.org>
+ */
+public interface BindingsProvider {
+
+    /**
+     * Called when additional completion is requested for a particular file.
+     *
+     * @param htmlFile the HTML file opened in editor
+     * @return {@code Response} instance with bindings
+     */
+    public Response findBindings(FileObject htmlFile);
+
+    /**
+     * Methods for {@link BindingsProvider}s to provide a response when
+     * {@link BindingsProvider#findBindings(org.openide.filesystems.FileObject, org.netbeans.spi.knockout.BindingsProvider.Response) queries}
+     * about a particular HTML file.
+     */
+    public static final class Response {
+
+        Bindings bindings;
+        String targetId;
+
+        private Response(Bindings bindings) {
+            this.bindings = bindings;
+            this.targetId = null;
+        }
+
+        private Response(Bindings bindings, String targetId) {
+            this.bindings = bindings;
+            this.targetId = targetId;
+        }
+
+        /**
+         * Used by a {@link BindingsProvider provider} to tell the editing
+         * infrastructure to expose a JSON like structure in code completion.
+         *
+         * @param bindings Java model of JSON-like structure
+         * @return new {@code Response} instance
+         */
+        public static Response create(Bindings bindings) {
+            return new Response(bindings);
+        }
+
+        /**
+         * Used by a {@link BindingsProvider provider} to tell the editing
+         * infrastructure to expose a JSON like structure in code completion.
+         *
+         * @param bindings Java model of JSON-like structure
+         * @param targetId an id of an element on the page to identify a subtree
+         * where these bindings will be applied to
+         * @return new {@code Response} instance
+         */
+        public Response create(Bindings bindings, String targetId) {
+            return new Response(bindings, targetId);
+        }
+    }
+}
diff --git a/api.knockout/src/org/netbeans/spi/knockout/Bundle.properties b/api.knockout/src/org/netbeans/spi/knockout/Bundle.properties
new file mode 100644
index 0000000000..e21e3dad55
--- /dev/null
+++ b/api.knockout/src/org/netbeans/spi/knockout/Bundle.properties
@@ -0,0 +1,17 @@
+# 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.
+OpenIDE-Module-Name=Knockout Model Provider API
diff --git a/api.knockout/src/org/netbeans/spi/knockout/package.html b/api.knockout/src/org/netbeans/spi/knockout/package.html
new file mode 100644
index 0000000000..4e7f59a81d
--- /dev/null
+++ b/api.knockout/src/org/netbeans/spi/knockout/package.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<!--
+
+    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.
+
+-->
+<html>
+    <body>
+        <div>Java {@link org.netbeans.spi.knockout.Bindings model class} to describe JSON-like <a href="http://knockoutjs.com">Knockout</a> bindings and
+            register {@link org.netbeans.spi.knockout.BindingsProvider a provider} used by the editor infrastructure
+            to query for the {@link org.netbeans.spi.knockout.Bindings model}.
+        </div>
+    </body>
+</html>
diff --git a/api.knockout/test/unit/src/org/netbeans/spi/knockout/BindingsNGTest.java b/api.knockout/test/unit/src/org/netbeans/spi/knockout/BindingsNGTest.java
new file mode 100644
index 0000000000..db6aaca361
--- /dev/null
+++ b/api.knockout/test/unit/src/org/netbeans/spi/knockout/BindingsNGTest.java
@@ -0,0 +1,128 @@
+/*
+ * 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.spi.knockout;
+
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineManager;
+import javax.script.ScriptException;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+import static org.testng.Assert.*;
+
+/**
+ *
+ * @author Jaroslav Tulach <jt...@netbeans.org>
+ */
+public class BindingsNGTest {
+    private ScriptEngine eng;
+
+    public BindingsNGTest() {
+    }
+
+    @BeforeMethod public void initEngine() {
+        ScriptEngineManager sem = new ScriptEngineManager();
+        eng = sem.getEngineByMimeType("text/javascript");
+    }
+
+    @Test public void generateTwitterModel() throws Exception {
+        Bindings tweet = Bindings.create("Tweet").
+            stringProperty("from_user", false).
+            intProperty("from_user_id", false);
+
+        Bindings tweeters = Bindings.create("Tweeters").
+            stringProperty("name", false).
+            stringProperty("userNames", true);
+
+        Bindings twitterClient = Bindings.create("TwitterClient");
+        twitterClient.
+            stringProperty("activeTweetersName", false).
+            stringProperty("activeTweeters", true).
+            stringProperty("userNameToAdd", false).
+            booleanProperty("loading", false).
+            modelProperty("currentTweets", tweet, true).
+            modelProperty("savedLists", tweeters, true);
+
+        String txt = twitterClient.generate();
+
+        assertValidJS(txt);
+
+        assertNotNull(eng.eval("ko"));
+        assertNotNull(eng.eval("ko.value"));
+        assertEquals(eng.eval("ko.value.loading"), true, "Boolean values are set to true");
+        assertEquals(eng.eval("ko.value.currentTweets[0].from_user_id"), 0d, "Boolean values are set to true");
+    }
+
+    @Test
+    public void generateRecursiveModel() throws Exception {
+        Bindings m1 = Bindings.create("Hello");
+        Bindings m2 = Bindings.create("Multi");
+        m1.modelProperty("multi", m2, false);
+        m2.modelProperty("hello", m1, false);
+        m2.intProperty("int", false);
+        String txt = m2.generate();
+        assertValidJS(txt);
+        assertNotNull(eng.eval("ko"), txt);
+        assertNotNull(eng.eval("Hello.multi"), txt);
+        assertEquals(eng.eval("Hello.multi.hello === Hello"), Boolean.TRUE, txt);
+    }
+    
+    public void generateModelWithFunctions() throws Exception {
+        Bindings myModel = Bindings.create("MyModel")
+                .function("myFunc1")
+                .function("func2");
+
+        String txt = myModel.generate();
+        assertNotNull(eng.eval("ko"), txt);
+        assertNotNull(eng.eval("Hello.multi"), txt);
+        assertEquals(eng.eval("Hello.multi.hello === Hello"), Boolean.TRUE, txt);
+        assertNotNull(eng.eval("ko"));
+        assertNotNull(eng.eval("ko.value"));
+        assertNotNull(eng.eval("ko.value.myFunc1"));
+        assertNotNull(eng.eval("ko.value.func2"));
+        assertEquals("function", eng.eval("typeof ko.value.myFunc1"));
+        assertEquals("function", eng.eval("typeof ko.value.func2"));
+    }
+
+    @Test
+    public void generateRecursiveModel2() throws Exception {
+        Bindings one = Bindings.create("One");
+        Bindings two = Bindings.create("Two");
+        Bindings three = Bindings.create("Three");
+        one.modelProperty("three", three, false);
+        two.modelProperty("one", one, false);
+        three.modelProperty("two",two , false);
+        String txt = two.generate();
+        assertValidJS(txt);
+        assertNotNull(eng.eval("ko"), txt);
+        assertNotNull(eng.eval("One.three"), txt);
+        assertNotNull(eng.eval("One.three.two"), txt);
+        assertEquals(eng.eval("One.three.two.one === One"), Boolean.TRUE, txt);
+    }
+
+    private void assertValidJS(String txt) {
+        assertNotNull(txt, "We have some script");
+        try {
+            eng.eval("ko = {}; ko.applyBindings = function(val) { ko.value = val; }");
+            eng.eval(txt);
+        } catch (ScriptException ex) {
+            throw new AssertionError(txt, ex);
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/api.web.webmodule/apichanges.xml b/api.web.webmodule/apichanges.xml
new file mode 100644
index 0000000000..d3a07dd73f
--- /dev/null
+++ b/api.web.webmodule/apichanges.xml
@@ -0,0 +1,265 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    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.
+
+-->
+<?xml-stylesheet type="text/xml" href="../nbbuild/javadoctools/apichanges.xsl"?>
+<!DOCTYPE apichanges PUBLIC "-//NetBeans//DTD API changes list 1.0//EN" "../nbbuild/javadoctools/apichanges.dtd">
+
+<!--
+
+INFO FOR PEOPLE ADDING CHANGES:
+
+Check the DTD (apichanges.dtd) for details on the syntax. You do not
+need to regenerate the HTML, as this is part of Javadoc generation; just
+change the XML. Rough syntax of a change (several parts optional):
+
+<change>
+    <api name="compiler"/>
+    <summary>Some brief description here, can use <b>XHTML</b></summary>
+    <version major="1" minor="99"/>
+    <date day="13" month="6" year="2001"/>
+    <author login="jrhacker"/>
+    <compatibility addition="yes"/>
+    <description>
+        The main description of the change here.
+        Again can use full <b>XHTML</b> as needed.
+    </description>
+    <class package="org.openide.compiler" name="DoWhatIWantCompiler"/>
+    <issue number="14309"/>
+</change>
+
+Also permitted elements: <package>, <branch>. <version> is API spec
+version, recommended for all new changes. <compatibility> should say
+if things were added/modified/deprecated/etc. and give all information
+related to upgrading old code. List affected top-level classes and
+link to issue numbers if applicable. See the DTD for more details.
+
+Changes need not be in any particular order, they are sorted in various
+ways by the stylesheet anyway.
+
+Dates are assumed to mean "on the trunk". If you *also* make the same
+change on a stabilization branch, use the <branch> tag to indicate this
+and explain why the change was made on a branch in the <description>.
+
+Please only change this file on the trunk! Rather: you can change it
+on branches if you want, but these changes will be ignored; only the
+trunk version of this file is important.
+
+Deprecations do not count as incompatible, assuming that code using the
+deprecated calls continues to see their documented behavior. But do
+specify deprecation="yes" in <compatibility>.
+
+This file is not a replacement for Javadoc: it is intended to list changes,
+not describe the complete current behavior, for which ordinary documentation
+is the proper place.
+
+-->
+
+<apichanges>
+
+    <!-- First, a list of API names you may use: -->
+    <apidefs>
+        <apidef name="WebModuleAPI">Web Module API</apidef>
+    </apidefs>
+
+    <!-- ACTUAL CHANGES BEGIN HERE: -->
+
+    <changes>
+        <change id="Adding_WebModuleExtender_Savable">
+            <api name="WebModuleAPI"/>
+            <summary>Adding <code>WebModuleExtender.Savable</code> interface</summary>
+            <version major="1" minor="26"/>
+            <date day="26" month="9" year="2011"/>
+            <author login="marfous@netbeans.org"/>
+            <compatibility addition="yes"/>
+            <description>
+                <p>
+                    Added interface <code>WebModuleExtender.Savable</code> for ability to 
+                    save framework settings of already included extender after confirming
+                    project customizer.
+                </p>
+            </description>
+        </change>
+        <change id="ListenableWebModuleImplementation2">
+            <api name="WebModuleAPI"/>
+            <summary>Adding ability to listen on WebModuleImplementation2 changes</summary>
+            <version major="1" minor="16"/>
+            <date day="21" month="9" year="2009"/>
+            <author login="dkonecny"/>
+            <compatibility addition="yes"/>
+            <description>
+                <p>
+                    Adding ability to listen on changes of document base or
+                    WEB-INF folder. WebModuleImplementation2 was introduced in this
+                    release so I'm taking advantage of it and adding requested methods.
+                </p>
+            </description>
+            <class package="org.netbeans.modules.web.spi.webmodule" name="WebModuleImplementation2"/>
+            <issue number="154944"/>
+        </change>
+        <change id="Adding_requresWebXml">
+            <api name="WebModuleAPI"/>
+            <summary>Adding method requiresWebXml</summary>
+            <version major="1" minor="15"/>
+            <date day="1" month="7" year="2009"/>
+            <author login="pslechta@netbeans.org"/>
+            <compatibility addition="yes"/>
+            <description>
+                <p>
+                    New method requiresWebXml added. Framework specifies via this method if it reqires web.xml DD or not.
+                </p>
+            </description>
+        </change>
+        <change id="Making_WebModuleAPI_Public">
+            <api name="WebModuleAPI"/>
+            <summary>Making the WebModule API public</summary>
+            <version major="1" minor="10"/>
+            <date day="28" month="9" year="2007"/>
+            <author login="abadea@netbeans.org"/>
+            <compatibility modification="yes"/>
+            <description>
+                <p>
+                    Made the WebModule API public with the stability level "under development".
+                </p>
+            </description>
+            <issue number="112441"/>
+        </change>
+        <change id="Deprecating_WebFrameworkProvider_Methods">
+            <api name="WebModuleAPI"/>
+            <summary>Deprecating <code>WebFrameworkProvider.extend()</code> and <code>WebFrameworkProvider.getConfigurationPanel()</code></summary>
+            <version major="1" minor="9"/>
+            <date day="14" month="9" year="2007"/>
+            <author login="abadea@netbeans.org"/>
+            <compatibility deprecation="yes"/>
+            <description>
+                <p>
+                    Deprecated methods <code>WebFrameworkProvider.extend()</code> and <code>WebFrameworkProvider.getConfigurationPanel()</code>.
+                    Class <code>WebConfigurationPanel</code> has been deprecated too.
+                </p>
+                <p>
+                    Introduced a <code>WebModuleExtender</code> class and a <code>WebModule.createWebModuleExtender()</code> method returning it.
+                    This allows for better encapsulation of the web module extending process.
+                </p>
+            </description>
+            <class package="org.netbeans.modules.web.spi.webmodule" name="FrameworkConfigurationPanel"/>
+            <class package="org.netbeans.modules.web.spi.webmodule" name="WebFrameworkProvider"/>
+            <class package="org.netbeans.modules.web.spi.webmodule" name="WebModuleExtender"/>
+        </change>
+        <change id="Deprecating_getJavaSources">
+            <api name="WebModuleAPI"/>
+            <summary>Deprecating <code>WebModule.getJavaSources</code></summary>
+            <version major="1" minor="9"/>
+            <date day="14" month="9" year="2007"/>
+            <author login="abadea@netbeans.org"/>
+            <compatibility deprecation="yes"/>
+            <description>
+                <p>
+                    Deprecated <code>WebModule.getJavaSources</code> because its return value is not generic enough.
+                </p>
+            </description>
+            <class package="org.netbeans.modules.web.api.webmodule" name="WebModule"/>
+        </change>
+        <change id="Adding_getServletPath">
+            <api name="WebModuleAPI"/>
+            <summary>Adding <code>WebFrameworkProvider.getServletPath()</code></summary>
+            <version major="1" minor="5"/>
+            <date day="8" month="3" year="2006"/>
+            <author login="ppisl@netbeans.org"/>
+            <compatibility addition="yes"/>
+            <description>
+                <p>
+                    Added method <code>WebFrameworkProvider.getServletPath()</code> for obtaining the servlet path for a JSP. 
+                </p>
+            </description>
+            <class package="org.netbeans.modules.web.spi.webmodule" name="WebFrameworkProvider"/>
+        </change>
+        <change id="Adding_Framework_Support">
+            <api name="WebModuleAPI"/>
+            <summary>Adding web framework support</summary>
+            <version major="1" minor="4"/>
+            <date day="28" month="7" year="2005"/>
+            <author login="ppisl@netbeans.org"/>
+            <compatibility addition="yes"/>
+            <description>
+                <p>
+                    There are some frameworks like Struts, JSF, Spring etc., which extend the web applications. 
+                    This change introduces the concept of a web framework provider to the Web Module API/SPI
+                    which allows to implement supporting these frameworks.
+                </p>
+            </description>
+            <class package="org.netbeans.modules.web.api.webmodule" name="WebFrameworks"/>
+            <class package="org.netbeans.modules.web.spi.webmodule" name="WebFrameworkProvider"/>
+        </change>
+         
+        <change id="Remove_URLCookie">
+            <api name="WebModuleAPI"/>
+            <summary>Replace URLCookie with a RequestParametersQuery API and RequestParametersQueryImplementation SPI</summary>
+            <version major="1" minor="2"/>
+            <date day="27" month="1" year="2005"/>
+            <author login="pbuzek@netbeans.org"/>
+            <compatibility binary="incompatible" source="incompatible" semantic="incompatible" addition="no"/>
+            <description>
+                <p>
+                    Node.Cookie should not be exposed in API. The URLCookie has been replaced with a query pattern
+                    with a corresponding SPI.
+                </p>
+            </description>
+            <class package="org.netbeans.modules.web.api.webmodule" name="URLCookie" link="no" />
+            <class package="org.netbeans.modules.web.api.webmodule" name="RequestParametersQuery"/>
+            <class package="org.netbeans.modules.web.spi.webmodule" name="RequestParametersQueryImplementation"/>
+         </change>
+    </changes>
+
+    <!-- Now the surrounding HTML text and document structure: -->
+
+    <htmlcontents>
+<!--
+
+                            NO NO NO NO NO!
+
+         ==============>    DO NOT EDIT ME!  <==============
+
+          AUTOMATICALLY GENERATED FROM APICHANGES.XML, DO NOT EDIT
+
+                SEE web/webapi/apichanges.xml
+
+-->
+    <head>
+      <title>Change History for the WebModule API</title>
+      <link rel="stylesheet" href="prose.css" type="text/css"/>
+    </head>
+    <body>
+
+<p class="overviewlink"><a href="overview-summary.html">Overview</a></p>
+
+<h1>Introduction</h1>
+
+<p>This document lists changes made to the <a href="@TOP@overview-summary.html">WebModule API</a>.</p>
+
+<!-- The actual lists of changes, as summaries and details: -->
+      <hr/>
+      <standard-changelists module-code-name="org.netbeans.api.web.webmodule"/>
+
+      <hr/><p>@FOOTER@</p>
+
+    </body>
+  </htmlcontents>
+
+</apichanges>
diff --git a/api.web.webmodule/arch.xml b/api.web.webmodule/arch.xml
new file mode 100644
index 0000000000..0fdb0caa0d
--- /dev/null
+++ b/api.web.webmodule/arch.xml
@@ -0,0 +1,892 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    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.
+
+-->
+<!DOCTYPE api-answers PUBLIC "-//NetBeans//DTD Arch Answers//EN" "../nbbuild/antsrc/org/netbeans/nbbuild/Arch.dtd" [
+  <!ENTITY api-questions SYSTEM "../nbbuild/antsrc/org/netbeans/nbbuild/Arch-api-questions.xml">
+]>
+
+<api-answers
+  question-version="1.29"
+  author="pavel.buzek@sun.com"
+>
+
+  &api-questions;
+
+<!--
+        <question id="arch-what" when="init" >
+            What is this project good for?
+            <hint>
+            Please provide here a few lines describing the project,
+            what problem it should solve, provide links to documentation, 
+            specifications, etc.
+            </hint>
+        </question>
+-->
+        
+<answer id="arch-what">
+<p>
+There are multiple IDE modules that need access to definition of web module.
+On one side there are modules that provide wizards, edititing, debugging etc. 
+for JSPs, web.xml, servlets, and similar. On the other side there are also 
+multiple project types that can contain web modules in them. 
+This API/SPI exists for communication between these two types of modules.
+</p>
+</answer>
+
+<!--
+        <question id="arch-overall" when="init">
+            Describe the overall architecture. 
+            <hint>
+            What will be API for 
+            <a href="http://openide.netbeans.org/tutorial/api-design.html#design.apiandspi">
+                clients and what support API</a>? 
+            What parts will be pluggable?
+            How will plug-ins be registered? Please use <code>&lt;api type="export"/&gt;</code>
+            to describe your general APIs.
+            If possible please provide 
+            simple diagrams. 
+            </hint>
+        </question>
+-->
+<answer id="arch-overall">
+<p>
+<api group="java" name="WebModuleAPI" type="export" category="devel">
+The API part provides access to web module properties and defines constants for use
+web module projects (such as action commands or source types).
+The SPI part can be implemented by modules that provide web module "project" support.
+It can be implemented with project APIs but other implementations are also possible. 
+There is also an SPI which allows implementors to provides support for web frameworks
+such as Struts and JSF.
+</api>
+</p>
+</answer>
+<!--        
+        <question id="arch-usecases" when="init">
+            Describe the main <a href="http://openide.netbeans.org/tutorial/api-design.html#usecase">
+            use cases</a> of the new API. Who will use it at
+            what circumstances and what will be the typical code to write
+            to use the module.
+        </question>
+-->
+<answer id="arch-usecases">
+ <usecase id="web-module-properties" name="Retrieving the propertis of a web module">
+  <p>
+   The <code>WebModule</code> class, which encapsulates a web module, has methods
+   for retrieving the module's properties:
+  </p>
+  <pre xml:space="preserve">
+   FileObject myServlet = ...;
+   WebModule wm1 = WebModule.getWebModule (myServlet);
+   String version = wm1.getJ2eePlatformVersion ();
+   System.out.println ("Servlet is in version:" + version + " web module");
+  </pre>
+ </usecase>
+ <usecase id="web-module-implementation" name="Implementing a web module">
+  <p>
+   Most often the web module is implemented inside a project:
+  </p>
+  <pre xml:space="preserve">
+   public class MyProjectType implements Project {
+     Lookup getLookup () {
+       return Lookups.fixed(new Object[] {
+         new MyProvider (),
+         ...
+       }
+     }
+     private class MyProvider implements WebModuleProvider {
+       WebModule findWebModule(FileObject file) {
+         if (isMyFile (file)) {
+           WebModule wm;
+           synchronized (this) {
+             wm = cachedWebModule (file);
+             if (wm == null) {
+               wm = WebModuleFactory.createWebModule (new WebModuleImpl ());
+               cache (file, wm);
+             }
+           }
+           return wm;
+         }
+       }
+       boolean isMyFile (FileObject file) {...}
+       WebModule cachedWebModule (FileObject file) {...}
+       cache (FileObject file, WebModule wm) {...}
+     }
+     
+     private class WebModuleImpl implements WebModuleImplementation {
+       ...
+     }
+   }
+  </pre>
+  <p>
+   It is also possible to implement web modules backed by other means than
+   a project by implementing a <code>WebModuleProvider</code> and registering
+   it in the default lookup.
+  </p>
+ </usecase>
+ <usecase id="web-framework-implementation" name="Implementing support for a web framework">
+  <p>
+   Support for web frameworks, such as Struts and JSF, can
+   extend a <code>WebModule</code> with framework-specific features, such as configuration files. An implementor
+   wanting to provide such support implements <code>WebFrameworkProvider</code> and registers it in the
+   <code>j2ee/webtier/framework</code> in the default file system.
+  </p>
+ </usecase>
+</answer>
+<!--         
+        <question id="arch-time" when="init">
+            What are the time estimates of the work?
+            <hint>
+            Please express your estimates of how long the design, implementation,
+            stabilization are likely to last. How many people will be needed to
+            implement this and what is the expected milestone the work should be 
+            ready.
+            </hint>
+        </question>
+-->
+<answer id="arch-time">
+The work scoped for promotion D is to make the API/SPI suite the needs of web 
+apps and the new build system implementation. This work is done. 
+</answer>
+<!--    
+        <question id="arch-quality" when="init">
+            How the quality of your code will be tested and 
+            how future regressions are going to be prevented?
+            <hint>
+            What kind of testing you want to use? What/how much area of functionality
+            should be covered by the tests? 
+            </hint>
+        </question>
+-->
+<answer id="arch-quality">
+There are unit tests for registration of web module providers in global lookup.
+Additional tests in ant/freeform module test a provider that is registered in 
+project lookup and test all properties of the web module on this provider.
+</answer>
+<!-- 
+    </category>
+    <category id="dep" name="Project and platform dependencies">
+        <question id="dep-nb" when="init" >
+            What other NetBeans projects and modules does this one depend on?
+            <hint>
+            If you want, describe such projects as imported API using
+            the <code>&lt;api name="identification" type="import or export" category="stable" url="where is the description" /&gt;</code>
+            </hint>
+        </question>
+-->
+<answer id="dep-nb">
+<defaultanswer generate='here' />
+</answer>
+<!--
+        <question id="dep-non-nb" when="init" >
+            What other projects outside NetBeans does this one depend on?
+            
+            <hint>
+            Some non-NetBeans projects are packaged as NetBeans modules
+            (see <a href="http://libs.netbeans.org/">libraries</a>) and
+            it is preferred to use this approach when more modules may
+            depend on such third-party library.
+            </hint>
+        </question>
+-->
+<answer id="dep-non-nb">
+None.
+</answer>
+<!-- 
+        <question id="dep-platform" when="init" >
+            On which platforms does your module run? Does it run in the same
+            way on each?
+            <hint>
+            If your module is using JNI or deals with special differences of
+            OSes like filesystems, etc. please describe here what they are.
+            </hint>
+        </question>
+-->
+<answer id="dep-platform">
+It should run anywhere.
+</answer>
+<!-- 
+        <question id="dep-jre" when="final" >
+            Which version of JRE do you need (1.2, 1.3, 1.4, etc.)?
+            <hint>
+            It is expected that if your module runs on 1.x that it will run 
+            on 1.x+1 if no, state that please. Also describe here cases where
+            you run different code on different versions of JRE and why.
+            </hint>
+        </question>
+-->
+<answer id="dep-jre">
+JRE 1.3
+</answer>
+<!-- 
+        <question id="dep-jrejdk" when="final" >
+            Do you require the JDK or is the JRE enough?
+        </question>
+-->
+<answer id="dep-jrejdk">
+JRE is enough.
+</answer>
+<!-- 
+    </category>
+    <category id="deploy" name="Deployment">
+        <question id="deploy-jar" when="impl" >
+            Do you deploy just module JAR file(s) or other files as well?
+            <hint>
+            If your module consists of just one module JAR file, just confirm that.
+            If it uses more than one JAR, describe where they are located, how
+            they refer to each other. 
+            If it consist of module JAR(s) and other files, please describe
+            what is their purpose, why other files are necessary. Please 
+            make sure that installation/uninstallation leaves the system 
+            in state as it was before installation.
+            </hint>
+        </question>
+-->
+<answer id="deploy-jar">
+No other files are deployed.
+</answer>
+<!-- 
+        <question id="deploy-nbm" when="impl" >
+            Can you deploy an NBM via the Update Center?
+            <hint>
+            If not why?
+            </hint>
+        </question>
+-->
+<answer id="deploy-nbm">
+Yes
+</answer>
+<!-- 
+        <question id="deploy-shared" when="final" >
+            Do you need to be installed in the shared location only, or in the user directory only,
+            or can your module be installed anywhere?
+            <hint>
+            Installation location shall not matter, if it does explain why.
+            Consider also whether <code>InstalledFileLocator</code> can help.
+            </hint>
+        </question>
+-->
+<answer id="deploy-shared">
+Anywhere.
+</answer>
+<!--
+        <question id="deploy-packages" when="init" >
+            Are packages of your module made inaccessible by not declaring them public?
+            <hint>
+            NetBeans module system allows restriction of access rights to
+            public classes of your module from other modules. This prevents
+            unwanted dependencies of others on your code and should be used
+            whenever possible (<a href="http://www.netbeans.org/download/javadoc/OpenAPIs/org/openide/doc-files/upgrade.html#3.4-public-packages">
+            public packages
+            </a>). If you do not restrict access to your classes you are
+            making it too easy for other people to misuse your implementation
+            details, that is why you should have good reason for not 
+            restricting package access.
+            </hint>
+        </question>
+-->
+<answer id="deploy-packages">
+<p>
+There are 2 public packages that are both specified in manifest:
+</p>
+<ul>
+<li>org.netbeans.modules.web.api.webmodule</li>
+<li>org.netbeans.modules.web.spi.webmodule</li>
+</ul>
+</answer>
+<answer id="deploy-dependencies">
+<p>
+Nothing.
+</p>
+</answer>
+<!-- 
+    </category>
+    <category id="compat" name="Compatibility with environment">
+        <question id="compat-i18n" when="impl" >
+            Is your module correctly internationalized?
+            <hint>
+            Correct internationalization means that it obeys instructions 
+            at <a href="http://www.netbeans.org/download/dev/javadoc/org-openide-modules/org/openide/modules/doc-files/i18n-branding.html">
+            NetBeans I18N pages</a>.
+            </hint>
+        </question>
+-->
+<answer id="compat-i18n">
+Not applicable.
+</answer>
+<!-- 
+        <question id="compat-standards" when="init" >
+            Does the module implement or define any standards? Is the 
+            implementation exact or does it deviate somehow?
+        </question>
+-->
+<answer id="compat-standards">
+No.
+</answer>
+<!-- 
+        <question id="compat-version" when="impl" >
+            Can your module coexist with earlier and future
+            versions of itself? Can you correctly read all old settings? Will future
+            versions be able to read your current settings? Can you read
+            or politely ignore settings stored by a future version?
+            
+            <hint>
+            Very helpful for reading settings is to store version number
+            there, so future versions can decide whether how to read/convert
+            the settings and older versions can ignore the new ones.
+            </hint>
+        </question>
+-->
+<answer id="compat-version">
+This is the first version. Modules does not store any settings.
+</answer>
+<!-- 
+    </category>
+    <category id="resources" name="Access to resources">
+        <question id="resources-file" when="final">
+            Does your module use <code>java.io.File</code> directly?       
+            <hint>
+            NetBeans provide a logical wrapper over plain files called 
+            <code>org.openide.filesystems.FileObject</code> that
+            provides uniform access to such resources and is the preferred
+            way that should be used. But of course there can be situations when
+            this is not suitable.
+            </hint>
+        </question>
+-->
+<answer id="resources-file">
+No.
+</answer>
+<!-- 
+        <question id="resources-layer" when="final">
+            Does your module provide own layer? Does it create any files or
+            folders in it? What it is trying to communicate by that and with which 
+            components?
+            
+            <hint>
+            NetBeans allows automatic and declarative installation of resources 
+            by module layers. Module register files into appropriate places
+            and other components use that information to perform their task
+            (build menu, toolbar, window layout, list of templates, set of
+            options, etc.). 
+            </hint>
+        </question>
+-->
+<answer id="resources-layer">
+No.
+</answer>
+<!-- 
+        <question id="resources-read" when="final">
+            Does your module read any resources from layers? For what purpose?
+            
+            <hint>
+            As this is some kind of intermodule dependency, it is a kind of API.
+            Please describe it and classify according to 
+            <a href="http://openide.netbeans.org/tutorial/api-design.html#categories">
+            common stability categories</a>.
+            </hint>
+        </question>
+-->
+<answer id="resources-read">
+No.
+</answer>
+<!--
+        <question id="resources-mask" when="final">
+            Does your module mask/hide/override any resources provided by other modules in
+            their layers?
+            
+            <hint>
+            If you mask a file provided by another module, you probably depend
+            on that and do not want the other module to (for example) change
+            the file's name. That module shall thus make that file available as an API
+            of some stability category.
+            </hint>
+        </question>
+    </category>
+-->
+<answer id="resources-mask">
+No.
+</answer>
+<!--
+    <category id="lookup" name="Lookup of components">
+        <question id="lookup-lookup" when="init" >
+            Does your module use <code>org.openide.util.Lookup</code>
+            to find any components to communicate with? Which ones?
+            
+            <hint>
+            Please describe the interfaces you are searching for, where 
+            are defined, whether you are searching for just one or more of them,
+            if the order is important, etc. Also classify the stability of such
+            API contract.
+            </hint>
+        </question>
+-->
+<answer id="lookup-lookup">
+<p>
+The module is looking for <code>org.netbeans.spi.web.webmodule.WebModuleProvider</code> instances
+and uses them to resolve <code>org.netbeans.api.web.webmodule.WebModule.getWebModule()</code> query.
+</p>
+</answer>
+<!--
+        <question id="lookup-register" when="final" >
+            Do you register anything into lookup for other code to find?
+            <hint>
+            Do you register using layer file or using <code>META-INF/services</code>?
+            Who is supposed to find your component?
+            </hint>
+        </question>
+-->
+<answer id="lookup-register">
+<p>
+The module registers an instance of <code>org.netbeans.spi.web.webmodule.WebModuleProvider</code>
+that implements the query based on projects - it delegates to <code>WebModuleProvider</code>
+instances found in lookup of the project that owns the given file.
+</p>
+</answer>
+<!--
+        <question id="lookup-remove" when="final" >
+            Do you remove entries of other modules from lookup?
+            <hint>
+            Why? Of course, that is possible, but it can be dangerous. Is the module
+            your are masking resource from aware of what you are doing?
+            </hint>
+        </question>
+-->
+<answer id="lookup-remove">
+No.
+</answer>
+<!--
+    </category>
+-->
+    <!-- classification of interfaces -->
+    <!-- package names -->
+<!--
+    <category id="exec" name="Execution Environment">
+        <question id="exec-property" when="impl" >
+            Is execution of your code influenced by any environment or
+            Java system (<code>System.getProperty</code>) property?
+            
+            <hint>
+            If there is a property that can change the behavior of your 
+            code, somebody will likely use it. You should describe what it does 
+            and the <a href="http://openide.netbeans.org/tutorial/api-design.html#life">stability category</a>
+            of this API. You may use
+            <pre>
+                &lt;api type="export" group="property" name="id" category="private" url="http://..."&gt;
+                    description of the property, where it is used, what it influence, etc.
+                &lt;/api&gt;            
+            </pre>
+            </hint>
+        </question>
+-->
+<answer id="exec-property">
+No.
+</answer>
+<!--
+        <question id="exec-component" when="impl" >
+            Is execution of your code influenced by any (string) property
+            of any of your components?
+            
+            <hint>
+            Often <code>JComponent.getClientProperty</code>, <code>Action.getValue</code>
+            or <code>PropertyDescriptor.getValue</code>, etc. are used to influence
+            a behavior of some code. This of course forms an interface that should
+            be documented. Also if one depends on some interface that an object
+            implements (<code>component instanceof Runnable</code>) that forms an
+            API as well.
+            </hint>
+        </question>
+-->
+<answer id="exec-component">
+No.
+</answer>
+<!--
+        <question id="exec-classloader" when="impl" >
+            Does your code create its own class loader(s)?
+            <hint>
+            A bit unusual. Please explain why and what for.
+            </hint>
+        </question>
+-->
+<answer id="exec-classloader">
+No.
+</answer>
+<!--
+        <question id="exec-reflection" when="impl" >
+            Does your code use Java Reflection to execute other code?
+            <hint>
+            This usually indicates a missing or insufficient API in the other
+            part of the system. If the other side is not aware of your dependency
+            this contract can be easily broken.
+            </hint>
+        </question>
+-->
+<answer id="exec-reflection">
+No.
+</answer>
+<!--
+        <question id="exec-privateaccess" when="final" >
+            Are you aware of any other parts of the system calling some of 
+            your methods by reflection?
+            <hint>
+            If so, describe the "contract" as an API. Likely private or friend one, but
+            still API and consider rewrite of it.
+            </hint>
+        </question>
+-->
+<answer id="exec-privateaccess">
+No.
+</answer>
+<!--
+        <question id="exec-process" when="impl" >
+            Do you execute an external process from your module? How do you ensure
+            that the result is the same on different platforms? Do you parse output?
+            Do you depend on result code?
+            <hint>
+            If you feed an input, parse the output please declare that as an API.
+            </hint>
+        </question>
+-->
+<answer id="exec-process">
+No.
+</answer>
+<!--
+        <question id="exec-introspection" when="impl" >
+            Does your module use any kind of runtime type information (<code>instanceof</code>,
+            work with <code>java.lang.Class</code>, etc.)?
+            <hint>
+            Check for cases when you have an object of type A and you also
+            expect it to (possibly) be of type B and do some special action. That
+            should be documented. The same applies on operations in meta-level
+            (Class.isInstance(...), Class.isAssignableFrom(...), etc.).
+            </hint>
+        </question>
+-->
+<answer id="exec-introspection">
+No.
+</answer>
+<!--
+        <question id="exec-threading" when="impl">
+            What threading models, if any, does your module adhere to?
+            <hint>
+                If your module calls foreign APIs which have a specific threading model,
+                indicate how you comply with the requirements for multithreaded access
+                (synchronization, mutexes, etc.) applicable to those APIs.
+                If your module defines any APIs, or has complex internal structures
+                that might be used from multiple threads, declare how you protect
+                data against concurrent access, race conditions, deadlocks, etc.,
+                and whether such rules are enforced by runtime warnings, errors, assertions, etc.
+                Examples: a class might be non-thread-safe (like Java Collections); might
+                be fully thread-safe (internal locking); might require access through a mutex
+                (and may or may not automatically acquire that mutex on behalf of a client method);
+                might be able to run only in the event queue; etc.
+                Also describe when any events are fired: synchronously, asynchronously, etc.
+                Ideas: <a href="http://core.netbeans.org/proposals/threading/index.html#recommendations">Threading Recommendations</a> (in progress)
+            </hint>
+        </question>
+-->
+<answer id="exec-threading">
+None.
+</answer>
+<!--
+    </category>
+    <category id="format" name="Format of files and protocols">
+        <question id="format-types" when="impl" >
+            Which protocols and file formats (if any) does your module read or write on disk,
+            or transmit or receive over the network?
+        </question>
+-->
+<answer id="format-types">
+None.
+</answer>
+<!--
+        <question id="format-dnd" when="impl" >
+            Which protocols (if any) does your code understand during Drag &amp; Drop?
+            <hint>
+            Often Node's deal with clipboard by usage of <code>Node.drag, Node.getDropType</code>. 
+            Check your code for overriding these methods. Btw. if they are not overridden, they
+            by default delegate to <code>Node.clipboardCopy, Node.clipboardCut and Node.pasteTypes</code>.
+            </hint>
+        </question>
+-->
+<answer id="format-dnd">
+Not applicable.
+</answer>
+<!--
+        <question id="format-clipboard" when="impl" >
+            Which data flavors (if any) does your code read from or insert to
+            the clipboard (by access to clipboard on means calling methods on <code>java.awt.datatransfer.Transferable</code>?
+            
+            <hint>
+            Often Node's deal with clipboard by usage of <code>Node.clipboardCopy, Node.clipboardCut and Node.pasteTypes</code>.
+            Check your code for overriding these methods.
+            </hint>
+        </question>
+-->
+<answer id="format-clipboard">
+Not applicable.
+</answer>
+<!--
+    </category>
+    <category id="performance" name="Performance and Scalability">
+        <question id="perf-startup" when="final" >
+            Does your module run any code on startup?
+        </question>
+-->
+<answer id="perf-startup">
+No.
+</answer>
+<!--
+        <question id="perf-exit" when="final">
+            Does your module run any code on exit?
+        </question>
+-->
+<answer id="perf-exit">
+No.
+</answer>
+<!--
+        <question id="perf-scale" when="init">
+            Which external criteria influence the performance of your
+            program (size of file in editor, number of files in menu, 
+            in source directory, etc.) and how well your code scales?
+            <hint>
+            Please include some estimates, there are other more detailed 
+            questions to answer in later phases of implementation. 
+            </hint>
+        </question>
+-->
+<answer id="perf-scale">
+Number of registered web module providers, number of open projects.
+No performance problems anticipated.
+</answer>
+<!--
+        <question id="perf-limit" when="init">
+            Are there any hard-coded or practical limits in the number or size of
+            elements your code can handle?
+        </question>
+-->
+<answer id="perf-limit">
+Not aware of any.
+</answer>
+        <!-- multithreading -->
+<!--
+        <question id="perf-mem" when="final" >
+            How much memory does your component consume? Estimate
+            with a relation to the number of windows, etc.
+        </question>
+-->
+<answer id="perf-mem">
+The memory consumption of this module does not grow with number of implementations,
+the memory would be consumed by the implementation modules.
+</answer>
+<!--
+        <question id="perf-wakeup" when="final">
+            Does any piece of your code wake up periodically and do something
+            even when the system is otherwise idle (no user interaction)?
+        </question>
+-->
+<answer id="perf-wakeupp">
+No.
+</answer>
+<!--
+        <question id="perf-progress" when="final">
+            Does your module execute any long-running tasks?
+            
+            <hint>Long running tasks should never block 
+            AWT thread as it badly hurts the UI
+            <a href="http://performance.netbeans.org/responsiveness/issues.html">
+            responsiveness</a>.
+            Tasks like connecting over
+            network, computing huge amount of data, compilation
+            be done asynchronously (for example
+            using <code>RequestProcessor</code>), definitively it should 
+            not block AWT thread.
+            </hint>
+        </question>
+-->
+<answer id="perf-progress">
+No.
+</answer>
+<!--
+        <question id="perf-huge_dialogs" when="final">
+            Does your module contain any dialogs or wizards with a large number of
+            GUI controls such as combo boxes, lists, trees, or text areas?
+        </question>
+-->
+<answer id="perf-huge_dialogs">
+No.
+</answer>
+<!--
+        <question id="perf-menus" when="final">
+            Does your module use dynamically updated context menus, or
+            context-sensitive actions with complicated enablement logic?
+        </question>
+-->
+<answer id="perf-menus">
+No.
+</answer>
+<!--
+        <question  id="perf-spi" when="init">
+            How the performance of the plugged in code will be enforced?
+            <hint>
+            If you allow foreign code to be plugged into your own module, how
+            do you enforce, that it will behave correctly and fast and will not
+            negatively influence the performance of your own module?
+            </hint>
+        </question>
+-->
+<answer id="perf-spi">
+<code>WebModuleProvider.findWebModule()</code> is the critical method for SPI performance 
+(both time and memory). It is expected that implementations will cache the results
+and that the implementation will be reasonably fast.
+</answer>
+
+
+<!--
+        <question id="exec-ant-tasks" when="impl">
+            Do you define or register any ant tasks that other can use?
+            
+            <hint>
+            If you provide an ant task that users can use, you need to be very
+            careful about its syntax and behaviour, as it most likely forms an
+	          API for end users and as there is a lot of end users, their reaction
+            when such API gets broken can be pretty strong.
+            </hint>
+        </question>
+-->
+ <answer id="exec-ant-tasks">
+  <p>
+   No
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="perf-wakeup" when="final">
+            Does any piece of your code wake up periodically and do something
+            even when the system is otherwise idle (no user interaction)?
+        </question>
+-->
+ <answer id="perf-wakeup">
+  <p>
+   No
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="security-grant" when="final">
+            Does your code grant additional rights to some other code?
+            <hint>Avoid using a class loader that adds extra
+            permissions to loaded code unless really necessary.
+            Also note that your API implementation
+            can also expose unneeded permissions to enemy code by
+            calling AccessController.doPrivileged().</hint>
+        </question>
+-->
+ <answer id="security-grant">
+  <p>
+   No
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="security-policy" when="final">
+            Does your functionality require modifications to the standard policy file?
+            <hint>Your code might pass control to third-party code not
+            coming from trusted domains. This could be code downloaded over the
+            network or code coming from libraries that are not bundled
+            with NetBeans. Which permissions need to be granted to which domains?</hint>
+        </question>
+-->
+ <answer id="security-policy">
+  <p>
+   No
+  </p>
+ </answer>
+
+
+
+
+
+
+<!--
+        <question id="arch-where" when="impl">
+            Where one can find sources for your module?
+            <hint>
+                Please provide link to the CVS web client at
+                http://www.netbeans.org/download/source_browse.html
+                or just use tag defaultanswer generate='here'
+            </hint>
+        </question>
+-->
+ <answer id="arch-where">
+  <defaultanswer generate='here' />
+ </answer>
+
+
+
+<!--
+        <question id="compat-deprecation" when="init">
+            How the introduction of your project influences functionality
+            provided by previous version of the product?
+            <hint>
+            If you are planning to deprecate/remove/change any existing APIs,
+            list them here accompanied with the reason explaining why you
+            are doing so.
+            </hint>
+        </question>
+-->
+ <answer id="compat-deprecation">
+  <p>
+   This module does not deprecate any existing APIs.
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="resources-preferences" when="final">
+            Does your module uses preferences via Preferences API? Does your module use NbPreferences or
+            or regular JDK Preferences ? Does it read, write or both ? 
+            Does it share preferences with other modules ? If so, then why ?
+            <hint>
+                You may use
+                    &lt;api type="export" group="preferences"
+                    name="preference node name" category="private"&gt;
+                    description of individual keys, where it is used, what it
+                    influences, whether the module reads/write it, etc.
+                    &lt;/api&gt;
+                Due to XML ID restrictions, rather than /org/netbeans/modules/foo give the "name" as org.netbeans.modules.foo.
+                Note that if you use NbPreferences this name will then be the same as the code name base of the module.
+            </hint>
+        </question>
+-->
+ <answer id="resources-preferences">
+  <p>
+   No.
+  </p>
+ </answer>
+
+</api-answers>
diff --git a/api.web.webmodule/build.xml b/api.web.webmodule/build.xml
new file mode 100644
index 0000000000..abac896683
--- /dev/null
+++ b/api.web.webmodule/build.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    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.
+
+-->
+<project basedir="." default="netbeans" name="api.web.webmodule">
+    <import file="../nbbuild/templates/projectized.xml"/>
+</project>
diff --git a/api.web.webmodule/manifest.mf b/api.web.webmodule/manifest.mf
new file mode 100644
index 0000000000..942c92a5ed
--- /dev/null
+++ b/api.web.webmodule/manifest.mf
@@ -0,0 +1,5 @@
+Manifest-Version: 1.0
+OpenIDE-Module: org.netbeans.api.web.webmodule
+OpenIDE-Module-Specification-Version: 1.42
+OpenIDE-Module-Layer: org/netbeans/modules/web/webmodule/resources/layer.xml
+OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/web/webmodule/Bundle.properties
diff --git a/api.web.webmodule/nbproject/org-netbeans-api-web-webmodule.sig b/api.web.webmodule/nbproject/org-netbeans-api-web-webmodule.sig
new file mode 100644
index 0000000000..f9f6f7c0e7
--- /dev/null
+++ b/api.web.webmodule/nbproject/org-netbeans-api-web-webmodule.sig
@@ -0,0 +1,371 @@
+#Signature file v4.1
+#Version 1.40.1
+
+CLSS public abstract interface !annotation java.lang.Deprecated
+ anno 0 java.lang.annotation.Documented()
+ anno 0 java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy value=RUNTIME)
+ anno 0 java.lang.annotation.Target(java.lang.annotation.ElementType[] value=[CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE])
+intf java.lang.annotation.Annotation
+
+CLSS public java.lang.Object
+cons public init()
+meth protected java.lang.Object clone() throws java.lang.CloneNotSupportedException
+meth protected void finalize() throws java.lang.Throwable
+meth public boolean equals(java.lang.Object)
+meth public final java.lang.Class<?> getClass()
+meth public final void notify()
+meth public final void notifyAll()
+meth public final void wait() throws java.lang.InterruptedException
+meth public final void wait(long) throws java.lang.InterruptedException
+meth public final void wait(long,int) throws java.lang.InterruptedException
+meth public int hashCode()
+meth public java.lang.String toString()
+
+CLSS public abstract interface java.lang.annotation.Annotation
+meth public abstract boolean equals(java.lang.Object)
+meth public abstract int hashCode()
+meth public abstract java.lang.Class<? extends java.lang.annotation.Annotation> annotationType()
+meth public abstract java.lang.String toString()
+
+CLSS public abstract interface !annotation java.lang.annotation.Documented
+ anno 0 java.lang.annotation.Documented()
+ anno 0 java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy value=RUNTIME)
+ anno 0 java.lang.annotation.Target(java.lang.annotation.ElementType[] value=[ANNOTATION_TYPE])
+intf java.lang.annotation.Annotation
+
+CLSS public abstract interface !annotation java.lang.annotation.Retention
+ anno 0 java.lang.annotation.Documented()
+ anno 0 java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy value=RUNTIME)
+ anno 0 java.lang.annotation.Target(java.lang.annotation.ElementType[] value=[ANNOTATION_TYPE])
+intf java.lang.annotation.Annotation
+meth public abstract java.lang.annotation.RetentionPolicy value()
+
+CLSS public abstract interface !annotation java.lang.annotation.Target
+ anno 0 java.lang.annotation.Documented()
+ anno 0 java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy value=RUNTIME)
+ anno 0 java.lang.annotation.Target(java.lang.annotation.ElementType[] value=[ANNOTATION_TYPE])
+intf java.lang.annotation.Annotation
+meth public abstract java.lang.annotation.ElementType[] value()
+
+CLSS public org.netbeans.modules.web.api.webmodule.ExtenderController
+innr public static Properties
+meth public java.lang.String getErrorMessage()
+meth public org.netbeans.modules.web.api.webmodule.ExtenderController$Properties getProperties()
+meth public static org.netbeans.modules.web.api.webmodule.ExtenderController create()
+meth public void setErrorMessage(java.lang.String)
+supr java.lang.Object
+hfds errorMessage,properties
+
+CLSS public static org.netbeans.modules.web.api.webmodule.ExtenderController$Properties
+ outer org.netbeans.modules.web.api.webmodule.ExtenderController
+cons public init()
+meth public java.lang.Object getProperty(java.lang.String)
+meth public java.util.Map<java.lang.String,java.lang.Object> getProperties()
+meth public void setProperty(java.lang.String,java.lang.Object)
+supr java.lang.Object
+hfds properties
+
+CLSS public final org.netbeans.modules.web.api.webmodule.RequestParametersQuery
+cons public init()
+meth public static java.lang.String getFileAndParameters(org.openide.filesystems.FileObject)
+supr java.lang.Object
+hfds implementations
+
+CLSS public final org.netbeans.modules.web.api.webmodule.WebFrameworks
+meth public static java.util.List<org.netbeans.modules.web.spi.webmodule.WebFrameworkProvider> getFrameworks()
+supr java.lang.Object
+hfds FRAMEWORK_PATH
+
+CLSS public final org.netbeans.modules.web.api.webmodule.WebModule
+fld public final static java.lang.String J2EE_13_LEVEL = "1.3"
+ anno 0 java.lang.Deprecated()
+fld public final static java.lang.String J2EE_14_LEVEL = "1.4"
+ anno 0 java.lang.Deprecated()
+fld public final static java.lang.String JAVA_EE_5_LEVEL = "1.5"
+ anno 0 java.lang.Deprecated()
+meth public java.lang.String getContextPath()
+meth public java.lang.String getJ2eePlatformVersion()
+meth public org.netbeans.api.j2ee.core.Profile getJ2eeProfile()
+meth public org.netbeans.modules.j2ee.metadata.model.api.MetadataModel<org.netbeans.modules.j2ee.dd.api.web.WebAppMetadata> getMetadataModel()
+meth public org.openide.filesystems.FileObject getDeploymentDescriptor()
+meth public org.openide.filesystems.FileObject getDocumentBase()
+meth public org.openide.filesystems.FileObject getWebInf()
+meth public org.openide.filesystems.FileObject[] getJavaSources()
+ anno 0 java.lang.Deprecated()
+meth public static org.netbeans.modules.web.api.webmodule.WebModule getWebModule(org.openide.filesystems.FileObject)
+supr java.lang.Object
+hfds impl,impl2,implementations
+
+CLSS public final org.netbeans.modules.web.api.webmodule.WebProjectConstants
+fld public final static java.lang.String ARTIFACT_TYPE_WAR = "war"
+fld public final static java.lang.String ARTIFACT_TYPE_WAR_EAR_ARCHIVE = "j2ee_ear_archive"
+fld public final static java.lang.String COMMAND_REDEPLOY = "redeploy"
+fld public final static java.lang.String TYPE_DOC_ROOT = "doc_root"
+fld public final static java.lang.String TYPE_WEB_INF = "web_inf"
+supr java.lang.Object
+
+CLSS public abstract interface org.netbeans.modules.web.spi.webmodule.FrameworkConfigurationPanel
+ anno 0 java.lang.Deprecated()
+intf org.openide.WizardDescriptor$Panel
+meth public abstract void enableComponents(boolean)
+
+CLSS public abstract interface org.netbeans.modules.web.spi.webmodule.RequestParametersQueryImplementation
+meth public abstract java.lang.String getFileAndParameters(org.openide.filesystems.FileObject)
+
+CLSS public abstract org.netbeans.modules.web.spi.webmodule.WebFrameworkProvider
+cons public init(java.lang.String,java.lang.String)
+meth public abstract boolean isInWebModule(org.netbeans.modules.web.api.webmodule.WebModule)
+meth public abstract java.io.File[] getConfigurationFiles(org.netbeans.modules.web.api.webmodule.WebModule)
+meth public boolean requiresWebXml()
+meth public java.lang.String getDescription()
+meth public java.lang.String getName()
+meth public java.lang.String getServletPath(org.openide.filesystems.FileObject)
+meth public java.util.Set extend(org.netbeans.modules.web.api.webmodule.WebModule)
+ anno 0 java.lang.Deprecated()
+meth public org.netbeans.modules.web.spi.webmodule.FrameworkConfigurationPanel getConfigurationPanel(org.netbeans.modules.web.api.webmodule.WebModule)
+ anno 0 java.lang.Deprecated()
+meth public org.netbeans.modules.web.spi.webmodule.WebModuleExtender createWebModuleExtender(org.netbeans.modules.web.api.webmodule.WebModule,org.netbeans.modules.web.api.webmodule.ExtenderController)
+supr java.lang.Object
+hfds description,name
+
+CLSS public abstract org.netbeans.modules.web.spi.webmodule.WebModuleExtender
+cons public init()
+innr public abstract interface static Savable
+meth public abstract boolean isValid()
+meth public abstract java.util.Set<org.openide.filesystems.FileObject> extend(org.netbeans.modules.web.api.webmodule.WebModule)
+meth public abstract javax.swing.JComponent getComponent()
+meth public abstract org.openide.util.HelpCtx getHelp()
+meth public abstract void addChangeListener(javax.swing.event.ChangeListener)
+meth public abstract void removeChangeListener(javax.swing.event.ChangeListener)
+meth public abstract void update()
+supr java.lang.Object
+
+CLSS public abstract interface static org.netbeans.modules.web.spi.webmodule.WebModuleExtender$Savable
+ outer org.netbeans.modules.web.spi.webmodule.WebModuleExtender
+meth public abstract void save(org.netbeans.modules.web.api.webmodule.WebModule)
+ anno 1 org.netbeans.api.annotations.common.NonNull()
+
+CLSS public final org.netbeans.modules.web.spi.webmodule.WebModuleFactory
+meth public static org.netbeans.modules.web.api.webmodule.WebModule createWebModule(org.netbeans.modules.web.spi.webmodule.WebModuleImplementation)
+meth public static org.netbeans.modules.web.api.webmodule.WebModule createWebModule(org.netbeans.modules.web.spi.webmodule.WebModuleImplementation2)
+supr java.lang.Object
+
+CLSS public abstract interface org.netbeans.modules.web.spi.webmodule.WebModuleImplementation
+meth public abstract java.lang.String getContextPath()
+meth public abstract java.lang.String getJ2eePlatformVersion()
+meth public abstract org.netbeans.modules.j2ee.metadata.model.api.MetadataModel<org.netbeans.modules.j2ee.dd.api.web.WebAppMetadata> getMetadataModel()
+meth public abstract org.openide.filesystems.FileObject getDeploymentDescriptor()
+meth public abstract org.openide.filesystems.FileObject getDocumentBase()
+meth public abstract org.openide.filesystems.FileObject getWebInf()
+meth public abstract org.openide.filesystems.FileObject[] getJavaSources()
+ anno 0 java.lang.Deprecated()
+
+CLSS public abstract interface org.netbeans.modules.web.spi.webmodule.WebModuleImplementation2
+fld public final static java.lang.String PROPERTY_DOCUMENT_BASE = "documentBase"
+fld public final static java.lang.String PROPERTY_WEB_INF = "webInf"
+meth public abstract java.lang.String getContextPath()
+meth public abstract org.netbeans.api.j2ee.core.Profile getJ2eeProfile()
+meth public abstract org.netbeans.modules.j2ee.metadata.model.api.MetadataModel<org.netbeans.modules.j2ee.dd.api.web.WebAppMetadata> getMetadataModel()
+meth public abstract org.openide.filesystems.FileObject getDeploymentDescriptor()
+meth public abstract org.openide.filesystems.FileObject getDocumentBase()
+meth public abstract org.openide.filesystems.FileObject getWebInf()
+meth public abstract org.openide.filesystems.FileObject[] getJavaSources()
+ anno 0 java.lang.Deprecated()
+meth public abstract void addPropertyChangeListener(java.beans.PropertyChangeListener)
+meth public abstract void removePropertyChangeListener(java.beans.PropertyChangeListener)
+
+CLSS public abstract interface org.netbeans.modules.web.spi.webmodule.WebModuleProvider
+meth public abstract org.netbeans.modules.web.api.webmodule.WebModule findWebModule(org.openide.filesystems.FileObject)
+
+CLSS public abstract interface org.netbeans.modules.web.spi.webmodule.WebPrivilegedTemplates
+meth public abstract java.lang.String[] getPrivilegedTemplates(org.netbeans.modules.web.api.webmodule.WebModule)
+
+CLSS public org.openide.DialogDescriptor
+cons public init(java.lang.Object,java.lang.String)
+cons public init(java.lang.Object,java.lang.String,boolean,int,java.lang.Object,int,org.openide.util.HelpCtx,java.awt.event.ActionListener)
+cons public init(java.lang.Object,java.lang.String,boolean,int,java.lang.Object,java.awt.event.ActionListener)
+cons public init(java.lang.Object,java.lang.String,boolean,java.awt.event.ActionListener)
+cons public init(java.lang.Object,java.lang.String,boolean,java.lang.Object[],java.lang.Object,int,org.openide.util.HelpCtx,java.awt.event.ActionListener)
+cons public init(java.lang.Object,java.lang.String,boolean,java.lang.Object[],java.lang.Object,int,org.openide.util.HelpCtx,java.awt.event.ActionListener,boolean)
+fld public final static int BOTTOM_ALIGN = 0
+fld public final static int DEFAULT_ALIGN = 0
+fld public final static int RIGHT_ALIGN = 1
+fld public final static java.lang.String PROP_BUTTON_LISTENER = "buttonListener"
+fld public final static java.lang.String PROP_CLOSING_OPTIONS = "closingOptions"
+fld public final static java.lang.String PROP_HELP_CTX = "helpCtx"
+fld public final static java.lang.String PROP_LEAF = "leaf"
+fld public final static java.lang.String PROP_MODAL = "modal"
+fld public final static java.lang.String PROP_OPTIONS_ALIGN = "optionsAlign"
+intf org.openide.util.HelpCtx$Provider
+meth public boolean isLeaf()
+meth public boolean isModal()
+meth public int getOptionsAlign()
+meth public java.awt.event.ActionListener getButtonListener()
+meth public java.lang.Object[] getClosingOptions()
+meth public org.openide.util.HelpCtx getHelpCtx()
+meth public void setButtonListener(java.awt.event.ActionListener)
+meth public void setClosingOptions(java.lang.Object[])
+meth public void setHelpCtx(org.openide.util.HelpCtx)
+meth public void setLeaf(boolean)
+meth public void setModal(boolean)
+meth public void setOptionsAlign(int)
+supr org.openide.NotifyDescriptor
+hfds DEFAULT_CLOSING_OPTIONS,buttonListener,closingOptions,helpCtx,leaf,modal,optionsAlign
+
+CLSS public org.openide.NotifyDescriptor
+cons public init(java.lang.Object,java.lang.String,int,int,java.lang.Object[],java.lang.Object)
+fld public final static int DEFAULT_OPTION = -1
+fld public final static int ERROR_MESSAGE = 0
+fld public final static int INFORMATION_MESSAGE = 1
+fld public final static int OK_CANCEL_OPTION = 2
+fld public final static int PLAIN_MESSAGE = -1
+fld public final static int QUESTION_MESSAGE = 3
+fld public final static int WARNING_MESSAGE = 2
+fld public final static int YES_NO_CANCEL_OPTION = 1
+fld public final static int YES_NO_OPTION = 0
+fld public final static java.lang.Object CANCEL_OPTION
+fld public final static java.lang.Object CLOSED_OPTION
+fld public final static java.lang.Object NO_OPTION
+fld public final static java.lang.Object OK_OPTION
+fld public final static java.lang.Object YES_OPTION
+fld public final static java.lang.String PROP_DETAIL = "detail"
+fld public final static java.lang.String PROP_ERROR_NOTIFICATION = "errorNotification"
+fld public final static java.lang.String PROP_INFO_NOTIFICATION = "infoNotification"
+fld public final static java.lang.String PROP_MESSAGE = "message"
+fld public final static java.lang.String PROP_MESSAGE_TYPE = "messageType"
+fld public final static java.lang.String PROP_NO_DEFAULT_CLOSE = "noDefaultClose"
+fld public final static java.lang.String PROP_OPTIONS = "options"
+fld public final static java.lang.String PROP_OPTION_TYPE = "optionType"
+fld public final static java.lang.String PROP_TITLE = "title"
+fld public final static java.lang.String PROP_VALID = "valid"
+fld public final static java.lang.String PROP_VALUE = "value"
+fld public final static java.lang.String PROP_WARNING_NOTIFICATION = "warningNotification"
+innr public final static Exception
+innr public static Confirmation
+innr public static InputLine
+innr public static Message
+meth protected static java.lang.String getTitleForType(int)
+meth protected void firePropertyChange(java.lang.String,java.lang.Object,java.lang.Object)
+meth protected void initialize()
+meth public boolean isNoDefaultClose()
+meth public final boolean isValid()
+meth public final org.openide.NotificationLineSupport createNotificationLineSupport()
+meth public final org.openide.NotificationLineSupport getNotificationLineSupport()
+meth public final void setValid(boolean)
+meth public int getMessageType()
+meth public int getOptionType()
+meth public java.lang.Object getDefaultValue()
+meth public java.lang.Object getMessage()
+meth public java.lang.Object getValue()
+meth public java.lang.Object[] getAdditionalOptions()
+meth public java.lang.Object[] getOptions()
+meth public java.lang.String getTitle()
+meth public void addPropertyChangeListener(java.beans.PropertyChangeListener)
+meth public void removePropertyChangeListener(java.beans.PropertyChangeListener)
+meth public void setAdditionalOptions(java.lang.Object[])
+meth public void setMessage(java.lang.Object)
+meth public void setMessageType(int)
+meth public void setNoDefaultClose(boolean)
+meth public void setOptionType(int)
+meth public void setOptions(java.lang.Object[])
+meth public void setTitle(java.lang.String)
+meth public void setValue(java.lang.Object)
+supr java.lang.Object
+hfds MAXIMUM_TEXT_WIDTH,SIZE_PREFERRED_HEIGHT,SIZE_PREFERRED_WIDTH,adOptions,changeSupport,defaultValue,errMsg,infoMsg,message,messageType,noDefaultClose,notificationLineSupport,optionType,options,title,valid,value,warnMsg
+
+CLSS public org.openide.WizardDescriptor
+cons protected init()
+cons public <%0 extends java.lang.Object> init(org.openide.WizardDescriptor$Iterator<{%%0}>,{%%0})
+cons public <%0 extends java.lang.Object> init(org.openide.WizardDescriptor$Panel<{%%0}>[],{%%0})
+cons public init(org.openide.WizardDescriptor$Iterator<org.openide.WizardDescriptor>)
+cons public init(org.openide.WizardDescriptor$Panel<org.openide.WizardDescriptor>[])
+fld public final static java.lang.Object FINISH_OPTION
+fld public final static java.lang.Object NEXT_OPTION
+fld public final static java.lang.Object PREVIOUS_OPTION
+fld public final static java.lang.String PROP_AUTO_WIZARD_STYLE = "WizardPanel_autoWizardStyle"
+fld public final static java.lang.String PROP_CONTENT_BACK_COLOR = "WizardPanel_contentBackColor"
+fld public final static java.lang.String PROP_CONTENT_DATA = "WizardPanel_contentData"
+fld public final static java.lang.String PROP_CONTENT_DISPLAYED = "WizardPanel_contentDisplayed"
+fld public final static java.lang.String PROP_CONTENT_FOREGROUND_COLOR = "WizardPanel_contentForegroundColor"
+fld public final static java.lang.String PROP_CONTENT_NUMBERED = "WizardPanel_contentNumbered"
+fld public final static java.lang.String PROP_CONTENT_SELECTED_INDEX = "WizardPanel_contentSelectedIndex"
+fld public final static java.lang.String PROP_ERROR_MESSAGE = "WizardPanel_errorMessage"
+fld public final static java.lang.String PROP_HELP_DISPLAYED = "WizardPanel_helpDisplayed"
+fld public final static java.lang.String PROP_HELP_URL = "WizardPanel_helpURL"
+fld public final static java.lang.String PROP_IMAGE = "WizardPanel_image"
+fld public final static java.lang.String PROP_IMAGE_ALIGNMENT = "WizardPanel_imageAlignment"
+fld public final static java.lang.String PROP_INFO_MESSAGE = "WizardPanel_infoMessage"
+fld public final static java.lang.String PROP_LEFT_DIMENSION = "WizardPanel_leftDimension"
+fld public final static java.lang.String PROP_WARNING_MESSAGE = "WizardPanel_warningMessage"
+innr public abstract interface static AsynchronousInstantiatingIterator
+innr public abstract interface static AsynchronousValidatingPanel
+innr public abstract interface static BackgroundInstantiatingIterator
+innr public abstract interface static ExtendedAsynchronousValidatingPanel
+innr public abstract interface static FinishPanel
+innr public abstract interface static FinishablePanel
+innr public abstract interface static InstantiatingIterator
+innr public abstract interface static Iterator
+innr public abstract interface static Panel
+innr public abstract interface static ProgressInstantiatingIterator
+innr public abstract interface static ValidatingPanel
+innr public static ArrayIterator
+meth protected void initialize()
+meth protected void updateState()
+meth public final <%0 extends java.lang.Object> void setPanelsAndSettings(org.openide.WizardDescriptor$Iterator<{%%0}>,{%%0})
+meth public final void doCancelClick()
+meth public final void doFinishClick()
+meth public final void doNextClick()
+meth public final void doPreviousClick()
+meth public final void setPanels(org.openide.WizardDescriptor$Iterator)
+ anno 0 java.lang.Deprecated()
+meth public java.lang.Object getProperty(java.lang.String)
+meth public java.lang.Object getValue()
+meth public java.text.MessageFormat getTitleFormat()
+meth public java.util.Map<java.lang.String,java.lang.Object> getProperties()
+meth public java.util.Set getInstantiatedObjects()
+meth public void putProperty(java.lang.String,java.lang.Object)
+meth public void setAdditionalOptions(java.lang.Object[])
+meth public void setClosingOptions(java.lang.Object[])
+meth public void setHelpCtx(org.openide.util.HelpCtx)
+meth public void setOptions(java.lang.Object[])
+meth public void setTitleFormat(java.text.MessageFormat)
+meth public void setValue(java.lang.Object)
+supr org.openide.DialogDescriptor
+hfds ASYNCHRONOUS_JOBS_RP,CLOSE_PREVENTER,PROGRESS_BAR_DISPLAY_NAME,addedWindowListener,autoWizardStyle,backgroundValidationTask,baseListener,bundle,cancelButton,changeStateInProgress,contentBackColor,contentData,contentForegroundColor,contentSelectedIndex,currentPanelWasChangedWhileStoreSettings,data,err,escapeActionListener,finishButton,finishOption,handle,helpURL,image,imageAlignment,init,initialized,isWizardWideHelpSet,logged,newObjects,nextButton,previousButton,propListener,properties,titleFormat,validationRuns,waitingComponent,weakCancelButtonListener,weakChangeListener,weakFinishButtonListener,weakNextButtonListener,weakPreviousButtonListener,weakPropertyChangeListener,wizardPanel
+hcls BoundedHtmlBrowser,EmptyPanel,FinishAction,FixedHeightLabel,FixedHeightPane,ImagedPanel,Listener,PropL,SettingsAndIterator,WizardPanel,WrappedCellRenderer
+
+CLSS public abstract interface static org.openide.WizardDescriptor$Panel<%0 extends java.lang.Object>
+ outer org.openide.WizardDescriptor
+meth public abstract boolean isValid()
+meth public abstract java.awt.Component getComponent()
+meth public abstract org.openide.util.HelpCtx getHelp()
+meth public abstract void addChangeListener(javax.swing.event.ChangeListener)
+meth public abstract void readSettings({org.openide.WizardDescriptor$Panel%0})
+meth public abstract void removeChangeListener(javax.swing.event.ChangeListener)
+meth public abstract void storeSettings({org.openide.WizardDescriptor$Panel%0})
+
+CLSS public final org.openide.util.HelpCtx
+cons public init(java.lang.Class<?>)
+ anno 0 java.lang.Deprecated()
+cons public init(java.lang.String)
+cons public init(java.net.URL)
+ anno 0 java.lang.Deprecated()
+fld public final static org.openide.util.HelpCtx DEFAULT_HELP
+innr public abstract interface static Displayer
+innr public abstract interface static Provider
+meth public boolean display()
+meth public boolean equals(java.lang.Object)
+meth public int hashCode()
+meth public java.lang.String getHelpID()
+meth public java.lang.String toString()
+meth public java.net.URL getHelp()
+meth public static org.openide.util.HelpCtx findHelp(java.awt.Component)
+meth public static org.openide.util.HelpCtx findHelp(java.lang.Object)
+meth public static void setHelpIDString(javax.swing.JComponent,java.lang.String)
+supr java.lang.Object
+hfds err,helpCtx,helpID
+
+CLSS public abstract interface static org.openide.util.HelpCtx$Provider
+ outer org.openide.util.HelpCtx
+meth public abstract org.openide.util.HelpCtx getHelpCtx()
+
diff --git a/api.web.webmodule/nbproject/project.properties b/api.web.webmodule/nbproject/project.properties
new file mode 100644
index 0000000000..2336b2a81e
--- /dev/null
+++ b/api.web.webmodule/nbproject/project.properties
@@ -0,0 +1,25 @@
+# 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.
+
+javac.source=1.6
+javac.compilerargs=-Xlint -Xlint:-serial
+
+is.autoload=true
+javadoc.arch=${basedir}/arch.xml
+javadoc.apichanges=${basedir}/apichanges.xml
+
+test.config.stableBTD.includes=**/*Test.class
diff --git a/api.web.webmodule/nbproject/project.xml b/api.web.webmodule/nbproject/project.xml
new file mode 100644
index 0000000000..efb62f9ff9
--- /dev/null
+++ b/api.web.webmodule/nbproject/project.xml
@@ -0,0 +1,189 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    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.
+
+-->
+<project xmlns="http://www.netbeans.org/ns/project/1">
+    <type>org.netbeans.modules.apisupport.project</type>
+    <configuration>
+        <data xmlns="http://www.netbeans.org/ns/nb-module-project/3">
+            <code-name-base>org.netbeans.api.web.webmodule</code-name-base>
+            <module-dependencies>
+                <dependency>
+                    <code-name-base>org.netbeans.api.annotations.common</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>1</release-version>
+                        <specification-version>1.11</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.api.java</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>1</release-version>
+                        <specification-version>1.18</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.api.java.classpath</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>1</release-version>
+                        <specification-version>1.0</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.modules.j2ee.core</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>0-1</release-version>
+                        <specification-version>1.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.modules.j2ee.dd</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>1</release-version>
+                        <specification-version>1.10</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.modules.j2ee.metadata</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>0</release-version>
+                        <specification-version>1.2</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.modules.projectapi</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>1</release-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.dialogs</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>7.8</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.filesystems</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>9.0</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.loaders</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                      <specification-version>7.61</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.nodes</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>7.23</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.util.ui</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>9.3</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.util</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>9.3</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.0</specification-version>
+                    </run-dependency>
+                </dependency>
+            </module-dependencies>
+            <test-dependencies>
+                <test-type>
+                    <name>unit</name>
+                    <test-dependency>
+                        <code-name-base>org.netbeans.api.web.webmodule</code-name-base>
+                        <recursive/>
+                        <compile-dependency/>
+                    </test-dependency>
+                    <test-dependency>
+                        <code-name-base>org.netbeans.libs.junit4</code-name-base>
+                        <compile-dependency/>
+                    </test-dependency>
+                    <test-dependency>
+                        <code-name-base>org.netbeans.modules.masterfs</code-name-base>
+                    </test-dependency>
+                    <test-dependency>
+                        <code-name-base>org.netbeans.modules.nbjunit</code-name-base>
+                        <recursive/>
+                        <compile-dependency/>
+                    </test-dependency>
+                    <test-dependency>
+                        <code-name-base>org.netbeans.modules.projectapi.nb</code-name-base>
+                        <compile-dependency/>
+                    </test-dependency>
+                    <test-dependency>
+                        <code-name-base>org.openide.util.ui</code-name-base>
+                        <compile-dependency/>
+                        <test/>
+                    </test-dependency>
+                    <test-dependency>
+                        <code-name-base>org.openide.util.lookup</code-name-base>
+                        <compile-dependency/>
+                        <test/>
+                    </test-dependency>
+                </test-type>
+            </test-dependencies>
+            <public-packages>
+                <package>org.netbeans.modules.web.api.webmodule</package>
+                <package>org.netbeans.modules.web.spi.webmodule</package>
+            </public-packages>
+        </data>
+    </configuration>
+</project>
diff --git a/api.web.webmodule/src/org/netbeans/modules/web/api/webmodule/ExtenderController.java b/api.web.webmodule/src/org/netbeans/modules/web/api/webmodule/ExtenderController.java
new file mode 100644
index 0000000000..34bfc74879
--- /dev/null
+++ b/api.web.webmodule/src/org/netbeans/modules/web/api/webmodule/ExtenderController.java
@@ -0,0 +1,128 @@
+/*
+ * 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.web.api.webmodule;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import org.openide.util.Parameters;
+
+/**
+ * This class allows a {@link org.netbeans.modules.web.spi.webmodule.WebModuleExtender}
+ * to communicate with its environment.
+ *
+ * @author Andrei Badea
+ *
+ * @since 1.9
+ */
+public class ExtenderController {
+
+    private final Properties properties = new Properties();
+    private String errorMessage;
+
+    /**
+     * Creates a new controller.
+     *
+     * @return a new controller.
+     */
+    public static ExtenderController create() {
+        return new ExtenderController();
+    }
+
+    private ExtenderController() {
+    }
+
+    /**
+     * Gets the error message for this controller.
+     *
+     * @return the error message or null if there is no error message.
+     */
+    public String getErrorMessage() {
+        return errorMessage;
+    }
+
+    /**
+     * Sets an error message for this controller, which creator of the controller
+     * may use to e.g. display it in the UI.
+     *
+     * @param  errorMessage the error message; can be null if there is no error message.
+     */
+    public void setErrorMessage(String errorMessage) {
+        this.errorMessage = errorMessage;
+    }
+
+    /**
+     * Returns the properties of this controller. This allows the creator
+     * of the controller to communicate with the extenders. Usually
+     * the creator of the controller will set some properties and then call
+     * {@link org.netbeans.modules.web.spi.webmodule.WebModuleExtender#update}
+     * to let the extender know that the properties have changed.
+     *
+     * @return an instance of {@link Properties}; never null.
+     */
+    public Properties getProperties() {
+        return properties;
+    }
+
+    /**
+     * Encapsulates the properties of an {@link ExtenderController}, which are
+     * arbitrary <code>Object</code> values with a <code>String</code> name.
+     */
+    public static class Properties {
+
+        private final Map<String, Object> properties = new HashMap<String, Object>();
+
+        /**
+         * Return the value of a given property.
+         *
+         * @param  name the property name; never null.
+         * @return the property value; can be null.
+         * @throws NullPointerException if the <code>name</code> parameter is null.
+         */
+        public Object getProperty(String name) {
+            Parameters.notNull("name", name); // NOI18N
+            return properties.get(name);
+        }
+
+        /**
+         * Sets the value of a property.
+         *
+         * @param  name the property name; never null.
+         * @param  value the property value; can be null.
+         * @throws NullPointerException if the <code>name</code> parameter is null.
+         */
+        public void setProperty(String name, Object value) {
+            Parameters.notNull("name", name); // NOI18N
+            if (value != null) {
+                properties.put(name, value);
+            } else {
+                properties.remove(name);
+            }
+        }
+
+        /**
+         * Returns a {@link java.util.Map} containing all properties.
+         *
+         * @return a map containinig all properties; never null.
+         */
+        public Map<String, Object> getProperties() {
+            return Collections.unmodifiableMap(new HashMap<String, Object>(properties));
+        }
+    }
+}
diff --git a/api.web.webmodule/src/org/netbeans/modules/web/api/webmodule/RequestParametersQuery.java b/api.web.webmodule/src/org/netbeans/modules/web/api/webmodule/RequestParametersQuery.java
new file mode 100644
index 0000000000..28346af43a
--- /dev/null
+++ b/api.web.webmodule/src/org/netbeans/modules/web/api/webmodule/RequestParametersQuery.java
@@ -0,0 +1,56 @@
+/*
+ * 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.web.api.webmodule;
+
+import org.openide.filesystems.FileObject;
+import org.openide.util.Lookup;
+import org.netbeans.modules.web.spi.webmodule.RequestParametersQueryImplementation;
+import org.openide.util.Parameters;
+
+/**
+ * This query serves for executing single file in the server.
+ * It returns the request parameters for a given file.
+ *
+ * @see org.netbeans.modules.web.spi.webmodule.RequestParametersQueryImplementation
+ *
+ * @author Pavel Buzek
+ */
+public final class RequestParametersQuery {
+
+    private static final Lookup.Result<RequestParametersQueryImplementation> implementations =
+        Lookup.getDefault().lookupResult(RequestParametersQueryImplementation.class);
+
+    /**
+     * Returns the part of URL for access the file. It can include the query string.
+     * @param  file the file to find the request parameters for.
+     * @return path from the context; can be null.
+     * @throws NullPointerException if the <code>file</code> parameter is null.
+     */
+    public static String getFileAndParameters(FileObject file) {
+        Parameters.notNull("file", file); // NOI18N
+        for (RequestParametersQueryImplementation impl : implementations.allInstances()) {
+            String params = impl.getFileAndParameters(file);
+            if (params != null) {
+                return params;
+            }
+        }
+        return null;
+    }
+}
diff --git a/api.web.webmodule/src/org/netbeans/modules/web/api/webmodule/WebFrameworks.java b/api.web.webmodule/src/org/netbeans/modules/web/api/webmodule/WebFrameworks.java
new file mode 100644
index 0000000000..e68e920989
--- /dev/null
+++ b/api.web.webmodule/src/org/netbeans/modules/web/api/webmodule/WebFrameworks.java
@@ -0,0 +1,49 @@
+/*
+ * 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.web.api.webmodule;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import org.netbeans.modules.web.spi.webmodule.WebFrameworkProvider;
+import org.openide.util.lookup.Lookups;
+
+/**
+ * This class provides access to the list of registered web frameworks.
+ *
+ *  @author Petr Pisl
+ **/
+public final class WebFrameworks {
+
+    private static final String FRAMEWORK_PATH = "j2ee/webtier/framework"; //NOI18N
+
+    private WebFrameworks() {}
+
+    /**
+     * This method returns all registered {@link org.netbeans.modules.web.spi.webmodule.WebFrameworkProvider}s.
+     *
+     * @return a list of all registered {@link org.netbeans.modules.web.spi.webmodule.WebFrameworkProvider}s; never null.
+     */
+    public static List <WebFrameworkProvider> getFrameworks() {
+       Collection <? extends WebFrameworkProvider> providers =
+                Lookups.forPath(FRAMEWORK_PATH).lookupAll(WebFrameworkProvider.class);
+        return new ArrayList<WebFrameworkProvider>(providers);
+    }
+}
diff --git a/api.web.webmodule/src/org/netbeans/modules/web/api/webmodule/WebModule.java b/api.web.webmodule/src/org/netbeans/modules/web/api/webmodule/WebModule.java
new file mode 100644
index 0000000000..b8555a8971
--- /dev/null
+++ b/api.web.webmodule/src/org/netbeans/modules/web/api/webmodule/WebModule.java
@@ -0,0 +1,232 @@
+/*
+ * 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.web.api.webmodule;
+
+import java.util.Iterator;
+import org.netbeans.api.j2ee.core.Profile;
+import org.netbeans.modules.j2ee.dd.api.web.WebAppMetadata;
+import org.netbeans.modules.j2ee.metadata.model.api.MetadataModel;
+import org.netbeans.modules.web.spi.webmodule.WebModuleImplementation;
+import org.netbeans.modules.web.spi.webmodule.WebModuleImplementation2;
+import org.netbeans.modules.web.spi.webmodule.WebModuleProvider;
+import org.netbeans.modules.web.webmodule.WebModuleAccessor;
+import org.openide.filesystems.FileObject;
+import org.openide.util.Lookup;
+import org.openide.util.Parameters;
+
+/**
+ * This class encapsulates a web module.
+ * 
+ * <p>A client may obtain a <code>WebModule</code> instance using
+ * method {@link #getWebModule}, for any
+ * {@link org.openide.filesystems.FileObject} in the web module directory structure.</p>
+ * <div class="nonnormative">
+ * <p>Use the classpath API to obtain the classpath for the document base (this classpath
+ * is used for code completion of JSPs). An example:</p>
+ * <pre>
+ *     WebModule wm = ...;
+ *     FileObject docRoot = wm.getDocumentBase ();
+ *     ClassPath cp = ClassPath.getClassPath(docRoot, ClassPath.EXECUTE);
+ * </pre>
+ * <p>Note that no particular directory structure for web module is guaranteed 
+ * by this API.</p>
+ * </div>
+ *
+ * @author  Pavel Buzek
+ */
+public final class WebModule {
+
+    @Deprecated
+    public static final String J2EE_13_LEVEL = "1.3"; //NOI18N
+
+    @Deprecated
+    public static final String J2EE_14_LEVEL = "1.4"; //NOI18N
+
+    @Deprecated
+    public static final String JAVA_EE_5_LEVEL = "1.5"; //NOI18N
+
+    @SuppressWarnings("deprecation")
+    private final WebModuleImplementation impl;
+
+    private final WebModuleImplementation2 impl2;
+
+    private static final Lookup.Result implementations =
+            Lookup.getDefault().lookupResult(WebModuleProvider.class);
+    
+    static  {
+        WebModuleAccessor.setDefault(new WebModuleAccessor() {
+
+            @Override
+            public WebModule createWebModule(WebModuleImplementation spiWebmodule) {
+                return new WebModule(spiWebmodule, null);
+            }
+
+            @Override
+            public WebModule createWebModule(WebModuleImplementation2 spiWebmodule) {
+                return new WebModule(null, spiWebmodule);
+            }
+        });
+    }
+
+    @SuppressWarnings("deprecation")
+    private WebModule (WebModuleImplementation impl, WebModuleImplementation2 impl2) {
+        assert (impl != null && impl2 == null) || (impl == null && impl2 != null);
+        this.impl = impl;
+        this.impl2 = impl2;
+    }
+    
+    /**
+     * Finds the web module that a given file belongs to. The given file should
+     * be one known to be owned by a web module (e.g., it can be a file in a
+     * Java source group, such as a servlet, or it can be a file in the document
+     * base, such as a JSP page).
+     *
+     * @param  file the file to find the web module for; never null.
+     * @return the web module this file belongs to or null if the file does not belong
+     *         to any web module.
+     * @throws NullPointerException if the <code>file</code> parameter is null.
+     */
+    public static WebModule getWebModule (FileObject file) {
+        Parameters.notNull("file", file); // NOI18N
+        Iterator it = implementations.allInstances().iterator();
+        while (it.hasNext()) {
+            WebModuleProvider impl = (WebModuleProvider)it.next();
+            WebModule wm = impl.findWebModule (file);
+            if (wm != null) {
+                return wm;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Returns the folder that contains sources of the static documents for
+     * the web module (html, JSPs, etc.).
+     *
+     * @return the static documents folder; can be null.
+     */
+    public FileObject getDocumentBase () {
+        if (impl2 != null) {
+            return impl2.getDocumentBase ();
+        }
+        return impl.getDocumentBase ();
+    }
+    
+    /**
+     * Returns the WEB-INF folder for the web module.
+     * It may return null for web module that does not have any WEB-INF folder.
+     * <div class="nonnormative">
+     * <p>The WEB-INF folder would typically be a child of the folder returned
+     * by {@link #getDocumentBase} but does not need to be.</p>
+     * </div>
+     *
+     * @return the WEB-INF folder; can be null.
+     */
+    public FileObject getWebInf () {
+        if (impl2 != null) {
+            return impl2.getWebInf();
+        }
+        return impl.getWebInf ();
+    }
+
+    /**
+     * Returns the deployment descriptor (<code>web.xml</code> file) of the web module.
+     * <div class="nonnormative">
+     * The web.xml file would typically be a child of the folder returned
+     * by {@link #getWebInf} but does not need to be.
+     * </div>
+     *
+     * @return the <code>web.xml</code> file; can be null.
+     */
+    public FileObject getDeploymentDescriptor () {
+        if (impl2 != null) {
+            return impl2.getDeploymentDescriptor();
+        }
+        return impl.getDeploymentDescriptor ();
+    }
+    
+    /**
+     * Returns the context path of the web module.
+     *
+     * @return the context path; can be null.
+     */
+    public String getContextPath () {
+        if (impl2 != null) {
+            return impl2.getContextPath();
+        }
+        return impl.getContextPath ();
+    }
+    
+    /**
+     * Returns the J2EE platform version of this module. The returned value is
+     * one of the properties string for constants defined in {@link Profile}.
+     *
+     * @return J2EE platform version; never null.
+     * @deprecated use {@link #getJ2eeProfile()}
+     */
+    public String getJ2eePlatformVersion () {
+        if (impl2 != null) {
+            return impl2.getJ2eeProfile().toPropertiesString();
+        }
+        return impl.getJ2eePlatformVersion();
+    }
+
+    public Profile getJ2eeProfile() {
+         if (impl2 != null) {
+            return impl2.getJ2eeProfile();
+        }
+        return Profile.fromPropertiesString(impl.getJ2eePlatformVersion());
+    }
+    
+    /**
+     * Returns the Java source roots associated with the web module.
+     * <div class="nonnormative">
+     * <p>Note that not all the java source roots in the project (e.g. in a freeform project)
+     * belong to the web module.</p>
+     * </div>
+     *
+     * @return this web module's Java source roots; never null.
+     *
+     * @deprecated This method is deprecated, because its return values does
+     * not contain enough information about the source roots. Source roots
+     * are usually implemented by a <code>org.netbeans.api.project.SourceGroup</code>,
+     * which is more than just a container for a {@link org.openide.filesystems.FileObject}.
+     */
+    @Deprecated
+    public FileObject[] getJavaSources() {
+        if (impl2 != null) {
+            return impl2.getJavaSources();
+        }
+        return impl.getJavaSources();
+    }
+
+    /**
+     * Returns a model describing the metadata of this web module (servlets,
+     * resources, etc.).
+     *
+     * @return this web module's metadata model; never null.
+     */
+    public MetadataModel<WebAppMetadata> getMetadataModel() {
+        if (impl2 != null) {
+            return impl2.getMetadataModel();
+        }
+        return impl.getMetadataModel();
+    }
+}
diff --git a/api.web.webmodule/src/org/netbeans/modules/web/api/webmodule/WebProjectConstants.java b/api.web.webmodule/src/org/netbeans/modules/web/api/webmodule/WebProjectConstants.java
new file mode 100644
index 0000000000..5efce8d9bd
--- /dev/null
+++ b/api.web.webmodule/src/org/netbeans/modules/web/api/webmodule/WebProjectConstants.java
@@ -0,0 +1,61 @@
+/*
+ * 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.web.api.webmodule;
+
+/**
+ * Constants useful for web-based projects.
+ *
+ * @author  Milan Kuchtiak
+ */
+public final class WebProjectConstants {
+
+    private WebProjectConstants () {}
+
+    /**
+     * Document root root sources type (source folders for JSPs, HTML, ...).
+     * See <code>org.netbeans.api.project.Sources</code>.
+     */
+    public static final String TYPE_DOC_ROOT="doc_root"; //NOI18N
+
+    /**
+     * WEB-INF sources type (source folders for TLD files, ...).
+     * See <code>org.netbeans.api.project.Sources</code>.
+     */
+    public static final String TYPE_WEB_INF="web_inf"; //NOI18N
+    
+    /**
+     * Standard command for redeploying a web project.
+     * See <code>org.netbeans.api.project.ActionProvider</code>.
+     */
+    public static final String COMMAND_REDEPLOY = "redeploy" ; //NOI18N
+    
+    /**
+     * Standard artifact type representing a WAR file.
+     * See <code>org.netbeans.api.project.ant.AntArtifact</code>.
+     */
+    public static final String ARTIFACT_TYPE_WAR = "war"; // NOI18N
+    
+    /**
+     * Standard artifact type representing a WAR file used for adding
+     * Web module into a J2EE Application (ear project).
+     * See <code>org.netbeans.api.project.ant.AntArtifact</code>.
+     */
+    public static final String ARTIFACT_TYPE_WAR_EAR_ARCHIVE = "j2ee_ear_archive"; //NOI18N
+}
diff --git a/api.web.webmodule/src/org/netbeans/modules/web/api/webmodule/package.html b/api.web.webmodule/src/org/netbeans/modules/web/api/webmodule/package.html
new file mode 100644
index 0000000000..aec8468676
--- /dev/null
+++ b/api.web.webmodule/src/org/netbeans/modules/web/api/webmodule/package.html
@@ -0,0 +1,32 @@
+<!--
+
+    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.
+
+-->
+<html>
+<body>
+
+API to access the properties of J2EE web modules.
+
+<p>This API will typically be used by modules that provide data objects,
+wizards, editors, etc. for files used in J2EE web module (JSP, Html, deployment
+descriptor, etc.). It will be also used by web framework clients and implementors.
+</p>
+
+</body>
+</html>
diff --git a/api.web.webmodule/src/org/netbeans/modules/web/spi/webmodule/FrameworkConfigurationPanel.java b/api.web.webmodule/src/org/netbeans/modules/web/spi/webmodule/FrameworkConfigurationPanel.java
new file mode 100644
index 0000000000..efbad18679
--- /dev/null
+++ b/api.web.webmodule/src/org/netbeans/modules/web/spi/webmodule/FrameworkConfigurationPanel.java
@@ -0,0 +1,40 @@
+/*
+ * 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.web.spi.webmodule;
+
+import org.openide.WizardDescriptor;
+
+/**
+ * Extension to {@link org.openide.WizardDescriptor.Panel}. It allows to enable or disable
+ * the framework configuration panel components as requested by the different
+ * usages of the panel.
+ *
+ * @deprecated This class has been replaced with {@link org.netbeans.modules.web.spi.webmodule.WebModuleExtender}.
+ */
+@Deprecated
+public interface FrameworkConfigurationPanel extends WizardDescriptor.Panel {
+
+    /**
+     * Enables or disables the panel components.
+     *
+     * @param enable if the components should be enabled or disabled
+     */
+    public void enableComponents(boolean enable);
+}
diff --git a/api.web.webmodule/src/org/netbeans/modules/web/spi/webmodule/RequestParametersQueryImplementation.java b/api.web.webmodule/src/org/netbeans/modules/web/spi/webmodule/RequestParametersQueryImplementation.java
new file mode 100644
index 0000000000..a44f17e0aa
--- /dev/null
+++ b/api.web.webmodule/src/org/netbeans/modules/web/spi/webmodule/RequestParametersQueryImplementation.java
@@ -0,0 +1,40 @@
+/*
+ * 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.web.spi.webmodule;
+
+import org.openide.filesystems.FileObject;
+
+/**
+ * This is the SPI counterpart of {@link org.netbeans.modules.web.api.webmodule.RequestParametersQuery}.
+ * Register an instance of this provider in the default lookup to provide
+ * access to the file part of URL and request parameters.
+ *
+ * @author Pavel Buzek
+ */
+public interface RequestParametersQueryImplementation {
+
+    /**
+     * Return the part of URL for access the file. It can include the query string.
+     *
+     * @param  file the file for find the request parameters for; never null.
+     * @return path fom the context; can be null.
+     */
+    String getFileAndParameters (FileObject file);
+}
diff --git a/api.web.webmodule/src/org/netbeans/modules/web/spi/webmodule/WebFrameworkProvider.java b/api.web.webmodule/src/org/netbeans/modules/web/spi/webmodule/WebFrameworkProvider.java
new file mode 100644
index 0000000000..ac803884d8
--- /dev/null
+++ b/api.web.webmodule/src/org/netbeans/modules/web/spi/webmodule/WebFrameworkProvider.java
@@ -0,0 +1,185 @@
+/*
+ * 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.web.spi.webmodule;
+
+import java.io.File;
+import java.util.Set;
+
+import org.netbeans.modules.web.api.webmodule.*;
+import org.netbeans.modules.web.webmodule.WebModuleExtenderBridge;
+import org.openide.filesystems.FileObject;
+import org.openide.util.Parameters;
+
+/**
+ * Encapsulates a web framework.
+ * 
+ * <p>This class allows providing support for web frameworks. It can be used
+ * to extend a web module with a web framework, to find out whether a web
+ * module is already extender by a web framework, or to retrieve a web framework's
+ * specific configuration files.</p>
+ * 
+ * <p>Instances of this class are registered in the <code>j2ee/webtier/framework</code>
+ * in the module layer.</p>
+ *
+ * @author Petr Pisl, Andrei Badea, Petr Slechta
+ */
+public abstract class WebFrameworkProvider {
+
+    private final String name;
+    private final String description;
+
+    /**
+     * Creates a new web framework with a name and description.
+     *
+     * @param  name the short name of this web framework (e.g., "Struts"); never null.
+     * @param  description the description of this web framework (e.g., "An open source framework based on the MVC pattern"); can be null.
+     * @throws NullPointerException if the <code>name</code> parameter is null.
+     */
+    public WebFrameworkProvider(String name, String description){
+        Parameters.notNull("name", name); // NOI18N
+        this.name = name;
+        this.description = description;
+    }
+    
+    /**
+     * Returns the name of this web framework.
+     *
+     * @return the name; never null.
+     */
+    public String getName(){
+        return this.name;
+    }
+    
+    /**
+     * Returns the description of this web framework. Defaults to the name
+     * if a null <code>description</code> parameter was passed to the constructor.
+     * 
+     * @return the description; never null.
+     */
+    public String getDescription(){
+        if (description != null) {
+            return this.description;
+        }
+        return getName();
+    }
+    
+    /**
+     * Extends a web module with this web frameworks. For example it might be
+     * called in order to add the web framework to a newly created web application
+     * or in order to add the web framework to an existing application.
+     *
+     * @param  wm the {@link org.netbeans.modules.web.api.webmodule.WebModule} to be extended; never null.
+     * @return the list of new files created in the web module as the result
+     *         of extending it with this framework; never null.
+     *
+     * @deprecated This method has been replaced with {@link #createWebModuleExtender createWebModuleExtender}.
+     */
+    @Deprecated
+    public Set extend(WebModule wm) {
+        throw new IllegalStateException("This framework does not implemement the deprecated extend() method. Use createWebModuleExtender() instead."); // NOI18N
+    }
+    
+    /**
+     * Finds out if a given web module has already been extended with this framework.
+     *
+     * @param  wm the web module; never null.
+     * @return true if the web module has already been extended with this framework, false otherwise.
+     */
+    public abstract boolean isInWebModule (WebModule wm);
+    
+    /**
+     * Returns the configuration files belonging to this framework.
+     *
+     * @param  wm the web module for which the configuration files are returned; never null.
+     * @return an array containing the configuration files; never null.
+     */
+    public abstract File[] getConfigurationFiles(WebModule wm);
+    
+    /**
+     * Returns a configuration panel for this web framework. The panel is used
+     * to allow the user configure the way the web module will be extended.
+     * The configuration panel might be displayed to the user when creating
+     * a new web application or when editing the properties of an existing application.
+     *
+     * @param  wm the web module to be configured.
+     * @return a configuration panel for this web framework.
+     *
+     * @deprecated This method has been replaced with {@link #createWebModuleExtender createWebModuleExtender}.
+     */
+    @Deprecated
+    public FrameworkConfigurationPanel getConfigurationPanel(WebModule wm) {
+        throw new IllegalStateException("This framework does not implemement the deprecated getConfigurationPanel() method. Use createWebModuleExtender() instead."); // NOI18N
+    }
+    
+    /**
+     * Creates a {@link WebModuleExtender web module extender} for this framework
+     * and the given web module. This method needs to be implemented instead of the
+     * deprecated {@link #extend} and {@link #getConfigurationPanel} methods. It
+     * needs to be implemented even if this web framework doesn't support extending
+     * a web module (it would just return null in this case).
+     *
+     * @param  wm the web module to be extended; can be null, e.g., if the
+     *         method is called while creating a new web application, in which
+     *         case the module doesn't exist yet.
+     * @param  controller an instance of {@link ExtenderController} allowing the
+     *         newly created extender to communicate with its environment. See the
+     *         <code>ExtenderController</code> for details. Never null.
+     * @return a new web module extender; can be null if the framework doesn't support
+     *         extending (either web modules in general of the particular web module
+     *         passed in the <code>wm</code> parameter.
+     */
+    public WebModuleExtender createWebModuleExtender(WebModule wm, ExtenderController controller) {
+        return WebModuleExtenderBridge.create(this, wm, controller);
+    }
+    
+    /**
+     * Returns the path of the request URL to a given file .
+     * This path starts with a "/" character and includes either the servlet name
+     * or a path to the servlet/JSP. Includes the servlet mapping, but does not include
+     * any extra path information or a query string. The method can return null.
+     *
+     * <p>JSF Example: consider an index.jsp file in the document base. Normaly the URL
+     * for accessing this page in browser should be <code>http://server:port/contextpath/index.jsp</code>.
+     * The servlet path is <code>/index.jsp</code>.</p>
+     *
+     * <p>However, because the <code>index.jsp</code> file includes JSF tags,
+     * its URL should include the appropriate JSF servlet
+     * mapping. If the mapping is /faces/*, then the URL is
+     * <code>http://server:port/contextpath/faces/index.jsp</code> and this method
+     * should return <code>/faces/index.jsp</code>.</p>
+     *
+     * @param  file an arbitrary <code>FileObject</code>, usually a JSP file; never null.
+     * @return a string that contains the servlet path including the mapping; can be null.
+     */
+    public String getServletPath(FileObject file){
+        return null;
+    }
+
+    /**
+     * Test if this framework requires web.xml deployment descriptor for its
+     * functioning.
+     * @return true if web.xml is required by this framework
+     * @since 1.15
+     */
+    public boolean requiresWebXml() {
+        return true;
+    }
+
+}
diff --git a/api.web.webmodule/src/org/netbeans/modules/web/spi/webmodule/WebModuleExtender.java b/api.web.webmodule/src/org/netbeans/modules/web/spi/webmodule/WebModuleExtender.java
new file mode 100644
index 0000000000..07f61cdaca
--- /dev/null
+++ b/api.web.webmodule/src/org/netbeans/modules/web/spi/webmodule/WebModuleExtender.java
@@ -0,0 +1,112 @@
+/*
+ * 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.web.spi.webmodule;
+
+import java.util.Set;
+import javax.swing.JComponent;
+import javax.swing.event.ChangeListener;
+import org.netbeans.api.annotations.common.NonNull;
+import org.netbeans.modules.web.api.webmodule.WebModule;
+import org.openide.filesystems.FileObject;
+import org.openide.util.HelpCtx;
+
+/**
+ * Provides support for extending a web module with a web framework, that is,
+ * it allows to modify the web module to make use of the framework.
+ *
+ * @author Andrei Badea
+ *
+ * @since 1.9
+ */
+public abstract class WebModuleExtender {
+
+    /**
+     * Attaches a change listener that is to be notified of changes
+     * in the extender (e.g., the result of the {@link #isValid} method
+     * has changed.
+     *
+     * @param  listener a listener.
+     */
+    public abstract void addChangeListener(ChangeListener listener);
+
+    /**
+     * Removes a change listener.
+     *
+     * @param  listener a listener.
+     */
+    public abstract void removeChangeListener(ChangeListener listener);
+
+    /**
+     * Returns a UI component used to allow the user to customize this extender.
+     *
+     * @return a component or null if this extender does not provide a configuration UI.
+     *         This method might be called more than once and it is expected to always
+     *         return the same instance.
+     */
+    public abstract JComponent getComponent();
+
+    /**
+     * Returns a help context for {@link #getComponent}.
+     *
+     * @return a help context; can be null.
+     */
+    public abstract HelpCtx getHelp();
+
+    /**
+     * Called when the component returned by {@link #getComponent} needs to be filled
+     * with external data.
+     */
+    public abstract void update();
+
+    /**
+     * Checks if this extender is valid (e.g., if the configuration set
+     * using the UI component returned by {@link #getComponent} is valid).
+     *
+     * @return true if the configuration is valid, false otherwise.
+     */
+    public abstract boolean isValid();
+
+    /**
+     * Called to extend the given web module with the web framework
+     * corresponding to this extender.
+     *
+     * @param  webModule the web module to be extended; never null.
+     * @return the set of newly created files in the web module.
+     */
+    public abstract Set<FileObject> extend(WebModule webModule);
+
+    /**
+     * Interface that represents ability to save {@code WebModuleExtender}
+     * properties for a {@link WebModule}.
+     *
+     * @since 1.26
+     */
+    public interface Savable {
+
+        /**
+         * Called to save extender configuration for given web module in cases that
+         * the web module was already extended by the {@code WebModuleExtender}.
+         *
+         * @param webModule the web module to store extender settings; never null.
+         */
+        void save(@NonNull WebModule webModule);
+
+    }
+
+}
diff --git a/api.web.webmodule/src/org/netbeans/modules/web/spi/webmodule/WebModuleFactory.java b/api.web.webmodule/src/org/netbeans/modules/web/spi/webmodule/WebModuleFactory.java
new file mode 100644
index 0000000000..9d7eda5c51
--- /dev/null
+++ b/api.web.webmodule/src/org/netbeans/modules/web/spi/webmodule/WebModuleFactory.java
@@ -0,0 +1,50 @@
+/*
+ * 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.web.spi.webmodule;
+
+import org.netbeans.modules.web.api.webmodule.WebModule;
+import org.netbeans.modules.web.webmodule.WebModuleAccessor;
+
+/**
+ * Most general way to create {@link WebModule} instances.
+ * You are not permitted to create them directly; instead you implement
+ * {@link WebModuleImplementation} and use this factory.
+ *
+ * @author Pavel Buzek
+ */
+public final class WebModuleFactory {
+
+    private WebModuleFactory () {}
+
+    /**
+     * Creates an API web module instance for the given SPI web module.
+     *
+     * @param  spiWebmodule an instance of a SPI web module.
+     * @return an instance of a API web module.
+     * @deprecated use {@link #createWebModule(org.netbeans.modules.web.spi.webmodule.WebModuleImplementation2)}
+     */
+    public static WebModule createWebModule(WebModuleImplementation spiWebmodule) {
+        return WebModuleAccessor.getDefault().createWebModule (spiWebmodule);
+    }
+
+    public static WebModule createWebModule(WebModuleImplementation2 spiWebmodule) {
+        return WebModuleAccessor.getDefault().createWebModule (spiWebmodule);
+    }
+}
diff --git a/api.web.webmodule/src/org/netbeans/modules/web/spi/webmodule/WebModuleImplementation.java b/api.web.webmodule/src/org/netbeans/modules/web/spi/webmodule/WebModuleImplementation.java
new file mode 100644
index 0000000000..d0ec99d38b
--- /dev/null
+++ b/api.web.webmodule/src/org/netbeans/modules/web/spi/webmodule/WebModuleImplementation.java
@@ -0,0 +1,104 @@
+/*
+ * 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.web.spi.webmodule;
+
+import org.netbeans.modules.j2ee.dd.api.web.WebAppMetadata;
+import org.netbeans.modules.j2ee.metadata.model.api.MetadataModel;
+import org.openide.filesystems.FileObject;
+
+/**
+ * SPI for {@link org.netbeans.modules.web.api.webmodule.WebModule}.
+ *
+ * @see WebModuleFactory
+ * @deprecated implement {@link WebModuleImplementation2}
+ */
+public interface WebModuleImplementation {
+
+    /**
+     * Returns the folder that contains sources of the static documents for
+     * the web module (html, JSPs, etc.).
+     *
+     * @return the static documents folder; can be null.
+     */
+    FileObject getDocumentBase ();
+
+    /**
+     * Returns the context path of the web module.
+     *
+     * @return the context path; can be null.
+     */
+    String getContextPath ();
+
+    /**
+     * Returns the J2EE platform version of this module. The returned value is
+     * one of the constants {@link org.netbeans.modules.web.api.webmodule.WebModule#J2EE_13_LEVEL},
+     * {@link org.netbeans.modules.web.api.webmodule.WebModule#J2EE_14_LEVEL} or
+     * {@link org.netbeans.modules.web.api.webmodule.WebModule#JAVA_EE_5_LEVEL}.
+     *
+     * @return J2EE platform version; never null.
+     */
+    String getJ2eePlatformVersion ();
+
+    /**
+     * WEB-INF folder for the web module.
+     * <div class="nonnormative">
+     * The WEB-INF folder would typically be a child of the folder returned
+     * by {@link #getDocumentBase} but does not need to be.
+     * </div>
+     *
+     * @return the {@link FileObject}; might be <code>null</code>
+     */
+    FileObject getWebInf ();
+
+    /**
+     * Returns the deployment descriptor (<code>web.xml</code> file) of the web module.
+     * <div class="nonnormative">
+     * The web.xml file would typically be a child of the folder returned
+     * by {@link #getWebInf} but does not need to be.
+     * </div>
+     *
+     * @return the <code>web.xml</code> file; can be null.
+     */
+    FileObject getDeploymentDescriptor ();
+
+    /**
+     * Returns the Java source roots associated with the web module.
+     * <div class="nonnormative">
+     * <p>Note that not all the java source roots in the project (e.g. in a freeform project)
+     * belong to the web module.</p>
+     * </div>
+     *
+     * @return this web module's Java source roots; never null.
+     * 
+     * @deprecated This method is deprecated, because its return values does
+     * not contain enough information about the source roots. Source roots
+     * are usually implemented by a <code>org.netbeans.api.project.SourceGroup</code>,
+     * which is more than just a container for a {@link org.openide.filesystems.FileObject}.
+     */
+    @Deprecated
+    FileObject[] getJavaSources();
+
+    /**
+     * Returns a model describing the metadata of this web module (servlets,
+     * resources, etc.).
+     *
+     * @return this web module's metadata model; never null.
+     */
+    MetadataModel<WebAppMetadata> getMetadataModel();
+}
diff --git a/api.web.webmodule/src/org/netbeans/modules/web/spi/webmodule/WebModuleImplementation2.java b/api.web.webmodule/src/org/netbeans/modules/web/spi/webmodule/WebModuleImplementation2.java
new file mode 100644
index 0000000000..2ae2119e1e
--- /dev/null
+++ b/api.web.webmodule/src/org/netbeans/modules/web/spi/webmodule/WebModuleImplementation2.java
@@ -0,0 +1,121 @@
+/*
+ * 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.web.spi.webmodule;
+
+import java.beans.PropertyChangeListener;
+import org.netbeans.api.j2ee.core.Profile;
+import org.netbeans.modules.j2ee.dd.api.web.WebAppMetadata;
+import org.netbeans.modules.j2ee.metadata.model.api.MetadataModel;
+import org.openide.filesystems.FileObject;
+
+/**
+ * SPI for {@link org.netbeans.modules.web.api.webmodule.WebModule}.
+ *
+ * @see WebModuleFactory
+ */
+public interface WebModuleImplementation2 {
+
+    /**
+     * @since org.netbeans.api.web.webmodule/1 1.16
+     */
+    static final String PROPERTY_DOCUMENT_BASE = "documentBase";
+    
+    /**
+     * @since org.netbeans.api.web.webmodule/1 1.16
+     */
+    static final String PROPERTY_WEB_INF = "webInf";
+    
+    /**
+     * Returns the folder that contains sources of the static documents for
+     * the web module (html, JSPs, etc.).
+     *
+     * @return the static documents folder; can be null.
+     */
+    FileObject getDocumentBase ();
+
+    /**
+     * Returns the context path of the web module.
+     *
+     * @return the context path; can be null.
+     */
+    String getContextPath ();
+
+    Profile getJ2eeProfile();
+
+    /**
+     * WEB-INF folder for the web module.
+     * <div class="nonnormative">
+     * The WEB-INF folder would typically be a child of the folder returned
+     * by {@link #getDocumentBase} but does not need to be.
+     * </div>
+     *
+     * @return the {@link FileObject}; might be <code>null</code>
+     */
+    FileObject getWebInf ();
+
+    /**
+     * Returns the deployment descriptor (<code>web.xml</code> file) of the web module.
+     * <div class="nonnormative">
+     * The web.xml file would typically be a child of the folder returned
+     * by {@link #getWebInf} but does not need to be.
+     * </div>
+     *
+     * @return the <code>web.xml</code> file; can be null.
+     */
+    FileObject getDeploymentDescriptor ();
+
+    /**
+     * Returns the Java source roots associated with the web module.
+     * <div class="nonnormative">
+     * <p>Note that not all the java source roots in the project (e.g. in a freeform project)
+     * belong to the web module.</p>
+     * </div>
+     *
+     * @return this web module's Java source roots; never null.
+     *
+     * @deprecated This method is deprecated, because its return values does
+     * not contain enough information about the source roots. Source roots
+     * are usually implemented by a <code>org.netbeans.api.project.SourceGroup</code>,
+     * which is more than just a container for a {@link org.openide.filesystems.FileObject}.
+     */
+    @Deprecated
+    FileObject[] getJavaSources();
+
+    /**
+     * Returns a model describing the metadata of this web module (servlets,
+     * resources, etc.).
+     *
+     * @return this web module's metadata model; never null.
+     */
+    MetadataModel<WebAppMetadata> getMetadataModel();
+
+    /**
+     * Add propertty change listener.
+     *
+     * @since org.netbeans.api.web.webmodule/1 1.16
+     */
+    void addPropertyChangeListener(PropertyChangeListener listener);
+    
+    /**
+     * Remove propertty change listener.
+     *
+     * @since org.netbeans.api.web.webmodule/1 1.16
+     */
+    void removePropertyChangeListener(PropertyChangeListener listener);
+}
diff --git a/api.web.webmodule/src/org/netbeans/modules/web/spi/webmodule/WebModuleProvider.java b/api.web.webmodule/src/org/netbeans/modules/web/spi/webmodule/WebModuleProvider.java
new file mode 100644
index 0000000000..b06f9b16a6
--- /dev/null
+++ b/api.web.webmodule/src/org/netbeans/modules/web/spi/webmodule/WebModuleProvider.java
@@ -0,0 +1,55 @@
+/*
+ * 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.web.spi.webmodule;
+
+import org.netbeans.modules.web.api.webmodule.WebModule;
+import org.openide.filesystems.FileObject;
+
+/**
+ * Provider interface for web modules.
+ *
+ * <p>The <code>org.netbeans.api.web.webmodule</code> module registers an
+ * implementation of this interface to global lookup which looks for the
+ * project which owns a file (if any) and checks its lookup for this interface,
+ * and if it finds an instance, delegates to it. Therefore it is not normally
+ * necessary for a project type provider to register its own instance just to
+ * define the web module for files it owns, assuming it uses projects for
+ * implementation of the web module.</p>
+ *
+ * <p>If needed a new implementation of this interface can be registered in
+ * global lookup.</p>
+ *
+ * @see WebModule#getWebModule
+ *
+ * @author Pavel Buzek
+ */
+public interface WebModuleProvider {
+
+    /**
+     * Find the web module containing a given file.
+     *
+     * @param  file a file; never null.
+     * @return a web module, or null if this provider could not find a web module
+     *         containing this file.
+     *
+     * @see WebModuleFactory
+     */
+    WebModule findWebModule(FileObject file);
+}
diff --git a/api.web.webmodule/src/org/netbeans/modules/web/spi/webmodule/WebPrivilegedTemplates.java b/api.web.webmodule/src/org/netbeans/modules/web/spi/webmodule/WebPrivilegedTemplates.java
new file mode 100644
index 0000000000..da0b9a2f74
--- /dev/null
+++ b/api.web.webmodule/src/org/netbeans/modules/web/spi/webmodule/WebPrivilegedTemplates.java
@@ -0,0 +1,44 @@
+/*
+ * 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.web.spi.webmodule;
+
+import org.netbeans.modules.web.api.webmodule.WebModule;
+
+/**
+ * List of templates which should be in the initial "privileged" list
+ * when creating a new file. An instance should be placed in the
+ * <code>j2ee/webtier/templates</code> folder in a module layer.
+ *
+ * @author Petr Pisl
+ */
+public interface WebPrivilegedTemplates {
+
+    /**
+     * Returns the list of templates which should be added in the initial "privileged" list
+     * when created a new file.
+     *
+     * @param  webModule the web module to return the templates for.
+     *         For example, it can be used to find out whether the web module is extended
+     *         by a framework and then appropriate templates for the framework can be offered
+     *         in the list of privileged list of templates.
+     *
+     * @return full paths to privileged templates, e.g. <samp>Templates/Other/XmlFile.xml</samp>; never null.
+     */
+    public String[] getPrivilegedTemplates(WebModule webModule);
+}
diff --git a/api.web.webmodule/src/org/netbeans/modules/web/spi/webmodule/package.html b/api.web.webmodule/src/org/netbeans/modules/web/spi/webmodule/package.html
new file mode 100644
index 0000000000..01b934f3d2
--- /dev/null
+++ b/api.web.webmodule/src/org/netbeans/modules/web/spi/webmodule/package.html
@@ -0,0 +1,44 @@
+<!--
+
+    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.
+
+-->
+<html>
+<body>
+
+SPI for providers of J2EE web modules and frameworks.
+
+<p>This API will typically be used by modules that implement project types for
+J2EE web module (various implementations of web module project, web module with
+web services, portlets, etc.). It can be also used for implementation of web
+module that is not based on Projects API. Another use case is implementing
+support for web frameworks such as Struts or JSF.</p>
+
+<p>A module that implements this API needs to expose an implementation of
+{@link org.netbeans.modules.web.spi.webmodule.WebModuleProvider} either in
+the project lookup (for implementations based on the Projects API) or in the global lookup.
+The module will implement {@link org.netbeans.modules.web.spi.webmodule.WebModuleImplementation}
+and use {@link org.netbeans.modules.web.spi.webmodule.WebModuleFactory}
+to create a {@link org.netbeans.modules.web.api.webmodule.WebModule}.</p>
+
+<p>A module wanting to provide support for a web framework needs to implement
+{@link org.netbeans.modules.web.spi.webmodule.WebFrameworkProvider} and usually
+also {@link org.netbeans.modules.web.spi.webmodule.WebModuleExtender}.</p>
+
+</body>
+</html>
diff --git a/api.web.webmodule/src/org/netbeans/modules/web/webmodule/Bundle.properties b/api.web.webmodule/src/org/netbeans/modules/web/webmodule/Bundle.properties
new file mode 100644
index 0000000000..bcad9d1e10
--- /dev/null
+++ b/api.web.webmodule/src/org/netbeans/modules/web/webmodule/Bundle.properties
@@ -0,0 +1,47 @@
+OpenIDE-Module-Long-Description=\
+    APIs for web module development support modules (such as support for various web frameworks).
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+#
+# Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
+#
+# Oracle and Java are registered trademarks of Oracle and/or its affiliates.
+# Other names may be trademarks of their respective owners.
+#
+# The contents of this file are subject to the terms of either the GNU
+# General Public License Version 2 only ("GPL") or the Common
+# Development and Distribution License("CDDL") (collectively, the
+# "License"). You may not use this file except in compliance with the
+# License. You can obtain a copy of the License at
+# http://www.netbeans.org/cddl-gplv2.html
+# or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
+# specific language governing permissions and limitations under the
+# License.  When distributing the software, include this License Header
+# Notice in each file and include the License file at
+# nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the GPL Version 2 section of the License file that
+# accompanied this code. If applicable, add the following below the
+# License Header, with the fields enclosed by brackets [] replaced by
+# your own identifying information:
+# "Portions Copyrighted [year] [name of copyright owner]"
+#
+# Contributor(s):
+#
+# The Original Software is NetBeans. The Initial Developer of the Original
+# Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
+# Microsystems, Inc. All Rights Reserved.
+#
+# If you wish your version of this file to be governed by only the CDDL
+# or only the GPL Version 2, indicate your decision by adding
+# "[Contributor] elects to include this software in this distribution
+# under the [CDDL or GPL Version 2] license." If you do not indicate a
+# single choice of license, a recipient has the option to distribute
+# your version of this file under either the CDDL, the GPL Version 2 or
+# to extend the choice of license to its licensees as provided above.
+# However, if you add GPL Version 2 code and therefore, elected the GPL
+# Version 2 license, then the option applies only if the new code is
+# made subject to such option by the copyright holder.
+OpenIDE-Module-Name=Web APIs
+OpenIDE-Module-Display-Category=Libraries
+OpenIDE-Module-Short-Description=APIs for web module development support modules.
+#OpenIDE-Module-Long-Description=XXX
diff --git a/api.web.webmodule/src/org/netbeans/modules/web/webmodule/ProjectWebModuleProvider.java b/api.web.webmodule/src/org/netbeans/modules/web/webmodule/ProjectWebModuleProvider.java
new file mode 100644
index 0000000000..00fb6f73b0
--- /dev/null
+++ b/api.web.webmodule/src/org/netbeans/modules/web/webmodule/ProjectWebModuleProvider.java
@@ -0,0 +1,44 @@
+/*
+ * 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.web.webmodule;
+
+import org.netbeans.api.project.FileOwnerQuery;
+import org.netbeans.api.project.Project;
+import org.netbeans.modules.web.api.webmodule.WebModule;
+import org.netbeans.modules.web.spi.webmodule.WebModuleProvider;
+import org.openide.filesystems.FileObject;
+
+@org.openide.util.lookup.ServiceProvider(service=org.netbeans.modules.web.spi.webmodule.WebModuleProvider.class)
+public class ProjectWebModuleProvider implements WebModuleProvider {
+
+    public ProjectWebModuleProvider () {
+    }
+
+    public WebModule findWebModule (FileObject file) {
+        Project project = FileOwnerQuery.getOwner (file);
+        if (project != null) {
+            WebModuleProvider provider = project.getLookup ().lookup (WebModuleProvider.class);
+            if (provider != null) {
+                return provider.findWebModule (file);
+            }
+        }
+        return null;
+    }
+}
diff --git a/api.web.webmodule/src/org/netbeans/modules/web/webmodule/WebModuleAccessor.java b/api.web.webmodule/src/org/netbeans/modules/web/webmodule/WebModuleAccessor.java
new file mode 100644
index 0000000000..5b04a4ac29
--- /dev/null
+++ b/api.web.webmodule/src/org/netbeans/modules/web/webmodule/WebModuleAccessor.java
@@ -0,0 +1,61 @@
+/*
+ * 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.web.webmodule;
+
+import org.netbeans.modules.web.api.webmodule.WebModule;
+import org.netbeans.modules.web.spi.webmodule.WebModuleImplementation;
+import org.netbeans.modules.web.spi.webmodule.WebModuleImplementation2;
+import org.openide.util.Exceptions;
+
+/**
+ * This class provides access to the {@link WebModule}'s private constructor
+ * from outside in the way that this class is implemented by an inner class of
+ * {@link WebModule} and the instance is set via {@link #setDefault(WebModuleAccessor)}.
+ */
+public abstract class WebModuleAccessor {
+
+    private static volatile WebModuleAccessor accessor;
+
+    public static void setDefault(WebModuleAccessor accessor) {
+        if (WebModuleAccessor.accessor != null) {
+            throw new IllegalStateException("Already initialized accessor"); // NOI18N
+        }
+        WebModuleAccessor.accessor = accessor;
+    }
+
+    public static WebModuleAccessor getDefault() {
+        if (accessor != null) {
+            return accessor;
+        }
+
+        Class c = WebModule.class;
+        try {
+            Class.forName(c.getName(), true, c.getClassLoader());
+        } catch (Exception ex) {
+            Exceptions.printStackTrace(ex);
+        }
+
+        return accessor;
+    }
+
+    @Deprecated
+    public abstract WebModule createWebModule(WebModuleImplementation spiWebmodule);
+
+    public abstract WebModule createWebModule(WebModuleImplementation2 spiWebmodule);
+}
diff --git a/api.web.webmodule/src/org/netbeans/modules/web/webmodule/WebModuleExtenderBridge.java b/api.web.webmodule/src/org/netbeans/modules/web/webmodule/WebModuleExtenderBridge.java
new file mode 100644
index 0000000000..bd779f3d95
--- /dev/null
+++ b/api.web.webmodule/src/org/netbeans/modules/web/webmodule/WebModuleExtenderBridge.java
@@ -0,0 +1,182 @@
+/*
+ * 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.web.webmodule;
+
+import java.awt.Component;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.util.Map;
+import java.util.Set;
+import javax.swing.JComponent;
+import javax.swing.JPanel;
+import javax.swing.event.ChangeListener;
+import org.netbeans.modules.web.api.webmodule.ExtenderController;
+import org.netbeans.modules.web.api.webmodule.WebModule;
+import org.netbeans.modules.web.spi.webmodule.FrameworkConfigurationPanel;
+import org.netbeans.modules.web.spi.webmodule.WebFrameworkProvider;
+import org.netbeans.modules.web.spi.webmodule.WebModuleExtender;
+import org.openide.WizardDescriptor;
+import org.openide.filesystems.FileObject;
+import org.openide.util.HelpCtx;
+
+/**
+ * This class is a bridge between the deprecated {@link WebFrameworkProvider#getConfigurationPanel}
+ * and {@link WebFrameworkProvider#extend} methods and the new {@link WebModuleExtender} class
+ * which replaces them.
+ *
+ * @author Andrei Badea
+ */
+@SuppressWarnings("deprecation")
+public class WebModuleExtenderBridge extends WebModuleExtender {
+
+    private final WebFrameworkProvider framework;
+    private final WebModule webModule;
+    private final ExtenderController controller;
+    private final FrameworkConfigurationPanel configPanel;
+    private final WizardDescriptor wizard;
+
+    private Map<String, Object> oldProps;
+
+    public static WebModuleExtenderBridge create(WebFrameworkProvider framework, WebModule webModule, ExtenderController controller) {
+        WebModuleExtenderBridge result = new WebModuleExtenderBridge(framework, webModule, controller);
+        result.initialize();
+        return result;
+    }
+
+    private WebModuleExtenderBridge(WebFrameworkProvider framework, WebModule webModule, final ExtenderController controller) {
+        this.framework = framework;
+        this.webModule = webModule;
+        this.controller = controller;
+        FrameworkConfigurationPanel tmpPanel = framework.getConfigurationPanel(webModule);
+        configPanel = (tmpPanel != null) ? tmpPanel : new EmptyConfigPanel();
+        // we don't want to send configPanel to the wizard descriptor in order to
+        // keep full control over the methods called on configPanel,
+        // so we create a special panel for the wizard
+        @SuppressWarnings("unchecked") // NOI18N
+        WizardDescriptor tmpWizard = new WizardDescriptor(new WizardDescriptor.Panel[] { new EmptyPanel() });
+        wizard = tmpWizard;
+    }
+
+    /**
+     * Not done in the constructor to avoid escaping "this" before the constructor
+     * has finished executing.
+     */
+    private void initialize() {
+        wizard.addPropertyChangeListener(new PropertyChangeListener() {
+            public void propertyChange(PropertyChangeEvent evt) {
+                String message = (String) wizard.getProperty(WizardDescriptor.PROP_ERROR_MESSAGE);
+                if (message != null && message.trim().length() == 0) {
+                    // many WizardDescriptor clients pass " " for no error message to ensure
+                    // that it still takes up vertical space
+                    message = null;
+                }
+                controller.setErrorMessage(message); // NOI18N
+            }
+        });
+    }
+
+    public void addChangeListener(ChangeListener listener) {
+        configPanel.addChangeListener(listener);
+    }
+
+    @SuppressWarnings("unchecked")
+    public Set<FileObject> extend(WebModule webModule) {
+        configPanel.storeSettings(wizard);
+        return (Set<FileObject>) framework.extend(webModule);
+    }
+
+    public JComponent getComponent() {
+        return (JComponent) configPanel.getComponent();
+    }
+
+    public HelpCtx getHelp() {
+        return configPanel.getHelp();
+    }
+
+    public boolean isValid() {
+        return configPanel.isValid();
+    }
+
+    public void removeChangeListener(ChangeListener listener) {
+        configPanel.removeChangeListener(listener);
+    }
+
+    @SuppressWarnings("unchecked")
+    public void update() {
+        if (oldProps != null) {
+            for (Map.Entry<String, Object> entry : oldProps.entrySet()) {
+                wizard.putProperty(entry.getKey(), null);
+            }
+        }
+        Map<String, Object> newProps = controller.getProperties().getProperties();
+        for (Map.Entry<String, Object> entry : newProps.entrySet()) {
+            wizard.putProperty(entry.getKey(), entry.getValue());
+        }
+        oldProps = newProps;
+        configPanel.readSettings(wizard);
+    }
+
+    private static class EmptyPanel implements WizardDescriptor.Panel {
+
+        private JPanel component;
+
+        public void addChangeListener(ChangeListener l) {
+        }
+
+        public Component getComponent() {
+            if (component == null) {
+                component = new JPanel();
+            }
+            return component;
+        }
+
+        public HelpCtx getHelp() {
+            return null;
+        }
+
+        public boolean isValid() {
+            return true;
+        }
+
+        public void readSettings(Object settings) {
+        }
+
+        public void removeChangeListener(ChangeListener l) {
+        }
+
+        public void storeSettings(Object settings) {
+        }
+    }
+
+    /**
+     * An empty framework configuration panel to which WebModuleExtenderBridge will delegate
+     * when the framework doesn't have a framework configuration panel.
+     */
+    private final static class EmptyConfigPanel extends EmptyPanel implements FrameworkConfigurationPanel {
+
+        @Override
+        public Component getComponent() {
+            return null;
+        }
+
+        public void enableComponents(boolean enable) {
+        }
+    }
+}
diff --git a/api.web.webmodule/src/org/netbeans/modules/web/webmodule/resources/layer.xml b/api.web.webmodule/src/org/netbeans/modules/web/webmodule/resources/layer.xml
new file mode 100644
index 0000000000..7de9193dd3
--- /dev/null
+++ b/api.web.webmodule/src/org/netbeans/modules/web/webmodule/resources/layer.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    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.
+
+-->
+<!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.1//EN" "http://www.netbeans.org/dtds/filesystem-1_1.dtd">
+<filesystem>
+    <!-- empty folders as workaround to avoid os fs folder creation -->
+    <folder name="j2ee">
+        <folder name="webtier">
+            <folder name="framework">
+            </folder>  
+            
+            <folder name="templates">
+            </folder>            
+        </folder>
+    </folder>
+</filesystem>
+
diff --git a/api.web.webmodule/test/unit/data/WEB-INF/web.xml b/api.web.webmodule/test/unit/data/WEB-INF/web.xml
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/api.web.webmodule/test/unit/data/a.foo b/api.web.webmodule/test/unit/data/a.foo
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/api.web.webmodule/test/unit/data/b.bar b/api.web.webmodule/test/unit/data/b.bar
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/api.web.webmodule/test/unit/src/org/netbeans/modules/web/webmodule/RequestParametersQueryTest.java b/api.web.webmodule/test/unit/src/org/netbeans/modules/web/webmodule/RequestParametersQueryTest.java
new file mode 100644
index 0000000000..adb93958a0
--- /dev/null
+++ b/api.web.webmodule/test/unit/src/org/netbeans/modules/web/webmodule/RequestParametersQueryTest.java
@@ -0,0 +1,77 @@
+/*
+ * 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.web.webmodule;
+
+import org.netbeans.junit.MockServices;
+import org.netbeans.junit.NbTestCase;
+import org.netbeans.modules.web.api.webmodule.RequestParametersQuery;
+import org.netbeans.modules.web.spi.webmodule.RequestParametersQueryImplementation;
+import org.openide.filesystems.FileObject;
+import org.openide.filesystems.FileUtil;
+
+/**
+ *
+ * @author Pavel Buzek, Andrei Badea
+ */
+public class RequestParametersQueryTest extends NbTestCase {
+
+    private static final String PARAMS = "MyJsp?foo=1&bar=0";
+
+    public RequestParametersQueryTest(String name) {
+        super(name);
+    }
+
+    private FileObject datadir;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        MockServices.setServices(RequestParametersQueryImpl.class);
+        datadir = FileUtil.toFileObject(getDataDir());
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        super.tearDown();
+        MockServices.setServices();
+    }
+
+    public void testGetParams() throws Exception {
+        FileObject foo = datadir.getFileObject("a.foo");
+        FileObject bar = datadir.getFileObject("b.bar");
+        String params1 = RequestParametersQuery.getFileAndParameters(foo);
+        assertNotNull("found params", params1);
+        String params2 = RequestParametersQuery.getFileAndParameters(bar);
+        assertEquals("different parameters expected", PARAMS, params1);
+        assertNull("no params expected", params2);
+    }
+
+    public static final class RequestParametersQueryImpl implements RequestParametersQueryImplementation {
+
+        public RequestParametersQueryImpl() {}
+
+        public String getFileAndParameters(FileObject f) {
+            if (f.getNameExt().equals("a.foo")) {
+                return PARAMS;
+            }
+            return null;
+        }
+    }
+}
diff --git a/api.web.webmodule/test/unit/src/org/netbeans/modules/web/webmodule/SimpleWebModuleImpl.java b/api.web.webmodule/test/unit/src/org/netbeans/modules/web/webmodule/SimpleWebModuleImpl.java
new file mode 100644
index 0000000000..ce767c3f45
--- /dev/null
+++ b/api.web.webmodule/test/unit/src/org/netbeans/modules/web/webmodule/SimpleWebModuleImpl.java
@@ -0,0 +1,67 @@
+/*
+ * 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.web.webmodule;
+
+import java.beans.PropertyChangeListener;
+import org.netbeans.api.j2ee.core.Profile;
+import org.netbeans.modules.j2ee.dd.api.web.WebAppMetadata;
+import org.netbeans.modules.j2ee.metadata.model.api.MetadataModel;
+import org.netbeans.modules.web.spi.webmodule.WebModuleImplementation2;
+import org.openide.filesystems.FileObject;
+
+/**
+ *
+ * @author Andrei Badea
+ */
+public class SimpleWebModuleImpl implements WebModuleImplementation2 {
+
+    public String getContextPath() {
+        return null;
+    }
+
+    public FileObject getDocumentBase() {
+        return null;
+    }
+
+    public Profile getJ2eeProfile() {
+        return null;
+    }
+
+    public FileObject getDeploymentDescriptor() {
+        return null;
+    }
+
+    public FileObject getWebInf() {
+        return null;
+    }
+
+    public FileObject[] getJavaSources() {
+        return new FileObject[0];
+    }
+
+    public MetadataModel<WebAppMetadata> getMetadataModel() {
+        return null;
+    }
+
+    public void addPropertyChangeListener(PropertyChangeListener listener) {
+    }
+
+    public void removePropertyChangeListener(PropertyChangeListener listener) {
+    }
+}
diff --git a/api.web.webmodule/test/unit/src/org/netbeans/modules/web/webmodule/WebModuleExtenderBridgeTest.java b/api.web.webmodule/test/unit/src/org/netbeans/modules/web/webmodule/WebModuleExtenderBridgeTest.java
new file mode 100644
index 0000000000..7498142cca
--- /dev/null
+++ b/api.web.webmodule/test/unit/src/org/netbeans/modules/web/webmodule/WebModuleExtenderBridgeTest.java
@@ -0,0 +1,177 @@
+/*
+ * 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.web.webmodule;
+
+import java.awt.Component;
+import java.io.File;
+import java.util.HashSet;
+import java.util.Set;
+import javax.swing.JPanel;
+import javax.swing.event.ChangeListener;
+import org.netbeans.junit.NbTestCase;
+import org.netbeans.modules.web.api.webmodule.ExtenderController;
+import org.netbeans.modules.web.api.webmodule.WebModule;
+import org.netbeans.modules.web.spi.webmodule.FrameworkConfigurationPanel;
+import org.netbeans.modules.web.spi.webmodule.WebFrameworkProvider;
+import org.netbeans.modules.web.spi.webmodule.WebModuleExtender;
+import org.netbeans.modules.web.spi.webmodule.WebModuleFactory;
+import org.openide.WizardDescriptor;
+import org.openide.util.ChangeSupport;
+import org.openide.util.HelpCtx;
+import org.openide.util.test.MockChangeListener;
+
+/**
+ *
+ * @author Andrei Badea
+ */
+@SuppressWarnings("deprecation")
+public class WebModuleExtenderBridgeTest extends NbTestCase {
+
+    private WebModule webModule;
+    private ExtenderController controller;
+
+    @Override
+    protected void setUp() {
+        webModule = WebModuleFactory.createWebModule(new SimpleWebModuleImpl());
+        controller = ExtenderController.create();
+    }
+
+    public WebModuleExtenderBridgeTest(String testName) {
+        super(testName);
+    }
+
+    public void testBasic() {
+
+        PanelImpl panel = new PanelImpl();
+        FrameworkImpl framework = new FrameworkImpl(panel);
+        WebModuleExtender extender = framework.createWebModuleExtender(webModule, controller);
+        MockChangeListener listener = new MockChangeListener();
+
+        extender.update();
+        extender.addChangeListener(listener);
+        assertFalse(extender.isValid());
+        assertEquals("Not valid", controller.getErrorMessage());
+
+        assertTrue(extender.getComponent() instanceof JPanel);
+
+        controller.getProperties().setProperty("prop", "foo");
+        extender.update();
+        assertTrue(extender.isValid());
+        assertNull(controller.getErrorMessage());
+
+        panel.forceInvalid(true);
+        listener.assertEventCount(1);
+        assertFalse(extender.isValid());
+        assertEquals("Not valid", controller.getErrorMessage());
+
+        panel.forceInvalid(false);
+        listener.assertEventCount(1);
+        assertTrue(extender.isValid());
+
+        controller.getProperties().setProperty("prop", null);
+        extender.update();
+        assertFalse(extender.isValid());
+
+        assertFalse(framework.extendCalled);
+        extender.extend(webModule);
+        assertTrue(framework.extendCalled);
+    }
+
+    public void testConfigurationPanelCanBeNullIssue121712() {
+        FrameworkImpl framework = new FrameworkImpl(null);
+        WebModuleExtender extender = framework.createWebModuleExtender(webModule, controller);
+        extender.update(); // should not throw NPE
+    }
+
+    private static final class PanelImpl implements FrameworkConfigurationPanel {
+
+        private final ChangeSupport changeSupport = new ChangeSupport(this);
+        private WizardDescriptor wizard;
+        private boolean forcedInvalid;
+
+        public void enableComponents(boolean enable) {
+        }
+
+        public void addChangeListener(ChangeListener l) {
+            changeSupport.addChangeListener(l);
+        }
+
+        public Component getComponent() {
+            return new JPanel();
+        }
+
+        public HelpCtx getHelp() {
+            return new HelpCtx("help me");
+        }
+
+        public boolean isValid() {
+            boolean valid = "foo".equals(wizard.getProperty("prop")) && !forcedInvalid;
+            wizard.putProperty(WizardDescriptor.PROP_ERROR_MESSAGE, valid ? " " : "Not valid");
+            return valid;
+        }
+
+        public void readSettings(Object settings) {
+            wizard = (WizardDescriptor) settings;
+        }
+
+        public void removeChangeListener(ChangeListener l) {
+            changeSupport.removeChangeListener(l);
+        }
+
+        public void storeSettings(Object settings) {
+        }
+
+        void forceInvalid(boolean value) {
+            forcedInvalid = value;
+            changeSupport.fireChange();
+        }
+    }
+
+    @SuppressWarnings("deprecation")
+    private static final class FrameworkImpl extends WebFrameworkProvider {
+
+        private final PanelImpl panel;
+        private boolean extendCalled;
+
+        public FrameworkImpl(PanelImpl panel) {
+            super("name", "description");
+            this.panel = panel;
+        }
+
+        @Override
+        public FrameworkConfigurationPanel getConfigurationPanel(WebModule wm) {
+            return panel;
+        }
+
+        @Override
+        public Set extend(WebModule wm) {
+            extendCalled = true;
+            return new HashSet();
+        }
+
+        public File[] getConfigurationFiles(WebModule wm) {
+            return new File[0];
+        }
+
+        public boolean isInWebModule(WebModule wm) {
+            return false;
+        }
+    }
+}
diff --git a/api.web.webmodule/test/unit/src/org/netbeans/modules/web/webmodule/WebModuleTest.java b/api.web.webmodule/test/unit/src/org/netbeans/modules/web/webmodule/WebModuleTest.java
new file mode 100644
index 0000000000..c63e0f72e0
--- /dev/null
+++ b/api.web.webmodule/test/unit/src/org/netbeans/modules/web/webmodule/WebModuleTest.java
@@ -0,0 +1,92 @@
+/*
+ * 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.web.webmodule;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import org.netbeans.junit.MockServices;
+import org.netbeans.junit.MockServices;
+import org.netbeans.junit.NbTestCase;
+import org.netbeans.modules.web.api.webmodule.WebModule;
+import org.netbeans.modules.web.spi.webmodule.WebModuleFactory;
+import org.netbeans.modules.web.spi.webmodule.WebModuleProvider;
+import org.openide.filesystems.FileObject;
+import org.openide.filesystems.FileUtil;
+import org.openide.util.Lookup;
+
+/**
+ *
+ * @author Pavel Buzek, Andrei Badea
+ */
+public class WebModuleTest extends NbTestCase {
+
+    private FileObject datadir;
+
+    public WebModuleTest(String name) {
+        super(name);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        MockServices.setServices(WebModuleProviderImpl.class);
+        datadir = FileUtil.toFileObject(getDataDir());
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        super.tearDown();
+        MockServices.setServices();
+    }
+
+    public void testProviders() throws Exception {
+        Collection<? extends WebModuleProvider> providers = Lookup.getDefault().lookupAll(WebModuleProvider.class);
+        assertEquals("there should be 2 instances - one from web/webapi and one from tests", 2, providers.size());
+    }
+
+    public void testGetWebModule() throws Exception {
+        FileObject foo = datadir.getFileObject("a.foo");
+        FileObject bar = datadir.getFileObject("b.bar");
+        WebModule wm1 = WebModule.getWebModule(foo);
+        assertNotNull("found web module", wm1);
+        WebModule wm2 = WebModule.getWebModule(bar);
+        assertNull("no web module", wm2);
+    }
+
+    public static final class WebModuleProviderImpl implements WebModuleProvider {
+
+        private final Map<FileObject, WebModule> cache = new HashMap<FileObject, WebModule>();
+
+        public WebModuleProviderImpl() {}
+
+        public WebModule findWebModule(FileObject file) {
+            if (file.getExt().equals("foo")) {
+                WebModule wm = cache.get(file.getParent());
+                if (wm == null) {
+                    wm = WebModuleFactory.createWebModule(new SimpleWebModuleImpl());
+                    cache.put(file.getParent(), wm);
+                }
+                return wm;
+            }
+            return null;
+        }
+    }
+}
diff --git a/cloud.amazon/build.xml b/cloud.amazon/build.xml
new file mode 100644
index 0000000000..af658be4aa
--- /dev/null
+++ b/cloud.amazon/build.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    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.
+
+-->
+<project basedir="." default="netbeans" name="cloud.amazon">
+    <description>Builds, tests, and runs the project org.netbeans.modules.cloud.amazon</description>
+    <import file="../nbbuild/templates/projectized.xml"/>
+
+    <property name="resourcesdir" value="./src/org/netbeans/modules/cloud/amazon/resources/"/>
+    <target name="build-init" depends="projectized.build-init">
+        <unzip src="external/cloud.amazon-external-resources.zip" dest="${resourcesdir}"/>
+    </target>
+
+</project>
diff --git a/cloud.amazon/external/binaries-list b/cloud.amazon/external/binaries-list
new file mode 100644
index 0000000000..ea44ad26ba
--- /dev/null
+++ b/cloud.amazon/external/binaries-list
@@ -0,0 +1 @@
+CB42B7B480F6D21EA391CE7ACB23A46446D1395B cloud.amazon-external-resources.zip
diff --git a/cloud.amazon/external/cloud.amazon-netbeans-license.txt b/cloud.amazon/external/cloud.amazon-netbeans-license.txt
new file mode 100644
index 0000000000..0289ba99b2
--- /dev/null
+++ b/cloud.amazon/external/cloud.amazon-netbeans-license.txt
@@ -0,0 +1,141 @@
+COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0
+
+1. Definitions.
+1.1. "Contributor" means each individual or entity that creates or contributes to the creation of Modifications.
+1.2. "Contributor Version" means the combination of the Original Software, prior Modifications used by a Contributor (if any), and the Modifications made by that particular Contributor.
+1.3. "Covered Software" means (a) the Original Software, or (b) Modifications, or (c) the combination of files containing Original Software with files containing Modifications, in each case including portions thereof.
+1.4. "Executable" means the Covered Software in any form other than Source Code.
+1.5. "Initial Developer" means the individual or entity that first makes Original Software available under this License.
+1.6. "Larger Work" means a work which combines Covered Software or portions thereof with code not governed by the terms of this License.
+1.7. "License" means this document.
+1.8. "Licensable" means having the right to grant, to the maximum extent possible, whether at the time of the initial grant or subsequently acquired, any and all of the rights conveyed herein.
+1.9 "Modifications" means the Source Code and Executable form of any of the following:
+A. Any file that results from an addition to, deletion from or modification of the contents of a file containing Original Software or previous Modifications;
+B. Any new file that contains any part of the Original Software or previous Modification; or
+C. Any new file that is contributed or otherwise made available under the terms of this License.
+1.10. "Original Software" means the Source Code and Executable form of computer software code that is originally released under this License.
+1.11. "Patent Claims" means any patent claim(s), now owned or hereafter acquired, including without limitation, method, process, and apparatus claims, in any patent Licensable by grantor.
+1.12. "Source Code" means (a) the common form of computer software code in which modifications are made and (b) associated documentation included in or with such code.
+1.13. "You" (or "Your") means an individual or a legal entity exercising rights under, and complying with all of the terms of, this License. For legal entities, "You" includes any entity which controls, is controlled by, or is under common control with You. For purposes of this definition, "control" means (a) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (b) ownership of more than fifty percent (50%) of the outstanding shares or beneficial ownership of such entity.
+2. License Grants.
+2.1. The Initial Developer Grant.
+Conditioned upon Your compliance with Section 3.1 below and subject to third party intellectual property claims, the Initial Developer hereby grants You a world-wide, royalty-free, non-exclusive license:
+(a) under intellectual property rights (other than patent or trademark) Licensable by Initial Developer, to use, reproduce, modify, display, perform, sublicense and distribute the Original Software (or portions thereof), with or without Modifications, and/or as part of a Larger Work; and
+(b) under Patent Claims infringed by the making, using or selling of Original Software, to make, have made, use, practice, sell, and offer for sale, and/or otherwise dispose of the Original Software (or portions thereof).
+(c) The licenses granted in Sections 2.1(a) and (b) are effective on the date Initial Developer first distributes or otherwise makes the Original Software available to a third party under the terms of this License.
+(d) Notwithstanding Section 2.1(b) above, no patent license is granted: (1) for code that You delete from the Original Software, or (2) for infringements caused by: (i) the modification of the Original Software, or (ii) the combination of the Original Software with other software or devices.
+2.2. Contributor Grant.
+Conditioned upon Your compliance with Section 3.1 below and subject to third party intellectual property claims, each Contributor hereby grants You a world-wide, royalty-free, non-exclusive license:
+(a) under intellectual property rights (other than patent or trademark) Licensable by Contributor to use, reproduce, modify, display, perform, sublicense and distribute the Modifications created by such Contributor (or portions thereof), either on an unmodified basis, with other Modifications, as Covered Software and/or as part of a Larger Work; and
+(b) under Patent Claims infringed by the making, using, or selling of Modifications made by that Contributor either alone and/or in combination with its Contributor Version (or portions of such combination), to make, use, sell, offer for sale, have made, and/or otherwise dispose of: (1) Modifications made by that Contributor (or portions thereof); and (2) the combination of Modifications made by that Contributor with its Contributor Version (or portions of such combination).
+(c) The licenses granted in Sections 2.2(a) and 2.2(b) are effective on the date Contributor first distributes or otherwise makes the Modifications available to a third party.
+(d) Notwithstanding Section 2.2(b) above, no patent license is granted: (1) for any code that Contributor has deleted from the Contributor Version; (2) for infringements caused by: (i) third party modifications of Contributor Version, or (ii) the combination of Modifications made by that Contributor with other software (except as part of the Contributor Version) or other devices; or (3) under Patent Claims infringed by Covered Software in the absence of Modifications made by that Contributor.
+3. Distribution Obligations.
+3.1. Availability of Source Code.
+Any Covered Software that You distribute or otherwise make available in Executable form must also be made available in Source Code form and that Source Code form must be distributed only under the terms of this License. You must include a copy of this License with every copy of the Source Code form of the Covered Software You distribute or otherwise make available. You must inform recipients of any such Covered Software in Executable form as to how they can obtain such Covered Software in Source Code form in a reasonable manner on or through a medium customarily used for software exchange.
+3.2. Modifications.
+The Modifications that You create or to which You contribute are governed by the terms of this License. You represent that You believe Your Modifications are Your original creation(s) and/or You have sufficient rights to grant the rights conveyed by this License.
+3.3. Required Notices.
+You must include a notice in each of Your Modifications that identifies You as the Contributor of the Modification. You may not remove or alter any copyright, patent or trademark notices contained within the Covered Software, or any notices of licensing or any descriptive text giving attribution to any Contributor or the Initial Developer.
+3.4. Application of Additional Terms.
+You may not offer or impose any terms on any Covered Software in Source Code form that alters or restricts the applicable version of this License or the recipients� rights hereunder. You may choose to offer, and to charge a fee for, warranty, support, indemnity or liability obligations to one or more recipients of Covered Software. However, you may do so only on Your own behalf, and not on behalf of the Initial Developer or any Contributor. You must make it absolutely clear that any such warranty, support, indemnity or liability obligation is offered by You alone, and You hereby agree to indemnify the Initial Developer and every Contributor for any liability incurred by the Initial Developer or such Contributor as a result of warranty, support, indemnity or liability terms You offer.
+3.5. Distribution of Executable Versions.
+You may distribute the Executable form of the Covered Software under the terms of this License or under the terms of a license of Your choice, which may contain terms different from this License, provided that You are in compliance with the terms of this License and that the license for the Executable form does not attempt to limit or alter the recipient�s rights in the Source Code form from the rights set forth in this License. If You distribute the Covered Software in Executable form under a different license, You must make it absolutely clear that any terms which differ from this License are offered by You alone, not by the Initial Developer or Contributor. You hereby agree to indemnify the Initial Developer and every Contributor for any liability incurred by the Initial Developer or such Contributor as a result of any such terms You offer.
+3.6. Larger Works.
+You may create a Larger Work by combining Covered Software with other code not governed by the terms of this License and distribute the Larger Work as a single product. In such a case, You must make sure the requirements of this License are fulfilled for the Covered Software.
+4. Versions of the License.
+4.1. New Versions.
+Oracle Corp. is the initial license steward and may publish revised and/or new versions of this License from time to time. Each version will be given a distinguishing version number. Except as provided in Section 4.3, no one other than the license steward has the right to modify this License.
+4.2. Effect of New Versions.
+You may always continue to use, distribute or otherwise make the Covered Software available under the terms of the version of the License under which You originally received the Covered Software. If the Initial Developer includes a notice in the Original Software prohibiting it from being distributed or otherwise made available under any subsequent version of the License, You must distribute and make the Covered Software available under the terms of the version of the License under which You originally received the Covered Software. Otherwise, You may also choose to use, distribute or otherwise make the Covered Software available under the terms of any subsequent version of the License published by the license steward.
+4.3. Modified Versions.
+When You are an Initial Developer and You want to create a new license for Your Original Software, You may create and use a modified version of this License if You: (a) rename the license and remove any references to the name of the license steward (except to note that the license differs from this License); and (b) otherwise make it clear that the license contains terms which differ from this License.
+5. DISCLAIMER OF WARRANTY.
+COVERED SOFTWARE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES THAT THE COVERED SOFTWARE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED SOFTWARE IS WITH YOU. SHOULD ANY COVERED SOFTWARE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF ANY COVERED SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER.
+6. TERMINATION.
+6.1. This License and the rights granted hereunder will terminate automatically if You fail to comply with terms herein and fail to cure such breach within 30 days of becoming aware of the breach. Provisions which, by their nature, must remain in effect beyond the termination of this License shall survive.
+6.2. If You assert a patent infringement claim (excluding declaratory judgment actions) against Initial Developer or a Contributor (the Initial Developer or Contributor against whom You assert such claim is referred to as "Participant") alleging that the Participant Software (meaning the Contributor Version where the Participant is a Contributor or the Original Software where the Participant is the Initial Developer) directly or indirectly infringes any patent, then any and all rights granted directly or indirectly to You by such Participant, the Initial Developer (if the Initial Developer is not the Participant) and all Contributors under Sections 2.1 and/or 2.2 of this License shall, upon 60 days notice from Participant terminate prospectively and automatically at the expiration of such 60 day notice period, unless if within such 60 day period You withdraw Your claim with respect to the Participant Software against such Participant either unilaterally or pursuant to a written agreement with Participant.
+6.3. In the event of termination under Sections 6.1 or 6.2 above, all end user licenses that have been validly granted by You or any distributor hereunder prior to termination (excluding licenses granted to You by any distributor) shall survive termination.
+7. LIMITATION OF LIABILITY.
+UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL YOU, THE INITIAL DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF COVERED SOFTWARE, OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO ANY PERSON FOR ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOST PROFITS, LOSS OF GOODWILL, WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY RESULTING FROM SUCH PARTY�S NEGLIGENCE TO THE EXTENT APPLICABLE LAW PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THIS EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU.
+8. U.S. GOVERNMENT END USERS.
+The Covered Software is a "commercial item," as that term is defined in 48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial computer software" (as that term is defined at 48 C.F.R. �252.227-7014(a)(1)) and "commercial computer software documentation" as such terms are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48 C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995), all U.S. Government End Users acquire Covered Software with only those rights set forth herein. This U.S. Government Rights clause is in lieu of, and supersedes, any other FAR, DFAR, or other clause or provision that addresses Government rights in computer software under this License.
+9. MISCELLANEOUS.
+This License represents the complete agreement concerning subject matter hereof. If any provision of this License is held to be unenforceable, such provision shall be reformed only to the extent necessary to make it enforceable. This License shall be governed by the law of the jurisdiction specified in a notice contained within the Original Software (except to the extent applicable law, if any, provides otherwise), excluding such jurisdiction�s conflict-of-law provisions. Any litigation relating to this License shall be subject to the jurisdiction of the courts located in the jurisdiction and venue specified in a notice contained within the Original Software, with the losing party responsible for costs, including, without limitation, court costs and reasonable attorneys� fees and expenses. The application of the United Nations Convention on Contracts for the International Sale of Goods is expressly excluded. Any law or regulation which provides that the language of a contract shall be construed against the drafter shall not apply to this License. You agree that You alone are responsible for compliance with the United States export administration regulations (and the export control laws and regulation of any other countries) when You use, distribute or otherwise make available any Covered Software.
+10. RESPONSIBILITY FOR CLAIMS.
+As between Initial Developer and the Contributors, each party is responsible for claims and damages arising, directly or indirectly, out of its utilization of rights under this License and You agree to work with Initial Developer and Contributors to distribute such responsibility on an equitable basis. Nothing herein is intended or shall be deemed to constitute any admission of liability.
+NOTICE PURSUANT TO SECTION 9 OF THE COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL)
+The code released under the CDDL shall be governed by the laws of the State of California (excluding conflict-of-law provisions). Any litigation relating to this License shall be subject to the jurisdiction of the Federal Courts of the Northern District of California and the state courts of the State of California, with venue lying in Santa Clara County, California.
+The GNU General Public License (GPL) Version 2, June 1991
+
+Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.
+Preamble
+The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too.
+When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things.
+To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it.
+For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights.
+We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software.
+Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations.
+Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all.
+The precise terms and conditions for copying, distribution and modification follow.
+TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you".
+Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does.
+1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program.
+You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee.
+2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions:
+a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change.
+b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License.
+c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.)
+These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it.
+Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program.
+In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License.
+3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following:
+a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or,
+b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or,
+c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.)
+The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable.
+If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code.
+4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance.
+5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it.
+6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License.
+7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program.
+If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances.
+It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice.
+This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License.
+8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License.
+9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.
+Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation.
+10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally.
+NO WARRANTY
+11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+END OF TERMS AND CONDITIONS
+How to Apply These Terms to Your New Programs
+If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms.
+To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found.
+One line to give the program's name and a brief idea of what it does.
+Copyright (C)
+This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+Also add information on how to contact you by electronic and paper mail.
+If the program is interactive, make it output a short notice like this when it starts in an interactive mode:
+Gnomovision version 69, Copyright (C) year name of author
+Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details.
+The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program.
+You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names:
+Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker.
+signature of Ty Coon, 1 April 1989
+Ty Coon, President of Vice
+This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License.
+"CLASSPATH" EXCEPTION TO THE GPL VERSION 2
+Certain source files distributed by Oracle America, Inc. and/or its affiliates are subject to the following clarification and special exception to the GPLv2, based on the GNU Project exception for its Classpath libraries, known as the GNU Classpath Exception, but only where Oracle has expressly included in the particular source file's header the words "Oracle designates this particular file as subject to the "Classpath" exception as provided by Oracle in the LICENSE file that accompanied this code."
+You should also note that Oracle includes multiple, independent programs in this software package. Some of those programs are provided under licenses deemed incompatible with the GPLv2 by the Free Software Foundation and others. For example, the package includes programs licensed under the Apache License, Version 2.0. Such programs are licensed to you under their original licenses.
+Oracle facilitates your further distribution of this package by adding the Classpath Exception to the necessary parts of its GPLv2 code, which permits you to use that code in combination with other independent modules not licensed under the GPLv2. However, note that this would not permit you to commingle code under an incompatible license with Oracle's GPLv2 licensed code by, for example, cutting and pasting such code into a file also containing Oracle's GPLv2 licensed code and then distributing the result.
+Additionally, if you were to remove the Classpath Exception from any of the files to which it applies and distribute the result, you would likely be required to license some or all of the other code in that distribution under the GPLv2 as well, and since the GPLv2 is incompatible with the license terms of some items included in the distribution by Oracle, removing the Classpath Exception could therefore effectively compromise your ability to further distribute the package.
+Proceed with caution and we recommend that you obtain the advice of a lawyer skilled in open source matters before removing the Classpath Exception or making modifications to this package which may subsequently be redistributed and/or involve the use of third party software.
+CLASSPATH EXCEPTION
+Linking this library statically or dynamically with other modules is making a combined work based on this library. Thus, the terms and conditions of the GNU General Public License version 2 cover the whole combination.
+As a special exception, the copyright holders of this library give you permission to link this library with independent modules to produce an executable, regardless of the license terms of these independent modules, and to copy and distribute the resulting executable under terms of your choice, provided that you also meet, for each linked independent module, the terms and conditions of the license of that module. An independent module is a module which is not derived from or based on this library. If you modify this library, you may extend this exception to your version of the library, but you are not obligated to do so. If you do not wish to do so, delete this exception statement from your version.
diff --git a/cloud.amazon/manifest.mf b/cloud.amazon/manifest.mf
new file mode 100644
index 0000000000..1df03def5a
--- /dev/null
+++ b/cloud.amazon/manifest.mf
@@ -0,0 +1,8 @@
+Manifest-Version: 1.0
+AutoUpdate-Show-In-Client: false
+OpenIDE-Module: org.netbeans.modules.cloud.amazon/0
+OpenIDE-Module-Provides: org.netbeans.modules.serverplugins.javaee
+OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/cloud/amazon/Bundle.properties
+OpenIDE-Module-Layer: org/netbeans/modules/cloud/amazon/resources/layer.xml
+OpenIDE-Module-Specification-Version: 1.16
+
diff --git a/cloud.amazon/nbproject/project.properties b/cloud.amazon/nbproject/project.properties
new file mode 100644
index 0000000000..c0af75f0c2
--- /dev/null
+++ b/cloud.amazon/nbproject/project.properties
@@ -0,0 +1,18 @@
+# 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.
+javac.source=1.6
+javac.compilerargs=-Xlint -Xlint:-serial
diff --git a/cloud.amazon/nbproject/project.xml b/cloud.amazon/nbproject/project.xml
new file mode 100644
index 0000000000..dca571fedd
--- /dev/null
+++ b/cloud.amazon/nbproject/project.xml
@@ -0,0 +1,175 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    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.
+
+-->
+<project xmlns="http://www.netbeans.org/ns/project/1">
+    <type>org.netbeans.modules.apisupport.project</type>
+    <configuration>
+        <data xmlns="http://www.netbeans.org/ns/nb-module-project/3">
+            <code-name-base>org.netbeans.modules.cloud.amazon</code-name-base>
+            <module-dependencies>
+                <dependency>
+                    <code-name-base>org.netbeans.libs.amazon</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>1</release-version>
+                        <specification-version>1.0</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.modules.cloud.common</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.0</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.modules.j2ee.core</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>0</release-version>
+                        <specification-version>1.9</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.modules.j2eeapis</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>1</release-version>
+                        <specification-version>1.20</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.modules.j2eeserver</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>4</release-version>
+                        <specification-version>1.82</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.modules.java.platform</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>1</release-version>
+                        <specification-version>1.22</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.modules.keyring</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.7</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.modules.project.libraries</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>1</release-version>
+                        <specification-version>1.49</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.modules.server</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>0</release-version>
+                        <specification-version>1.14</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.awt</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>7.35</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.dialogs</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>7.21</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.filesystems</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>9.0</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.nodes</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>7.23</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.util.ui</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>9.3</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.util</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>9.3</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.9</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.modules.web.common</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.49</specification-version>
+                    </run-dependency>
+                </dependency>
+            </module-dependencies>
+            <public-packages/>
+        </data>
+    </configuration>
+</project>
diff --git a/cloud.amazon/src/org/netbeans/modules/cloud/amazon/AmazonInstance.java b/cloud.amazon/src/org/netbeans/modules/cloud/amazon/AmazonInstance.java
new file mode 100644
index 0000000000..04039d4f33
--- /dev/null
+++ b/cloud.amazon/src/org/netbeans/modules/cloud/amazon/AmazonInstance.java
@@ -0,0 +1,417 @@
+/*
+ * 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.cloud.amazon;
+
+import com.amazonaws.AmazonClientException;
+import com.amazonaws.AmazonServiceException;
+import java.io.IOException;
+import java.util.List;
+import org.netbeans.modules.cloud.amazon.serverplugin.AmazonJ2EEInstance;
+import com.amazonaws.auth.AWSCredentials;
+import com.amazonaws.auth.BasicAWSCredentials;
+import com.amazonaws.services.elasticbeanstalk.AWSElasticBeanstalk;
+import com.amazonaws.services.elasticbeanstalk.AWSElasticBeanstalkClient;
+import com.amazonaws.services.elasticbeanstalk.model.ApplicationDescription;
+import com.amazonaws.services.elasticbeanstalk.model.CheckDNSAvailabilityRequest;
+import com.amazonaws.services.elasticbeanstalk.model.CheckDNSAvailabilityResult;
+import com.amazonaws.services.elasticbeanstalk.model.CreateApplicationRequest;
+import com.amazonaws.services.elasticbeanstalk.model.CreateApplicationVersionRequest;
+import com.amazonaws.services.elasticbeanstalk.model.CreateApplicationVersionResult;
+import com.amazonaws.services.elasticbeanstalk.model.CreateEnvironmentRequest;
+import com.amazonaws.services.elasticbeanstalk.model.DescribeEnvironmentsRequest;
+import com.amazonaws.services.elasticbeanstalk.model.DescribeEnvironmentsResult;
+import com.amazonaws.services.elasticbeanstalk.model.EnvironmentDescription;
+import com.amazonaws.services.elasticbeanstalk.model.EnvironmentStatus;
+import com.amazonaws.services.elasticbeanstalk.model.S3Location;
+import com.amazonaws.services.elasticbeanstalk.model.UpdateEnvironmentRequest;
+import com.amazonaws.services.elasticbeanstalk.model.UpdateEnvironmentResult;
+import com.amazonaws.services.s3.AmazonS3;
+import com.amazonaws.services.s3.AmazonS3Client;
+import com.amazonaws.services.s3.model.AmazonS3Exception;
+import com.amazonaws.services.s3.model.ObjectMetadata;
+import com.amazonaws.services.s3.model.PutObjectRequest;
+import java.io.File;
+import java.io.InputStream;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.Callable;
+import java.util.concurrent.Future;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.swing.SwingUtilities;
+import org.netbeans.api.server.ServerInstance;
+import org.netbeans.modules.cloud.common.spi.support.serverplugin.DeploymentStatus;
+import org.netbeans.modules.cloud.common.spi.support.serverplugin.ProgressObjectImpl;
+import org.openide.util.Exceptions;
+import org.openide.util.NbBundle;
+import org.openide.util.RequestProcessor;
+
+/**
+ * Describes single Amazon account.
+ */
+public class AmazonInstance {
+
+    private static final RequestProcessor AMAZON_RP = new RequestProcessor("amazon aws", 1); // NOI18N
+    
+    private static final Logger LOG = Logger.getLogger(AmazonInstance.class.getSimpleName());
+    
+    public static final String DEFAULT_EMPTY_APPLICATION = "empty-nb-app-1.0.war";
+    
+    private final String keyId;
+    private final String key;
+    private final String name;
+    private final String regionUrl;
+    
+    private ServerInstance serverInstance;
+
+    public AmazonInstance(String name, String keyId, String key, String regionURL) {
+        this.keyId = keyId;
+        this.key = key;
+        this.name = name;
+        this.regionUrl = regionURL;
+    }
+
+    void setServerInstance(ServerInstance serverInstance) {
+        this.serverInstance = serverInstance;
+    }
+
+    public ServerInstance getServerInstance() {
+        return serverInstance;
+    }
+    
+    public String getKeyId() {
+        return keyId;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public String getKey() {
+        return key;
+    }
+
+    public String getRegionURL() {
+        return regionUrl;
+    }
+    
+    private AWSCredentials getCredentials() {
+        return new BasicAWSCredentials(keyId, key);
+    }
+    
+    private static AWSCredentials getCredentials(String keyId, String key) {
+        return new BasicAWSCredentials(keyId, key);
+    }
+    
+    public void testConnection() {
+        assert !SwingUtilities.isEventDispatchThread();
+        AWSElasticBeanstalk client = new AWSElasticBeanstalkClient(getCredentials());
+        if (regionUrl != null) {
+            client.setEndpoint(regionUrl);
+        }
+        client.createStorageLocation();
+    }
+    
+    public List<AmazonJ2EEInstance> readJ2EEServerInstances() {
+        assert !SwingUtilities.isEventDispatchThread();
+        List<AmazonJ2EEInstance> res = new ArrayList<AmazonJ2EEInstance>();
+
+//        try {
+            LOG.log(Level.INFO, "read AWS environments"); // NOI18N
+            AWSElasticBeanstalk client = new AWSElasticBeanstalkClient(getCredentials());
+            if (regionUrl != null) {
+                client.setEndpoint(regionUrl);
+            }
+            for (EnvironmentDescription ed : client.describeEnvironments().getEnvironments()) {
+                AmazonJ2EEInstance inst = new AmazonJ2EEInstance(this, ed.getApplicationName(), 
+                        ed.getEnvironmentName(), ed.getEnvironmentId(),
+                        ed.getSolutionStackName());
+                inst.updateState(ed.getStatus());
+                res.add(inst);
+            }
+            LOG.log(Level.INFO, "environments available: "+res); // NOI18N
+//        } catch (AmazonClientException ex) {
+//            Exceptions.printStackTrace(ex);
+//        }
+        
+// fake it:
+//        res.add(new AmazonJ2EEInstance(this, "app", "env"));
+            
+        return res;
+    }
+
+    public List<String> readApplicationNames() {
+        assert !SwingUtilities.isEventDispatchThread();
+        List<String> res = new ArrayList<String>();
+
+        try {
+            LOG.log(Level.INFO, "read AWS applications"); // NOI18N
+            AWSElasticBeanstalk client = new AWSElasticBeanstalkClient(getCredentials());
+            if (regionUrl != null) {
+                client.setEndpoint(regionUrl);
+            }
+            for (ApplicationDescription ad : client.describeApplications().getApplications()) {
+                res.add(ad.getApplicationName());
+            }
+            LOG.log(Level.INFO, "applications available: "+res); // NOI18N
+        } catch (AmazonClientException ex) {
+            Exceptions.printStackTrace(ex);
+        }
+        
+        return res;
+    }
+
+    /**
+     * @return Map<application name, List<template name>>
+     */
+    public Map<String, List<String>> readApplicationTemplates() {
+        assert !SwingUtilities.isEventDispatchThread();
+        Map<String, List<String>> res = new HashMap<String, List<String>>();
+
+        try {
+            LOG.log(Level.INFO, "read AWS application templates"); // NOI18N
+            AWSElasticBeanstalk client = new AWSElasticBeanstalkClient(getCredentials());
+            if (regionUrl != null) {
+                client.setEndpoint(regionUrl);
+            }
+            for (ApplicationDescription ad : client.describeApplications().getApplications()) {
+                res.put(ad.getApplicationName(), ad.getConfigurationTemplates());
+            }
+            LOG.log(Level.INFO, "applications templates available: "+res); // NOI18N
+        } catch (AmazonClientException ex) {
+            Exceptions.printStackTrace(ex);
+        }
+        
+        return res;
+    }
+    
+    public List<String> readContainerTypes() {
+        assert !SwingUtilities.isEventDispatchThread();
+        List<String> res = new ArrayList<String>();
+
+        try {
+            LOG.log(Level.INFO, "read AWS solution stacks"); // NOI18N
+            AWSElasticBeanstalk client = new AWSElasticBeanstalkClient(getCredentials());
+            if (regionUrl != null) {
+                client.setEndpoint(regionUrl);
+            }
+            res = client.listAvailableSolutionStacks().getSolutionStacks();
+            LOG.log(Level.INFO, "solution stacks available: "+res); // NOI18N
+        } catch (AmazonClientException ex) {
+            Exceptions.printStackTrace(ex);
+        }
+        
+        return res;
+    }
+    
+    public boolean checkURLValidity(String url) {
+        assert !SwingUtilities.isEventDispatchThread();
+        AWSElasticBeanstalk client = new AWSElasticBeanstalkClient(getCredentials());
+        if (regionUrl != null) {
+            client.setEndpoint(regionUrl);
+        }
+        CheckDNSAvailabilityResult res = client.checkDNSAvailability(new CheckDNSAvailabilityRequest(url));
+        return res.isAvailable();
+    }
+
+    public void createApplication(String appName) {
+        assert !SwingUtilities.isEventDispatchThread();
+        AWSElasticBeanstalk client = new AWSElasticBeanstalkClient(getCredentials());
+        if (regionUrl != null) {
+            client.setEndpoint(regionUrl);
+        }
+        CreateApplicationRequest req = new CreateApplicationRequest(appName);
+        client.createApplication(req).getApplication();
+    }
+    
+    public S3Location createDefaultEmptyApplication() {
+        assert !SwingUtilities.isEventDispatchThread();
+        AWSElasticBeanstalk client = new AWSElasticBeanstalkClient(getCredentials());
+        if (regionUrl != null) {
+            client.setEndpoint(regionUrl);
+        }
+        AmazonS3 s3 = new AmazonS3Client(getCredentials(keyId, key));
+        
+        String bucket = client.createStorageLocation().getS3Bucket();
+        boolean exist = false;
+        try {
+            s3.getObjectMetadata(bucket, DEFAULT_EMPTY_APPLICATION);
+            exist = true;
+        } catch (AmazonS3Exception ex) {
+            // this mean object does not exist in S3 - fine
+        }
+        if (!exist) {
+            InputStream is = AmazonInstance.class.getResourceAsStream("resources/empty.war");
+            s3.putObject(new PutObjectRequest(bucket, DEFAULT_EMPTY_APPLICATION, is, new ObjectMetadata()));
+            try {
+                is.close();
+            } catch (IOException ex) {
+                Exceptions.printStackTrace(ex);
+            }
+        }
+        return new S3Location().withS3Bucket(bucket).withS3Key(DEFAULT_EMPTY_APPLICATION);
+    }
+    
+    public void createInitialEmptyApplication(String appName) {
+        assert !SwingUtilities.isEventDispatchThread();
+        AWSElasticBeanstalk client = new AWSElasticBeanstalkClient(getCredentials());
+        if (regionUrl != null) {
+            client.setEndpoint(regionUrl);
+        }
+        S3Location slocation = createDefaultEmptyApplication();
+        
+        CreateApplicationVersionRequest req = new CreateApplicationVersionRequest(appName, "blank application from NetBeans").
+                withSourceBundle(slocation);
+        client.createApplicationVersion(req);
+    }
+
+    public String createEnvironment(String appName, String envName, String url, String containerType, String template) {
+        assert !SwingUtilities.isEventDispatchThread();
+        AWSElasticBeanstalk client = new AWSElasticBeanstalkClient(getCredentials());
+        if (regionUrl != null) {
+            client.setEndpoint(regionUrl);
+        }
+        CreateEnvironmentRequest req = new CreateEnvironmentRequest(appName, envName).
+                withCNAMEPrefix(url).
+                withSolutionStackName(containerType);
+        if (template != null) {
+            req = req.withTemplateName(template);
+        }
+        return client.createEnvironment(req).getEnvironmentId();
+    }
+
+    public static Future<DeploymentStatus> deployAsync(final File f, final String applicationName, 
+                         final String environmentId, final String keyId, final String key,
+                         final ProgressObjectImpl po, final String regionUrl) {
+        return runAsynchronously(new Callable<DeploymentStatus>() {
+            @Override
+            public DeploymentStatus call() throws Exception {
+                String url[] = new String[1];
+                DeploymentStatus ds = deploy(f, applicationName, environmentId, keyId, key, po, url, regionUrl);
+                LOG.log(Level.INFO, "deployment result: "+ds); // NOI18N
+                po.updateDepoymentResult(ds, url[0]);
+                return ds;
+            }
+        });
+    }
+    
+    public static DeploymentStatus deploy(File f, String applicationName, 
+                          String environmentId, String keyId, String key,
+                          ProgressObjectImpl po, String[] url, String regionUrl) {
+        assert !SwingUtilities.isEventDispatchThread();
+        try {
+            if (po != null) {
+                try {
+                po.updateDepoymentStage(NbBundle.getMessage(AmazonInstance.class, "MSG_DEPLOY_AUTH"));
+                } catch (Throwable tt) {
+                    tt.printStackTrace();
+                }
+            }
+            LOG.log(Level.INFO, "deploy to AWS["+environmentId+"] "+f); // NOI18N
+            AWSElasticBeanstalk client = new AWSElasticBeanstalkClient(getCredentials(keyId, key));
+            if (regionUrl != null) {
+                client.setEndpoint(regionUrl);
+            }
+            AmazonS3 s3 = new AmazonS3Client(getCredentials(keyId, key));
+
+            if (po != null) {
+                po.updateDepoymentStage(NbBundle.getMessage(AmazonInstance.class, "MSG_DEPLOY_UPLOAD"));
+            }
+            String label = f.getName().toLowerCase();
+            assert label.endsWith(".war") || label.endsWith(".ear") || label.endsWith(".jar") : "war/jar/ear archive expected: "+f; // NOI18N
+            String version = new SimpleDateFormat("yyyyMMdd-HHmmss-SSSS").format(new Date()); // NOI18N
+            label = label.substring(0, label.length()-4) + "-" + version + "." + label.substring(label.length()-3); // NOI18N
+
+            String bucket = client.createStorageLocation().getS3Bucket();
+            LOG.log(Level.INFO, "using bucket "+bucket); // NOI18N
+            LOG.log(Level.INFO, "label "+label); // NOI18N
+            s3.putObject(new PutObjectRequest(bucket, label, f));
+            S3Location slocation = new S3Location().withS3Bucket(bucket).withS3Key(label);
+
+            if (po != null) {
+                po.updateDepoymentStage(NbBundle.getMessage(AmazonInstance.class, "MSG_DEPLOY_UPDATE"));
+            }
+            CreateApplicationVersionRequest newApp = new CreateApplicationVersionRequest().
+                    withVersionLabel(label).
+                    withApplicationName(applicationName).
+                    withDescription(NbBundle.getMessage(AmazonInstance.class, "MSG_DEPLOY_NB")).
+                    withAutoCreateApplication(Boolean.FALSE).
+                    withSourceBundle(slocation);
+            client.createApplicationVersion(newApp);
+
+            UpdateEnvironmentRequest updateReq = new UpdateEnvironmentRequest().
+                    withEnvironmentId(environmentId).
+                    withVersionLabel(label);
+            try {
+                UpdateEnvironmentResult result = client.updateEnvironment(updateReq);
+                url[0] = "http://"+result.getEndpointURL(); // NOI18N
+                LOG.log(Level.INFO, "environment updated "+result); // NOI18N
+            } catch (AmazonServiceException as) {
+                LOG.log(Level.INFO, "environment update failed", as); // NOI18N
+                if (po != null) {
+                    po.updateDepoymentStage(as.toString());
+                }
+                return DeploymentStatus.FAILED;
+            }
+
+            if (po != null) {
+                po.updateDepoymentStage(NbBundle.getMessage(AmazonInstance.class, "MSG_DEPLOY_REDEPLOY"));
+            }
+            DescribeEnvironmentsRequest request = new DescribeEnvironmentsRequest().withEnvironmentIds(environmentId);
+            while (true) {
+                try {
+                    // let's wait
+                    Thread.sleep(5000);
+                } catch (InterruptedException ex) {
+                    Exceptions.printStackTrace(ex);
+                }
+                DescribeEnvironmentsResult envir = client.describeEnvironments(request);
+                if (envir.getEnvironments().size() != 1) {
+                    // something wrong - environment was deleted??
+                    return DeploymentStatus.UNKNOWN;
+                }
+                EnvironmentDescription env = envir.getEnvironments().get(0);
+                LOG.log(Level.INFO, "AWS["+environmentId+"] status: "+env.getStatus() +" and health:"+ env.getHealth()); // NOI18N
+                if (EnvironmentStatus.fromValue(env.getStatus()) == EnvironmentStatus.Ready) {
+                    return DeploymentStatus.SUCCESS;
+                }
+                if (EnvironmentStatus.fromValue(env.getStatus()) == EnvironmentStatus.Terminated ||
+                        EnvironmentStatus.fromValue(env.getStatus()) == EnvironmentStatus.Terminating) {
+                    return DeploymentStatus.UNKNOWN;
+                }
+            }
+        } catch (AmazonClientException ex) {
+            Exceptions.printStackTrace(ex);
+            return DeploymentStatus.UNKNOWN;
+        }
+    }
+
+    public static <T> Future<T> runAsynchronously(Callable<T> callable) {
+        return runAsynchronously(callable, null);
+    }
+    
+    public static synchronized <T> Future<T> runAsynchronously(Callable<T> callable, AmazonInstance ai) {
+        Future<T> f = AMAZON_RP.submit(callable);
+        return f;
+    }
+    
+}
diff --git a/cloud.amazon/src/org/netbeans/modules/cloud/amazon/AmazonInstanceManager.java b/cloud.amazon/src/org/netbeans/modules/cloud/amazon/AmazonInstanceManager.java
new file mode 100644
index 0000000000..1a5ca14713
--- /dev/null
+++ b/cloud.amazon/src/org/netbeans/modules/cloud/amazon/AmazonInstanceManager.java
@@ -0,0 +1,139 @@
+/*
+ * 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.cloud.amazon;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.swing.event.ChangeListener;
+import org.netbeans.api.keyring.Keyring;
+import org.netbeans.api.server.properties.InstanceProperties;
+import org.netbeans.api.server.properties.InstancePropertiesManager;
+import org.openide.util.ChangeSupport;
+
+/**
+ * Manager of all Amazon accounts registered in the IDE (usually just one).
+ */
+public class AmazonInstanceManager {
+
+    private static final String AMAZON_IP_NAMESPACE = "cloud.amazon"; // NOI18N
+    
+    private static final String PREFIX = "org.netbeans.modules.cloud.amazon."; // NOI18N
+    private static final String KEY_ID = "access-key-id"; // NOI18N
+    private static final String KEY = "secret-access-key"; // NOI18N
+    private static final String REGION = "region"; // NOI18N
+    
+    private static AmazonInstanceManager instance;
+    private List<AmazonInstance> instances = new ArrayList<AmazonInstance>();
+    private ChangeSupport listeners;
+    
+    private static final Logger LOG = Logger.getLogger(AmazonInstanceManager.class.getSimpleName());
+    
+    
+    public static synchronized AmazonInstanceManager getDefault() {
+        if (instance == null) {
+            instance = new AmazonInstanceManager();
+        }
+        return instance;
+    }
+    
+    private AmazonInstanceManager() {
+        listeners = new ChangeSupport(this);
+        /*if (getAmazonInstanceNames().size() == 0) {
+            store(new AmazonInstance("test1", "somekey", "somepwd"));
+            store(new AmazonInstance("some2", "somekey2", "somepwd2"));
+            store(new AmazonInstance("last3", "somekey3", "somepwd3"));
+        }*/
+        init();
+    }
+    
+    private void init() {
+       instances.addAll(load());
+       notifyChange();
+    }
+    
+    private void notifyChange() {
+       listeners.fireChange();
+    }
+
+    public List<AmazonInstance> getInstances() {
+        return instances;
+    }
+    
+    public void add(AmazonInstance ai) {
+        store(ai);
+        instances.add(ai);
+        notifyChange();
+    }
+    
+    private void store(AmazonInstance ai) {
+        InstanceProperties props = InstancePropertiesManager.getInstance().createProperties(AMAZON_IP_NAMESPACE);
+        
+        Keyring.save(PREFIX+KEY_ID+"."+ai.getName(), ai.getKeyId().toCharArray(), "Amazon Access Key ID"); // NOI18N
+        Keyring.save(PREFIX+KEY+"."+ai.getName(), ai.getKey().toCharArray(), "Amazon Secret Access Key"); // NOI18N
+        
+        props.putString("name", ai.getName()); // NOI18N
+        props.putString("region", ai.getRegionURL()); // NOI18N
+    }
+    
+    
+    private static List<AmazonInstance> load() {
+        List<AmazonInstance> result = new ArrayList<AmazonInstance>();
+        for(InstanceProperties props : InstancePropertiesManager.getInstance().getProperties(AMAZON_IP_NAMESPACE)) {
+            String name = props.getString("name", null); // NOI18N
+            assert name != null : "Instance without name";
+            String region = props.getString(REGION, null); // NOI18N
+            
+            char ch[] = Keyring.read(PREFIX+KEY_ID+"."+name);
+            if (ch == null) {
+                LOG.log(Level.WARNING, "no access key id found for "+name);
+                continue;
+            }
+            String keyId = new String(ch);
+            ch = Keyring.read(PREFIX+KEY+"."+name);
+            if (ch == null) {
+                LOG.log(Level.WARNING, "no secret access key found for "+name);
+                continue;
+            }
+            String key = new String(ch);
+            result.add(new AmazonInstance(name, keyId, key, region));
+        }
+        return result;
+    }
+
+    public void addChangeListener(ChangeListener l) {
+        listeners.addChangeListener(l);
+    }
+    
+    public void removeChangeListener(ChangeListener l) {
+        listeners.removeChangeListener(l);
+    }
+
+    void remove(AmazonInstance ai) {
+        for (InstanceProperties props : InstancePropertiesManager.getInstance().getProperties(AMAZON_IP_NAMESPACE)) {
+            if (ai.getName().equals(props.getString("name", null))) { // NOI18N
+                props.remove();
+                break;
+            }
+        }
+        instances.remove(ai);
+        notifyChange();
+    }
+}
diff --git a/cloud.amazon/src/org/netbeans/modules/cloud/amazon/AmazonServerInstanceImplementation.java b/cloud.amazon/src/org/netbeans/modules/cloud/amazon/AmazonServerInstanceImplementation.java
new file mode 100644
index 0000000000..ea13a363b9
--- /dev/null
+++ b/cloud.amazon/src/org/netbeans/modules/cloud/amazon/AmazonServerInstanceImplementation.java
@@ -0,0 +1,76 @@
+/*
+ * 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.cloud.amazon;
+
+import javax.swing.JComponent;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+import org.netbeans.modules.cloud.amazon.ui.AmazonInstanceNode;
+import org.netbeans.modules.cloud.amazon.ui.AmazonWizardComponent;
+import org.netbeans.spi.server.ServerInstanceImplementation;
+import org.openide.nodes.Node;
+
+/**
+ * Representation of single amazon cloud account under "Cloud" node.
+ */
+public class AmazonServerInstanceImplementation implements ServerInstanceImplementation {
+
+    private AmazonInstance ai;
+
+    public AmazonServerInstanceImplementation(AmazonInstance ai) {
+        this.ai = ai;
+    }
+    
+    @Override
+    public String getDisplayName() {
+        return ai.getName();
+    }
+
+    @Override
+    public String getServerDisplayName() {
+        return "Amazon Beanstalk";
+    }
+
+    @Override
+    public Node getFullNode() {
+        return getBasicNode();
+    }
+
+    @Override
+    public Node getBasicNode() {
+        return new AmazonInstanceNode(ai);
+    }
+
+    @Override
+    public JComponent getCustomizer() {
+        AmazonWizardComponent panel = new AmazonWizardComponent(null, ai);
+        return panel;
+    }
+
+    @Override
+    public void remove() {
+        AmazonInstanceManager.getDefault().remove(ai);
+    }
+
+    @Override
+    public boolean isRemovable() {
+        return true;
+    }
+    
+}
diff --git a/cloud.amazon/src/org/netbeans/modules/cloud/amazon/AmazonServerInstanceProvider.java b/cloud.amazon/src/org/netbeans/modules/cloud/amazon/AmazonServerInstanceProvider.java
new file mode 100644
index 0000000000..1e857e0f8d
--- /dev/null
+++ b/cloud.amazon/src/org/netbeans/modules/cloud/amazon/AmazonServerInstanceProvider.java
@@ -0,0 +1,84 @@
+/*
+ * 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.cloud.amazon;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+import org.netbeans.api.server.ServerInstance;
+import org.netbeans.spi.server.ServerInstanceFactory;
+import org.netbeans.spi.server.ServerInstanceProvider;
+import org.openide.util.ChangeSupport;
+
+/**
+ * Provider of registered Amazon accounts in the IDE.
+ */
+public class AmazonServerInstanceProvider implements ServerInstanceProvider, ChangeListener {
+
+    private ChangeSupport listeners;
+    private List<ServerInstance> instances;
+    private static AmazonServerInstanceProvider instance;
+    
+    private AmazonServerInstanceProvider() {
+        listeners = new ChangeSupport(this);
+        instances = Collections.<ServerInstance>emptyList();
+        AmazonInstanceManager.getDefault().addChangeListener(this);
+        refreshServers();
+    }
+    
+    public static synchronized AmazonServerInstanceProvider getProvider() {
+        if (instance == null) {
+            instance = new AmazonServerInstanceProvider();
+        }
+        return instance;
+    }
+
+    @Override
+    public List<ServerInstance> getInstances() {
+        return instances;
+    }
+
+    @Override
+    public void addChangeListener(ChangeListener listener) {
+        listeners.addChangeListener(listener);
+    }
+
+    @Override
+    public void removeChangeListener(ChangeListener listener) {
+        listeners.removeChangeListener(listener);
+    }
+    
+    private void refreshServers() {
+        List<ServerInstance> servers = new ArrayList<ServerInstance>();
+        for (AmazonInstance ai : AmazonInstanceManager.getDefault().getInstances()) {
+            ServerInstance si = ServerInstanceFactory.createServerInstance(new AmazonServerInstanceImplementation(ai));
+            ai.setServerInstance(si);
+            servers.add(si);
+        }
+        this.instances = servers;
+        listeners.fireChange();
+    }
+
+    @Override
+    public void stateChanged(ChangeEvent e) {
+        refreshServers();
+    }
+}
diff --git a/cloud.amazon/src/org/netbeans/modules/cloud/amazon/AmazonServerWizardProvider.java b/cloud.amazon/src/org/netbeans/modules/cloud/amazon/AmazonServerWizardProvider.java
new file mode 100644
index 0000000000..5611a88b87
--- /dev/null
+++ b/cloud.amazon/src/org/netbeans/modules/cloud/amazon/AmazonServerWizardProvider.java
@@ -0,0 +1,39 @@
+/*
+ * 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.cloud.amazon;
+
+import org.netbeans.modules.cloud.amazon.ui.AmazonWizardIterator;
+import org.netbeans.spi.server.ServerWizardProvider;
+
+/**
+ *
+ */
+public class AmazonServerWizardProvider implements ServerWizardProvider {
+
+    @Override
+    public String getDisplayName() {
+        return "Amazon Beanstalk";
+    }
+
+    @Override
+    public org.openide.WizardDescriptor.InstantiatingIterator getInstantiatingIterator() {
+        return new AmazonWizardIterator();
+    }
+    
+}
diff --git a/cloud.amazon/src/org/netbeans/modules/cloud/amazon/Bundle.properties b/cloud.amazon/src/org/netbeans/modules/cloud/amazon/Bundle.properties
new file mode 100644
index 0000000000..a64c5bfbd4
--- /dev/null
+++ b/cloud.amazon/src/org/netbeans/modules/cloud/amazon/Bundle.properties
@@ -0,0 +1,23 @@
+# 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.
+OpenIDE-Module-Name=Amazon Elastic Beanstalk
+
+MSG_DEPLOY_AUTH=Authenticating ...
+MSG_DEPLOY_UPLOAD=Uploading ...
+MSG_DEPLOY_UPDATE=Updating ...
+MSG_DEPLOY_REDEPLOY=Redeploying ...
+MSG_DEPLOY_NB=Deployed by NetBeans IDE
diff --git a/cloud.amazon/src/org/netbeans/modules/cloud/amazon/resources/layer.xml b/cloud.amazon/src/org/netbeans/modules/cloud/amazon/resources/layer.xml
new file mode 100644
index 0000000000..6c9b841c9c
--- /dev/null
+++ b/cloud.amazon/src/org/netbeans/modules/cloud/amazon/resources/layer.xml
@@ -0,0 +1,109 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    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.
+
+-->
+<!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.2//EN" "http://www.netbeans.org/dtds/filesystem-1_2.dtd">
+<filesystem>
+
+    <folder name="Cloud">
+        <file name="AmazonServerInstanceProvider.instance">
+            <attr name="instanceCreate" methodvalue="org.netbeans.modules.cloud.amazon.AmazonServerInstanceProvider.getProvider"/>
+            <attr name="instanceClass" stringvalue="org.netbeans.modules.cloud.amazon.AmazonServerInstanceProvider"/>
+            <attr name="instanceOf" stringvalue="org.netbeans.spi.server.ServerInstanceProvider"/>
+        </file>
+        <file name="org-netbeans-modules-cloud-amazon-AmazonServerWizardProvider.instance">
+            <attr name="instanceClass" stringvalue="org.netbeans.modules.cloud.amazon.AmazonServerWizardProvider"/>
+            <attr name="instanceOf" stringvalue="org.netbeans.spi.server.ServerWizardProvider"/>
+            <attr name="displayName" bundlevalue="org.netbeans.modules.cloud.amazon.ui.Bundle#Amazon_Node_Name"/>
+        </file>
+    </folder>
+
+    <folder name="Servers">
+        <file name="AmazonJ2EEServerInstanceProvider.instance">
+            <attr name="instanceCreate" methodvalue="org.netbeans.modules.cloud.amazon.serverplugin.AmazonJ2EEServerInstanceProvider.getProvider"/>
+            <attr name="instanceClass" stringvalue="org.netbeans.modules.cloud.amazon.serverplugin.AmazonJ2EEServerInstanceProvider"/>
+            <attr name="instanceOf" stringvalue="org.netbeans.spi.server.ServerInstanceProvider"/>
+        </file>
+<!--        <file name="org-netbeans-modules-cloud-amazon-serverplugin-AmazonJ2EEServerWizardProvider.instance">
+            <attr name="instanceClass" stringvalue="org.netbeans.modules.cloud.amazon.serverplugin.AmazonJ2EEServerWizardProvider"/>
+            <attr name="instanceOf" stringvalue="org.netbeans.spi.server.ServerWizardProvider"/>
+        </file> -->
+    </folder>
+    
+    <folder name="J2EE">
+        <folder name="DeploymentPlugins">
+            <folder name="Amazon Beanstalk">
+                
+                <!-- 
+                    An instance of the class implementing the DeploymentFactory 
+                    interface, it will be used as the main entry point for the
+                    plugin
+                -->
+                <file name="Factory.instance">
+                    <attr name="urlPattern" stringvalue="^amazon:.*$"/>
+                    <attr name="instanceCreate" methodvalue="org.netbeans.modules.j2ee.deployment.plugins.spi.support.ProxyDeploymentFactory.create"/>
+                    <attr name="delegate" newvalue="org.netbeans.modules.cloud.amazon.serverplugin.AmazonDeploymentFactory"/>
+                    <attr name="instanceClass" stringvalue="org.netbeans.modules.j2ee.deployment.plugins.spi.support.ProxyDeploymentFactory"/>
+                    <attr name="instanceOf" stringvalue="javax.enterprise.deploy.spi.factories.DeploymentFactory"/>
+                </file>
+                
+                <!--
+                    An instance of the factory for creating the nodes that will 
+                    appear in the Server Registry, namely the Manager (Instance)
+                    node and the Target node
+                -->
+                <file name="RegistryNodeFactory.instance">
+                    <attr name="instanceClass" stringvalue="org.netbeans.modules.cloud.common.spi.support.serverplugin.RegistryNodeFactoryImpl"/>
+                    <attr name="instanceOf" stringvalue="org.netbeans.modules.j2ee.deployment.plugins.spi.RegistryNodeFactory"/>
+                </file>
+                
+                <!--
+                    An instance of the class implementing the 
+                    J2eeDeploymentFactory interface, it will be used to create 
+                    objects that describe the environment that exists on a 
+                    particular instance of the server
+                -->
+                <file name="J2eePlatformFactory.instance">
+                    <attr name="instanceClass" stringvalue="org.netbeans.modules.cloud.amazon.serverplugin.AmazonJ2eePlatformFactory"/>
+                    <attr name="instanceOf" stringvalue="org.netbeans.modules.j2ee.deployment.plugins.spi.J2eePlatformFactory"/>
+                </file>
+                
+                <!--
+                    A factory that creates objects that provide optional 
+                    functionality for the plugin, i.e. starting/stopping the
+                    server, getting a custom wizard for instance registration, 
+                    etc.
+                -->
+                <file name="ModuleConfigurationFactory.instance">
+                    <attr name="instanceClass" stringvalue="org.netbeans.modules.cloud.common.spi.support.serverplugin.ModuleConfigurationFactoryImpl"/>
+                    <attr name="instanceOf" stringvalue="org.netbeans.modules.j2ee.deployment.plugins.spi.config.ModuleConfigurationFactory"/>
+                </file>
+                
+                <file name="OptionalDeploymentManagerFactory.instance">
+                    <attr name="instanceClass" stringvalue="org.netbeans.modules.cloud.amazon.serverplugin.AmazonOptionalDeploymentManagerFactory"/>
+                    <attr name="instanceOf" stringvalue="org.netbeans.modules.j2ee.deployment.plugins.spi.OptionalDeploymentManagerFactory"/>
+                </file>
+                
+                <file name="Descriptor" url="nbdep.xml"/>
+            </folder>
+        </folder>
+    </folder>
+
+</filesystem>
diff --git a/cloud.amazon/src/org/netbeans/modules/cloud/amazon/resources/nbdep.xml b/cloud.amazon/src/org/netbeans/modules/cloud/amazon/resources/nbdep.xml
new file mode 100644
index 0000000000..23ecd6b157
--- /dev/null
+++ b/cloud.amazon/src/org/netbeans/modules/cloud/amazon/resources/nbdep.xml
@@ -0,0 +1,35 @@
+<!--
+
+    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.
+
+-->
+
+<netbeans-deployment>
+    <!--
+        URL for the disconnected deployment manager
+    -->
+    <disconnected-string>amazon:000</disconnected-string>
+
+    <!--
+        Web module's context root xpath
+    -->
+    <web-context-root>
+        <xpath>/</xpath>
+        <prop-name>contextRoot</prop-name>
+    </web-context-root>
+</netbeans-deployment>
diff --git a/cloud.amazon/src/org/netbeans/modules/cloud/amazon/serverplugin/AmazonDeploymentFactory.java b/cloud.amazon/src/org/netbeans/modules/cloud/amazon/serverplugin/AmazonDeploymentFactory.java
new file mode 100644
index 0000000000..90dc369f03
--- /dev/null
+++ b/cloud.amazon/src/org/netbeans/modules/cloud/amazon/serverplugin/AmazonDeploymentFactory.java
@@ -0,0 +1,72 @@
+/*
+ * 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.cloud.amazon.serverplugin;
+
+import javax.enterprise.deploy.spi.DeploymentManager;
+import javax.enterprise.deploy.spi.exceptions.DeploymentManagerCreationException;
+import javax.enterprise.deploy.spi.factories.DeploymentFactory;
+import org.netbeans.modules.j2ee.deployment.plugins.api.InstanceProperties;
+import org.openide.util.NbBundle;
+
+/**
+ *
+ */
+public class AmazonDeploymentFactory implements DeploymentFactory {
+
+    public static final String AMAZON_URI = "amazon:";  // NOI18N
+
+    // some instance properties:
+    public static final String IP_APPLICATION_NAME = "application-name";  // NOI18N
+    public static final String IP_ENVIRONMENT_ID = "environment--id";  // NOI18N
+    public static final String IP_KEY_ID = "access-key-id";  // NOI18N
+    public static final String IP_KEY = "access-key";  // NOI18N
+    public static final String IP_CONTAINER_TYPE = "container-type";  // NOI18N
+    public static final String IP_REGION_URL = "region-url";  // NOI18N
+    
+    @Override
+    public boolean handlesURI(String string) {
+        return string.startsWith(AMAZON_URI);
+    }
+
+    @Override
+    public DeploymentManager getDeploymentManager(String uri, String username,
+            String password) throws DeploymentManagerCreationException {
+        InstanceProperties props = InstanceProperties.getInstanceProperties(uri);
+        return new AmazonDeploymentManager(props.getProperty(IP_APPLICATION_NAME), props.getProperty(IP_ENVIRONMENT_ID), 
+                props.getProperty(IP_KEY_ID), props.getProperty(IP_KEY), props.getProperty(IP_CONTAINER_TYPE), props.getProperty(IP_REGION_URL));
+    }
+
+    @Override
+    public DeploymentManager getDisconnectedDeploymentManager(String uri) throws DeploymentManagerCreationException {
+        InstanceProperties props = InstanceProperties.getInstanceProperties(uri);
+        return new AmazonDeploymentManager(props.getProperty(IP_APPLICATION_NAME), props.getProperty(IP_ENVIRONMENT_ID), 
+                props.getProperty(IP_KEY_ID), props.getProperty(IP_KEY), props.getProperty(IP_CONTAINER_TYPE), props.getProperty(IP_REGION_URL));
+    }
+
+    @Override
+    public String getDisplayName() {
+        return NbBundle.getMessage(AmazonDeploymentFactory.class, "AmazonDeploymentFactory.displayName");
+    }
+
+    @Override
+    public String getProductVersion() {
+        return "1.0"; // NOI18N
+    }
+    
+}
diff --git a/cloud.amazon/src/org/netbeans/modules/cloud/amazon/serverplugin/AmazonDeploymentManager.java b/cloud.amazon/src/org/netbeans/modules/cloud/amazon/serverplugin/AmazonDeploymentManager.java
new file mode 100644
index 0000000000..07417d8bba
--- /dev/null
+++ b/cloud.amazon/src/org/netbeans/modules/cloud/amazon/serverplugin/AmazonDeploymentManager.java
@@ -0,0 +1,196 @@
+/*
+ * 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.cloud.amazon.serverplugin;
+
+import java.io.File;
+import java.io.InputStream;
+import java.util.Locale;
+import java.util.concurrent.Future;
+import javax.enterprise.deploy.model.DeployableObject;
+import javax.enterprise.deploy.shared.DConfigBeanVersionType;
+import javax.enterprise.deploy.shared.ModuleType;
+import javax.enterprise.deploy.spi.DeploymentConfiguration;
+import javax.enterprise.deploy.spi.Target;
+import javax.enterprise.deploy.spi.TargetModuleID;
+import javax.enterprise.deploy.spi.exceptions.DConfigBeanVersionUnsupportedException;
+import javax.enterprise.deploy.spi.exceptions.InvalidModuleException;
+import javax.enterprise.deploy.spi.exceptions.TargetException;
+import javax.enterprise.deploy.spi.status.ProgressObject;
+import org.netbeans.modules.cloud.amazon.AmazonInstance;
+import org.netbeans.modules.cloud.common.spi.support.serverplugin.DeploymentStatus;
+import org.netbeans.modules.cloud.common.spi.support.serverplugin.ProgressObjectImpl;
+import org.netbeans.modules.cloud.common.spi.support.serverplugin.TargetImpl;
+import org.netbeans.modules.j2ee.deployment.plugins.spi.DeploymentContext;
+import org.netbeans.modules.j2ee.deployment.plugins.spi.DeploymentManager2;
+import org.openide.util.NbBundle;
+
+/**
+ *
+ */
+public class AmazonDeploymentManager implements DeploymentManager2 {
+
+    private String appName;
+    private String envID;
+    private String keyId;
+    private String key;
+    private String containerType;
+    private String regionUrl;
+
+    public AmazonDeploymentManager(String appName, String envID, String keyId, String key, String containerType, String regionUrl) {
+        this.appName = appName;
+        this.envID = envID;
+        this.keyId = keyId;
+        this.key = key;
+        this.containerType = containerType;
+        this.regionUrl = regionUrl;
+    }
+    
+    @Override
+    public ProgressObject redeploy(TargetModuleID[] tmids, DeploymentContext deployment) {
+        throw new UnsupportedOperationException("Not supported yet."); // NOI18N
+    }
+
+    @Override
+    public ProgressObject distribute(Target[] targets, DeploymentContext deployment) {
+        File f = deployment.getModuleFile();
+        ProgressObjectImpl po = new ProgressObjectImpl(NbBundle.getMessage(AmazonDeploymentManager.class, "AmazonDeploymentManager.distributing"), false);
+        AmazonInstance.deployAsync(f, appName, envID, keyId, key, po, regionUrl);
+        return po;
+    }
+
+    @Override
+    public Target[] getTargets() throws IllegalStateException {
+        return new Target[]{TargetImpl.SOME};
+    }
+
+    @Override
+    public TargetModuleID[] getRunningModules(ModuleType mt, Target[] targets) throws TargetException, IllegalStateException {
+        throw new UnsupportedOperationException("Not supported yet."); // NOI18N
+    }
+
+    @Override
+    public TargetModuleID[] getNonRunningModules(ModuleType mt, Target[] targets) throws TargetException, IllegalStateException {
+        throw new UnsupportedOperationException("Not supported yet."); // NOI18N
+    }
+
+    @Override
+    public TargetModuleID[] getAvailableModules(ModuleType mt, Target[] targets) throws TargetException, IllegalStateException {
+        return new TargetModuleID[0];
+    }
+
+    @Override
+    public DeploymentConfiguration createConfiguration(DeployableObject d) throws InvalidModuleException {
+        throw new UnsupportedOperationException("Not supported yet."); // NOI18N
+    }
+
+    @Override
+    public ProgressObject distribute(Target[] targets, File file, File file1) throws IllegalStateException {
+        throw new UnsupportedOperationException("Not supported yet."); // NOI18N
+    }
+
+    @Override
+    @Deprecated
+    public ProgressObject distribute(Target[] targets, InputStream in, InputStream in1) throws IllegalStateException {
+        throw new UnsupportedOperationException("Not supported yet."); // NOI18N
+    }
+
+    @Override
+    public ProgressObject distribute(Target[] targets, ModuleType mt, InputStream in, InputStream in1) throws IllegalStateException {
+        throw new UnsupportedOperationException("Not supported yet."); // NOI18N
+    }
+
+    @Override
+    public ProgressObject start(TargetModuleID[] tmids) throws IllegalStateException {
+        return new ProgressObjectImpl("", true); // NOI18N
+    }
+
+    @Override
+    public ProgressObject stop(TargetModuleID[] tmids) throws IllegalStateException {
+        return new ProgressObjectImpl("", true); // NOI18N
+    }
+
+    @Override
+    public ProgressObject undeploy(TargetModuleID[] tmids) throws IllegalStateException {
+        throw new UnsupportedOperationException("Not supported yet."); // NOI18N
+    }
+
+    @Override
+    public boolean isRedeploySupported() {
+        return true;
+    }
+
+    @Override
+    public ProgressObject redeploy(TargetModuleID[] tmids, File file, File file1) throws UnsupportedOperationException, IllegalStateException {
+        throw new UnsupportedOperationException("Not supported yet."); // NOI18N
+    }
+
+    @Override
+    public ProgressObject redeploy(TargetModuleID[] tmids, InputStream in, InputStream in1) throws UnsupportedOperationException, IllegalStateException {
+        throw new UnsupportedOperationException("Not supported yet."); // NOI18N
+    }
+
+    @Override
+    public void release() {
+    }
+
+    @Override
+    public Locale getDefaultLocale() {
+        throw new UnsupportedOperationException("Not supported yet."); // NOI18N
+    }
+
+    @Override
+    public Locale getCurrentLocale() {
+        throw new UnsupportedOperationException("Not supported yet."); // NOI18N
+    }
+
+    @Override
+    public void setLocale(Locale locale) throws UnsupportedOperationException {
+        throw new UnsupportedOperationException("Not supported yet."); // NOI18N
+    }
+
+    @Override
+    public Locale[] getSupportedLocales() {
+        throw new UnsupportedOperationException("Not supported yet."); // NOI18N
+    }
+
+    @Override
+    public boolean isLocaleSupported(Locale locale) {
+        throw new UnsupportedOperationException("Not supported yet."); // NOI18N
+    }
+
+    @Override
+    public DConfigBeanVersionType getDConfigBeanVersion() {
+        throw new UnsupportedOperationException("Not supported yet."); // NOI18N
+    }
+
+    @Override
+    public boolean isDConfigBeanVersionSupported(DConfigBeanVersionType dcbvt) {
+        throw new UnsupportedOperationException("Not supported yet."); // NOI18N
+    }
+
+    @Override
+    public void setDConfigBeanVersion(DConfigBeanVersionType dcbvt) throws DConfigBeanVersionUnsupportedException {
+        throw new UnsupportedOperationException("Not supported yet."); // NOI18N
+    }
+
+    public String getContainerType() {
+        return containerType;
+    }
+    
+}
diff --git a/cloud.amazon/src/org/netbeans/modules/cloud/amazon/serverplugin/AmazonJ2EEInstance.java b/cloud.amazon/src/org/netbeans/modules/cloud/amazon/serverplugin/AmazonJ2EEInstance.java
new file mode 100644
index 0000000000..72fb618856
--- /dev/null
+++ b/cloud.amazon/src/org/netbeans/modules/cloud/amazon/serverplugin/AmazonJ2EEInstance.java
@@ -0,0 +1,131 @@
+/*
+ * 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.cloud.amazon.serverplugin;
+
+import com.amazonaws.services.elasticbeanstalk.model.EnvironmentStatus;
+import org.netbeans.api.server.ServerInstance;
+import org.netbeans.modules.cloud.amazon.AmazonInstance;
+import org.netbeans.modules.cloud.common.spi.support.serverplugin.InstanceState;
+
+/**
+ *
+ */
+public class AmazonJ2EEInstance {
+   
+    private AmazonInstance amazonInstance;
+    private String applicationName;
+    private String environmentName;
+    private String environmentId;
+    private InstanceState state;
+    private String containerType;
+    private ServerInstance instance;
+
+    public AmazonJ2EEInstance(AmazonInstance amazonInstance, String applicationName, 
+            String environmentName, String environmentId, String containerType) {
+        this.amazonInstance = amazonInstance;
+        this.applicationName = applicationName;
+        this.environmentName = environmentName;
+        this.environmentId = environmentId;
+        this.state = InstanceState.READY;
+        this.containerType = containerType;
+    }
+
+    public AmazonInstance getAmazonInstance() {
+        return amazonInstance;
+    }
+
+    public void updateState(String stateDesc) {
+        switch (EnvironmentStatus.valueOf(stateDesc)) {
+            case Launching:
+                state = InstanceState.LAUNCHING;
+                break;
+            case Ready:
+                state = InstanceState.READY;
+                break;
+            case Terminated:
+                state = InstanceState.TERMINATED;
+                break;
+            case Terminating:
+                state = InstanceState.TERMINATING;
+                break;
+            case Updating:
+                state = InstanceState.UPDATING;
+                break;
+        }
+    }
+    
+    public ServerInstance getInstance() {
+        return instance;
+    }
+
+    void setInstance(ServerInstance instance) {
+        this.instance = instance;
+    }
+
+    public InstanceState getState() {
+        return state;
+    }
+    
+    public void setAmazonInstance(AmazonInstance amazonInstance) {
+        this.amazonInstance = amazonInstance;
+    }
+
+    public String getId() {
+        return createURL(getApplicationName(), getEnvironmentId(), getContainerType());
+    }
+    
+    public static String createURL(String appName, String envID, String container) {
+        return AmazonDeploymentFactory.AMAZON_URI+appName + "-" +envID+"-"+container;
+    }
+    
+    public String getApplicationName() {
+        return applicationName;
+    }
+
+    public void setApplicationName(String applicationName) {
+        this.applicationName = applicationName;
+    }
+
+    public String getEnvironmentName() {
+        return environmentName;
+    }
+
+    public String getEnvironmentId() {
+        return environmentId;
+    }
+    
+    public void setEnvironmentName(String environmentName) {
+        this.environmentName = environmentName;
+    }
+
+    public String getContainerType() {
+        return containerType;
+    }
+
+    @Override
+    public String toString() {
+        return "AmazonJ2EEInstance{" + "amazonInstance=" + amazonInstance + ", applicationName=" + applicationName + ", environmentName=" + environmentName + ", environmentId=" + environmentId + '}';
+    }
+
+    public String getDisplayName() {
+        return getEnvironmentName()+"/"+getApplicationName()+" on "+getAmazonInstance().getName();
+    }
+    
+    
+}
diff --git a/cloud.amazon/src/org/netbeans/modules/cloud/amazon/serverplugin/AmazonJ2EEServerInstanceImplementation.java b/cloud.amazon/src/org/netbeans/modules/cloud/amazon/serverplugin/AmazonJ2EEServerInstanceImplementation.java
new file mode 100644
index 0000000000..b8e1e06706
--- /dev/null
+++ b/cloud.amazon/src/org/netbeans/modules/cloud/amazon/serverplugin/AmazonJ2EEServerInstanceImplementation.java
@@ -0,0 +1,75 @@
+/*
+ * 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.cloud.amazon.serverplugin;
+
+import javax.swing.JComponent;
+import javax.swing.JLabel;
+import org.netbeans.modules.cloud.amazon.ui.AmazonJ2EEInstanceNode;
+import org.netbeans.modules.cloud.amazon.ui.serverplugin.AmazonJ2EEServerWizardComponent;
+import org.netbeans.spi.server.ServerInstanceImplementation;
+import org.openide.nodes.Node;
+
+/**
+ *
+ */
+public class AmazonJ2EEServerInstanceImplementation implements ServerInstanceImplementation {
+
+    private AmazonJ2EEInstance aij;
+
+    public AmazonJ2EEServerInstanceImplementation(AmazonJ2EEInstance aij) {
+        this.aij = aij;
+    }
+    
+    @Override
+    public String getDisplayName() {
+        return getBasicNode().getDisplayName(); //aij.getApplicationName() + " - " + aij.getEnvironmentName();
+    }
+
+    @Override
+    public String getServerDisplayName() {
+        return "Tomcat";
+    }
+
+    @Override
+    public Node getFullNode() {
+        return getBasicNode();
+    }
+
+    @Override
+    public Node getBasicNode() {
+        return new AmazonJ2EEInstanceNode(aij);
+    }
+
+    @Override
+    public JComponent getCustomizer() {
+        AmazonJ2EEServerWizardComponent panel = new AmazonJ2EEServerWizardComponent(null, null, aij);
+        return panel;
+    }
+
+    @Override
+    public void remove() {
+        throw new UnsupportedOperationException("Not supported yet.");
+    }
+
+    @Override
+    public boolean isRemovable() {
+        return false;
+    }
+
+}
diff --git a/cloud.amazon/src/org/netbeans/modules/cloud/amazon/serverplugin/AmazonJ2EEServerInstanceProvider.java b/cloud.amazon/src/org/netbeans/modules/cloud/amazon/serverplugin/AmazonJ2EEServerInstanceProvider.java
new file mode 100644
index 0000000000..a1b5fd4898
--- /dev/null
+++ b/cloud.amazon/src/org/netbeans/modules/cloud/amazon/serverplugin/AmazonJ2EEServerInstanceProvider.java
@@ -0,0 +1,136 @@
+/*
+ * 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.cloud.amazon.serverplugin;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Callable;
+import java.util.concurrent.Future;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+import org.netbeans.api.server.ServerInstance;
+import org.netbeans.modules.cloud.amazon.AmazonInstance;
+import org.netbeans.modules.cloud.amazon.AmazonInstanceManager;
+import org.netbeans.modules.j2ee.deployment.plugins.api.InstanceCreationException;
+import org.netbeans.modules.j2ee.deployment.plugins.api.InstanceProperties;
+import org.netbeans.spi.server.ServerInstanceFactory;
+import org.netbeans.spi.server.ServerInstanceProvider;
+import org.openide.util.ChangeSupport;
+import org.openide.util.Exceptions;
+
+/**
+ *
+ */
+public final class AmazonJ2EEServerInstanceProvider implements ServerInstanceProvider, ChangeListener {
+
+    private ChangeSupport listeners;
+    private List<ServerInstance> instances;
+    private static AmazonJ2EEServerInstanceProvider instance;
+    
+    private static Logger LOG = Logger.getLogger(AmazonJ2EEServerInstanceProvider.class.getName());
+    
+    private AmazonJ2EEServerInstanceProvider() {
+        listeners = new ChangeSupport(this);
+        instances = Collections.<ServerInstance>emptyList();
+        //refreshServers();
+    }
+    
+    public static synchronized AmazonJ2EEServerInstanceProvider getProvider() {
+        if (instance == null) {
+            instance = new AmazonJ2EEServerInstanceProvider();
+            AmazonInstanceManager.getDefault().addChangeListener(instance);
+        }
+        return instance;
+    }
+
+    @Override
+    public List<ServerInstance> getInstances() {
+        return instances;
+    }
+
+    @Override
+    public void addChangeListener(ChangeListener listener) {
+        listeners.addChangeListener(listener);
+    }
+
+    @Override
+    public void removeChangeListener(ChangeListener listener) {
+        listeners.removeChangeListener(listener);
+    }
+
+    private void refreshServersSynchronously() {
+        List<ServerInstance> servers = new ArrayList<ServerInstance>();
+        for (AmazonInstance ai : AmazonInstanceManager.getDefault().getInstances()) {
+            for (AmazonJ2EEInstance inst : ai.readJ2EEServerInstances()) {
+                ServerInstance si = ServerInstanceFactory.createServerInstance(new AmazonJ2EEServerInstanceImplementation(inst));
+                InstanceProperties ip = InstanceProperties.getInstanceProperties(inst.getId());
+                if (ip == null) {
+                    Map<String, String> props = new HashMap<String, String>();
+                    props.put(AmazonDeploymentFactory.IP_ENVIRONMENT_ID, inst.getEnvironmentId());
+                    props.put(AmazonDeploymentFactory.IP_APPLICATION_NAME, inst.getApplicationName());
+                    props.put(AmazonDeploymentFactory.IP_KEY_ID, ai.getKeyId());
+                    props.put(AmazonDeploymentFactory.IP_KEY, ai.getKey());
+                    props.put(AmazonDeploymentFactory.IP_CONTAINER_TYPE, inst.getContainerType());
+                    props.put(InstanceProperties.URL_ATTR, inst.getId());
+                    props.put(AmazonDeploymentFactory.IP_REGION_URL, ai.getRegionURL());
+                    try {
+                        ip = InstanceProperties.createInstancePropertiesNonPersistent(inst.getId(), 
+                                ai.getKeyId(), ai.getKey(), inst.getDisplayName(), props);
+                    } catch (InstanceCreationException ex) {
+                        Exceptions.printStackTrace(ex);
+                    }
+                }
+                inst.setInstance(si);
+                servers.add(si);
+            }
+        }
+        instances = servers;
+        listeners.fireChange();
+    }
+    
+    public final Future<Void> refreshServers() {
+        return AmazonInstance.runAsynchronously(new Callable<Void>() {
+            @Override
+            public Void call() throws Exception {
+                try {
+                    refreshServersSynchronously();
+                    
+                    // TODO: set state of all amazon cloud instances to be in OK mode
+                    
+                } catch (RuntimeException e) {
+                    LOG.log(Level.INFO, "refreshServers failed. perhaps AWS is not accessible?", e);
+                    
+                    // TODO: set state of all amazon cloud instances to be in ERROR mode
+                    
+                }
+                return null;
+            }
+        });
+    }
+
+    @Override
+    public void stateChanged(ChangeEvent e) {
+        refreshServers();
+    }
+}
diff --git a/cloud.amazon/src/org/netbeans/modules/cloud/amazon/serverplugin/AmazonJ2EEServerWizardProvider.java b/cloud.amazon/src/org/netbeans/modules/cloud/amazon/serverplugin/AmazonJ2EEServerWizardProvider.java
new file mode 100644
index 0000000000..be3f57966f
--- /dev/null
+++ b/cloud.amazon/src/org/netbeans/modules/cloud/amazon/serverplugin/AmazonJ2EEServerWizardProvider.java
@@ -0,0 +1,39 @@
+/*
+ * 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.cloud.amazon.serverplugin;
+
+import org.netbeans.modules.cloud.amazon.ui.serverplugin.AmazonJ2EEServerWizardIterator;
+import org.netbeans.spi.server.ServerWizardProvider;
+
+/**
+ *
+ */
+public class AmazonJ2EEServerWizardProvider implements ServerWizardProvider {
+
+    @Override
+    public String getDisplayName() {
+        return "Amazon Beanstalk";
+    }
+
+    @Override
+    public org.openide.WizardDescriptor.InstantiatingIterator getInstantiatingIterator() {
+        return new AmazonJ2EEServerWizardIterator();
+    }
+    
+}
diff --git a/cloud.amazon/src/org/netbeans/modules/cloud/amazon/serverplugin/AmazonJ2eePlatformFactory.java b/cloud.amazon/src/org/netbeans/modules/cloud/amazon/serverplugin/AmazonJ2eePlatformFactory.java
new file mode 100644
index 0000000000..8e0367284c
--- /dev/null
+++ b/cloud.amazon/src/org/netbeans/modules/cloud/amazon/serverplugin/AmazonJ2eePlatformFactory.java
@@ -0,0 +1,35 @@
+/*
+ * 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.cloud.amazon.serverplugin;
+
+import javax.enterprise.deploy.spi.DeploymentManager;
+import org.netbeans.modules.j2ee.deployment.plugins.spi.J2eePlatformFactory;
+import org.netbeans.modules.j2ee.deployment.plugins.spi.J2eePlatformImpl;
+
+/**
+ *
+ */
+public class AmazonJ2eePlatformFactory extends J2eePlatformFactory {
+
+    @Override
+    public J2eePlatformImpl getJ2eePlatformImpl(DeploymentManager dm) {
+        return new AmazonJ2eePlatformImpl2(dm);
+    }
+    
+}
diff --git a/cloud.amazon/src/org/netbeans/modules/cloud/amazon/serverplugin/AmazonJ2eePlatformImpl2.java b/cloud.amazon/src/org/netbeans/modules/cloud/amazon/serverplugin/AmazonJ2eePlatformImpl2.java
new file mode 100644
index 0000000000..397ba0fd8b
--- /dev/null
+++ b/cloud.amazon/src/org/netbeans/modules/cloud/amazon/serverplugin/AmazonJ2eePlatformImpl2.java
@@ -0,0 +1,153 @@
+/*
+ * 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.cloud.amazon.serverplugin;
+
+import java.awt.Image;
+import java.io.File;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import javax.enterprise.deploy.spi.DeploymentManager;
+import org.netbeans.api.j2ee.core.Profile;
+import org.netbeans.api.java.platform.JavaPlatformManager;
+import org.netbeans.api.project.libraries.Library;
+import org.netbeans.api.project.libraries.LibraryManager;
+import org.netbeans.modules.j2ee.deployment.common.api.J2eeLibraryTypeProvider;
+import org.netbeans.modules.j2ee.deployment.devmodules.api.J2eeModule.Type;
+import org.netbeans.modules.j2ee.deployment.plugins.spi.J2eePlatformImpl2;
+import org.netbeans.spi.project.libraries.LibraryImplementation;
+import org.openide.filesystems.FileObject;
+import org.openide.filesystems.FileUtil;
+import org.openide.filesystems.URLMapper;
+import org.openide.util.ImageUtilities;
+
+/**
+ *
+ */
+public class AmazonJ2eePlatformImpl2 extends J2eePlatformImpl2 {
+
+    private AmazonDeploymentManager dm;
+
+    public AmazonJ2eePlatformImpl2(DeploymentManager dm) {
+        assert dm instanceof AmazonDeploymentManager;
+        this.dm = (AmazonDeploymentManager)dm;
+    }
+    
+    @Override
+    public File getServerHome() {
+        return null;
+    }
+
+    @Override
+    public File getDomainHome() {
+        return null;
+    }
+
+    @Override
+    public File getMiddlewareHome() {
+        return null;
+    }
+
+    @Override
+    public LibraryImplementation[] getLibraries() {
+        Library l = LibraryManager.getDefault().getLibrary("javaee-api-6.0");
+        
+        LibraryImplementation library = new J2eeLibraryTypeProvider().createLibrary();
+
+        // set its name
+        library.setName("JavaEEAPI");
+
+        library.setContent(J2eeLibraryTypeProvider.
+                VOLUME_TYPE_CLASSPATH, l.getContent("classpath"));
+        
+        return new LibraryImplementation[]{library};
+    }
+
+    @Override
+    public Set<Type> getSupportedTypes() {
+        return Collections.<Type>singleton(Type.WAR);
+    }
+
+    @Override
+    public Set<Profile> getSupportedProfiles() {
+        if (dm.getContainerType().contains("Tomcat 6")) {
+            return new HashSet<Profile>(Arrays.<Profile>asList(new Profile[]{Profile.JAVA_EE_5, Profile.J2EE_14}));
+        } else if (dm.getContainerType().contains("Tomcat 7")) {
+            return new HashSet<Profile>(Arrays.<Profile>asList(new Profile[]{Profile.JAVA_EE_6_FULL, Profile.JAVA_EE_6_WEB, Profile.JAVA_EE_5, Profile.J2EE_14}));
+        } else {
+            return new HashSet<Profile>(Arrays.<Profile>asList(new Profile[]{Profile.JAVA_EE_6_FULL, Profile.JAVA_EE_6_WEB, Profile.JAVA_EE_5, Profile.J2EE_14}));
+        }
+    }
+
+    @Override
+    public Set<Profile> getSupportedProfiles(Type moduleType) {
+        return getSupportedProfiles();
+    }
+    
+    @Override
+    public String getDisplayName() {
+        return "Amazon Beanstalk Tomcat";
+    }
+
+    @Override
+    public Image getIcon() {
+        return ImageUtilities.loadImage("org/netbeans/modules/cloud/amazon/resources/tomcat.png"); // NOI18N
+    }
+
+    @Override
+    public File[] getPlatformRoots() {
+//        Library l = LibraryManager.getDefault().getLibrary("javaee-api-6.0");
+//        assert l != null;
+//        List<File> res = new ArrayList<File>();
+//        for (URL url : l.getContent("classpath")) {
+//            FileObject fo = URLMapper.findFileObject(url);
+//            fo = FileUtil.getArchiveFile(fo);
+//            assert fo != null;
+//            res.add(FileUtil.toFile(fo));
+//        }
+//        return res.toArray(new File[res.size()]);
+        return null;
+    }
+
+    @Override
+    public File[] getToolClasspathEntries(String toolName) {
+        return new File[0];
+    }
+
+    @Override
+    @Deprecated
+    public boolean isToolSupported(String toolName) {
+        return false;
+    }
+
+    @Override
+    public Set getSupportedJavaPlatformVersions() {
+        return new HashSet<String>(Arrays.asList(new String[] {"1.6","1.5"}));
+    }
+
+    @Override
+    public org.netbeans.api.java.platform.JavaPlatform getJavaPlatform() {
+        return JavaPlatformManager.getDefault().getDefaultPlatform();
+    }
+    
+}
diff --git a/cloud.amazon/src/org/netbeans/modules/cloud/amazon/serverplugin/AmazonOptionalDeploymentManagerFactory.java b/cloud.amazon/src/org/netbeans/modules/cloud/amazon/serverplugin/AmazonOptionalDeploymentManagerFactory.java
new file mode 100644
index 0000000000..766e7608eb
--- /dev/null
+++ b/cloud.amazon/src/org/netbeans/modules/cloud/amazon/serverplugin/AmazonOptionalDeploymentManagerFactory.java
@@ -0,0 +1,126 @@
+/*
+ * 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.cloud.amazon.serverplugin;
+
+import javax.enterprise.deploy.spi.DeploymentManager;
+import javax.enterprise.deploy.spi.Target;
+import javax.enterprise.deploy.spi.status.ProgressObject;
+import org.netbeans.modules.cloud.amazon.ui.serverplugin.AmazonJ2EEServerWizardIterator;
+import org.netbeans.modules.j2ee.deployment.plugins.api.ServerDebugInfo;
+import org.netbeans.modules.j2ee.deployment.plugins.spi.FindJSPServlet;
+import org.netbeans.modules.j2ee.deployment.plugins.spi.IncrementalDeployment;
+import org.netbeans.modules.j2ee.deployment.plugins.spi.OptionalDeploymentManagerFactory;
+import org.netbeans.modules.j2ee.deployment.plugins.spi.ServerInitializationException;
+import org.netbeans.modules.j2ee.deployment.plugins.spi.StartServer;
+import org.openide.WizardDescriptor.InstantiatingIterator;
+
+/**
+ *
+ */
+public class AmazonOptionalDeploymentManagerFactory extends OptionalDeploymentManagerFactory {
+
+    @Override
+    public StartServer getStartServer(DeploymentManager dm) {
+        return new AmazonStartServer();
+    }
+
+    @Override
+    public IncrementalDeployment getIncrementalDeployment(DeploymentManager dm) {
+        return null;
+    }
+
+    @Override
+    public InstantiatingIterator getAddInstanceIterator() {
+        return new AmazonJ2EEServerWizardIterator();
+    }
+    
+    @Override
+    public FindJSPServlet getFindJSPServlet(DeploymentManager dm) {
+        throw new UnsupportedOperationException("Not supported yet.");
+    }
+
+    @Override
+    public boolean isCommonUIRequired() {
+        return false;
+    }
+
+    @Override
+    public void finishServerInitialization() throws ServerInitializationException {
+        AmazonJ2EEServerInstanceProvider.getProvider().refreshServers();
+    }
+
+    public static final class AmazonStartServer extends StartServer {
+
+        @Override
+        public boolean isAlsoTargetServer(Target target) {
+            return true;
+        }
+
+        @Override
+        public boolean supportsStartDeploymentManager() {
+            return false;
+        }
+
+        @Override
+        public ProgressObject startDeploymentManager() {
+            throw new UnsupportedOperationException("Not supported yet.");
+        }
+
+        @Override
+        public ProgressObject stopDeploymentManager() {
+            throw new UnsupportedOperationException("Not supported yet.");
+        }
+
+        @Override
+        public boolean needsStartForConfigure() {
+            throw new UnsupportedOperationException("Not supported yet.");
+        }
+
+        @Override
+        public boolean needsStartForTargetList() {
+            throw new UnsupportedOperationException("Not supported yet.");
+        }
+
+        @Override
+        public boolean needsStartForAdminConfig() {
+            throw new UnsupportedOperationException("Not supported yet.");
+        }
+
+        @Override
+        public boolean isRunning() {
+            return true;
+        }
+
+        @Override
+        public boolean isDebuggable(Target target) {
+            return false;
+        }
+
+        @Override
+        public ProgressObject startDebugging(Target target) {
+            throw new UnsupportedOperationException("Not supported yet.");
+        }
+
+        @Override
+        public ServerDebugInfo getDebugInfo(Target target) {
+            return null;
+        }
+        
+    }
+}
diff --git a/cloud.amazon/src/org/netbeans/modules/cloud/amazon/serverplugin/Bundle.properties b/cloud.amazon/src/org/netbeans/modules/cloud/amazon/serverplugin/Bundle.properties
new file mode 100644
index 0000000000..a26d0f24e2
--- /dev/null
+++ b/cloud.amazon/src/org/netbeans/modules/cloud/amazon/serverplugin/Bundle.properties
@@ -0,0 +1,20 @@
+# 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.
+
+AmazonDeploymentFactory.displayName=Amazon Beanstalk
+
+AmazonDeploymentManager.distributing=Distributing...
diff --git a/cloud.amazon/src/org/netbeans/modules/cloud/amazon/ui/AmazonInstanceNode.java b/cloud.amazon/src/org/netbeans/modules/cloud/amazon/ui/AmazonInstanceNode.java
new file mode 100644
index 0000000000..e81fc8bd78
--- /dev/null
+++ b/cloud.amazon/src/org/netbeans/modules/cloud/amazon/ui/AmazonInstanceNode.java
@@ -0,0 +1,72 @@
+/*
+ * 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.cloud.amazon.ui;
+
+import java.awt.Image;
+import javax.swing.Action;
+import org.netbeans.modules.cloud.amazon.AmazonInstance;
+import org.openide.nodes.AbstractNode;
+import org.openide.nodes.Children;
+import org.openide.util.ImageUtilities;
+import org.openide.util.actions.SystemAction;
+import org.openide.util.lookup.Lookups;
+
+/**
+ *
+ */
+public class AmazonInstanceNode extends AbstractNode {
+    
+    private static final String AMAZON_ICON = "org/netbeans/modules/cloud/amazon/ui/resources/amazon.png"; // NOI18N
+    
+    public AmazonInstanceNode(AmazonInstance ai) {
+        super(Children.LEAF, Lookups.fixed(ai));
+        setName(""); // NOI18N
+        setDisplayName(ai.getName());
+        setIconBaseWithExtension(AMAZON_ICON);
+    }
+    
+    private static final String WAITING_ICON
+            = "org/netbeans/modules/cloud/amazon/ui/resources/waiting.png"; // NOI18N
+    
+    @Override
+    public Image getIcon(int type) {
+        return badgeIcon(super.getIcon(type));
+    }
+    
+    @Override
+    public Image getOpenedIcon(int type) {
+        return badgeIcon(super.getOpenedIcon(type));
+    }
+    
+    private Image badgeIcon(Image origImg) {
+        return origImg;
+    }
+    @Override
+    public Action[] getActions(boolean context) {
+        return new Action[] {
+            SystemAction.get(RefreshAmazonInstanceNodeAction.class),
+            SystemAction.get(ViewAdminConsoleAction.class),
+            null,
+            SystemAction.get(RemoveAmazonInstanceAction.class),
+            null,
+            SystemAction.get(PropertiesAction.class)
+        };
+    }
+
+}
diff --git a/cloud.amazon/src/org/netbeans/modules/cloud/amazon/ui/AmazonJ2EEInstanceNode.java b/cloud.amazon/src/org/netbeans/modules/cloud/amazon/ui/AmazonJ2EEInstanceNode.java
new file mode 100644
index 0000000000..610424ac6f
--- /dev/null
+++ b/cloud.amazon/src/org/netbeans/modules/cloud/amazon/ui/AmazonJ2EEInstanceNode.java
@@ -0,0 +1,94 @@
+/*
+ * 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.cloud.amazon.ui;
+
+import java.awt.Image;
+import javax.swing.Action;
+import org.netbeans.modules.cloud.amazon.serverplugin.AmazonJ2EEInstance;
+import org.openide.nodes.AbstractNode;
+import org.openide.nodes.Children;
+import org.openide.util.ImageUtilities;
+import org.openide.util.actions.SystemAction;
+import org.openide.util.lookup.Lookups;
+
+/**
+ *
+ */
+public class AmazonJ2EEInstanceNode extends AbstractNode {
+    
+    public static final String TOMCAT_ICON = "org/netbeans/modules/cloud/amazon/ui/resources/tomcat.png"; // NOI18N
+    
+    private AmazonJ2EEInstance aij;
+    
+    public AmazonJ2EEInstanceNode(AmazonJ2EEInstance aij) {
+        super(Children.LEAF, Lookups.fixed(aij));
+        this.aij = aij;
+        setName(""); // NOI18N
+        setDisplayName(aij.getDisplayName());
+        //setShortDescription(NbBundle.getMessage(RootNode.class, "Amazon_Node_Short_Description"));
+        setIconBaseWithExtension(TOMCAT_ICON);
+    }
+    
+    void showServerType() {
+        setDisplayName(aij.getEnvironmentName()+" ["+aij.getApplicationName()+"]"+" on "+aij.getContainerType());
+    }
+
+    @Override
+    public Image getIcon(int type) {
+        return badgeIcon(super.getIcon(type));
+    }
+    
+    @Override
+    public Image getOpenedIcon(int type) {
+        return badgeIcon(super.getOpenedIcon(type));
+    }   
+    
+    private static final String RUNNING_ICON 
+            = "org/netbeans/modules/cloud/amazon/ui/resources/running.png"; // NOI18N
+    private static final String WAITING_ICON
+            = "org/netbeans/modules/cloud/amazon/ui/resources/waiting.png"; // NOI18N
+    private static final String TERMINATED_ICON
+            = "org/netbeans/modules/cloud/amazon/ui/resources/terminated.png"; // NOI18N
+    
+    private Image badgeIcon(Image origImg) {
+        Image badge = null;        
+        switch (aij.getState()) {
+            case UPDATING:
+            case LAUNCHING:
+            case TERMINATING:
+                badge = ImageUtilities.loadImage(WAITING_ICON);
+                break;
+            case READY:
+                badge = ImageUtilities.loadImage(RUNNING_ICON);
+                break;
+            case TERMINATED:
+                badge = ImageUtilities.loadImage(TERMINATED_ICON);
+                break;
+        }
+        return badge != null ? ImageUtilities.mergeImages(origImg, badge, 15, 8) : origImg;
+    }
+
+    @Override
+    public Action[] getActions(boolean context) {
+        return new Action[] {
+            SystemAction.get(RemoteServerPropertiesAction.class)
+        };
+    }
+    
+}
diff --git a/cloud.amazon/src/org/netbeans/modules/cloud/amazon/ui/AmazonWizardComponent.form b/cloud.amazon/src/org/netbeans/modules/cloud/amazon/ui/AmazonWizardComponent.form
new file mode 100644
index 0000000000..bf95f0d83d
--- /dev/null
+++ b/cloud.amazon/src/org/netbeans/modules/cloud/amazon/ui/AmazonWizardComponent.form
@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<Form version="1.5" maxVersion="1.7" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
+  <AuxValues>
+    <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
+    <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
+    <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
+    <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
+    <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
+    <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
+    <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
+    <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
+    <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
+  </AuxValues>
+
+  <Layout>
+    <DimensionLayout dim="0">
+      <Group type="103" groupAlignment="0" attributes="0">
+          <Group type="102" alignment="0" attributes="0">
+              <Group type="103" groupAlignment="0" attributes="0">
+                  <Component id="jLabel2" alignment="0" min="-2" max="-2" attributes="0"/>
+                  <Component id="jLabel1" alignment="0" min="-2" max="-2" attributes="0"/>
+                  <Component id="jLabel3" alignment="0" min="-2" max="-2" attributes="0"/>
+              </Group>
+              <EmptySpace max="-2" attributes="0"/>
+              <Group type="103" groupAlignment="0" attributes="0">
+                  <Component id="secret" pref="173" max="32767" attributes="1"/>
+                  <Component id="accessKey" alignment="0" pref="173" max="32767" attributes="1"/>
+                  <Component id="jRegionComboBox" alignment="0" max="32767" attributes="0"/>
+              </Group>
+          </Group>
+      </Group>
+    </DimensionLayout>
+    <DimensionLayout dim="1">
+      <Group type="103" groupAlignment="0" attributes="0">
+          <Group type="102" alignment="0" attributes="0">
+              <Group type="103" groupAlignment="3" attributes="0">
+                  <Component id="jLabel3" alignment="3" min="-2" max="-2" attributes="0"/>
+                  <Component id="jRegionComboBox" alignment="3" min="-2" max="-2" attributes="0"/>
+              </Group>
+              <EmptySpace min="-2" max="-2" attributes="0"/>
+              <Group type="103" groupAlignment="3" attributes="0">
+                  <Component id="accessKey" alignment="3" min="-2" max="-2" attributes="0"/>
+                  <Component id="jLabel1" alignment="3" min="-2" max="-2" attributes="0"/>
+              </Group>
+              <EmptySpace max="-2" attributes="0"/>
+              <Group type="103" groupAlignment="3" attributes="0">
+                  <Component id="jLabel2" alignment="3" min="-2" max="-2" attributes="0"/>
+                  <Component id="secret" alignment="3" min="-2" max="-2" attributes="0"/>
+              </Group>
+              <EmptySpace pref="39" max="32767" attributes="0"/>
+          </Group>
+      </Group>
+    </DimensionLayout>
+  </Layout>
+  <SubComponents>
+    <Component class="javax.swing.JLabel" name="jLabel1">
+      <Properties>
+        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+          <ResourceString bundle="org/netbeans/modules/cloud/amazon/ui/Bundle.properties" key="AmazonWizardComponent.jLabel1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+        </Property>
+      </Properties>
+    </Component>
+    <Component class="javax.swing.JTextField" name="accessKey">
+      <Properties>
+        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+          <ResourceString bundle="org/netbeans/modules/cloud/amazon/ui/Bundle.properties" key="AmazonWizardComponent.accessKey.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+        </Property>
+      </Properties>
+    </Component>
+    <Component class="javax.swing.JLabel" name="jLabel2">
+      <Properties>
+        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+          <ResourceString bundle="org/netbeans/modules/cloud/amazon/ui/Bundle.properties" key="AmazonWizardComponent.jLabel2.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+        </Property>
+      </Properties>
+    </Component>
+    <Component class="javax.swing.JPasswordField" name="secret">
+      <Properties>
+        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+          <ResourceString bundle="org/netbeans/modules/cloud/amazon/ui/Bundle.properties" key="AmazonWizardComponent.secret.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+        </Property>
+      </Properties>
+    </Component>
+    <Component class="javax.swing.JLabel" name="jLabel3">
+      <Properties>
+        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+          <ResourceString bundle="org/netbeans/modules/cloud/amazon/ui/Bundle.properties" key="AmazonWizardComponent.jLabel3.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+        </Property>
+      </Properties>
+    </Component>
+    <Component class="javax.swing.JComboBox" name="jRegionComboBox">
+    </Component>
+  </SubComponents>
+</Form>
diff --git a/cloud.amazon/src/org/netbeans/modules/cloud/amazon/ui/AmazonWizardComponent.java b/cloud.amazon/src/org/netbeans/modules/cloud/amazon/ui/AmazonWizardComponent.java
new file mode 100644
index 0000000000..8ec41547dd
--- /dev/null
+++ b/cloud.amazon/src/org/netbeans/modules/cloud/amazon/ui/AmazonWizardComponent.java
@@ -0,0 +1,204 @@
+/*
+ * 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.cloud.amazon.ui;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.swing.DefaultComboBoxModel;
+import javax.swing.event.DocumentEvent;
+import javax.swing.event.DocumentListener;
+import org.netbeans.modules.cloud.amazon.AmazonInstance;
+import org.openide.util.NbBundle;
+
+/**
+ *
+ */
+public class AmazonWizardComponent extends javax.swing.JPanel implements DocumentListener {
+
+    private AmazonWizardPanel panel;
+    private List<Region> regions;
+    
+    /** Creates new form AmazonWizardComponent */
+    public AmazonWizardComponent(AmazonWizardPanel panel, AmazonInstance ai) {
+        this.panel = panel;
+        initComponents();
+        initRegions();
+        jRegionComboBox.setModel(new DefaultComboBoxModel(regions.toArray()));
+        setName(NbBundle.getBundle(AmazonWizardComponent.class).getString("LBL_Name")); // NOI18N
+        if (ai != null) {
+            accessKey.setText(ai.getKeyId());
+            secret.setText(ai.getKey());
+            accessKey.setEditable(false);
+            secret.setEditable(false);
+            jRegionComboBox.setEnabled(false);
+            jRegionComboBox.setSelectedItem(findRegion(ai.getRegionURL()));
+        }
+        accessKey.getDocument().addDocumentListener(this);
+        secret.getDocument().addDocumentListener(this);
+    }
+    
+    private void initRegions() {
+        regions = new ArrayList<Region>();
+        regions.add(new Region("US East (Northern Virginia) Region", "elasticbeanstalk.us-east-1.amazonaws.com"));
+        regions.add(new Region("US West (Northern California) Region", "elasticbeanstalk.us-west-1.amazonaws.com"));
+        regions.add(new Region("US West (Oregon) Region", "elasticbeanstalk.us-west-2.amazonaws.com"));
+        regions.add(new Region("EU (Ireland) Region", "elasticbeanstalk.eu-west-1.amazonaws.com"));
+        regions.add(new Region("EU (Frankfurt) Region", "elasticbeanstalk.eu-central-1.amazonaws.com"));
+        regions.add(new Region("Asia Pacific (Tokyo) Region", "elasticbeanstalk.ap-northeast-1.amazonaws.com"));
+        regions.add(new Region("Asia Pacific (Seoul) Region", "elasticbeanstalk.ap-northeast-2.amazonaws.com"));
+        regions.add(new Region("Asia Pacific (Singapore) Region", "elasticbeanstalk.ap-southeast-1.amazonaws.com"));
+        regions.add(new Region("Asia Pacific (Sydney) Region", "elasticbeanstalk.ap-southeast-2.amazonaws.com"));
+        regions.add(new Region("South America (Sao Paulo) Region", "elasticbeanstalk.sa-east-1.amazonaws.com"));
+    }
+
+    /** This method is called from within the constructor to
+     * initialize the form.
+     * WARNING: Do NOT modify this code. The content of this method is
+     * always regenerated by the Form Editor.
+     */
+    @SuppressWarnings("unchecked")
+    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
+    private void initComponents() {
+
+        jLabel1 = new javax.swing.JLabel();
+        accessKey = new javax.swing.JTextField();
+        jLabel2 = new javax.swing.JLabel();
+        secret = new javax.swing.JPasswordField();
+        jLabel3 = new javax.swing.JLabel();
+        jRegionComboBox = new javax.swing.JComboBox();
+
+        jLabel1.setText(org.openide.util.NbBundle.getMessage(AmazonWizardComponent.class, "AmazonWizardComponent.jLabel1.text")); // NOI18N
+
+        accessKey.setText(org.openide.util.NbBundle.getMessage(AmazonWizardComponent.class, "AmazonWizardComponent.accessKey.text")); // NOI18N
+
+        jLabel2.setText(org.openide.util.NbBundle.getMessage(AmazonWizardComponent.class, "AmazonWizardComponent.jLabel2.text")); // NOI18N
+
+        secret.setText(org.openide.util.NbBundle.getMessage(AmazonWizardComponent.class, "AmazonWizardComponent.secret.text")); // NOI18N
+
+        jLabel3.setText(org.openide.util.NbBundle.getMessage(AmazonWizardComponent.class, "AmazonWizardComponent.jLabel3.text")); // NOI18N
+
+        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
+        this.setLayout(layout);
+        layout.setHorizontalGroup(
+            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addGroup(layout.createSequentialGroup()
+                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+                    .addComponent(jLabel2)
+                    .addComponent(jLabel1)
+                    .addComponent(jLabel3))
+                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+                    .addComponent(secret, javax.swing.GroupLayout.DEFAULT_SIZE, 173, Short.MAX_VALUE)
+                    .addComponent(accessKey, javax.swing.GroupLayout.DEFAULT_SIZE, 173, Short.MAX_VALUE)
+                    .addComponent(jRegionComboBox, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
+        );
+        layout.setVerticalGroup(
+            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addGroup(layout.createSequentialGroup()
+                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+                    .addComponent(jLabel3)
+                    .addComponent(jRegionComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+                    .addComponent(accessKey, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+                    .addComponent(jLabel1))
+                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+                    .addComponent(jLabel2)
+                    .addComponent(secret, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+                .addContainerGap(39, Short.MAX_VALUE))
+        );
+    }// </editor-fold>//GEN-END:initComponents
+    // Variables declaration - do not modify//GEN-BEGIN:variables
+    private javax.swing.JTextField accessKey;
+    private javax.swing.JLabel jLabel1;
+    private javax.swing.JLabel jLabel2;
+    private javax.swing.JLabel jLabel3;
+    private javax.swing.JComboBox jRegionComboBox;
+    private javax.swing.JPasswordField secret;
+    // End of variables declaration//GEN-END:variables
+
+    public String getKeyId() {
+        return accessKey.getText();
+    }
+    
+    public String getKey() {
+        return String.valueOf(secret.getPassword());
+    }
+
+    public String getRegionUrl() {
+        return ((Region)jRegionComboBox.getSelectedItem()).getUrl();
+    }
+    
+    @Override
+    public void insertUpdate(DocumentEvent e) {
+        if (panel != null) {
+            panel.fireChange();
+        }
+    }
+
+    @Override
+    public void removeUpdate(DocumentEvent e) {
+        if (panel != null) {
+            panel.fireChange();
+        }
+    }
+
+    @Override
+    public void changedUpdate(DocumentEvent e) {
+        if (panel != null) {
+            panel.fireChange();
+        }
+    }
+
+    private Object findRegion(String regionURL) {
+        for (Region r : regions) {
+            if (r.getUrl().equals(regionURL)) {
+                return r;
+            }
+        }
+        return regions.get(0);
+    }
+    
+    private static class Region {
+        private String name;
+        private String url;
+
+        public Region(String name, String url) {
+            this.name = name;
+            this.url = url;
+        }
+
+        public String getName() {
+            return name;
+        }
+
+        public String getUrl() {
+            return url;
+        }
+
+        @Override
+        public String toString() {
+            return name;
+        }
+
+        
+    }
+}
diff --git a/cloud.amazon/src/org/netbeans/modules/cloud/amazon/ui/AmazonWizardIterator.java b/cloud.amazon/src/org/netbeans/modules/cloud/amazon/ui/AmazonWizardIterator.java
new file mode 100644
index 0000000000..f572dc4b65
--- /dev/null
+++ b/cloud.amazon/src/org/netbeans/modules/cloud/amazon/ui/AmazonWizardIterator.java
@@ -0,0 +1,124 @@
+/*
+ * 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.cloud.amazon.ui;
+
+import org.netbeans.modules.cloud.common.spi.support.ui.CloudResourcesWizardPanel;
+import java.io.IOException;
+import java.util.Collections;
+import java.util.Set;
+import javax.swing.event.ChangeListener;
+import org.netbeans.modules.cloud.amazon.AmazonInstance;
+import org.netbeans.modules.cloud.amazon.AmazonInstanceManager;
+import org.openide.WizardDescriptor;
+import org.openide.WizardDescriptor.Panel;
+import org.openide.util.ChangeSupport;
+
+/**
+ *
+ */
+public class AmazonWizardIterator implements WizardDescriptor.InstantiatingIterator {
+
+    private ChangeSupport listeners;
+    private WizardDescriptor wizard;
+    private AmazonWizardPanel panel;
+    private CloudResourcesWizardPanel panel2;
+    boolean first = true;
+
+    public AmazonWizardIterator() {
+        listeners = new ChangeSupport(this);
+    }
+    
+    public static final String PROP_DISPLAY_NAME = "ServInstWizard_displayName"; // NOI18N
+
+    @Override
+    public Set instantiate() throws IOException {
+        String keyId = (String)wizard.getProperty(AmazonWizardPanel.KEY_ID);
+        assert keyId != null;
+        String key = (String)wizard.getProperty(AmazonWizardPanel.KEY);
+        assert key != null;
+        String name = (String)wizard.getProperty(PROP_DISPLAY_NAME);
+        assert name != null;
+        String regionUrl = (String)wizard.getProperty(AmazonWizardPanel.REGION);
+        
+        AmazonInstanceManager.getDefault().add(new AmazonInstance(name, keyId, key, regionUrl));
+        
+        return Collections.emptySet();
+    }
+
+    @Override
+    public void initialize(WizardDescriptor wizard) {
+        this.wizard = wizard;
+    }
+
+    @Override
+    public void uninitialize(WizardDescriptor wizard) {
+        panel = null;
+    }
+
+    @Override
+    public Panel current() {
+        if (first) {
+            if (panel == null) {
+                panel = new AmazonWizardPanel();
+            }
+            return panel;
+        } else {
+            if (panel2 == null) {
+                panel2 = new CloudResourcesWizardPanel(AmazonWizardPanel.getPanelContentData(), 1);
+            }
+            return panel2;
+        }
+    }
+
+    @Override
+    public String name() {
+        return "Amazon";
+    }
+
+    @Override
+    public boolean hasNext() {
+        return first;
+    }
+
+    @Override
+    public boolean hasPrevious() {
+        return !first;
+    }
+
+    @Override
+    public void nextPanel() {
+        first = false;
+    }
+
+    @Override
+    public void previousPanel() {
+        first = true;
+    }
+
+    @Override
+    public void addChangeListener(ChangeListener l) {
+        listeners.addChangeListener(l);
+    }
+
+    @Override
+    public void removeChangeListener(ChangeListener l) {
+        listeners.removeChangeListener(l);
+    }
+    
+}
diff --git a/cloud.amazon/src/org/netbeans/modules/cloud/amazon/ui/AmazonWizardPanel.java b/cloud.amazon/src/org/netbeans/modules/cloud/amazon/ui/AmazonWizardPanel.java
new file mode 100644
index 0000000000..955178e486
--- /dev/null
+++ b/cloud.amazon/src/org/netbeans/modules/cloud/amazon/ui/AmazonWizardPanel.java
@@ -0,0 +1,156 @@
+/*
+ * 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.cloud.amazon.ui;
+
+import com.amazonaws.AmazonClientException;
+import java.awt.Component;
+import java.beans.BeanInfo;
+import java.util.ArrayList;
+import java.util.List;
+import javax.swing.JComponent;
+import javax.swing.event.ChangeListener;
+import org.netbeans.modules.cloud.amazon.AmazonInstance;
+import org.netbeans.modules.cloud.amazon.serverplugin.AmazonJ2EEInstance;
+import org.netbeans.modules.cloud.common.spi.support.ui.CloudResourcesWizardPanel;
+import org.netbeans.modules.cloud.common.spi.support.ui.ServerResourceDescriptor;
+import org.openide.WizardDescriptor;
+import org.openide.WizardValidationException;
+import org.openide.nodes.Node;
+import org.openide.util.ChangeSupport;
+import org.openide.util.HelpCtx;
+import org.openide.util.ImageUtilities;
+import org.openide.util.NbBundle;
+import org.openide.util.Utilities;
+
+/**
+ *
+ */
+public class AmazonWizardPanel implements WizardDescriptor.AsynchronousValidatingPanel<WizardDescriptor> {
+
+    public static final String KEY_ID = "access-key-id"; // String
+    public static final String KEY = "secret-access-key"; // String
+    public static final String REGION = "region"; // String
+    
+    private ChangeSupport listeners;
+    private AmazonWizardComponent component;
+    private List<ServerResourceDescriptor> servers;
+    private WizardDescriptor wd = null;
+    
+    public AmazonWizardPanel() {
+        listeners = new ChangeSupport(this);
+    }
+    
+    @Override
+    public Component getComponent() {
+        if (component == null) {
+            component = new AmazonWizardComponent(this, null);
+            component.putClientProperty(WizardDescriptor.PROP_CONTENT_DATA, getPanelContentData());            
+            component.putClientProperty(WizardDescriptor.PROP_CONTENT_SELECTED_INDEX, Integer.valueOf(0));
+        }
+        return component;
+    }
+
+    static String[] getPanelContentData() {
+        return new String[] {
+                NbBundle.getMessage(AmazonWizardPanel.class, "LBL_ACIW_Amazon"),
+                NbBundle.getMessage(AmazonWizardPanel.class, "LBL_ACIW_Resources")
+            };
+    }
+    
+    @Override
+    public HelpCtx getHelp() {
+        return null;
+    }
+
+    @Override
+    public void readSettings(WizardDescriptor settings) {
+        wd = settings;
+    }
+
+    @Override
+    public void storeSettings(WizardDescriptor settings) {
+        if (component != null) {
+            settings.putProperty(KEY_ID, component.getKeyId());
+            settings.putProperty(KEY, component.getKey());
+            settings.putProperty(CloudResourcesWizardPanel.PROP_SERVER_RESOURCES, servers);
+            settings.putProperty(REGION, component.getRegionUrl());
+        }
+    }
+    
+    public void setErrorMessage(String message) {
+        wd.putProperty(WizardDescriptor.PROP_ERROR_MESSAGE, message);
+    }
+
+    @Override
+    public boolean isValid() {
+        if (component == null || wd == null) {
+            // ignore this case
+        } else if (component.getKeyId().trim().length() == 0) {
+            setErrorMessage(NbBundle.getMessage(AmazonWizardPanel.class, "AmazonWizardPanel.missingKeyID"));
+            return false;
+        } else if (component.getKey().trim().length() == 0) {
+            setErrorMessage(NbBundle.getMessage(AmazonWizardPanel.class, "AmazonWizardPanel.missingKey"));
+            return false;
+        }
+        setErrorMessage("");
+        return true;
+    }
+
+    @Override
+    public void addChangeListener(ChangeListener l) {
+        listeners.addChangeListener(l);
+    }
+
+    @Override
+    public void removeChangeListener(ChangeListener l) {
+        listeners.removeChangeListener(l);
+    }
+    
+    void fireChange() {
+        listeners.fireChange();
+    }
+
+    @Override
+    public void prepareValidation() {
+        getComponent().setCursor(Utilities.createProgressCursor(getComponent()));
+    }
+
+    @Override
+    public void validate() throws WizardValidationException {
+        try {
+            servers = new ArrayList<ServerResourceDescriptor>();
+            AmazonInstance ai = new AmazonInstance("temporary", component.getKeyId(), component.getKey(), component.getRegionUrl());
+            try {
+                ai.testConnection();
+            } catch (AmazonClientException ex) {
+                throw new WizardValidationException((JComponent)getComponent(), 
+                        "connection failed", NbBundle.getMessage(AmazonWizardPanel.class, "AmazonWizardPanel.wrong.credentials"));
+            }
+            List<AmazonJ2EEInstance> list = ai.readJ2EEServerInstances();
+            for (AmazonJ2EEInstance inst : list) {
+                AmazonJ2EEInstanceNode n = new AmazonJ2EEInstanceNode(inst);
+                n.showServerType();
+                servers.add(new ServerResourceDescriptor("Server", n.getDisplayName(), "", ImageUtilities.image2Icon(n.getIcon(BeanInfo.ICON_COLOR_16x16))));
+            }
+        } finally {
+            getComponent().setCursor(null);
+        }
+    }
+    
+}
diff --git a/cloud.amazon/src/org/netbeans/modules/cloud/amazon/ui/Bundle.properties b/cloud.amazon/src/org/netbeans/modules/cloud/amazon/ui/Bundle.properties
new file mode 100644
index 0000000000..5888037bd7
--- /dev/null
+++ b/cloud.amazon/src/org/netbeans/modules/cloud/amazon/ui/Bundle.properties
@@ -0,0 +1,33 @@
+# 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.
+
+Amazon_Node_Name=Amazon Beanstalk
+Amazon_Node_Short_Description=Amazon Beanstalk
+AmazonWizardComponent.jLabel1.text=Access Key ID:
+AmazonWizardComponent.jLabel2.text=Secret Access Key:
+AmazonWizardComponent.accessKey.text=
+AmazonWizardComponent.secret.text=
+
+LBL_ACIW_Amazon=Amazon Beanstalk
+LBL_Name=Amazon Beanstalk
+LBL_ACIW_Resources=Cloud Resources
+
+AmazonWizardPanel.wrong.credentials=Cannot connect to Amazon Beanstalk using provided credentials.
+
+AmazonWizardPanel.missingKeyID=Access Key ID is required
+AmazonWizardPanel.missingKey=Secret Access Key is required
+AmazonWizardComponent.jLabel3.text=Region:
diff --git a/cloud.amazon/src/org/netbeans/modules/cloud/amazon/ui/PropertiesAction.java b/cloud.amazon/src/org/netbeans/modules/cloud/amazon/ui/PropertiesAction.java
new file mode 100644
index 0000000000..34c4587e23
--- /dev/null
+++ b/cloud.amazon/src/org/netbeans/modules/cloud/amazon/ui/PropertiesAction.java
@@ -0,0 +1,62 @@
+/*
+ * 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.cloud.amazon.ui;
+
+import org.netbeans.api.server.CommonServerUIs;
+import org.netbeans.modules.cloud.amazon.AmazonInstance;
+import org.openide.nodes.Node;
+import org.openide.util.HelpCtx;
+import org.openide.util.actions.NodeAction;
+
+/**
+ *
+ */
+public class PropertiesAction extends NodeAction {
+
+    @Override
+    protected void performAction(Node[] activatedNodes) {
+        AmazonInstance ai = activatedNodes[0].getLookup().lookup(AmazonInstance.class);
+        CommonServerUIs.showCloudCustomizer(ai.getServerInstance());
+    }
+
+    @Override
+    protected boolean enable(Node[] activatedNodes) {
+        if (activatedNodes.length != 1) {
+            return false;
+        }
+        return activatedNodes.length > 0 && activatedNodes[0].getLookup().lookup(AmazonInstance.class) != null;
+    }
+
+    @Override
+    public String getName() {
+        return "Properties";
+    }
+
+    
+    @Override
+    protected boolean asynchronous() {
+        return false;
+    }
+
+    @Override
+    public HelpCtx getHelpCtx() {
+        return null;
+    }
+    
+}
diff --git a/cloud.amazon/src/org/netbeans/modules/cloud/amazon/ui/RefreshAmazonInstanceNodeAction.java b/cloud.amazon/src/org/netbeans/modules/cloud/amazon/ui/RefreshAmazonInstanceNodeAction.java
new file mode 100644
index 0000000000..0eeb3e844b
--- /dev/null
+++ b/cloud.amazon/src/org/netbeans/modules/cloud/amazon/ui/RefreshAmazonInstanceNodeAction.java
@@ -0,0 +1,56 @@
+/*
+ * 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.cloud.amazon.ui;
+
+import org.netbeans.modules.cloud.amazon.AmazonInstance;
+import org.netbeans.modules.cloud.amazon.serverplugin.AmazonJ2EEServerInstanceProvider;
+import org.openide.nodes.Node;
+import org.openide.util.HelpCtx;
+import org.openide.util.actions.NodeAction;
+
+/**
+ *
+ */
+public class RefreshAmazonInstanceNodeAction extends NodeAction {
+
+    @Override
+    protected void performAction(Node[] activatedNodes) {
+        //AmazonInstance ai = activatedNodes[0].getLookup().lookup(AmazonInstance.class);
+        AmazonJ2EEServerInstanceProvider.getProvider().refreshServers();
+    }
+
+    @Override
+    protected boolean enable(Node[] activatedNodes) {
+        if (activatedNodes.length != 1) {
+            return false;
+        }
+        return activatedNodes.length > 0 && activatedNodes[0].getLookup().lookup(AmazonInstance.class) != null;
+    }
+
+    @Override
+    public String getName() {
+        return "Refresh";
+    }
+
+    @Override
+    public HelpCtx getHelpCtx() {
+        return null;
+    }
+    
+}
diff --git a/cloud.amazon/src/org/netbeans/modules/cloud/amazon/ui/RemoteServerPropertiesAction.java b/cloud.amazon/src/org/netbeans/modules/cloud/amazon/ui/RemoteServerPropertiesAction.java
new file mode 100644
index 0000000000..9e3840f56d
--- /dev/null
+++ b/cloud.amazon/src/org/netbeans/modules/cloud/amazon/ui/RemoteServerPropertiesAction.java
@@ -0,0 +1,62 @@
+/*
+ * 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.cloud.amazon.ui;
+
+import org.netbeans.api.server.CommonServerUIs;
+import org.netbeans.modules.cloud.amazon.serverplugin.AmazonJ2EEInstance;
+import org.openide.nodes.Node;
+import org.openide.util.HelpCtx;
+import org.openide.util.actions.NodeAction;
+
+/**
+ *
+ */
+public class RemoteServerPropertiesAction extends NodeAction {
+
+    @Override
+    protected void performAction(Node[] activatedNodes) {
+        AmazonJ2EEInstance ai = activatedNodes[0].getLookup().lookup(AmazonJ2EEInstance.class);
+        CommonServerUIs.showCustomizer(ai.getInstance());
+    }
+
+    @Override
+    protected boolean enable(Node[] activatedNodes) {
+        if (activatedNodes.length != 1) {
+            return false;
+        }
+        return activatedNodes.length > 0 && activatedNodes[0].getLookup().lookup(AmazonJ2EEInstance.class) != null;
+    }
+
+    @Override
+    public String getName() {
+        return "Properties";
+    }
+
+    
+    @Override
+    protected boolean asynchronous() {
+        return false;
+    }
+
+    @Override
+    public HelpCtx getHelpCtx() {
+        return null;
+    }
+    
+}
diff --git a/cloud.amazon/src/org/netbeans/modules/cloud/amazon/ui/RemoveAmazonInstanceAction.java b/cloud.amazon/src/org/netbeans/modules/cloud/amazon/ui/RemoveAmazonInstanceAction.java
new file mode 100644
index 0000000000..9aa0c250ca
--- /dev/null
+++ b/cloud.amazon/src/org/netbeans/modules/cloud/amazon/ui/RemoveAmazonInstanceAction.java
@@ -0,0 +1,59 @@
+/*
+ * 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.cloud.amazon.ui;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import org.netbeans.modules.cloud.amazon.AmazonInstance;
+import org.openide.awt.HtmlBrowser;
+import org.openide.nodes.Node;
+import org.openide.util.Exceptions;
+import org.openide.util.HelpCtx;
+import org.openide.util.actions.NodeAction;
+
+/**
+ *
+ */
+public class RemoveAmazonInstanceAction extends NodeAction {
+
+    @Override
+    protected void performAction(Node[] activatedNodes) {
+        AmazonInstance ai = activatedNodes[0].getLookup().lookup(AmazonInstance.class);
+        ai.getServerInstance().remove();
+    }
+
+    @Override
+    protected boolean enable(Node[] activatedNodes) {
+        if (activatedNodes.length != 1) {
+            return false;
+        }
+        return activatedNodes.length > 0 && activatedNodes[0].getLookup().lookup(AmazonInstance.class) != null;
+    }
+
+    @Override
+    public String getName() {
+        return "Remove";
+    }
+
+    @Override
+    public HelpCtx getHelpCtx() {
+        return null;
+    }
+    
+}
diff --git a/cloud.amazon/src/org/netbeans/modules/cloud/amazon/ui/ViewAdminConsoleAction.java b/cloud.amazon/src/org/netbeans/modules/cloud/amazon/ui/ViewAdminConsoleAction.java
new file mode 100644
index 0000000000..7c09ee2aa4
--- /dev/null
+++ b/cloud.amazon/src/org/netbeans/modules/cloud/amazon/ui/ViewAdminConsoleAction.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.cloud.amazon.ui;
+
+import java.net.URL;
+import org.netbeans.modules.cloud.amazon.AmazonInstance;
+import org.netbeans.modules.web.common.api.WebUtils;
+import org.openide.awt.HtmlBrowser;
+import org.openide.nodes.Node;
+import org.openide.util.HelpCtx;
+import org.openide.util.actions.NodeAction;
+
+/**
+ *
+ */
+public class ViewAdminConsoleAction extends NodeAction {
+
+    @Override
+    protected void performAction(Node[] activatedNodes) {
+        AmazonInstance ai = activatedNodes[0].getLookup().lookup(AmazonInstance.class);
+        String region = ai.getRegionURL();
+        if (region != null) {
+            if (region.startsWith("elasticbeanstalk.") && region.endsWith(".amazonaws.com")) { // NOI18N
+                region = region.substring(17, region.length()-14);
+            } else {
+                region = null;
+            }
+        }
+        URL url = WebUtils.stringToUrl("https://console.aws.amazon.com/elasticbeanstalk/home" + 
+                (region != null ? "?region="+region : "")); // NOI18N
+        HtmlBrowser.URLDisplayer.getDefault().showURL(url);
+    }
+
+    @Override
+    protected boolean enable(Node[] activatedNodes) {
+        if (activatedNodes.length != 1) {
+            return false;
+        }
+        return activatedNodes.length > 0 && activatedNodes[0].getLookup().lookup(AmazonInstance.class) != null;
+    }
+
+    @Override
+    public String getName() {
+        return "Open AWS Console";
+    }
+
+    @Override
+    public HelpCtx getHelpCtx() {
+        return null;
+    }
+    
+}
diff --git a/cloud.amazon/src/org/netbeans/modules/cloud/amazon/ui/resources/amazon.png b/cloud.amazon/src/org/netbeans/modules/cloud/amazon/ui/resources/amazon.png
new file mode 100644
index 0000000000..f2b9230fb4
Binary files /dev/null and b/cloud.amazon/src/org/netbeans/modules/cloud/amazon/ui/resources/amazon.png differ
diff --git a/cloud.amazon/src/org/netbeans/modules/cloud/amazon/ui/resources/running.png b/cloud.amazon/src/org/netbeans/modules/cloud/amazon/ui/resources/running.png
new file mode 100644
index 0000000000..27f56c8ffa
Binary files /dev/null and b/cloud.amazon/src/org/netbeans/modules/cloud/amazon/ui/resources/running.png differ
diff --git a/cloud.amazon/src/org/netbeans/modules/cloud/amazon/ui/resources/terminated.png b/cloud.amazon/src/org/netbeans/modules/cloud/amazon/ui/resources/terminated.png
new file mode 100644
index 0000000000..7cb680aef2
Binary files /dev/null and b/cloud.amazon/src/org/netbeans/modules/cloud/amazon/ui/resources/terminated.png differ
diff --git a/cloud.amazon/src/org/netbeans/modules/cloud/amazon/ui/resources/tomcat.png b/cloud.amazon/src/org/netbeans/modules/cloud/amazon/ui/resources/tomcat.png
new file mode 100644
index 0000000000..dde0942211
Binary files /dev/null and b/cloud.amazon/src/org/netbeans/modules/cloud/amazon/ui/resources/tomcat.png differ
diff --git a/cloud.amazon/src/org/netbeans/modules/cloud/amazon/ui/resources/waiting.png b/cloud.amazon/src/org/netbeans/modules/cloud/amazon/ui/resources/waiting.png
new file mode 100644
index 0000000000..ef8945e2fd
Binary files /dev/null and b/cloud.amazon/src/org/netbeans/modules/cloud/amazon/ui/resources/waiting.png differ
diff --git a/cloud.amazon/src/org/netbeans/modules/cloud/amazon/ui/serverplugin/AmazonJ2EEServerWizardComponent.form b/cloud.amazon/src/org/netbeans/modules/cloud/amazon/ui/serverplugin/AmazonJ2EEServerWizardComponent.form
new file mode 100644
index 0000000000..a1ff04bf45
--- /dev/null
+++ b/cloud.amazon/src/org/netbeans/modules/cloud/amazon/ui/serverplugin/AmazonJ2EEServerWizardComponent.form
@@ -0,0 +1,160 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<Form version="1.5" maxVersion="1.7" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
+  <AuxValues>
+    <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
+    <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
+    <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
+    <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
+    <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
+    <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
+    <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
+    <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
+    <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
+  </AuxValues>
+
+  <Layout>
+    <DimensionLayout dim="0">
+      <Group type="103" groupAlignment="0" attributes="0">
+          <Group type="102" alignment="1" attributes="0">
+              <Group type="103" groupAlignment="0" attributes="0">
+                  <Component id="accountLavel" alignment="0" min="-2" max="-2" attributes="0"/>
+                  <Component id="appNameLabel" alignment="0" min="-2" max="-2" attributes="0"/>
+                  <Component id="templateLabel" alignment="0" min="-2" max="-2" attributes="0"/>
+                  <Component id="endNameLabel" alignment="0" min="-2" max="-2" attributes="0"/>
+                  <Component id="envURLLabel" alignment="0" min="-2" max="-2" attributes="0"/>
+                  <Component id="containerLabel" alignment="0" min="-2" max="-2" attributes="0"/>
+              </Group>
+              <EmptySpace min="-2" max="-2" attributes="0"/>
+              <Group type="103" groupAlignment="1" attributes="0">
+                  <Component id="envFullURLLabel" pref="251" max="32767" attributes="0"/>
+                  <Component id="containerComboBox" alignment="0" pref="251" max="32767" attributes="0"/>
+                  <Component id="envURLTextField" alignment="0" pref="251" max="32767" attributes="0"/>
+                  <Component id="envNameTextField" alignment="0" pref="251" max="32767" attributes="0"/>
+                  <Component id="templateComboBox" alignment="0" pref="251" max="32767" attributes="0"/>
+                  <Component id="accountComboBox" alignment="0" pref="251" max="32767" attributes="0"/>
+                  <Component id="appNameComboBox" alignment="0" pref="251" max="32767" attributes="0"/>
+              </Group>
+              <EmptySpace min="-2" max="-2" attributes="0"/>
+          </Group>
+      </Group>
+    </DimensionLayout>
+    <DimensionLayout dim="1">
+      <Group type="103" groupAlignment="0" attributes="0">
+          <Group type="102" alignment="0" attributes="0">
+              <Group type="103" groupAlignment="3" attributes="0">
+                  <Component id="accountLavel" alignment="3" min="-2" max="-2" attributes="0"/>
+                  <Component id="accountComboBox" alignment="3" min="-2" max="-2" attributes="0"/>
+              </Group>
+              <EmptySpace min="-2" max="-2" attributes="0"/>
+              <Group type="103" groupAlignment="3" attributes="0">
+                  <Component id="appNameLabel" alignment="3" min="-2" max="-2" attributes="0"/>
+                  <Component id="appNameComboBox" alignment="3" min="-2" max="-2" attributes="0"/>
+              </Group>
+              <EmptySpace max="-2" attributes="0"/>
+              <Group type="103" groupAlignment="3" attributes="0">
+                  <Component id="templateLabel" alignment="3" min="-2" max="-2" attributes="0"/>
+                  <Component id="templateComboBox" alignment="3" min="-2" max="-2" attributes="0"/>
+              </Group>
+              <EmptySpace max="-2" attributes="0"/>
+              <Group type="103" groupAlignment="3" attributes="0">
+                  <Component id="endNameLabel" alignment="3" min="-2" max="-2" attributes="0"/>
+                  <Component id="envNameTextField" alignment="3" min="-2" max="-2" attributes="0"/>
+              </Group>
+              <EmptySpace max="-2" attributes="0"/>
+              <Group type="103" groupAlignment="3" attributes="0">
+                  <Component id="envURLLabel" alignment="3" min="-2" max="-2" attributes="0"/>
+                  <Component id="envURLTextField" alignment="3" min="-2" max="-2" attributes="0"/>
+              </Group>
+              <EmptySpace max="-2" attributes="0"/>
+              <Component id="envFullURLLabel" min="-2" max="-2" attributes="0"/>
+              <EmptySpace max="-2" attributes="0"/>
+              <Group type="103" groupAlignment="3" attributes="0">
+                  <Component id="containerLabel" alignment="3" min="-2" max="-2" attributes="0"/>
+                  <Component id="containerComboBox" alignment="3" min="-2" max="-2" attributes="0"/>
+              </Group>
+          </Group>
+      </Group>
+    </DimensionLayout>
+  </Layout>
+  <SubComponents>
+    <Component class="javax.swing.JLabel" name="accountLavel">
+      <Properties>
+        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+          <ResourceString bundle="org/netbeans/modules/cloud/amazon/ui/serverplugin/Bundle.properties" key="AmazonJ2EEServerWizardComponent.accountLavel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+        </Property>
+      </Properties>
+    </Component>
+    <Component class="javax.swing.JComboBox" name="accountComboBox">
+    </Component>
+    <Component class="javax.swing.JLabel" name="appNameLabel">
+      <Properties>
+        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+          <ResourceString bundle="org/netbeans/modules/cloud/amazon/ui/serverplugin/Bundle.properties" key="AmazonJ2EEServerWizardComponent.appNameLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+        </Property>
+      </Properties>
+    </Component>
+    <Component class="javax.swing.JComboBox" name="appNameComboBox">
+      <Properties>
+        <Property name="editable" type="boolean" value="true"/>
+      </Properties>
+    </Component>
+    <Component class="javax.swing.JLabel" name="endNameLabel">
+      <Properties>
+        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+          <ResourceString bundle="org/netbeans/modules/cloud/amazon/ui/serverplugin/Bundle.properties" key="AmazonJ2EEServerWizardComponent.endNameLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+        </Property>
+      </Properties>
+    </Component>
+    <Component class="javax.swing.JTextField" name="envNameTextField">
+      <Properties>
+        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+          <ResourceString bundle="org/netbeans/modules/cloud/amazon/ui/serverplugin/Bundle.properties" key="AmazonJ2EEServerWizardComponent.envNameTextField.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+        </Property>
+      </Properties>
+    </Component>
+    <Component class="javax.swing.JLabel" name="envURLLabel">
+      <Properties>
+        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+          <ResourceString bundle="org/netbeans/modules/cloud/amazon/ui/serverplugin/Bundle.properties" key="AmazonJ2EEServerWizardComponent.envURLLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+        </Property>
+      </Properties>
+    </Component>
+    <Component class="javax.swing.JTextField" name="envURLTextField">
+    </Component>
+    <Component class="javax.swing.JLabel" name="envFullURLLabel">
+      <Properties>
+        <Property name="font" type="java.awt.Font" editor="org.netbeans.modules.form.editors2.FontEditor">
+          <FontInfo relative="true">
+            <Font component="envFullURLLabel" property="font" relativeSize="true" size="-2"/>
+          </FontInfo>
+        </Property>
+        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+          <ResourceString bundle="org/netbeans/modules/cloud/amazon/ui/serverplugin/Bundle.properties" key="AmazonJ2EEServerWizardComponent.envFullURLLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+        </Property>
+      </Properties>
+    </Component>
+    <Component class="javax.swing.JLabel" name="containerLabel">
+      <Properties>
+        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+          <ResourceString bundle="org/netbeans/modules/cloud/amazon/ui/serverplugin/Bundle.properties" key="AmazonJ2EEServerWizardComponent.containerLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+        </Property>
+      </Properties>
+    </Component>
+    <Component class="javax.swing.JComboBox" name="containerComboBox">
+    </Component>
+    <Component class="javax.swing.JLabel" name="templateLabel">
+      <Properties>
+        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+          <ResourceString bundle="org/netbeans/modules/cloud/amazon/ui/serverplugin/Bundle.properties" key="AmazonJ2EEServerWizardComponent.templateLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+        </Property>
+        <Property name="enabled" type="boolean" value="false"/>
+      </Properties>
+    </Component>
+    <Component class="javax.swing.JComboBox" name="templateComboBox">
+      <Properties>
+        <Property name="enabled" type="boolean" value="false"/>
+      </Properties>
+    </Component>
+  </SubComponents>
+</Form>
diff --git a/cloud.amazon/src/org/netbeans/modules/cloud/amazon/ui/serverplugin/AmazonJ2EEServerWizardComponent.java b/cloud.amazon/src/org/netbeans/modules/cloud/amazon/ui/serverplugin/AmazonJ2EEServerWizardComponent.java
new file mode 100644
index 0000000000..f427c9144d
--- /dev/null
+++ b/cloud.amazon/src/org/netbeans/modules/cloud/amazon/ui/serverplugin/AmazonJ2EEServerWizardComponent.java
@@ -0,0 +1,478 @@
+/*
+ * 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.cloud.amazon.ui.serverplugin;
+
+import java.awt.Component;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Callable;
+import javax.swing.DefaultComboBoxModel;
+import javax.swing.JLabel;
+import javax.swing.JList;
+import javax.swing.JTextField;
+import javax.swing.ListCellRenderer;
+import javax.swing.SwingUtilities;
+import javax.swing.event.ChangeListener;
+import javax.swing.event.DocumentEvent;
+import javax.swing.event.DocumentListener;
+import javax.swing.event.ListDataEvent;
+import javax.swing.event.ListDataListener;
+import org.netbeans.modules.cloud.amazon.AmazonInstance;
+import org.netbeans.modules.cloud.amazon.AmazonInstanceManager;
+import org.netbeans.modules.cloud.amazon.serverplugin.AmazonJ2EEInstance;
+import org.openide.util.NbBundle;
+
+/**
+ *
+ */
+public class AmazonJ2EEServerWizardComponent extends javax.swing.JPanel implements DocumentListener {
+
+    private AmazonJ2EEServerWizardPanel wizardPanel;
+    private String suggestedName;
+    private Map<String, List<String>> templates;
+    
+    private static final String SUFFIX = "-dev-env";
+    
+    /** Creates new form AmazonJ2EEServerWizardComponent */
+    public AmazonJ2EEServerWizardComponent(AmazonJ2EEServerWizardPanel wizardPanel, String suggestedName, AmazonJ2EEInstance aji) {
+        this.wizardPanel = wizardPanel;
+        this.suggestedName = suggestedName;
+        initComponents();
+        setName(NbBundle.getMessage(AmazonJ2EEServerWizardComponent.class, "AmazonJ2EEServerWizardComponent.name"));
+        if (suggestedName != null) {
+            if (suggestedName.length() > (23-SUFFIX.length())) {
+                envNameTextField.setText(suggestedName.substring(0, 23-SUFFIX.length()) +SUFFIX);
+            } else {
+                envNameTextField.setText(suggestedName+SUFFIX);
+            }
+            envURLTextField.setText(suggestedName+SUFFIX);
+            envFullURLLabel.setText("<html>"+envURLTextField.getText()+".elasticbeanstalk.com"); // NOI18N
+        }
+        if (aji != null) {
+            accountComboBox.setEditable(false);
+            accountComboBox.getModel().setSelectedItem(aji.getAmazonInstance().getName());
+            ((JTextField)(appNameComboBox.getEditor().getEditorComponent())).setText(aji.getApplicationName());
+            appNameComboBox.setEditable(false);
+            envNameTextField.setText(aji.getEnvironmentName());
+            envNameTextField.setEditable(false);
+            templateComboBox.setVisible(false);
+            templateLabel.setVisible(false);
+            envURLTextField.setVisible(false);
+            envURLLabel.setVisible(false);
+            envFullURLLabel.setVisible(false);
+            containerComboBox.getModel().setSelectedItem(aji.getContainerType());
+            containerComboBox.setEditable(false);
+        }
+    }
+    
+    void init() {
+        initAccounts();
+        initApplications();
+        enableApplicationComponent(hasAccount());
+        hookEnvironmentURL();
+        
+        if (hasAccount()) {
+            initContainersModel();
+            accountComboBox.setSelectedIndex(0);
+            reloadApplications();
+        }
+    }
+    
+    private void enableApplicationComponent(boolean enable) {
+        appNameComboBox.setEnabled(enable);
+        appNameLabel.setEnabled(enable);
+        containerComboBox.setEnabled(enable);
+        containerLabel.setEnabled(enable);
+        endNameLabel.setEnabled(enable);
+        envURLLabel.setEnabled(enable);
+        envFullURLLabel.setEnabled(enable);
+        envNameTextField.setEnabled(enable);
+        envURLTextField.setEnabled(enable);
+    }
+
+    
+    public String getApplicationName() {
+        return ((JTextField)(appNameComboBox.getEditor().getEditorComponent())).getText();
+    }
+    
+    public String getTemplateName() {
+        if (!templateComboBox.isEnabled()) {
+            return null;
+        }
+        String templ = (String)templateComboBox.getModel().getSelectedItem();
+        if (templ != null && templ.length() > 0) {
+            return templ;
+        }
+        return null;
+    }
+    
+    public String getEnvironmentName() {
+        return envNameTextField.getText();
+    }
+    
+    public String getURL() {
+        return envURLTextField.getText();
+    }
+    
+    public AmazonInstance getAmazonInstance() {
+        return (AmazonInstance)accountComboBox.getSelectedItem();
+    }
+
+    public String getContainerType() {
+        return (String)containerComboBox.getSelectedItem();
+    }
+    
+    public boolean hasAccount() {
+        return accountComboBox.getModel().getSize() > 0;
+    }
+    /** This method is called from within the constructor to
+     * initialize the form.
+     * WARNING: Do NOT modify this code. The content of this method is
+     * always regenerated by the Form Editor.
+     */
+    @SuppressWarnings("unchecked")
+    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
+    private void initComponents() {
+
+        accountLavel = new javax.swing.JLabel();
+        accountComboBox = new javax.swing.JComboBox();
+        appNameLabel = new javax.swing.JLabel();
+        appNameComboBox = new javax.swing.JComboBox();
+        endNameLabel = new javax.swing.JLabel();
+        envNameTextField = new javax.swing.JTextField();
+        envURLLabel = new javax.swing.JLabel();
+        envURLTextField = new javax.swing.JTextField();
+        envFullURLLabel = new javax.swing.JLabel();
+        containerLabel = new javax.swing.JLabel();
+        containerComboBox = new javax.swing.JComboBox();
+        templateLabel = new javax.swing.JLabel();
+        templateComboBox = new javax.swing.JComboBox();
+
+        accountLavel.setText(org.openide.util.NbBundle.getMessage(AmazonJ2EEServerWizardComponent.class, "AmazonJ2EEServerWizardComponent.accountLavel.text")); // NOI18N
+
+        appNameLabel.setText(org.openide.util.NbBundle.getMessage(AmazonJ2EEServerWizardComponent.class, "AmazonJ2EEServerWizardComponent.appNameLabel.text")); // NOI18N
+
+        appNameComboBox.setEditable(true);
+
+        endNameLabel.setText(org.openide.util.NbBundle.getMessage(AmazonJ2EEServerWizardComponent.class, "AmazonJ2EEServerWizardComponent.endNameLabel.text")); // NOI18N
+
+        envNameTextField.setText(org.openide.util.NbBundle.getMessage(AmazonJ2EEServerWizardComponent.class, "AmazonJ2EEServerWizardComponent.envNameTextField.text")); // NOI18N
+
+        envURLLabel.setText(org.openide.util.NbBundle.getMessage(AmazonJ2EEServerWizardComponent.class, "AmazonJ2EEServerWizardComponent.envURLLabel.text")); // NOI18N
+
+        envFullURLLabel.setFont(envFullURLLabel.getFont().deriveFont(envFullURLLabel.getFont().getSize()-2f));
+        envFullURLLabel.setText(org.openide.util.NbBundle.getMessage(AmazonJ2EEServerWizardComponent.class, "AmazonJ2EEServerWizardComponent.envFullURLLabel.text")); // NOI18N
+
+        containerLabel.setText(org.openide.util.NbBundle.getMessage(AmazonJ2EEServerWizardComponent.class, "AmazonJ2EEServerWizardComponent.containerLabel.text")); // NOI18N
+
+        templateLabel.setText(org.openide.util.NbBundle.getMessage(AmazonJ2EEServerWizardComponent.class, "AmazonJ2EEServerWizardComponent.templateLabel.text")); // NOI18N
+        templateLabel.setEnabled(false);
+
+        templateComboBox.setEnabled(false);
+
+        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
+        this.setLayout(layout);
+        layout.setHorizontalGroup(
+            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
+                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+                    .addComponent(accountLavel)
+                    .addComponent(appNameLabel)
+                    .addComponent(templateLabel)
+                    .addComponent(endNameLabel)
+                    .addComponent(envURLLabel)
+                    .addComponent(containerLabel))
+                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
+                    .addComponent(envFullURLLabel, javax.swing.GroupLayout.DEFAULT_SIZE, 251, Short.MAX_VALUE)
+                    .addComponent(containerComboBox, javax.swing.GroupLayout.Alignment.LEADING, 0, 251, Short.MAX_VALUE)
+                    .addComponent(envURLTextField, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 251, Short.MAX_VALUE)
+                    .addComponent(envNameTextField, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 251, Short.MAX_VALUE)
+                    .addComponent(templateComboBox, javax.swing.GroupLayout.Alignment.LEADING, 0, 251, Short.MAX_VALUE)
+                    .addComponent(accountComboBox, javax.swing.GroupLayout.Alignment.LEADING, 0, 251, Short.MAX_VALUE)
+                    .addComponent(appNameComboBox, javax.swing.GroupLayout.Alignment.LEADING, 0, 251, Short.MAX_VALUE))
+                .addContainerGap())
+        );
+        layout.setVerticalGroup(
+            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addGroup(layout.createSequentialGroup()
+                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+                    .addComponent(accountLavel)
+                    .addComponent(accountComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+                    .addComponent(appNameLabel)
+                    .addComponent(appNameComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+                    .addComponent(templateLabel)
+                    .addComponent(templateComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+                    .addComponent(endNameLabel)
+                    .addComponent(envNameTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+                    .addComponent(envURLLabel)
+                    .addComponent(envURLTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                .addComponent(envFullURLLabel)
+                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+                    .addComponent(containerLabel)
+                    .addComponent(containerComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
+        );
+    }// </editor-fold>//GEN-END:initComponents
+
+    
+    /*
+        NotifyDescriptor.InputLine il = new NotifyDescriptor.InputLine(
+                NbBundle.getMessage(AmazonJ2EEServerWizardComponent.class, "AmazonJ2EEServerWizardComponent.enterNewAppName"),
+                NbBundle.getMessage(AmazonJ2EEServerWizardComponent.class, "AmazonJ2EEServerWizardComponent.enterNewAppNameTitle"),
+                NotifyDescriptor.OK_CANCEL_OPTION, NotifyDescriptor.PLAIN_MESSAGE);
+        if (DialogDisplayer.getDefault().notify(il) != NotifyDescriptor.OK_OPTION) {
+            return;
+        }
+*/    
+    // Variables declaration - do not modify//GEN-BEGIN:variables
+    private javax.swing.JComboBox accountComboBox;
+    private javax.swing.JLabel accountLavel;
+    private javax.swing.JComboBox appNameComboBox;
+    private javax.swing.JLabel appNameLabel;
+    private javax.swing.JComboBox containerComboBox;
+    private javax.swing.JLabel containerLabel;
+    private javax.swing.JLabel endNameLabel;
+    private javax.swing.JLabel envFullURLLabel;
+    private javax.swing.JTextField envNameTextField;
+    private javax.swing.JLabel envURLLabel;
+    private javax.swing.JTextField envURLTextField;
+    private javax.swing.JComboBox templateComboBox;
+    private javax.swing.JLabel templateLabel;
+    // End of variables declaration//GEN-END:variables
+
+    private void initAccounts() {
+        List<AmazonInstance> l = AmazonInstanceManager.getDefault().getInstances();
+        DefaultComboBoxModel model = new DefaultComboBoxModel(l.toArray(new AmazonInstance[l.size()]));
+        accountComboBox.setModel(model);
+        accountComboBox.setRenderer(new ListCellRenderer() {
+            @Override
+            public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
+                String s;
+                if (value instanceof AmazonInstance) {
+                    s = ((AmazonInstance)value).getName();
+                } else {
+                    s = (String)value;
+                }
+                return new JLabel(s);
+            }
+        });
+        
+        accountComboBox.getModel().addListDataListener(new ListDataListener() {
+
+            @Override
+            public void intervalAdded(ListDataEvent e) {
+            }
+
+            @Override
+            public void intervalRemoved(ListDataEvent e) {
+            }
+
+            @Override
+            public void contentsChanged(ListDataEvent e) {
+                reloadApplications();
+            }
+        });
+    }
+    
+    private void initApplications() {
+        JTextField tf = (JTextField)(appNameComboBox.getEditor().getEditorComponent());
+        tf.getDocument().addDocumentListener(this);
+        DefaultComboBoxModel model = new DefaultComboBoxModel(new String[]{suggestedName == null ? "" : suggestedName});
+        appNameComboBox.setModel(model);
+        appNameComboBox.setRenderer(new ListCellRenderer() {
+            @Override
+            public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
+                if (value instanceof String) {
+                    return new JLabel((String)value);
+                } else {
+                    assert false;
+                    return null;
+                }
+            }
+        });
+        
+        ((JTextField)(appNameComboBox.getEditor().getEditorComponent())).getDocument().addDocumentListener(new DocumentListener() {
+
+            @Override
+            public void insertUpdate(DocumentEvent e) {
+                reloadTemplates();
+            }
+
+            @Override
+            public void removeUpdate(DocumentEvent e) {
+                reloadTemplates();
+            }
+
+            @Override
+            public void changedUpdate(DocumentEvent e) {
+                reloadTemplates();
+            }
+        });
+    }
+    
+    private void reloadTemplates() {
+        String appName = getApplicationName();
+        if (appName != null) {
+            List<String> templateNames = templates.get(appName);
+            if (templateNames != null && templateNames.size() > 0) {
+                templateNames = new ArrayList<String>(templateNames);
+                templateNames.add(0, "");
+                templateComboBox.setModel(new DefaultComboBoxModel(templateNames.toArray(new String[templateNames.size()])));
+                templateComboBox.setSelectedIndex(0);
+                templateComboBox.setEnabled(true);
+                templateLabel.setEnabled(true);
+                return;
+            }
+        }
+        templateComboBox.setModel(new DefaultComboBoxModel());
+        templateComboBox.setEnabled(false);
+        templateLabel.setEnabled(false);
+    }
+    
+    private void reloadApplications() {
+        DefaultComboBoxModel model = new DefaultComboBoxModel(new String[]{suggestedName == null ? "" : suggestedName, NbBundle.getMessage(AmazonJ2EEServerWizardComponent.class, "AmazonJ2EEServerWizardComponent.loadingApplications")});
+        appNameComboBox.setModel(model);
+        final AmazonInstance ai = (AmazonInstance)accountComboBox.getSelectedItem();
+        
+        AmazonInstance.runAsynchronously(new Callable<Void>() {
+            @Override
+            public Void call() {
+                templates = ai.readApplicationTemplates();
+                final List<String> apps = new ArrayList<String>(templates.keySet());
+                apps.add(0, suggestedName == null ? "" : suggestedName);
+                SwingUtilities.invokeLater(new Runnable() {
+                    @Override
+                    public void run() {
+                        appNameComboBox.setModel(new DefaultComboBoxModel(apps.toArray(new String[apps.size()])));
+                        appNameComboBox.setSelectedIndex(0);
+                    }
+                });
+                return null;
+            }
+        }, ai);
+    }
+
+    private void hookEnvironmentURL() {
+        envNameTextField.getDocument().addDocumentListener(new DocumentListener() {
+
+            @Override
+            public void insertUpdate(DocumentEvent e) {
+                suggestNewURL();
+            }
+
+            @Override
+            public void removeUpdate(DocumentEvent e) {
+                suggestNewURL();
+            }
+
+            @Override
+            public void changedUpdate(DocumentEvent e) {
+                suggestNewURL();
+            }
+        });
+        envURLTextField.getDocument().addDocumentListener(new DocumentListener() {
+
+            @Override
+            public void insertUpdate(DocumentEvent e) {
+                updateFullURL();
+            }
+
+            @Override
+            public void removeUpdate(DocumentEvent e) {
+                updateFullURL();
+            }
+
+            @Override
+            public void changedUpdate(DocumentEvent e) {
+                updateFullURL();
+            }
+        });
+    }
+    
+    private void suggestNewURL() {
+        envURLTextField.setText(envNameTextField.getText());
+        if (wizardPanel != null) {
+            wizardPanel.fireChange();
+        }
+    }
+
+    private void updateFullURL() {
+        envFullURLLabel.setText(envURLTextField.getText().length() > 0 ? 
+                "<html>"+envURLTextField.getText()+".elasticbeanstalk.com" : " "); // NOI18N
+        if (wizardPanel != null) {
+            wizardPanel.fireChange();
+        }
+    }
+
+    private void initContainersModel() {
+        DefaultComboBoxModel model = new DefaultComboBoxModel(new String[]{NbBundle.getMessage(AmazonJ2EEServerWizardComponent.class, "AmazonJ2EEServerWizardComponent.loadingApplications")});
+        final AmazonInstance ai = (AmazonInstance)accountComboBox.getSelectedItem();
+        containerComboBox.setModel(model);
+        AmazonInstance.runAsynchronously(new Callable<Void>() {
+            @Override
+            public Void call() {
+                final List<String> containers = ai.readContainerTypes();
+                SwingUtilities.invokeLater(new Runnable() {
+                    @Override
+                    public void run() {
+                        containerComboBox.setModel(new DefaultComboBoxModel(containers.toArray(new String[containers.size()])));
+                    }
+                });
+                return null;
+            }
+        }, ai);
+    }
+
+    @Override
+    public void insertUpdate(DocumentEvent e) {
+        updateState();
+    }
+
+    @Override
+    public void removeUpdate(DocumentEvent e) {
+        updateState();
+    }
+
+    @Override
+    public void changedUpdate(DocumentEvent e) {
+        updateState();
+    }
+
+    private void updateState() {
+        if (wizardPanel != null) {
+            wizardPanel.fireChange();
+        }
+    }
+
+    public void attachSingleListener(ChangeListener changeListener) {
+        throw new UnsupportedOperationException("Not yet implemented");
+    }
+}
diff --git a/cloud.amazon/src/org/netbeans/modules/cloud/amazon/ui/serverplugin/AmazonJ2EEServerWizardIterator.java b/cloud.amazon/src/org/netbeans/modules/cloud/amazon/ui/serverplugin/AmazonJ2EEServerWizardIterator.java
new file mode 100644
index 0000000000..3fa6f12efe
--- /dev/null
+++ b/cloud.amazon/src/org/netbeans/modules/cloud/amazon/ui/serverplugin/AmazonJ2EEServerWizardIterator.java
@@ -0,0 +1,100 @@
+/*
+ * 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.cloud.amazon.ui.serverplugin;
+
+import java.io.IOException;
+import java.util.Collections;
+import java.util.Set;
+import javax.swing.event.ChangeListener;
+import org.openide.WizardDescriptor;
+import org.openide.WizardDescriptor.Panel;
+import org.openide.util.ChangeSupport;
+
+/**
+ *
+ */
+public class AmazonJ2EEServerWizardIterator implements WizardDescriptor.AsynchronousInstantiatingIterator<WizardDescriptor> {
+
+    private ChangeSupport listeners;
+    private AmazonJ2EEServerWizardPanel panel;
+
+    public AmazonJ2EEServerWizardIterator() {
+        listeners = new ChangeSupport(this);
+    }
+    
+    public static final String PROP_DISPLAY_NAME = "ServInstWizard_displayName"; // NOI18N
+
+    @Override
+    public Set instantiate() throws IOException {
+        return Collections.singleton(panel.createServer());
+    }
+
+    @Override
+    public void initialize(WizardDescriptor wizard) {
+    }
+
+    @Override
+    public void uninitialize(WizardDescriptor wizard) {
+        panel = null;
+    }
+
+    @Override
+    public Panel<WizardDescriptor> current() {
+        if (panel == null) {
+            panel = new AmazonJ2EEServerWizardPanel();
+        }
+        return panel;
+    }
+
+    @Override
+    public String name() {
+        return "Amazon";
+    }
+
+    @Override
+    public boolean hasNext() {
+        return false;
+    }
+
+    @Override
+    public boolean hasPrevious() {
+        return false;
+    }
+
+    @Override
+    public void nextPanel() {
+        throw new UnsupportedOperationException("Not supported yet.");
+    }
+
+    @Override
+    public void previousPanel() {
+        throw new UnsupportedOperationException("Not supported yet.");
+    }
+
+    @Override
+    public void addChangeListener(ChangeListener l) {
+        listeners.addChangeListener(l);
+    }
+
+    @Override
+    public void removeChangeListener(ChangeListener l) {
+        listeners.removeChangeListener(l);
+    }
+    
+}
diff --git a/cloud.amazon/src/org/netbeans/modules/cloud/amazon/ui/serverplugin/AmazonJ2EEServerWizardPanel.java b/cloud.amazon/src/org/netbeans/modules/cloud/amazon/ui/serverplugin/AmazonJ2EEServerWizardPanel.java
new file mode 100644
index 0000000000..ec8355a7c9
--- /dev/null
+++ b/cloud.amazon/src/org/netbeans/modules/cloud/amazon/ui/serverplugin/AmazonJ2EEServerWizardPanel.java
@@ -0,0 +1,195 @@
+/*
+ * 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.cloud.amazon.ui.serverplugin;
+
+import java.awt.Component;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+import javax.swing.event.ChangeListener;
+import org.netbeans.api.server.ServerInstance;
+import org.netbeans.modules.cloud.amazon.AmazonInstance;
+import org.netbeans.modules.cloud.amazon.serverplugin.AmazonJ2EEInstance;
+import org.netbeans.modules.cloud.amazon.serverplugin.AmazonJ2EEServerInstanceProvider;
+import org.netbeans.modules.j2ee.deployment.plugins.api.InstanceProperties;
+import org.openide.WizardDescriptor;
+import org.openide.WizardValidationException;
+import org.openide.util.ChangeSupport;
+import org.openide.util.Exceptions;
+import org.openide.util.HelpCtx;
+import org.openide.util.NbBundle;
+
+/**
+ *
+ */
+public class AmazonJ2EEServerWizardPanel implements WizardDescriptor.AsynchronousValidatingPanel<WizardDescriptor> {
+
+    public static final String KEY_ID = "access-key-id";
+    public static final String KEY = "secret-access-key";
+    
+    private AmazonJ2EEServerWizardComponent component;
+    private WizardDescriptor wd;
+    private ChangeSupport listeners = new ChangeSupport(this);
+    
+    public AmazonJ2EEServerWizardPanel() {
+    }
+    
+    @Override
+    public Component getComponent() {
+        return getComponentImpl();
+    }
+        
+    AmazonJ2EEServerWizardComponent getComponentImpl() {
+        if (component == null) {
+            component = new AmazonJ2EEServerWizardComponent(this, (String)wd.getProperty("suggested-name"), null);
+            component.putClientProperty(WizardDescriptor.PROP_CONTENT_DATA, getPanelContentData());            
+            component.init();
+        }
+        return component;
+    }
+
+    private static String[] getPanelContentData() {
+        return new String[] {
+                NbBundle.getMessage(AmazonJ2EEServerWizardPanel.class, "AmazonJ2EEServerWizardDescriptor.name")
+            };
+    }
+    
+    @Override
+    public HelpCtx getHelp() {
+        return new HelpCtx(AmazonJ2EEServerWizardPanel.class.getName());
+    }
+
+    @Override
+    public void readSettings(WizardDescriptor settings) {
+        this.wd = settings;
+    }
+
+    @Override
+    public void storeSettings(WizardDescriptor settings) {
+    }
+    
+    public void setErrorMessage(String message) {
+        wd.putProperty(WizardDescriptor.PROP_ERROR_MESSAGE, message);
+    }
+    
+    @Override
+    public boolean isValid() {
+        if (!getComponentImpl().hasAccount()) {
+            setErrorMessage(NbBundle.getMessage(AmazonJ2EEServerWizardPanel.class, "AmazonJ2EEServerWizardPanel.missingAccount"));
+            return false;
+        }
+        if (getComponentImpl().getApplicationName().length() == 0) {
+            setErrorMessage(NbBundle.getMessage(AmazonJ2EEServerWizardPanel.class, "AmazonJ2EEServerWizardPanel.missingAppName"));
+            return false;
+        }
+        if (getComponentImpl().getEnvironmentName().length() == 0) {
+            setErrorMessage(NbBundle.getMessage(AmazonJ2EEServerWizardPanel.class, "AmazonJ2EEServerWizardPanel.missingEnvName"));
+            return false;
+        }
+        if (getComponentImpl().getURL().length() == 0) {
+            setErrorMessage(NbBundle.getMessage(AmazonJ2EEServerWizardPanel.class, "AmazonJ2EEServerWizardPanel.missingUrl"));
+            return false;
+        }
+        if (getComponentImpl().getEnvironmentName().length() < 4 || getComponentImpl().getEnvironmentName().length() > 23) {
+            setErrorMessage(NbBundle.getMessage(AmazonJ2EEServerWizardPanel.class, "AmazonJ2EEServerWizardPanel.envNameLength"));
+            return false;
+        }
+        setErrorMessage(null);
+        return true;
+    }
+
+    @Override
+    public void addChangeListener(ChangeListener l) {
+        listeners.addChangeListener(l);
+    }
+
+    @Override
+    public void removeChangeListener(ChangeListener l) {
+        listeners.removeChangeListener(l);
+    }
+    
+    void fireChange() {
+        listeners.fireChange();
+    }
+
+    @Override
+    public void prepareValidation() {
+    }
+
+    @Override
+    public void validate() throws WizardValidationException {
+        String appName = getComponentImpl().getApplicationName();
+        String envName = getComponentImpl().getEnvironmentName();
+        String url = getComponentImpl().getURL();
+        List<AmazonJ2EEInstance> list = getComponentImpl().getAmazonInstance().readJ2EEServerInstances();
+        for (AmazonJ2EEInstance ins : list) {
+            if (ins.getApplicationName().equals(appName) && 
+                ins.getEnvironmentName().equals(envName)) {
+                    throw new WizardValidationException(getComponentImpl(), "app/env already exist", 
+                            NbBundle.getMessage(AmazonJ2EEServerWizardPanel.class, "AmazonJ2EEServerWizardPanel.validation1", 
+                            appName, envName));
+            }
+        }
+        if (!getComponentImpl().getAmazonInstance().checkURLValidity(url)) {
+            throw new WizardValidationException(getComponentImpl(), "url already exist", 
+                    NbBundle.getMessage(AmazonJ2EEServerWizardPanel.class, "AmazonJ2EEServerWizardPanel.validation2", url));
+        }
+    }
+    
+    private boolean isNewApp(AmazonInstance ai, String appName) {
+        return !ai.readApplicationNames().contains(appName);
+    }
+
+    public InstanceProperties createServer() {
+        String envID = createAppEnv();
+        try {
+            AmazonJ2EEServerInstanceProvider.getProvider().refreshServers().get();
+        } catch (InterruptedException ex) {
+            Exceptions.printStackTrace(ex);
+        } catch (ExecutionException ex) {
+            Exceptions.printStackTrace(ex);
+        }
+        return findServer(envID);
+    }
+    
+    private String createAppEnv() {
+        String appName = getComponentImpl().getApplicationName();
+        String envName = getComponentImpl().getEnvironmentName();
+        String url = getComponentImpl().getURL();
+        String containerType = getComponentImpl().getContainerType();
+        String template = getComponentImpl().getTemplateName();
+        AmazonInstance ai = getComponentImpl().getAmazonInstance();
+        
+        boolean newApp = isNewApp(ai, appName);
+        if (newApp) {
+            ai.createApplication(appName);
+            ai.createInitialEmptyApplication(appName);
+        }
+        return ai.createEnvironment(appName, envName, url, containerType, template);
+    }
+    
+    private InstanceProperties findServer(String envID) {
+        String appName = getComponentImpl().getApplicationName();
+        String containerType = getComponentImpl().getContainerType();
+        String uri = AmazonJ2EEInstance.createURL(appName, envID, containerType);
+        InstanceProperties ip = InstanceProperties.getInstanceProperties(uri);
+        assert ip != null : "cannot find instance for " + uri;
+        return ip;
+    }
+
+}
diff --git a/cloud.amazon/src/org/netbeans/modules/cloud/amazon/ui/serverplugin/Bundle.properties b/cloud.amazon/src/org/netbeans/modules/cloud/amazon/ui/serverplugin/Bundle.properties
new file mode 100644
index 0000000000..46e28b7d75
--- /dev/null
+++ b/cloud.amazon/src/org/netbeans/modules/cloud/amazon/ui/serverplugin/Bundle.properties
@@ -0,0 +1,39 @@
+# 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.
+AmazonJ2EEServerWizardComponent.endNameLabel.text=Environment Name:
+AmazonJ2EEServerWizardComponent.envFullURLLabel.text=\ \
+AmazonJ2EEServerWizardComponent.containerLabel.text=Container Type:
+
+AmazonJ2EEServerWizardComponent.name=Create new virtual application or environment
+AmazonJ2EEServerWizardDescriptor.name=Amazon Beanstalk
+AmazonJ2EEServerWizardComponent.appNameLabel.text=Application Name:
+AmazonJ2EEServerWizardComponent.accountLavel.text=Amazon Account:
+AmazonJ2EEServerWizardComponent.envNameTextField.text=
+
+AmazonJ2EEServerWizardPanel.missingAccount=<html>You must first register an Amazon Beanstalk account is the IDE (via Cloud node in Services panel).
+AmazonJ2EEServerWizardPanel.missingAppName=<html>Application Name is required to continue.
+AmazonJ2EEServerWizardPanel.missingEnvName=<html>Environment Name is required to continue.
+AmazonJ2EEServerWizardPanel.missingUrl=<html>Environment URL is required to continue.
+AmazonJ2EEServerWizardPanel.validation1=<html>Environment {0} already exists for application {1}. Choose different names.
+AmazonJ2EEServerWizardPanel.validation2=<html>Hostname {0} is already taken. Choose different one. 
+AmazonJ2EEServerWizardPanel.envNameLength=<html>Environment Name must be from 4 to 23 characters in length.
+
+AmazonJ2EEServerWizardComponent.loadingApplications=Loading...
+AmazonJ2EEServerWizardComponent.enterNewAppName=Application name:
+AmazonJ2EEServerWizardComponent.enterNewAppNameTitle=Create New Application
+AmazonJ2EEServerWizardComponent.envURLLabel.text=Environment URL:
+AmazonJ2EEServerWizardComponent.templateLabel.text=Template
diff --git a/cloud.common/build.xml b/cloud.common/build.xml
new file mode 100644
index 0000000000..f0711271ed
--- /dev/null
+++ b/cloud.common/build.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    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.
+
+-->
+<project basedir="." default="netbeans" name="cloud.common">
+    <description>Builds, tests, and runs the project org.netbeans.modules.cloud.common</description>
+    <import file="../nbbuild/templates/projectized.xml"/>
+</project>
diff --git a/cloud.common/manifest.mf b/cloud.common/manifest.mf
new file mode 100644
index 0000000000..b66d362476
--- /dev/null
+++ b/cloud.common/manifest.mf
@@ -0,0 +1,5 @@
+Manifest-Version: 1.0
+AutoUpdate-Show-In-Client: false
+OpenIDE-Module: org.netbeans.modules.cloud.common
+OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/cloud/common/Bundle.properties
+OpenIDE-Module-Specification-Version: 1.15
diff --git a/cloud.common/nbproject/project.properties b/cloud.common/nbproject/project.properties
new file mode 100644
index 0000000000..c0af75f0c2
--- /dev/null
+++ b/cloud.common/nbproject/project.properties
@@ -0,0 +1,18 @@
+# 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.
+javac.source=1.6
+javac.compilerargs=-Xlint -Xlint:-serial
diff --git a/cloud.common/nbproject/project.xml b/cloud.common/nbproject/project.xml
new file mode 100644
index 0000000000..4fa58f7afc
--- /dev/null
+++ b/cloud.common/nbproject/project.xml
@@ -0,0 +1,155 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    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.
+
+-->
+<project xmlns="http://www.netbeans.org/ns/project/1">
+    <type>org.netbeans.modules.apisupport.project</type>
+    <configuration>
+        <data xmlns="http://www.netbeans.org/ns/nb-module-project/3">
+            <code-name-base>org.netbeans.modules.cloud.common</code-name-base>
+            <module-dependencies>
+                <dependency>
+                    <code-name-base>org.netbeans.modules.j2ee.core</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>0</release-version>
+                        <specification-version>1.9</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.modules.j2eeapis</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>1</release-version>
+                        <specification-version>1.20</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.modules.j2eeserver</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>4</release-version>
+                        <specification-version>1.82</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.modules.java.platform</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>1</release-version>
+                        <specification-version>1.22</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.modules.keyring</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.7</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.modules.project.libraries</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>1</release-version>
+                        <specification-version>1.49</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.modules.server</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>0</release-version>
+                        <specification-version>1.14</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.awt</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>7.35</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.dialogs</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>7.21</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.filesystems</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>9.0</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.nodes</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>7.23</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.util.ui</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>9.3</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.util</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>9.3</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.9</specification-version>
+                    </run-dependency>
+                </dependency>
+            </module-dependencies>
+            <friend-packages>
+                <friend>org.netbeans.modules.cloud.amazon</friend>
+                <friend>org.netbeans.modules.cloud.oracle</friend>
+                <package>org.netbeans.modules.cloud.common.spi.support.serverplugin</package>
+                <package>org.netbeans.modules.cloud.common.spi.support.ui</package>
+            </friend-packages>
+        </data>
+    </configuration>
+</project>
diff --git a/cloud.common/src/org/netbeans/modules/cloud/common/Bundle.properties b/cloud.common/src/org/netbeans/modules/cloud/common/Bundle.properties
new file mode 100644
index 0000000000..89572e616b
--- /dev/null
+++ b/cloud.common/src/org/netbeans/modules/cloud/common/Bundle.properties
@@ -0,0 +1,17 @@
+# 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.
+OpenIDE-Module-Name=Cloud Common
diff --git a/cloud.common/src/org/netbeans/modules/cloud/common/spi/support/serverplugin/DeploymentStatus.java b/cloud.common/src/org/netbeans/modules/cloud/common/spi/support/serverplugin/DeploymentStatus.java
new file mode 100644
index 0000000000..ad53a672ff
--- /dev/null
+++ b/cloud.common/src/org/netbeans/modules/cloud/common/spi/support/serverplugin/DeploymentStatus.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.cloud.common.spi.support.serverplugin;
+
+/**
+ *
+ */
+public enum DeploymentStatus {
+    SUCCESS,
+    FAILED,
+    UNKNOWN,
+    EXCEPTION
+}
diff --git a/cloud.common/src/org/netbeans/modules/cloud/common/spi/support/serverplugin/DeploymentStatusImpl.java b/cloud.common/src/org/netbeans/modules/cloud/common/spi/support/serverplugin/DeploymentStatusImpl.java
new file mode 100644
index 0000000000..22f764a77b
--- /dev/null
+++ b/cloud.common/src/org/netbeans/modules/cloud/common/spi/support/serverplugin/DeploymentStatusImpl.java
@@ -0,0 +1,83 @@
+/*
+ * 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.cloud.common.spi.support.serverplugin;
+
+import javax.enterprise.deploy.shared.ActionType;
+import javax.enterprise.deploy.shared.CommandType;
+import javax.enterprise.deploy.shared.StateType;
+import javax.enterprise.deploy.spi.status.DeploymentStatus;
+
+/**
+ *
+ */
+public class DeploymentStatusImpl implements DeploymentStatus {
+
+    private CommandType command;
+    private StateType state;
+    private ActionType action;
+    private String message;
+
+    public DeploymentStatusImpl(CommandType command, StateType state, ActionType action, String message) {
+        this.command = command;
+        this.state = state;
+        this.action = action;
+        this.message = message;
+    }
+    
+    @Override
+    public StateType getState() {
+        return state;
+    }
+
+    @Override
+    public CommandType getCommand() {
+        return command;
+    }
+
+    @Override
+    public ActionType getAction() {
+        return action;
+    }
+
+    @Override
+    public String getMessage() {
+        return message;
+    }
+
+    @Override
+    public boolean isCompleted() {
+        return StateType.COMPLETED.equals(state);
+    }
+
+    @Override
+    public boolean isFailed() {
+        return StateType.FAILED.equals(state);
+    }
+
+    @Override
+    public boolean isRunning() {
+        return StateType.RUNNING.equals(state);
+    }
+
+    @Override
+    public String toString() {
+        return "DeploymentStatusImpl{" + "command=" + command + ", state=" + state + ", action=" + action + ", message=" + message + '}';
+    }
+    
+}
diff --git a/cloud.common/src/org/netbeans/modules/cloud/common/spi/support/serverplugin/InstanceState.java b/cloud.common/src/org/netbeans/modules/cloud/common/spi/support/serverplugin/InstanceState.java
new file mode 100644
index 0000000000..beff5591e0
--- /dev/null
+++ b/cloud.common/src/org/netbeans/modules/cloud/common/spi/support/serverplugin/InstanceState.java
@@ -0,0 +1,31 @@
+/*
+ * 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.cloud.common.spi.support.serverplugin;
+
+/**
+ *
+ */
+public enum InstanceState {
+    LAUNCHING,
+    UPDATING,
+    READY,
+    TERMINATING,
+    TERMINATED
+}
+
diff --git a/cloud.common/src/org/netbeans/modules/cloud/common/spi/support/serverplugin/ModuleConfigurationFactoryImpl.java b/cloud.common/src/org/netbeans/modules/cloud/common/spi/support/serverplugin/ModuleConfigurationFactoryImpl.java
new file mode 100644
index 0000000000..efa54be2b7
--- /dev/null
+++ b/cloud.common/src/org/netbeans/modules/cloud/common/spi/support/serverplugin/ModuleConfigurationFactoryImpl.java
@@ -0,0 +1,44 @@
+/*
+ * 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.cloud.common.spi.support.serverplugin;
+
+import org.netbeans.modules.j2ee.deployment.common.api.ConfigurationException;
+import org.netbeans.modules.j2ee.deployment.devmodules.api.J2eeModule;
+import org.netbeans.modules.j2ee.deployment.plugins.spi.config.ModuleConfiguration;
+import org.netbeans.modules.j2ee.deployment.plugins.spi.config.ModuleConfigurationFactory2;
+
+/**
+ *
+ */
+public class ModuleConfigurationFactoryImpl implements ModuleConfigurationFactory2 {
+
+    public ModuleConfigurationFactoryImpl() {
+    }
+    
+    @Override
+    public ModuleConfiguration create(J2eeModule j2eeModule, String instanceUrl) throws ConfigurationException {
+        return new ModuleConfigurationImpl(j2eeModule);
+    }
+
+    @Override
+    public ModuleConfiguration create(J2eeModule j2eeModule) throws ConfigurationException {
+        return new ModuleConfigurationImpl(j2eeModule);
+    }
+    
+}
diff --git a/cloud.common/src/org/netbeans/modules/cloud/common/spi/support/serverplugin/ModuleConfigurationImpl.java b/cloud.common/src/org/netbeans/modules/cloud/common/spi/support/serverplugin/ModuleConfigurationImpl.java
new file mode 100644
index 0000000000..d34958e88b
--- /dev/null
+++ b/cloud.common/src/org/netbeans/modules/cloud/common/spi/support/serverplugin/ModuleConfigurationImpl.java
@@ -0,0 +1,50 @@
+/*
+ * 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.cloud.common.spi.support.serverplugin;
+
+import org.netbeans.modules.j2ee.deployment.devmodules.api.J2eeModule;
+import org.netbeans.modules.j2ee.deployment.plugins.spi.config.ModuleConfiguration;
+import org.openide.util.Lookup;
+
+/**
+ *
+ */
+public class ModuleConfigurationImpl implements ModuleConfiguration {
+
+    private J2eeModule module;
+
+    public ModuleConfigurationImpl(J2eeModule module) {
+        this.module = module;
+    }
+    
+    @Override
+    public Lookup getLookup() {
+        return  Lookup.EMPTY;
+    }
+
+    @Override
+    public J2eeModule getJ2eeModule() {
+        return module;
+    }
+
+    @Override
+    public void dispose() {
+    }
+    
+}
diff --git a/cloud.common/src/org/netbeans/modules/cloud/common/spi/support/serverplugin/ProgressObjectImpl.java b/cloud.common/src/org/netbeans/modules/cloud/common/spi/support/serverplugin/ProgressObjectImpl.java
new file mode 100644
index 0000000000..854cb859dd
--- /dev/null
+++ b/cloud.common/src/org/netbeans/modules/cloud/common/spi/support/serverplugin/ProgressObjectImpl.java
@@ -0,0 +1,189 @@
+/*
+ * 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.cloud.common.spi.support.serverplugin;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.enterprise.deploy.shared.ActionType;
+import javax.enterprise.deploy.shared.CommandType;
+import javax.enterprise.deploy.shared.StateType;
+import javax.enterprise.deploy.spi.Target;
+import javax.enterprise.deploy.spi.TargetModuleID;
+import javax.enterprise.deploy.spi.exceptions.OperationUnsupportedException;
+import javax.enterprise.deploy.spi.status.ClientConfiguration;
+import javax.enterprise.deploy.spi.status.DeploymentStatus;
+import javax.enterprise.deploy.spi.status.ProgressEvent;
+import javax.enterprise.deploy.spi.status.ProgressListener;
+import javax.enterprise.deploy.spi.status.ProgressObject;
+import javax.swing.SwingUtilities;
+
+/**
+ *
+ */
+public class ProgressObjectImpl implements ProgressObject {
+
+    private DeploymentStatusImpl status;
+    
+    private static final Logger LOG = Logger.getLogger(ProgressObjectImpl.class.getSimpleName());
+    
+    private final List<ProgressListener> listeners = new CopyOnWriteArrayList<ProgressListener>();
+    
+    private String url;
+    
+    public ProgressObjectImpl(String message, boolean completed) {
+        setStatus(new DeploymentStatusImpl(
+            CommandType.DISTRIBUTE, completed ? StateType.COMPLETED : StateType.RUNNING, ActionType.EXECUTE, message));
+    }
+    
+    @Override
+    public synchronized DeploymentStatus getDeploymentStatus() {
+        return status;
+    }
+
+    private synchronized void setStatus(DeploymentStatusImpl status) {
+        this.status = status;
+        LOG.log(Level.INFO, "status: {0}", status);
+    }
+    
+    @Override
+    public TargetModuleID[] getResultTargetModuleIDs() {
+        return new TargetModuleID[]{new TargetModuleIDImpl(url, "some-id", TargetImpl.SOME,
+                // this is hack: when EAR is deployed Deployment API asks EAR's child module for URL:
+                new TargetModuleIDImpl(url, "some-id-child", TargetImpl.SOME, null))};
+    }
+
+    @Override
+    public ClientConfiguration getClientConfiguration(TargetModuleID tmid) {
+        throw new UnsupportedOperationException("Not supported yet.");
+    }
+
+    @Override
+    public boolean isCancelSupported() {
+        return false;
+    }
+
+    @Override
+    public void cancel() throws OperationUnsupportedException {
+        throw new UnsupportedOperationException("Not supported yet.");
+    }
+
+    @Override
+    public boolean isStopSupported() {
+        return false;
+    }
+
+    @Override
+    public void stop() throws OperationUnsupportedException {
+        throw new UnsupportedOperationException("Not supported yet.");
+    }
+
+    @Override
+    public void addProgressListener(ProgressListener pl) {
+        listeners.add(pl);
+    }
+
+    @Override
+    public void removeProgressListener(ProgressListener pl) {
+        listeners.remove(pl);
+    }
+
+    public void updateDepoymentStage(String message) {
+        DeploymentStatusImpl st = new DeploymentStatusImpl(
+            CommandType.DISTRIBUTE, StateType.RUNNING, ActionType.EXECUTE, message);
+        setStatus(st);
+        fireChange(st);
+    }
+    
+    public void updateDepoymentResult(org.netbeans.modules.cloud.common.spi.support.serverplugin.DeploymentStatus result, String url) {
+        StateType st = StateType.FAILED;
+        if (result == org.netbeans.modules.cloud.common.spi.support.serverplugin.DeploymentStatus.SUCCESS) {
+            st = StateType.COMPLETED;
+            this.url = url;
+        } else if (result == org.netbeans.modules.cloud.common.spi.support.serverplugin.DeploymentStatus.FAILED ||
+                result == org.netbeans.modules.cloud.common.spi.support.serverplugin.DeploymentStatus.EXCEPTION ||
+                result == org.netbeans.modules.cloud.common.spi.support.serverplugin.DeploymentStatus.UNKNOWN) {
+            st = StateType.FAILED;
+        }
+        DeploymentStatusImpl st2 = new DeploymentStatusImpl(
+            CommandType.DISTRIBUTE, st, ActionType.EXECUTE, "Deployment finished.");
+        setStatus(st2);
+        fireChange(st2);
+    }
+    
+    private void fireChange(final DeploymentStatusImpl st) {
+        final List<ProgressListener> ls = new ArrayList<ProgressListener>(listeners);
+        SwingUtilities.invokeLater(new Runnable() {
+            @Override
+            public void run() {
+                for (ProgressListener listener : ls) {
+                    listener.handleProgressEvent(new ProgressEvent(this, null, st));
+                }
+            }
+        });
+    }
+    
+    private static class TargetModuleIDImpl implements TargetModuleID {
+
+        private String url;
+        private String id;
+        private Target target;
+        private TargetModuleID child;
+
+        public TargetModuleIDImpl(String url, String id, Target target, TargetModuleID child) {
+            this.url = url;
+            this.id = id;
+            this.target = target;
+            this.child = child;
+        }
+        
+        @Override
+        public Target getTarget() {
+            return target;
+        }
+
+        @Override
+        public String getModuleID() {
+            return id;
+        }
+
+        @Override
+        public String getWebURL() {
+            return url;
+        }
+
+        @Override
+        public TargetModuleID getParentTargetModuleID() {
+            return null;
+        }
+
+        @Override
+        public TargetModuleID[] getChildTargetModuleID() {
+            if (child == null) {
+                return null;
+            } else {
+                return new TargetModuleID[]{child};
+            }
+        }
+        
+    }
+    
+}
diff --git a/cloud.common/src/org/netbeans/modules/cloud/common/spi/support/serverplugin/RegistryNodeFactoryImpl.java b/cloud.common/src/org/netbeans/modules/cloud/common/spi/support/serverplugin/RegistryNodeFactoryImpl.java
new file mode 100644
index 0000000000..0e74b0a04c
--- /dev/null
+++ b/cloud.common/src/org/netbeans/modules/cloud/common/spi/support/serverplugin/RegistryNodeFactoryImpl.java
@@ -0,0 +1,46 @@
+/*
+ * 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.cloud.common.spi.support.serverplugin;
+
+import org.netbeans.modules.j2ee.deployment.plugins.spi.RegistryNodeFactory;
+import org.openide.nodes.AbstractNode;
+import org.openide.nodes.Children;
+import org.openide.nodes.Node;
+import org.openide.util.Lookup;
+
+/**
+ *
+ */
+public class RegistryNodeFactoryImpl implements RegistryNodeFactory {
+
+    @Override
+    public Node getManagerNode(Lookup lookup) {
+        AbstractNode an = new AbstractNode(Children.LEAF);
+        an.setName("manager node");
+        return an;
+    }
+
+    @Override
+    public Node getTargetNode(Lookup lookup) {
+        AbstractNode an = new AbstractNode(Children.LEAF);
+        an.setName("target node");
+        return an;
+    }
+    
+}
diff --git a/cloud.common/src/org/netbeans/modules/cloud/common/spi/support/serverplugin/TargetImpl.java b/cloud.common/src/org/netbeans/modules/cloud/common/spi/support/serverplugin/TargetImpl.java
new file mode 100644
index 0000000000..a313c51461
--- /dev/null
+++ b/cloud.common/src/org/netbeans/modules/cloud/common/spi/support/serverplugin/TargetImpl.java
@@ -0,0 +1,51 @@
+/*
+ * 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.cloud.common.spi.support.serverplugin;
+
+import javax.enterprise.deploy.spi.Target;
+
+/**
+ *
+ */
+public class TargetImpl implements Target {
+
+    private String name;
+
+    public static final Target SOME = new TargetImpl("some-target");
+    
+    private TargetImpl(String name) {
+        this.name = name;
+    }
+    
+    @Override
+    public String getName() {
+        return name;
+    }
+
+    @Override
+    public String getDescription() {
+        return "target-description";
+    }
+
+    @Override
+    public String toString() {
+        return "cloud-deployment"; // XXX these seems to be printed into output window during build
+    }
+    
+}
diff --git a/cloud.common/src/org/netbeans/modules/cloud/common/spi/support/ui/Bundle.properties b/cloud.common/src/org/netbeans/modules/cloud/common/spi/support/ui/Bundle.properties
new file mode 100644
index 0000000000..6297f3c8fe
--- /dev/null
+++ b/cloud.common/src/org/netbeans/modules/cloud/common/spi/support/ui/Bundle.properties
@@ -0,0 +1,20 @@
+# 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.
+
+CloudResourcesWizardComponent.jLabel1.text=<html>These resources were discovered in the cloud and are automatically available in the IDE:
+CloudResourcesWizardComponent.none=None available yet
+LBL_Name2=Available Cloud Resources
\ No newline at end of file
diff --git a/cloud.common/src/org/netbeans/modules/cloud/common/spi/support/ui/CloudResourcesWizardComponent.form b/cloud.common/src/org/netbeans/modules/cloud/common/spi/support/ui/CloudResourcesWizardComponent.form
new file mode 100644
index 0000000000..22b695a2e2
--- /dev/null
+++ b/cloud.common/src/org/netbeans/modules/cloud/common/spi/support/ui/CloudResourcesWizardComponent.form
@@ -0,0 +1,56 @@
+<?xml version="1.1" encoding="UTF-8" ?>
+
+<Form version="1.5" maxVersion="1.7" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
+  <AuxValues>
+    <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
+    <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
+    <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
+    <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
+    <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
+    <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
+    <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
+    <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
+    <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
+  </AuxValues>
+
+  <Layout>
+    <DimensionLayout dim="0">
+      <Group type="103" groupAlignment="0" attributes="0">
+          <Component id="jLabel1" alignment="0" pref="349" max="32767" attributes="2"/>
+          <Component id="jScrollPane1" alignment="0" pref="349" max="32767" attributes="2"/>
+      </Group>
+    </DimensionLayout>
+    <DimensionLayout dim="1">
+      <Group type="103" groupAlignment="0" attributes="0">
+          <Group type="102" alignment="0" attributes="0">
+              <Component id="jLabel1" min="-2" max="-2" attributes="0"/>
+              <EmptySpace max="-2" attributes="0"/>
+              <Component id="jScrollPane1" pref="227" max="32767" attributes="0"/>
+          </Group>
+      </Group>
+    </DimensionLayout>
+  </Layout>
+  <SubComponents>
+    <Component class="javax.swing.JLabel" name="jLabel1">
+      <Properties>
+        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+          <ResourceString bundle="org/netbeans/modules/cloud/common/spi/support/ui/Bundle.properties" key="CloudResourcesWizardComponent.jLabel1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+        </Property>
+      </Properties>
+    </Component>
+    <Container class="javax.swing.JScrollPane" name="jScrollPane1">
+      <AuxValues>
+        <AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
+      </AuxValues>
+
+      <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
+      <SubComponents>
+        <Component class="javax.swing.JTable" name="jTable">
+          <Properties>
+            <Property name="autoResizeMode" type="int" value="3"/>
+          </Properties>
+        </Component>
+      </SubComponents>
+    </Container>
+  </SubComponents>
+</Form>
diff --git a/cloud.common/src/org/netbeans/modules/cloud/common/spi/support/ui/CloudResourcesWizardComponent.java b/cloud.common/src/org/netbeans/modules/cloud/common/spi/support/ui/CloudResourcesWizardComponent.java
new file mode 100644
index 0000000000..ea95145b19
--- /dev/null
+++ b/cloud.common/src/org/netbeans/modules/cloud/common/spi/support/ui/CloudResourcesWizardComponent.java
@@ -0,0 +1,165 @@
+/*
+ * 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.cloud.common.spi.support.ui;
+
+import java.awt.Component;
+import java.util.ArrayList;
+import java.util.List;
+import javax.swing.JLabel;
+import javax.swing.JTable;
+import javax.swing.SwingConstants;
+import javax.swing.event.TableModelListener;
+import javax.swing.table.TableCellRenderer;
+import javax.swing.table.TableModel;
+import org.openide.util.NbBundle;
+
+/**
+ *
+ */
+public class CloudResourcesWizardComponent extends javax.swing.JPanel {
+
+    
+    /** Creates new form CloudResourcesWizardComponent */
+    public CloudResourcesWizardComponent(List<ServerResourceDescriptor> resources) {
+        initComponents();
+        setName(NbBundle.getBundle(CloudResourcesWizardComponent.class).getString("LBL_Name2")); // NOI18N
+        setResources(resources);
+    }
+
+    private void setResources(List<ServerResourceDescriptor> resources) {
+        ResourceModel m = new ResourceModel(resources);
+        jTable.setModel(m);
+        jTable.getColumnModel().getColumn(1).setCellRenderer(new TableCellRenderer() {
+            @Override
+            public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
+                if (value instanceof JLabel) {
+                    return (JLabel)value;
+                } else {
+                    return null;
+                }
+            }
+        });
+        jTable.getColumnModel().getColumn(0).setWidth(30);
+        jTable.getColumnModel().getColumn(1).setWidth(130);
+    }
+    
+    private static class ResourceModel implements TableModel {
+
+        private List<ServerResourceDescriptor> resources;
+
+        public ResourceModel(List<ServerResourceDescriptor> resources) {
+            this.resources = new ArrayList(resources);
+            if (this.resources.isEmpty()) {
+                this.resources.add(new ServerResourceDescriptor("", "none available yet", "", null));
+            }
+        }
+        
+        @Override
+        public int getRowCount() {
+            return resources.size();
+        }
+
+        @Override
+        public int getColumnCount() {
+            return 2;
+        }
+
+        private String[] header = new String[]{"Type", "Name"};
+        private Class[] headerClass = new Class[]{String.class, JLabel.class};
+        
+        @Override
+        public String getColumnName(int columnIndex) {
+            return header[columnIndex];
+        }
+
+        @Override
+        public Class<?> getColumnClass(int columnIndex) {
+            return headerClass[columnIndex];
+        }
+
+        @Override
+        public boolean isCellEditable(int rowIndex, int columnIndex) {
+            return false;
+        }
+
+        @Override
+        public Object getValueAt(int rowIndex, int columnIndex) {
+            ServerResourceDescriptor srd = resources.get(rowIndex);
+            if (columnIndex == 0) {
+                return srd.getType();
+            } else {
+                return new JLabel(srd.getName(), srd.getIcon(), SwingConstants.LEADING);
+            }
+        }
+
+        @Override
+        public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
+            throw new UnsupportedOperationException("Not supported yet.");
+        }
+
+        @Override
+        public void addTableModelListener(TableModelListener l) {
+        }
+
+        @Override
+        public void removeTableModelListener(TableModelListener l) {
+        }
+        
+    }
+
+    /** This method is called from within the constructor to
+     * initialize the form.
+     * WARNING: Do NOT modify this code. The content of this method is
+     * always regenerated by the Form Editor.
+     */
+    @SuppressWarnings("unchecked")
+    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
+    private void initComponents() {
+
+        jLabel1 = new javax.swing.JLabel();
+        jScrollPane1 = new javax.swing.JScrollPane();
+        jTable = new javax.swing.JTable();
+
+        jLabel1.setText(org.openide.util.NbBundle.getMessage(CloudResourcesWizardComponent.class, "CloudResourcesWizardComponent.jLabel1.text")); // NOI18N
+
+        jTable.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_LAST_COLUMN);
+        jScrollPane1.setViewportView(jTable);
+
+        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
+        this.setLayout(layout);
+        layout.setHorizontalGroup(
+            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addComponent(jLabel1, javax.swing.GroupLayout.DEFAULT_SIZE, 349, Short.MAX_VALUE)
+            .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 349, Short.MAX_VALUE)
+        );
+        layout.setVerticalGroup(
+            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addGroup(layout.createSequentialGroup()
+                .addComponent(jLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 227, Short.MAX_VALUE))
+        );
+    }// </editor-fold>//GEN-END:initComponents
+    // Variables declaration - do not modify//GEN-BEGIN:variables
+    private javax.swing.JLabel jLabel1;
+    private javax.swing.JScrollPane jScrollPane1;
+    private javax.swing.JTable jTable;
+    // End of variables declaration//GEN-END:variables
+}
diff --git a/cloud.common/src/org/netbeans/modules/cloud/common/spi/support/ui/CloudResourcesWizardPanel.java b/cloud.common/src/org/netbeans/modules/cloud/common/spi/support/ui/CloudResourcesWizardPanel.java
new file mode 100644
index 0000000000..0b1d177ef8
--- /dev/null
+++ b/cloud.common/src/org/netbeans/modules/cloud/common/spi/support/ui/CloudResourcesWizardPanel.java
@@ -0,0 +1,85 @@
+/*
+ * 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.cloud.common.spi.support.ui;
+
+import java.awt.Component;
+import java.util.List;
+import javax.swing.event.ChangeListener;
+import org.openide.WizardDescriptor;
+import org.openide.util.HelpCtx;
+
+/**
+ *
+ */
+public class CloudResourcesWizardPanel implements WizardDescriptor.Panel<WizardDescriptor> {
+
+    private CloudResourcesWizardComponent component;
+    private List<ServerResourceDescriptor> resources;
+    
+    public static final String PROP_SERVER_RESOURCES = "server-resources";
+    
+    private final String[] names;
+    
+    private final int step;
+	
+    public CloudResourcesWizardPanel(String[] names, int step) {
+        this.names = names.clone();
+        this.step = step;
+    }
+    
+    @Override
+    public Component getComponent() {
+        if (component == null) {
+            component = new CloudResourcesWizardComponent(resources);
+            component.putClientProperty(WizardDescriptor.PROP_CONTENT_DATA, names);
+            component.putClientProperty(WizardDescriptor.PROP_CONTENT_SELECTED_INDEX, Integer.valueOf(step));
+        }
+        return component;
+    }
+    
+    @Override
+    public HelpCtx getHelp() {
+        return null;
+    }
+
+    @Override
+    public void readSettings(WizardDescriptor settings) {
+        resources = (List<ServerResourceDescriptor>)settings.getProperty(PROP_SERVER_RESOURCES);
+        assert resources != null;
+        settings.getProperty(WizardDescriptor.PROP_CONTENT_DATA);
+    }
+
+    @Override
+    public void storeSettings(WizardDescriptor settings) {
+    }
+
+    @Override
+    public boolean isValid() {
+        return true;
+    }
+
+    @Override
+    public void addChangeListener(ChangeListener l) {
+    }
+
+    @Override
+    public void removeChangeListener(ChangeListener l) {
+    }
+
+}
diff --git a/cloud.common/src/org/netbeans/modules/cloud/common/spi/support/ui/ServerResourceDescriptor.java b/cloud.common/src/org/netbeans/modules/cloud/common/spi/support/ui/ServerResourceDescriptor.java
new file mode 100644
index 0000000000..09b9f800c8
--- /dev/null
+++ b/cloud.common/src/org/netbeans/modules/cloud/common/spi/support/ui/ServerResourceDescriptor.java
@@ -0,0 +1,59 @@
+/*
+ * 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.cloud.common.spi.support.ui;
+
+import javax.swing.Icon;
+
+/**
+ *
+ */
+public final class ServerResourceDescriptor {
+    
+    private String type; // server, database, etc.
+
+    private String name; // "Weblogic X, MySQL Y"
+    
+    private String desc; // not used right now
+    
+    private Icon icon; // optional
+
+    public ServerResourceDescriptor(String type, String name, String desc, Icon icon) {
+        this.type = type;
+        this.name = name;
+        this.desc = desc;
+        this.icon = icon;
+    }
+
+    public String getDesc() {
+        return desc;
+    }
+
+    public Icon getIcon() {
+        return icon;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public String getType() {
+        return type;
+    }
+    
+}
diff --git a/cordova.platforms.android/build.xml b/cordova.platforms.android/build.xml
new file mode 100644
index 0000000000..fc2b773ac7
--- /dev/null
+++ b/cordova.platforms.android/build.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    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.
+
+-->
+<project basedir="." default="netbeans" name="cordova.platforms.android">
+    <description>Builds, tests, and runs the project org.netbeans.modules.cordova.platforms.android</description>
+    <import file="../nbbuild/templates/projectized.xml"/>
+</project>
diff --git a/cordova.platforms.android/manifest.mf b/cordova.platforms.android/manifest.mf
new file mode 100644
index 0000000000..75b4e5f249
--- /dev/null
+++ b/cordova.platforms.android/manifest.mf
@@ -0,0 +1,6 @@
+Manifest-Version: 1.0
+AutoUpdate-Show-In-Client: false
+OpenIDE-Module: org.netbeans.modules.cordova.platforms.android
+OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/cordova/platforms/android/Bundle.properties
+OpenIDE-Module-Specification-Version: 1.29
+
diff --git a/cordova.platforms.android/nbproject/project.properties b/cordova.platforms.android/nbproject/project.properties
new file mode 100644
index 0000000000..ab06b416c0
--- /dev/null
+++ b/cordova.platforms.android/nbproject/project.properties
@@ -0,0 +1,18 @@
+# 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.
+javac.source=1.7
+javac.compilerargs=-Xlint -Xlint:-serial
diff --git a/cordova.platforms.android/nbproject/project.xml b/cordova.platforms.android/nbproject/project.xml
new file mode 100644
index 0000000000..adbdbcc4f5
--- /dev/null
+++ b/cordova.platforms.android/nbproject/project.xml
@@ -0,0 +1,198 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    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.
+
+-->
+<project xmlns="http://www.netbeans.org/ns/project/1">
+    <type>org.netbeans.modules.apisupport.project</type>
+    <configuration>
+        <data xmlns="http://www.netbeans.org/ns/nb-module-project/3">
+            <code-name-base>org.netbeans.modules.cordova.platforms.android</code-name-base>
+            <module-dependencies>
+                <dependency>
+                    <code-name-base>org.apache.tools.ant.module</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>3</release-version>
+                        <specification-version>3.60</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.api.progress</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>1</release-version>
+                        <specification-version>1.40</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.api.progress.nb</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.40</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.libs.json_simple</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>1</release-version>
+                        <specification-version>0.3</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.modules.cordova.platforms</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.31</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.modules.netserver</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.2</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.modules.options.api</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>1</release-version>
+                        <specification-version>1.30</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.modules.projectapi</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>1</release-version>
+                        <specification-version>1.49</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.modules.projectuiapi</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>1</release-version>
+                        <specification-version>1.79</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.modules.web.browser.api</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.30</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.modules.web.clientproject.api</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.40</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.modules.web.webkit.debugging</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.2</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.awt</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>7.54</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.dialogs</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>7.27</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.execution</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>9.0</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.filesystems</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>9.0</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.util.ui</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>9.3</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.util</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>9.3</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.18</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.windows</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>6.60</specification-version>
+                    </run-dependency>
+                </dependency>
+            </module-dependencies>
+            <public-packages/>
+        </data>
+    </configuration>
+</project>
diff --git a/cordova.platforms.android/src/org/netbeans/modules/cordova/platforms/android/AVD.java b/cordova.platforms.android/src/org/netbeans/modules/cordova/platforms/android/AVD.java
new file mode 100644
index 0000000000..bca36ba16d
--- /dev/null
+++ b/cordova.platforms.android/src/org/netbeans/modules/cordova/platforms/android/AVD.java
@@ -0,0 +1,155 @@
+/*
+ * 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.cordova.platforms.android;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Properties;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import org.netbeans.api.project.Project;
+import org.netbeans.modules.cordova.platforms.spi.Device;
+import org.netbeans.modules.cordova.platforms.spi.MobileDebugTransport;
+import org.netbeans.modules.cordova.platforms.spi.MobilePlatform;
+import org.netbeans.modules.cordova.platforms.api.PlatformManager;
+import org.netbeans.modules.cordova.platforms.api.ProcessUtilities;
+import org.netbeans.modules.cordova.platforms.spi.PropertyProvider;
+import org.netbeans.modules.web.clientproject.spi.platform.ProjectConfigurationCustomizer;
+import org.netbeans.spi.project.ActionProvider;
+import org.openide.util.Exceptions;
+
+/**
+ *
+ * @author Jan Becicka
+ */
+public class AVD implements Device {
+
+    private String name;
+    private HashMap<String, String> props;
+
+    private AVD() {
+        this.props = new HashMap();
+    }
+    
+    public static Collection<Device> parse(String output) throws IOException {
+        BufferedReader r = new BufferedReader(new StringReader(output));
+        
+        Pattern pattern = Pattern.compile(" *([\\w]*): (.*)"); //NOI18N
+        
+        ArrayList<Device> result = new ArrayList<Device>();
+        //ignore first line
+        String line = r.readLine();
+        
+        line = r.readLine();
+        
+        AVD current = new AVD();
+        String lastProp = null;
+        while (line != null) {
+            Matcher m = pattern.matcher(line);
+            if (m.matches()) {
+                if ("Name".equals(m.group(1))) { //NOI18N
+                    current.name = m.group(2);
+                } else {
+                    current.props.put(m.group(1), m.group(2));
+                    lastProp = m.group(1);
+                }
+            } else {
+                if (line.contains("---------")) { //NOI18N
+                    result.add(current);
+                    current = new AVD();
+                } else {
+                    current.props.put(lastProp, current.props.get(lastProp) + line);
+                }
+            }
+            line = r.readLine();
+            if (line == null && current.name != null) {
+                result.add(current);
+            }
+        }
+        return result;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    @Override
+    public String toString() {
+        return "AVD{" + "name=" + name + ", props=" + props + '}'; //NOI18N
+    }
+
+    @Override
+    public boolean isEmulator() {
+        return true;
+    }
+
+    @Override
+    public MobilePlatform getPlatform() {
+        return AndroidPlatform.getDefault();
+    }
+
+    @Override
+    public void addProperties(Properties props) {
+        final MobilePlatform android = getPlatform();
+        props.put("android.build.target", android.getPrefferedTarget().getName());//NOI18N
+        props.put("android.sdk.home", android.getSdkLocation());//NOI18N
+        props.put("android.target.device.arg", isEmulator() ? "emulate" : "run");//NOI18N
+    }
+
+    @Override
+    public ActionProvider getActionProvider(Project p) {
+        return new AndroidActionProvider(p);
+    }
+
+    @Override
+    public ProjectConfigurationCustomizer getProjectConfigurationCustomizer(Project project, PropertyProvider aThis) {
+        return new AndroidConfigurationPanel.AndroidConfigurationCustomizer(project, aThis);
+    }
+    
+    @Override
+    public void openUrl(String url) {
+        try {
+            String s = ProcessUtilities.callProcess(
+                    ((AndroidPlatform) getPlatform()).getAdbCommand(), 
+                    false, 
+                    AndroidPlatform.DEFAULT_TIMEOUT, 
+                    isEmulator()?"-d":"-e", // NOI18N
+                    "wait-for-device", // NOI18N
+                    "shell", "am", "start", "-a", "android.intent.action.VIEW", // NOI18N
+                    "-n", "com.android.browser/.BrowserActivity", url); //NOI18N
+        } catch (IOException ex) {
+            Exceptions.printStackTrace(ex);
+        }
+    }
+    
+    @Override
+    public MobileDebugTransport getDebugTransport() {
+        return new AndroidDebugTransport();
+    }
+
+    @Override
+    public boolean isWebViewDebugSupported() {
+        return AndroidPlatform.getDefault().isWebViewDebugSupported(isEmulator());
+    }
+
+}
diff --git a/cordova.platforms.android/src/org/netbeans/modules/cordova/platforms/android/AndroidActionProvider.java b/cordova.platforms.android/src/org/netbeans/modules/cordova/platforms/android/AndroidActionProvider.java
new file mode 100644
index 0000000000..23dc53ed3d
--- /dev/null
+++ b/cordova.platforms.android/src/org/netbeans/modules/cordova/platforms/android/AndroidActionProvider.java
@@ -0,0 +1,260 @@
+/*
+ * 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.cordova.platforms.android;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.logging.Logger;
+import javax.swing.SwingUtilities;
+import org.netbeans.api.options.OptionsDisplayer;
+import org.netbeans.api.progress.ProgressUtils;
+import org.netbeans.api.project.Project;
+import org.netbeans.modules.cordova.platforms.spi.BuildPerformer;
+import org.netbeans.modules.cordova.platforms.spi.Device;
+import org.netbeans.modules.web.browser.api.WebBrowser;
+import org.netbeans.modules.web.browser.spi.ProjectBrowserProvider;
+import org.netbeans.spi.project.ActionProvider;
+import static org.netbeans.spi.project.ActionProvider.COMMAND_BUILD;
+import org.openide.DialogDescriptor;
+import org.openide.DialogDisplayer;
+import org.openide.NotifyDescriptor;
+import org.openide.awt.StatusDisplayer;
+import org.openide.filesystems.FileObject;
+import org.openide.filesystems.FileUtil;
+import org.openide.util.Exceptions;
+import org.openide.util.Lookup;
+import org.openide.util.NbBundle;
+import org.openide.util.RequestProcessor;
+import org.openide.util.Utilities;
+
+/**
+ *
+ * @author Jan Becicka
+ */
+@NbBundle.Messages({
+    "ERR_Title=Error",
+    "LBL_CheckingDevice=Connecting to android device...",
+    
+    "ERR_WebDebug=Cannot connect to Chrome.\nMake sure, that:\n"
+        + "\u2022 Device is attached\n"
+        + "\u2022 USB Debugging is enabled on your device\n"
+        + "\u2022 Your computer and Android device are connected to the same WiFi network",        
+    
+    "ERR_NO_Cordova=NetBeans cannot find cordova or git on your PATH. Please install cordova and git.\n" +
+            "NetBeans might require restart for changes to take effect.\n"
+})
+/**
+ * Cordova Action Provider. Invokes cordova build.
+ * @author Jan Becicka
+ */
+public class AndroidActionProvider implements ActionProvider {
+
+    private final Project p;
+    private static final Logger LOGGER = Logger.getLogger(AndroidActionProvider.class.getName());
+
+    public AndroidActionProvider(Project p) {
+        this.p = p;
+    }
+    
+    @Override
+    public String[] getSupportedActions() {
+        return new String[]{
+                    COMMAND_BUILD,
+                    COMMAND_CLEAN,
+                    COMMAND_RUN,
+                    COMMAND_RUN_SINGLE,
+                    COMMAND_REBUILD
+                };
+    }
+
+    @NbBundle.Messages({
+        "LBL_AvdManager=AVD Manager",
+        "ERR_NO_JDK=NetBeans is currently running on JRE. Cordova Android build requires JDK. Please run NetBeans on JDK to continue."
+    })
+    @Override
+    public void invokeAction(String command, final Lookup context) throws IllegalArgumentException {
+        final BuildPerformer build = Lookup.getDefault().lookup(BuildPerformer.class);
+        String checkAndroid = checkAndroid();
+        if (checkAndroid != null) {
+            NotifyDescriptor not = new NotifyDescriptor(
+                    checkAndroid,
+                    Bundle.ERR_Title(),
+                    NotifyDescriptor.OK_CANCEL_OPTION,
+                    NotifyDescriptor.ERROR_MESSAGE,
+                    null,
+                    null);
+            Object value = DialogDisplayer.getDefault().notify(not);
+            if (NotifyDescriptor.CANCEL_OPTION != value) {
+                OptionsDisplayer.getDefault().open("Html5/MobilePlatforms"); // NOI18N
+            }
+            return;
+        }
+
+        // Quick fix for issue when IDE is running on JRE, Android build fails because it needs javac
+        String jdkHome = System.getProperty("jdk.home"); //NOI18N
+        NotifyDescriptor.Message notJDK = new DialogDescriptor.Message(
+                Bundle.ERR_NO_JDK(),
+                DialogDescriptor.ERROR_MESSAGE);
+        if (jdkHome == null || jdkHome.isEmpty()) {
+            DialogDisplayer.getDefault().notify(notJDK);
+            return;
+        } else {
+            FileObject jdkHomeFO = FileUtil.toFileObject(new File(jdkHome, "bin")); //NOI18N
+            String javacFileName = Utilities.isWindows() ? "javac.exe" : "javac"; //NOI18N
+            FileObject javacFO = jdkHomeFO.getFileObject(javacFileName);
+            if (javacFO == null) {
+                DialogDisplayer.getDefault().notify(notJDK);
+                return;
+            }
+        }
+
+        if (COMMAND_BUILD.equals(command) || COMMAND_CLEAN.equals(command) || COMMAND_REBUILD.equals(command)) {
+            try {
+                switch (command) {
+                    case COMMAND_BUILD:
+                        build.perform(BuildPerformer.BUILD_ANDROID, p);
+                        break;
+                    case COMMAND_CLEAN:
+                        build.perform(BuildPerformer.CLEAN_ANDROID, p);
+                        break;
+                    case COMMAND_REBUILD:
+                        build.perform(BuildPerformer.REBUILD_ANDROID, p);
+                        break;
+                }
+            } catch (UnsupportedOperationException ex) {
+                NotifyDescriptor.Message not = new DialogDescriptor.Message(
+                        Bundle.ERR_NO_Cordova(),
+                        DialogDescriptor.ERROR_MESSAGE);
+                Object value = DialogDisplayer.getDefault().notify(not);
+                return;
+            }
+        } else if (COMMAND_RUN.equals(command) || COMMAND_RUN_SINGLE.equals(command)) {
+            ProgressUtils.runOffEventDispatchThread(new Runnable() {
+                @Override
+                public void run() {
+                    String checkDevices = checkDevices(p);                    
+                    while (checkDevices != null) {
+                        NotifyDescriptor not = new NotifyDescriptor(
+                                checkDevices,
+                                Bundle.ERR_Title(),
+                                NotifyDescriptor.DEFAULT_OPTION,
+                                NotifyDescriptor.ERROR_MESSAGE,
+                                checkDevices.equals(Bundle.ERR_RunAndroidEmulator())
+                                        ? new Object[]{
+                                    DialogDescriptor.OK_OPTION,
+                                    DialogDescriptor.CANCEL_OPTION,
+                                    Bundle.LBL_AvdManager()
+                                } : null,
+                                null);
+                        Object value = DialogDisplayer.getDefault().notify(not);
+                        if (NotifyDescriptor.CANCEL_OPTION == value || checkDevices.equals(Bundle.ERR_AdbNotFound())) {
+                            return;
+                        } else if (Bundle.LBL_AvdManager().equals(value)) {
+                            RequestProcessor.getDefault().post(new Runnable() {
+                                @Override
+                                public void run() {
+                                    AndroidPlatform.getDefault().manageDevices();
+                                }
+                            });
+                            return;
+                        } else {
+                            checkDevices = checkDevices(p);
+                        }
+                    }
+                    SwingUtilities.invokeLater(new Runnable() {
+                        @Override
+                        public void run() {
+                            try {
+                                build.perform(BuildPerformer.RUN_ANDROID, p);
+                            } catch (UnsupportedOperationException ex) {
+                                NotifyDescriptor not = new NotifyDescriptor(
+                                        Bundle.ERR_NO_Cordova(),
+                                        Bundle.ERR_Title(),
+                                        NotifyDescriptor.OK_CANCEL_OPTION,
+                                        NotifyDescriptor.ERROR_MESSAGE,
+                                        null,
+                                        null);
+                                Object value = DialogDisplayer.getDefault().notify(not);
+                                if (NotifyDescriptor.CANCEL_OPTION != value) {
+                                    OptionsDisplayer.getDefault().open("Html5/MobilePlatforms"); // NOI18N
+                                }
+                                return;
+                            } catch (IllegalStateException ex) {
+                                StatusDisplayer.getDefault().setStatusText(ex.getMessage());
+                            }
+                        }
+                    });
+                }
+            }, Bundle.LBL_CheckingDevice(), new AtomicBoolean(), false);
+        }
+    }
+
+    @Override
+    public boolean isActionEnabled(String command, Lookup context) throws IllegalArgumentException {
+        return true;
+    }
+
+    @NbBundle.Messages({
+        "ERR_ConnectAndroidDevice=Please connect Android device and make sure that:\n"
+        + "\u2022 USB Debugging is enabled on your device\n"
+        + "\u2022 Your computer and Android device are connected to the same WiFi network",
+        "ERR_RunAndroidEmulator=Please run Android Emulator.",
+        "ERR_Unknown=Unknown Error.",
+        "ERR_AdbNotFound=ADB not found. Please make sure that:\n"
+        + "\u2022 Android SDK has been installed correctly,\n"
+        + "\u2022 Close Android SDK Manager, if it's opened."
+    })
+    static String checkDevices(Project p) {
+        if (!AndroidPlatform.getDefault().adbCommandExists()) {
+            return Bundle.ERR_AdbNotFound();
+        }
+        ProjectBrowserProvider provider = p.getLookup().lookup(ProjectBrowserProvider.class);
+        WebBrowser activeConfiguration = provider.getActiveBrowser();
+        try {
+            if (activeConfiguration.getId().endsWith("_1")) { //NOI18N
+                for (Device dev : AndroidPlatform.getDefault().getConnectedDevices()) {
+                    if (!dev.isEmulator()) {
+                        return null;
+                    }
+                }
+                return Bundle.ERR_ConnectAndroidDevice();
+            } else {
+                for (Device dev : AndroidPlatform.getDefault().getConnectedDevices()) {
+                    if (dev.isEmulator()) {
+                        return null;
+                    }
+                }
+                return Bundle.ERR_RunAndroidEmulator();
+            }
+        } catch (IOException iOException) {
+            Exceptions.printStackTrace(iOException);
+        }
+        return Bundle.ERR_Unknown();
+    }
+    
+    @NbBundle.Messages("ERR_AndroidNotConfigured=Android Platform is not configured.\nConfigure?")
+    static String checkAndroid() {
+        if (!AndroidPlatform.getDefault().isReady()) {
+            return Bundle.ERR_AndroidNotConfigured();
+        }
+        return null;
+    }
+    
+}
diff --git a/cordova.platforms.android/src/org/netbeans/modules/cordova/platforms/android/AndroidBrowser.java b/cordova.platforms.android/src/org/netbeans/modules/cordova/platforms/android/AndroidBrowser.java
new file mode 100644
index 0000000000..42dfaeb305
--- /dev/null
+++ b/cordova.platforms.android/src/org/netbeans/modules/cordova/platforms/android/AndroidBrowser.java
@@ -0,0 +1,306 @@
+/*
+ * 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.cordova.platforms.android;
+
+import java.awt.Component;
+import java.beans.PropertyChangeListener;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.swing.JOptionPane;
+import javax.swing.SwingUtilities;
+import org.netbeans.api.options.OptionsDisplayer;
+import org.netbeans.api.progress.ProgressUtils;
+import org.netbeans.api.project.Project;
+import org.netbeans.modules.cordova.platforms.spi.Device;
+import org.netbeans.modules.cordova.platforms.api.WebKitDebuggingSupport;
+import org.netbeans.modules.web.browser.api.BrowserFamilyId;
+import org.netbeans.modules.web.browser.api.BrowserSupport;
+import org.netbeans.modules.web.browser.api.WebBrowserFeatures;
+import org.netbeans.modules.web.browser.spi.EnhancedBrowser;
+import static org.netbeans.spi.project.ActionProvider.COMMAND_RUN;
+import static org.netbeans.spi.project.ActionProvider.COMMAND_RUN_SINGLE;
+import org.netbeans.spi.project.ui.CustomizerProvider2;
+import org.openide.DialogDescriptor;
+import org.openide.DialogDisplayer;
+import org.openide.NotifyDescriptor;
+import org.openide.awt.HtmlBrowser;
+import org.openide.filesystems.FileObject;
+import org.openide.util.Exceptions;
+import org.openide.util.ImageUtilities;
+import org.openide.util.Lookup;
+import org.openide.util.NbBundle;
+import org.openide.util.RequestProcessor;
+import org.openide.util.lookup.Lookups;
+import org.openide.util.lookup.ProxyLookup;
+import org.openide.windows.WindowManager;
+
+/**
+ *
+ * @author Jan Becicka
+ */
+public class AndroidBrowser extends HtmlBrowser.Impl implements EnhancedBrowser{
+    private final Kind kind;
+    
+    private static final Logger LOGGER = Logger.getLogger(AndroidBrowser.class.getName());
+    
+    private Lookup context;
+
+    @Override
+    public void initialize(WebBrowserFeatures browserFeatures) {
+    }
+
+    @Override
+    public void close(boolean closeTab) {
+        RequestProcessor.getDefault().post(new Runnable() {
+            @Override
+            public void run() {
+                WebKitDebuggingSupport.getDefault().stopDebugging(true);
+            }
+        });
+    }
+
+    @Override
+    public void setProjectContext(Lookup projectContext) {
+        context = projectContext;
+    }
+
+    @Override
+    public boolean canReloadPage() {
+        return true;
+    }
+
+    @Override
+    public boolean ignoreChange(FileObject fo) {
+        return BrowserSupport.ignoreChangeDefaultImpl(fo);
+    }
+    
+    public static enum Kind {
+        ANDROID_DEVICE_DEFAULT,
+        ANDROID_DEVICE_CHROME,
+        ANDROID_EMULATOR_DEFAULT
+    }
+    
+
+    public AndroidBrowser(Kind kind) {
+        this.kind = kind;
+    }
+    
+    private URL url;
+
+    @Override
+    public Component getComponent() {
+        return null;
+    }
+
+    @Override
+    public void reloadDocument() {
+        WebKitDebuggingSupport.getDefault().reload();
+    }
+
+    @Override
+    public void stopLoading() {
+    }
+
+    @Override
+    public void setURL(final URL url) {
+        final WebKitDebuggingSupport build = WebKitDebuggingSupport.getDefault();
+
+        final String checkAndroid = AndroidActionProvider.checkAndroid();
+        if (checkAndroid != null) {
+            SwingUtilities.invokeLater(new Runnable() {
+                @Override
+                public void run() {
+                    NotifyDescriptor not = new NotifyDescriptor(
+                            checkAndroid,
+                            Bundle.ERR_Title(),
+                            NotifyDescriptor.OK_CANCEL_OPTION,
+                            NotifyDescriptor.ERROR_MESSAGE,
+                            null,
+                            null);
+                    Object value = DialogDisplayer.getDefault().notify(not);
+                    if (NotifyDescriptor.CANCEL_OPTION != value) {
+                        OptionsDisplayer.getDefault().open("Html5/MobilePlatforms"); // NOI18N
+                    }
+                }
+            });
+            return;
+        }
+
+        ProgressUtils.runOffEventDispatchThread(new Runnable() {
+            @Override
+            public void run() {
+                String checkDevices = checkDevices();
+                while (checkDevices != null) {
+                    NotifyDescriptor not = new NotifyDescriptor(
+                            checkDevices,
+                            Bundle.ERR_Title(),
+                            NotifyDescriptor.DEFAULT_OPTION,
+                            NotifyDescriptor.ERROR_MESSAGE,
+                            null,
+                            null);
+                    Object value = DialogDisplayer.getDefault().notify(not);
+                    if (NotifyDescriptor.CANCEL_OPTION == value || checkDevices.equals(Bundle.ERR_AdbNotFound())) {
+                        return;
+                    } else {
+                        checkDevices = checkDevices();
+                    }
+                }
+
+                Browser b;
+                boolean emulator;
+                if (kind.equals(AndroidBrowser.Kind.ANDROID_DEVICE_DEFAULT)) {
+                    b = Browser.DEFAULT;
+                    emulator = false;
+                } else if (kind.equals(AndroidBrowser.Kind.ANDROID_DEVICE_CHROME)) {
+                    b = Browser.CHROME;
+                    emulator = false;
+                } else {
+                    b = Browser.DEFAULT;
+                    emulator = true;
+                }
+                Device device = new AndroidDevice("android", b, emulator); // NOI18N
+
+                device.openUrl(url.toExternalForm());
+
+                final Project project = context.lookup(Project.class);
+                if (Browser.CHROME.getName().equals(b.getName()) && project != null) {
+                    try {
+                        build.startDebugging(device, project, new ProxyLookup(context, Lookups.fixed(BrowserFamilyId.ANDROID, ImageUtilities.loadImage("org/netbeans/modules/cordova/platforms/android/androiddevice16.png"), url)), false);
+                    } catch (IllegalStateException ex) {
+                        LOGGER.log(Level.INFO, ex.getMessage(), ex);
+                        SwingUtilities.invokeLater(new Runnable() {
+                            @Override
+                            public void run() {
+                                JOptionPane.showMessageDialog(
+                                        WindowManager.getDefault().getMainWindow(),
+                                        Bundle.ERR_WebDebug());
+                            }
+                        });
+                    }
+                }
+
+            }
+        }, Bundle.LBL_CheckingDevice(), new AtomicBoolean(), false);
+        this.url = url;
+    }
+    
+    @NbBundle.Messages("ERR_StartFileNotFound=Start file cannot be found.")
+     public static void openBrowser(String command, final Lookup context, final AndroidBrowser.Kind kind, final Project project, final BrowserSupport support) throws IllegalArgumentException {
+        final WebKitDebuggingSupport build = WebKitDebuggingSupport.getDefault();
+         if (COMMAND_RUN.equals(command) || COMMAND_RUN_SINGLE.equals(command)) {
+            try {
+                final String urlString = build.getUrl(project, context);
+                if (urlString == null) {
+                    DialogDisplayer.getDefault().notify(
+                            new DialogDescriptor.Message(Bundle.ERR_StartFileNotFound()));
+                    CustomizerProvider2 cust = project.getLookup().lookup(CustomizerProvider2.class);
+                    cust.showCustomizer("RUN", null); //NOI18N
+                    return;
+                }
+                final URL urL = new URL(urlString);
+                FileObject f = build.getFile(project, context);
+                support.load(urL, f);
+            } catch (MalformedURLException ex) {
+                Exceptions.printStackTrace(ex);
+            }
+         }
+    }
+
+    private String checkDevices() {
+        if (!AndroidPlatform.getDefault().adbCommandExists()) {
+            return Bundle.ERR_AdbNotFound();
+        }
+        try {
+            if (kind.equals(AndroidBrowser.Kind.ANDROID_EMULATOR_DEFAULT)) { //NOI18N
+                for (Device dev : AndroidPlatform.getDefault().getConnectedDevices()) {
+                    if (dev.isEmulator()) {
+                        return null;
+                    }
+                }
+                return Bundle.ERR_RunAndroidEmulator();
+            } else {
+                for (Device dev : AndroidPlatform.getDefault().getConnectedDevices()) {
+                    if (!dev.isEmulator()) {
+                        return null;
+                    }
+                }
+                return Bundle.ERR_ConnectAndroidDevice();
+            }
+        } catch (IOException iOException) {
+            Exceptions.printStackTrace(iOException);
+        }
+        return Bundle.ERR_Unknown();
+    }
+
+    @Override
+    public URL getURL() {
+        return url;
+    }
+
+    @Override
+    public String getStatusMessage() {
+        return "";
+    }
+
+    @Override
+    @NbBundle.Messages("LBL_BrowserTitle=Android Browser")
+    public String getTitle() {
+        return Bundle.LBL_BrowserTitle();
+    }
+
+    @Override
+    public boolean isForward() {
+        return false;
+    }
+
+    @Override
+    public void forward() {
+    }
+
+    @Override
+    public boolean isBackward() {
+        return false;
+    }
+
+    @Override
+    public void backward() {
+    }
+
+    @Override
+    public boolean isHistory() {
+        return false;
+    }
+
+    @Override
+    public void showHistory() {
+    }
+
+    @Override
+    public void addPropertyChangeListener(PropertyChangeListener l) {
+    }
+
+    @Override
+    public void removePropertyChangeListener(PropertyChangeListener l) {
+    }
+    
+}
diff --git a/cordova.platforms.android/src/org/netbeans/modules/cordova/platforms/android/AndroidBrowserActionProvider.java b/cordova.platforms.android/src/org/netbeans/modules/cordova/platforms/android/AndroidBrowserActionProvider.java
new file mode 100644
index 0000000000..d7d58ac850
--- /dev/null
+++ b/cordova.platforms.android/src/org/netbeans/modules/cordova/platforms/android/AndroidBrowserActionProvider.java
@@ -0,0 +1,58 @@
+/*
+ * 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.cordova.platforms.android;
+
+import org.netbeans.api.project.Project;
+import org.netbeans.modules.cordova.platforms.api.WebKitDebuggingSupport;
+import org.netbeans.modules.web.browser.api.BrowserSupport;
+import org.netbeans.spi.project.ActionProvider;
+import org.openide.util.Lookup;
+
+/**
+ *
+ * @author Jan Becicka
+ */
+class AndroidBrowserActionProvider implements ActionProvider {
+    private BrowserSupport browserSupport;
+    private final Project project;
+    private final String browserId;
+
+    public AndroidBrowserActionProvider(BrowserSupport support, String browserId, Project project) {
+        this.browserSupport = support;
+        this.project = project;
+        this.browserId = browserId;
+    }
+
+    @Override
+    public String[] getSupportedActions() {
+        return new String[]{COMMAND_RUN, COMMAND_RUN_SINGLE};
+    }
+
+    @Override
+    public void invokeAction(String command, final Lookup context) throws IllegalArgumentException {
+        WebKitDebuggingSupport.getDefault().stopDebugging(true);
+        AndroidBrowser.openBrowser(command, context, AndroidBrowser.Kind.valueOf(browserId), project, browserSupport);
+    }
+
+    @Override
+    public boolean isActionEnabled(String command, Lookup context) throws IllegalArgumentException {
+        return true;
+    }
+    
+}
diff --git a/cordova.platforms.android/src/org/netbeans/modules/cordova/platforms/android/AndroidBrowserFactory.java b/cordova.platforms.android/src/org/netbeans/modules/cordova/platforms/android/AndroidBrowserFactory.java
new file mode 100644
index 0000000000..ff20c641a8
--- /dev/null
+++ b/cordova.platforms.android/src/org/netbeans/modules/cordova/platforms/android/AndroidBrowserFactory.java
@@ -0,0 +1,159 @@
+/*
+ * 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.cordova.platforms.android;
+
+import java.awt.Image;
+import org.netbeans.modules.cordova.platforms.api.ClientProjectUtilities;
+import org.netbeans.modules.web.browser.api.BrowserFamilyId;
+import org.netbeans.modules.web.browser.spi.BrowserURLMapperImplementation;
+import org.netbeans.modules.web.browser.spi.BrowserURLMapperProvider;
+import org.netbeans.modules.web.browser.spi.EnhancedBrowserFactory;
+import org.openide.awt.HtmlBrowser;
+import org.openide.util.ImageUtilities;
+import org.openide.util.NbBundle;
+import org.openide.util.lookup.ServiceProvider;
+
+
+/**
+ *
+ * @author Jan Becicka
+ */
+@NbBundle.Messages({
+    "LBL_DeviceDefault=Android Device (Default Browser)",
+    "LBL_DeviceChrome=Android Device (Chrome)",
+    "LBL_EmulatorDefault=Android Emulator (Default Browser)"
+})
+public abstract class AndroidBrowserFactory implements EnhancedBrowserFactory, HtmlBrowser.Factory, BrowserURLMapperProvider {
+
+    private BrowserURLMapperImplementation urlMapper;
+
+    public AndroidBrowserFactory() {
+        urlMapper = ClientProjectUtilities.createMobileBrowserURLMapper();
+    }
+    
+    
+    @Override
+    public BrowserFamilyId getBrowserFamilyId() {
+        return BrowserFamilyId.ANDROID;
+    }
+
+    @Override
+    public boolean canCreateHtmlBrowserImpl() {
+        return true;
+    }
+
+    @Override
+    public BrowserURLMapperImplementation getBrowserURLMapper() {
+        return urlMapper;
+    }
+
+
+    @ServiceProvider(service = HtmlBrowser.Factory.class, path = "Services/Browsers2")
+    public static class DeviceDefault extends AndroidBrowserFactory {
+
+        @Override
+        public String getDisplayName() {
+            return Bundle.LBL_DeviceDefault();
+        }
+
+        @Override
+        public HtmlBrowser.Impl createHtmlBrowserImpl() {
+            return new AndroidBrowser(AndroidBrowser.Kind.ANDROID_DEVICE_DEFAULT);
+        }
+
+        @Override
+        public String getId() {
+            return AndroidBrowser.Kind.ANDROID_DEVICE_DEFAULT.toString(); // NOI18N
+        }
+
+        @Override
+        public boolean hasNetBeansIntegration() {
+            return false;
+        }
+        
+        @Override
+        public Image getIconImage(boolean small) {
+            return ImageUtilities.loadImage("org/netbeans/modules/cordova/platforms/android/androiddevice" + (small?"16.png":".png"), false);
+        }
+        
+    }
+
+    @ServiceProvider(service = HtmlBrowser.Factory.class, path = "Services/Browsers2")
+    public static class DeviceChrome extends AndroidBrowserFactory {
+
+        @Override
+        public String getDisplayName() {
+            return Bundle.LBL_DeviceChrome();
+        }
+
+        @Override
+        public HtmlBrowser.Impl createHtmlBrowserImpl() {
+            return new AndroidBrowser(AndroidBrowser.Kind.ANDROID_DEVICE_CHROME);
+        }
+
+        @Override
+        public String getId() {
+            return AndroidBrowser.Kind.ANDROID_DEVICE_CHROME.toString(); // NOI18N
+        }
+        
+        @Override
+        public boolean hasNetBeansIntegration() {
+            return true;
+        }
+
+        @Override
+        public Image getIconImage(boolean small) {
+            return ImageUtilities.loadImage("org/netbeans/modules/cordova/platforms/android/androiddevice" + (small?"16.png":".png"), false);
+        }
+        
+        
+    }
+    
+    @ServiceProvider(service = HtmlBrowser.Factory.class, path = "Services/Browsers2")
+    public static class EmulatorDefault extends AndroidBrowserFactory {
+
+        @Override
+        public String getDisplayName() {
+            return Bundle.LBL_EmulatorDefault();
+        }
+
+        @Override
+        public HtmlBrowser.Impl createHtmlBrowserImpl() {
+            return new AndroidBrowser(AndroidBrowser.Kind.ANDROID_EMULATOR_DEFAULT);
+        }
+
+        @Override
+        public String getId() {
+            return AndroidBrowser.Kind.ANDROID_EMULATOR_DEFAULT.toString(); // NOI18N
+        }
+        
+        @Override
+        public boolean hasNetBeansIntegration() {
+            return false;
+        }
+        
+        @Override
+        public Image getIconImage(boolean small) {
+            return ImageUtilities.loadImage("org/netbeans/modules/cordova/platforms/android/androidemulator" + (small?"16.png":".png"), false);
+        }
+
+    }
+    
+
+}
diff --git a/cordova.platforms.android/src/org/netbeans/modules/cordova/platforms/android/AndroidConfigurationPanel.form b/cordova.platforms.android/src/org/netbeans/modules/cordova/platforms/android/AndroidConfigurationPanel.form
new file mode 100644
index 0000000000..3f9c7462d7
--- /dev/null
+++ b/cordova.platforms.android/src/org/netbeans/modules/cordova/platforms/android/AndroidConfigurationPanel.form
@@ -0,0 +1,154 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<Form version="1.5" maxVersion="1.8" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
+  <AuxValues>
+    <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
+    <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
+    <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
+    <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
+    <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
+    <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
+    <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
+    <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
+    <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
+  </AuxValues>
+
+  <Layout>
+    <DimensionLayout dim="0">
+      <Group type="103" groupAlignment="0" attributes="0">
+          <Group type="102" attributes="0">
+              <EmptySpace min="0" pref="0" max="-2" attributes="0"/>
+              <Group type="103" groupAlignment="0" attributes="0">
+                  <Group type="102" attributes="0">
+                      <Component id="debuggerCheckBox" min="-2" max="-2" attributes="0"/>
+                      <EmptySpace min="0" pref="0" max="32767" attributes="0"/>
+                  </Group>
+                  <Group type="102" alignment="0" attributes="0">
+                      <Group type="103" groupAlignment="1" attributes="0">
+                          <Component id="jLabel1" min="-2" max="-2" attributes="0"/>
+                          <Group type="103" groupAlignment="0" attributes="0">
+                              <Component id="deviceLabel" min="-2" max="-2" attributes="0"/>
+                              <Component id="avdLabel" alignment="0" min="-2" max="-2" attributes="0"/>
+                          </Group>
+                      </Group>
+                      <EmptySpace max="-2" attributes="0"/>
+                      <Group type="103" groupAlignment="0" attributes="0">
+                          <Component id="deviceCombo" pref="174" max="32767" attributes="0"/>
+                          <Component id="avdCombo" max="32767" attributes="0"/>
+                          <Component id="browserCombo" max="32767" attributes="0"/>
+                      </Group>
+                      <EmptySpace max="-2" attributes="0"/>
+                      <Component id="manageButton" min="-2" max="-2" attributes="0"/>
+                  </Group>
+              </Group>
+              <EmptySpace min="0" pref="0" max="-2" attributes="0"/>
+          </Group>
+      </Group>
+    </DimensionLayout>
+    <DimensionLayout dim="1">
+      <Group type="103" groupAlignment="0" attributes="0">
+          <Group type="102" alignment="0" attributes="0">
+              <EmptySpace min="0" pref="0" max="-2" attributes="0"/>
+              <Group type="103" groupAlignment="2" attributes="0">
+                  <Component id="deviceLabel" alignment="2" min="-2" max="-2" attributes="0"/>
+                  <Component id="deviceCombo" alignment="2" min="-2" max="-2" attributes="0"/>
+              </Group>
+              <EmptySpace max="-2" attributes="0"/>
+              <Group type="103" groupAlignment="3" attributes="0">
+                  <Component id="avdCombo" alignment="3" min="-2" max="-2" attributes="0"/>
+                  <Component id="manageButton" alignment="3" min="-2" max="-2" attributes="0"/>
+                  <Component id="avdLabel" alignment="3" min="-2" max="-2" attributes="0"/>
+              </Group>
+              <EmptySpace max="-2" attributes="0"/>
+              <Group type="103" groupAlignment="3" attributes="0">
+                  <Component id="jLabel1" alignment="3" min="-2" max="-2" attributes="0"/>
+                  <Component id="browserCombo" alignment="3" min="-2" max="-2" attributes="0"/>
+              </Group>
+              <EmptySpace max="-2" attributes="0"/>
+              <Component id="debuggerCheckBox" min="-2" max="-2" attributes="0"/>
+              <EmptySpace max="32767" attributes="0"/>
+          </Group>
+      </Group>
+    </DimensionLayout>
+  </Layout>
+  <SubComponents>
+    <Component class="javax.swing.JLabel" name="deviceLabel">
+      <Properties>
+        <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
+          <ComponentRef name="deviceCombo"/>
+        </Property>
+        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+          <ResourceString bundle="org/netbeans/modules/cordova/platforms/android/Bundle.properties" key="AndroidConfigurationPanel.deviceLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+        </Property>
+      </Properties>
+    </Component>
+    <Component class="javax.swing.JButton" name="manageButton">
+      <Properties>
+        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+          <ResourceString bundle="org/netbeans/modules/cordova/platforms/android/Bundle.properties" key="AndroidConfigurationPanel.manageButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+        </Property>
+      </Properties>
+      <Events>
+        <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="manageButtonActionPerformed"/>
+      </Events>
+    </Component>
+    <Component class="javax.swing.JComboBox" name="deviceCombo">
+      <Properties>
+        <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
+          <Connection code="new javax.swing.DefaultComboBoxModel(new String[] { Bundle.LBL_AndroidEmulator(), Bundle.LBL_AndroidConnectedDevice() })" type="code"/>
+        </Property>
+      </Properties>
+      <Events>
+        <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="deviceComboActionPerformed"/>
+      </Events>
+    </Component>
+    <Component class="javax.swing.JComboBox" name="avdCombo">
+      <Properties>
+        <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
+          <Connection code="new javax.swing.DefaultComboBoxModel(new String[] { Bundle.LBL_PleaseWait() })" type="code"/>
+        </Property>
+      </Properties>
+      <Events>
+        <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="avdComboActionPerformed"/>
+      </Events>
+    </Component>
+    <Component class="javax.swing.JLabel" name="avdLabel">
+      <Properties>
+        <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
+          <ComponentRef name="avdCombo"/>
+        </Property>
+        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+          <ResourceString bundle="org/netbeans/modules/cordova/platforms/android/Bundle.properties" key="AndroidConfigurationPanel.avdLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+        </Property>
+      </Properties>
+    </Component>
+    <Component class="javax.swing.JCheckBox" name="debuggerCheckBox">
+      <Properties>
+        <Property name="selected" type="boolean" value="true"/>
+        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+          <ResourceString bundle="org/netbeans/modules/cordova/platforms/android/Bundle.properties" key="AndroidConfigurationPanel.debuggerCheckBox.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+        </Property>
+      </Properties>
+      <Events>
+        <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="debuggerCheckBoxActionPerformed"/>
+      </Events>
+    </Component>
+    <Component class="javax.swing.JLabel" name="jLabel1">
+      <Properties>
+        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+          <ResourceString bundle="org/netbeans/modules/cordova/platforms/android/Bundle.properties" key="AndroidConfigurationPanel.jLabel1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+        </Property>
+      </Properties>
+    </Component>
+    <Component class="javax.swing.JComboBox" name="browserCombo">
+      <Properties>
+        <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
+          <Connection code="new javax.swing.DefaultComboBoxModel(new String[] { Bundle.LBL_DefaultBrowser(), Bundle.LBL_Chrome() })" type="code"/>
+        </Property>
+      </Properties>
+      <Events>
+        <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="browserComboActionPerformed"/>
+      </Events>
+    </Component>
+  </SubComponents>
+</Form>
diff --git a/cordova.platforms.android/src/org/netbeans/modules/cordova/platforms/android/AndroidConfigurationPanel.java b/cordova.platforms.android/src/org/netbeans/modules/cordova/platforms/android/AndroidConfigurationPanel.java
new file mode 100644
index 0000000000..ca8faf2c12
--- /dev/null
+++ b/cordova.platforms.android/src/org/netbeans/modules/cordova/platforms/android/AndroidConfigurationPanel.java
@@ -0,0 +1,343 @@
+/*
+ * 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.cordova.platforms.android;
+
+import java.awt.BorderLayout;
+import java.awt.Component;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.EnumSet;
+import javax.swing.DefaultComboBoxModel;
+import javax.swing.DefaultListCellRenderer;
+import javax.swing.JList;
+import javax.swing.JPanel;
+import javax.swing.SwingUtilities;
+import org.netbeans.api.project.Project;
+import org.netbeans.modules.cordova.platforms.api.ClientProjectUtilities;
+import org.netbeans.modules.cordova.platforms.spi.Device;
+import org.netbeans.modules.cordova.platforms.api.PlatformManager;
+import org.netbeans.modules.cordova.platforms.spi.PropertyProvider;
+import org.netbeans.modules.web.clientproject.spi.platform.ProjectConfigurationCustomizer;
+import org.openide.util.Exceptions;
+import org.openide.util.NbBundle;
+import org.openide.util.RequestProcessor;
+
+/**
+ *
+ * @author Jan Becicka
+ */
+public class AndroidConfigurationPanel extends javax.swing.JPanel {
+
+    
+    private PropertyProvider config;
+    final RequestProcessor RP = new RequestProcessor(AndroidConfigurationPanel.class);
+
+    private void initControls() {
+        initComponents();
+        String device = config.getProperty(Device.DEVICE_PROP); //NOI18N
+        if (Device.DEVICE.equals(device)) { //NOI18N
+            deviceCombo.setSelectedIndex(Device.DEVICE.equals(device)?1:0); //NOI18N
+        }
+        setAVDComboVisible(!Device.DEVICE.equals(device)); //NOI18N
+        debuggerCheckBox.setVisible(false);
+        deviceLabel.setVisible(false);
+        deviceCombo.setVisible(false);
+        
+        String property = config.getProperty(Device.BROWSER_PROP);
+        if (property!=null && property.equals(Browser.CHROME.getName())) {
+            browserCombo.setSelectedIndex(1);
+        }
+        
+        validate();
+    }
+
+    public static class AndroidConfigurationCustomizer implements ProjectConfigurationCustomizer {
+        
+        private final Project p;
+        private final PropertyProvider config;
+
+        public AndroidConfigurationCustomizer(Project p, PropertyProvider config) {
+            this.p = p;
+            this.config = config;
+        }
+
+        @Override
+        public JPanel createPanel() {
+            return new AndroidConfigurationPanel(config);
+        }
+
+        @Override
+        public EnumSet<HiddenProperties> getHiddenProperties() {
+            return EnumSet.of(HiddenProperties.WEB_SERVER);
+        }
+
+    }
+    
+    private static class DeviceRenderer extends DefaultListCellRenderer {
+
+        @Override
+        public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
+            super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
+            if (value instanceof AVD) {
+                setText(((AVD) value).getName());
+            }
+            return this;
+        }
+    }
+    
+    /**
+     * Creates new form AndroidConfigurationPanel
+     */
+    public AndroidConfigurationPanel(final PropertyProvider config) {
+        assert config != null;
+        this.config = config;
+        if (!AndroidPlatform.getDefault().isReady()) {
+            setLayout(new BorderLayout());
+            add(ClientProjectUtilities.createMobilePlatformsSetupPanel(), BorderLayout.CENTER);
+            validate();
+            AndroidPlatform.getDefault().addPropertyChangeListener(new PropertyChangeListener() {
+                @Override
+                public void propertyChange(PropertyChangeEvent evt) {
+                    if (AndroidPlatform.getDefault().isReady()) {
+                        removeAll();
+                        initControls();
+                        validate();
+                    }
+                }
+            });
+        } else {
+            initControls();
+        }
+    }
+
+    @NbBundle.Messages("LBL_PleaseWait=Please Wait...")
+    private void setAVDComboVisible(boolean visible) {
+        if (visible) {
+            avdCombo.setModel(new DefaultComboBoxModel(new Object[]{Bundle.LBL_PleaseWait()}));
+            avdCombo.setEnabled(false);
+            RP.post(new Runnable() {
+                @Override
+                public void run() {
+                    try {
+                        final Collection<? extends Device> avDs = AndroidPlatform.getDefault().getVirtualDevices();
+                        refreshCombo(avDs);
+                    } catch (IOException ex) {
+                        Exceptions.printStackTrace(ex);
+                    }
+                }
+            });
+        }        
+        avdLabel.setVisible(visible);
+        avdCombo.setVisible(visible);
+        manageButton.setVisible(visible);
+    }
+    
+    private void refreshCombo(final Collection<? extends Device> avDs) {
+        SwingUtilities.invokeLater(new Runnable() {
+            @Override
+            public void run() {
+                avdCombo.setEnabled(true);
+                avdCombo.setRenderer(new DeviceRenderer());
+                final AVD[] avds = (AVD[]) avDs.toArray(new AVD[avDs.size()]);
+                avdCombo.setModel(new DefaultComboBoxModel(avds));
+                for (AVD avd : avds) {
+                    if (avd.getName().equals(config.getProperty(Device.DEVICE_PROP))) {//NOI18N
+                        avdCombo.setSelectedItem(avd);
+                        break;
+                    }
+                }
+
+            }
+        });
+    }
+
+    /**
+     * This method is called from within the constructor to initialize the form.
+     * WARNING: Do NOT modify this code. The content of this method is always
+     * regenerated by the Form Editor.
+     */
+    @SuppressWarnings("unchecked")
+    @NbBundle.Messages({
+        "LBL_AndroidEmulator=Emulator",
+        "LBL_AndroidConnectedDevice=Connected Device",
+        "LBL_DefaultBrowser=Default Browser",
+        "LBL_Chrome=Mobile Chrome"
+    })
+    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
+    private void initComponents() {
+
+        deviceLabel = new javax.swing.JLabel();
+        manageButton = new javax.swing.JButton();
+        deviceCombo = new javax.swing.JComboBox();
+        avdCombo = new javax.swing.JComboBox();
+        avdLabel = new javax.swing.JLabel();
+        debuggerCheckBox = new javax.swing.JCheckBox();
+        jLabel1 = new javax.swing.JLabel();
+        browserCombo = new javax.swing.JComboBox();
+
+        deviceLabel.setLabelFor(deviceCombo);
+        org.openide.awt.Mnemonics.setLocalizedText(deviceLabel, org.openide.util.NbBundle.getMessage(AndroidConfigurationPanel.class, "AndroidConfigurationPanel.deviceLabel.text")); // NOI18N
+
+        org.openide.awt.Mnemonics.setLocalizedText(manageButton, org.openide.util.NbBundle.getMessage(AndroidConfigurationPanel.class, "AndroidConfigurationPanel.manageButton.text")); // NOI18N
+        manageButton.addActionListener(new java.awt.event.ActionListener() {
+            public void actionPerformed(java.awt.event.ActionEvent evt) {
+                manageButtonActionPerformed(evt);
+            }
+        });
+
+        deviceCombo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { Bundle.LBL_AndroidEmulator(), Bundle.LBL_AndroidConnectedDevice() }));
+        deviceCombo.addActionListener(new java.awt.event.ActionListener() {
+            public void actionPerformed(java.awt.event.ActionEvent evt) {
+                deviceComboActionPerformed(evt);
+            }
+        });
+
+        avdCombo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { Bundle.LBL_PleaseWait() }));
+        avdCombo.addActionListener(new java.awt.event.ActionListener() {
+            public void actionPerformed(java.awt.event.ActionEvent evt) {
+                avdComboActionPerformed(evt);
+            }
+        });
+
+        avdLabel.setLabelFor(avdCombo);
+        org.openide.awt.Mnemonics.setLocalizedText(avdLabel, org.openide.util.NbBundle.getMessage(AndroidConfigurationPanel.class, "AndroidConfigurationPanel.avdLabel.text")); // NOI18N
+
+        debuggerCheckBox.setSelected(true);
+        org.openide.awt.Mnemonics.setLocalizedText(debuggerCheckBox, org.openide.util.NbBundle.getMessage(AndroidConfigurationPanel.class, "AndroidConfigurationPanel.debuggerCheckBox.text")); // NOI18N
+        debuggerCheckBox.addActionListener(new java.awt.event.ActionListener() {
+            public void actionPerformed(java.awt.event.ActionEvent evt) {
+                debuggerCheckBoxActionPerformed(evt);
+            }
+        });
+
+        org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(AndroidConfigurationPanel.class, "AndroidConfigurationPanel.jLabel1.text")); // NOI18N
+
+        browserCombo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { Bundle.LBL_DefaultBrowser(), Bundle.LBL_Chrome() }));
+        browserCombo.addActionListener(new java.awt.event.ActionListener() {
+            public void actionPerformed(java.awt.event.ActionEvent evt) {
+                browserComboActionPerformed(evt);
+            }
+        });
+
+        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
+        this.setLayout(layout);
+        layout.setHorizontalGroup(
+            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addGroup(layout.createSequentialGroup()
+                .addGap(0, 0, 0)
+                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+                    .addGroup(layout.createSequentialGroup()
+                        .addComponent(debuggerCheckBox)
+                        .addGap(0, 0, Short.MAX_VALUE))
+                    .addGroup(layout.createSequentialGroup()
+                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
+                            .addComponent(jLabel1)
+                            .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+                                .addComponent(deviceLabel)
+                                .addComponent(avdLabel)))
+                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+                            .addComponent(deviceCombo, 0, 174, Short.MAX_VALUE)
+                            .addComponent(avdCombo, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+                            .addComponent(browserCombo, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                        .addComponent(manageButton)))
+                .addGap(0, 0, 0))
+        );
+        layout.setVerticalGroup(
+            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addGroup(layout.createSequentialGroup()
+                .addGap(0, 0, 0)
+                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER)
+                    .addComponent(deviceLabel)
+                    .addComponent(deviceCombo, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+                    .addComponent(avdCombo, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+                    .addComponent(manageButton)
+                    .addComponent(avdLabel))
+                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+                    .addComponent(jLabel1)
+                    .addComponent(browserCombo, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                .addComponent(debuggerCheckBox)
+                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+        );
+    }// </editor-fold>//GEN-END:initComponents
+
+    private void manageButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_manageButtonActionPerformed
+        manageButton.setEnabled(false);
+        RP.post(new Runnable() {
+
+            @Override
+            public void run() {
+                AndroidPlatform.getDefault().manageDevices();
+                Collection<? extends Device> avDs;
+                try {
+                    avDs = AndroidPlatform.getDefault().getVirtualDevices();
+                    refreshCombo(avDs);
+                } catch (IOException ex) {
+                    Exceptions.printStackTrace(ex);
+                }
+                SwingUtilities.invokeLater(new Runnable() {
+                    @Override
+                    public void run() {
+                        manageButton.setEnabled(true);
+                    }
+                });
+            }
+        });
+    }//GEN-LAST:event_manageButtonActionPerformed
+
+    private void avdComboActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_avdComboActionPerformed
+        config.putProperty("avd", ((AVD)avdCombo.getSelectedItem()).getName()); //NOI18N
+    }//GEN-LAST:event_avdComboActionPerformed
+
+    private void deviceComboActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_deviceComboActionPerformed
+        if (deviceCombo.getSelectedIndex() == 0) {
+            config.putProperty(Device.DEVICE_PROP, Device.EMULATOR); //NOI18N
+            setAVDComboVisible(true);
+        } else {
+            config.putProperty(Device.DEVICE_PROP, Device.DEVICE); //NOI18N
+            setAVDComboVisible(false);
+        }
+    }//GEN-LAST:event_deviceComboActionPerformed
+
+    private void debuggerCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_debuggerCheckBoxActionPerformed
+        config.putProperty("debug.enabled", Boolean.toString(debuggerCheckBox.isSelected())); //NOI18N
+    }//GEN-LAST:event_debuggerCheckBoxActionPerformed
+
+    private void browserComboActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_browserComboActionPerformed
+        config.putProperty(Device.BROWSER_PROP, browserCombo.getSelectedIndex() == 0 ? Browser.DEFAULT.getName():Browser.CHROME.getName());
+    }//GEN-LAST:event_browserComboActionPerformed
+
+    // Variables declaration - do not modify//GEN-BEGIN:variables
+    private javax.swing.JComboBox avdCombo;
+    private javax.swing.JLabel avdLabel;
+    private javax.swing.JComboBox browserCombo;
+    private javax.swing.JCheckBox debuggerCheckBox;
+    private javax.swing.JComboBox deviceCombo;
+    private javax.swing.JLabel deviceLabel;
+    private javax.swing.JLabel jLabel1;
+    private javax.swing.JButton manageButton;
+    // End of variables declaration//GEN-END:variables
+}
diff --git a/cordova.platforms.android/src/org/netbeans/modules/cordova/platforms/android/AndroidDebugTransport.java b/cordova.platforms.android/src/org/netbeans/modules/cordova/platforms/android/AndroidDebugTransport.java
new file mode 100644
index 0000000000..6cce73953f
--- /dev/null
+++ b/cordova.platforms.android/src/org/netbeans/modules/cordova/platforms/android/AndroidDebugTransport.java
@@ -0,0 +1,243 @@
+/*
+ * 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.cordova.platforms.android;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.Proxy;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.nio.channels.SelectionKey;
+import java.nio.charset.Charset;
+import java.util.concurrent.TimeUnit;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import org.json.simple.JSONArray;
+import org.json.simple.JSONObject;
+import org.json.simple.JSONValue;
+import org.json.simple.parser.JSONParser;
+import org.json.simple.parser.ParseException;
+import org.netbeans.modules.cordova.platforms.spi.MobileDebugTransport;
+import org.netbeans.modules.cordova.platforms.api.ProcessUtilities;
+import org.netbeans.modules.cordova.platforms.api.WebKitDebuggingSupport;
+import org.netbeans.modules.netserver.api.ProtocolDraft;
+import org.netbeans.modules.netserver.api.WebSocketClient;
+import org.netbeans.modules.netserver.api.WebSocketReadHandler;
+import org.netbeans.modules.web.webkit.debugging.spi.Command;
+import org.netbeans.modules.web.webkit.debugging.spi.Response;
+import org.openide.DialogDisplayer;
+import org.openide.NotifyDescriptor;
+import org.openide.util.Exceptions;
+import org.openide.util.NbBundle;
+
+/**
+ *
+ * @author Jan Becicka
+ */
+public class AndroidDebugTransport extends MobileDebugTransport implements WebSocketReadHandler {
+
+    private WebSocketClient webSocket;
+    private static final Logger LOGGER = Logger.getLogger(AndroidDebugTransport.class.getName());
+    private boolean flush;
+
+    @Override
+    public boolean detach() {
+        if (webSocket != null) {
+            webSocket.stop();
+        }
+        return true;
+    }
+
+    @Override
+    public void sendCommandImpl(Command command) {
+        String toString = translate(command.toString());
+        webSocket.sendMessage(toString);
+    }
+    
+    @Override
+    public void accepted(SelectionKey key) {
+        synchronized(webSocket) {
+            webSocket.notifyAll();
+        }
+    }
+
+    @Override
+    public void read(SelectionKey key, byte[] message, Integer dataType) {
+        final String string;
+        string = new String(message, Charset.forName("UTF-8")).trim(); //NOI18N
+        try {
+            final Object parse = JSONValue.parseWithException(string);
+            if (callBack == null) {
+                LOGGER.info("callBack is null. Ignoring response: " + string);
+            } else {
+                callBack.handleResponse(new Response((JSONObject) parse));
+            }
+        } catch (ParseException ex) {
+            Exceptions.attachMessage(ex, string);
+            Exceptions.printStackTrace(ex);
+        }
+    }
+
+    @Override
+    public void closed(SelectionKey key) {
+        WebKitDebuggingSupport.getDefault().stopDebugging(false);
+    }
+
+    public String getConnectionName() {
+        return "Android"; //NOI18N
+    }
+
+    public WebSocketClient createWebSocket(WebSocketReadHandler handler) throws IOException {
+        final URI uri = getURI();
+        if (uri != null) {
+            return new WebSocketClient(uri, ProtocolDraft.getRFC(), handler);
+        }
+        return null;
+    }
+
+    @Override
+    public boolean attach() {
+        try {
+            String s = ProcessUtilities.callProcess(
+                    ((AndroidPlatform) AndroidPlatform.getDefault()).getAdbCommand(), 
+                    true, 
+                    AndroidPlatform.DEFAULT_TIMEOUT, 
+                    "forward", // NOI18N
+                    "tcp:9222", getRedirectString()); //NOI18N
+        } catch (IOException ex) {
+            Exceptions.printStackTrace(ex);
+        }
+
+        try {
+            webSocket = createWebSocket(this);
+            if (webSocket != null) {
+            webSocket.start();
+            return true;
+            }
+        } catch (IOException ex) {
+            Exceptions.printStackTrace(ex);
+        }
+            return false;
+        }
+
+    private String getRedirectString() {
+        String appName = getBundleIdentifier();
+        if (appName == null) {
+            //chrome
+            return "localabstract:chrome_devtools_remote";
+        } else {
+            return "localabstract:webview_devtools_remote_" + AndroidPlatform.getDefault().getProcessIdByName(appName);
+        }
+    }
+    
+    
+
+    @Override
+    public String getVersion() {
+        return "1.0"; //NOI18N
+    }
+
+    @NbBundle.Messages({
+        "LBL_UriTitle=Could not connect to device or emulator",
+        "ERR_CouldNotConnect=Please connect Android device (or run Android emulator) and make sure that:\n"
+        + "\u2022 No more than one device or emulator is connected at the same time\n"
+        + "\u2022 Device or emulator is listed in the output when invoking command \"adb devices\"\n"
+        + "\u2022 USB Debugging is enabled on your device (if applicable)\n"
+        + "\u2022 Your computer and Android device are connected to the same WiFi network (if applicable)"
+    })
+    private URI getURI() {
+        JSONArray array = null;
+        for (long stop = System.nanoTime() + TimeUnit.MINUTES.toNanos(2); stop > System.nanoTime() && !flush;) {
+            try {
+                JSONParser parser = new JSONParser();
+
+                URL chromeJson = new URL("http://localhost:9222/json");
+                try (BufferedReader reader = new BufferedReader(new InputStreamReader(chromeJson.openConnection(Proxy.NO_PROXY).getInputStream()))) {
+                    Object obj = parser.parse(reader);
+                    array = (JSONArray) obj;
+                    if (array.size() == 0) {
+                        try (BufferedReader r = new BufferedReader(new InputStreamReader(chromeJson.openConnection(Proxy.NO_PROXY).getInputStream()))) {
+                            String line;
+                            while ((line = r.readLine()) != null) {
+                                LOGGER.info(line);
+                            }
+                        }
+                    }
+                    for (int i = 0; i < array.size(); i++) {
+                        JSONObject object = (JSONObject) array.get(i);
+                        String urlFromBrowser = object.get("url").toString(); // NOI18N
+                        int hash = urlFromBrowser.indexOf("#"); // NOI18N
+                        if (hash != -1) {
+                            urlFromBrowser = urlFromBrowser.substring(0, hash);
+                        }
+                        if (urlFromBrowser.endsWith("/")) { // NOI18N
+                            urlFromBrowser = urlFromBrowser.substring(0, urlFromBrowser.length() - 1);
+                        }
+                        URL conURL = getConnectionURL();
+                        if (conURL ==null) {
+                            //phonegap
+                            setBaseUrl(urlFromBrowser);
+                            if (object.containsKey("webSocketDebuggerUrl")) { // NOI18N
+                                return new URI(object.get("webSocketDebuggerUrl").toString()); // NOI18N
+                            } else {
+                                continue;
+                            }
+                        }
+                        final String connectionUrl = conURL.toExternalForm();
+                        final String shortenedUrl = connectionUrl.replace(":80/", "/"); // NOI18N
+
+                        if (connectionUrl.equals(urlFromBrowser) || shortenedUrl.equals(urlFromBrowser)) {
+                            if (object.containsKey("webSocketDebuggerUrl")) { // NOI18N
+                                return new URI(object.get("webSocketDebuggerUrl").toString()); // NOI18N
+                            }
+                        }
+                    }
+                }
+            } catch (IOException | ParseException | URISyntaxException ex) {
+                LOGGER.log(Level.FINE, "Cannot get websocket address, trying again...", ex);
+                try {
+                    Thread.sleep(500);
+                } catch (InterruptedException ex1) {
+                    Exceptions.printStackTrace(ex1);
+                }
+            }
+        }
+        if (array != null) {
+            LOGGER.info(array.toJSONString());
+        }
+
+        NotifyDescriptor not = new NotifyDescriptor(
+                Bundle.ERR_CouldNotConnect(),
+                Bundle.LBL_UriTitle(),
+                NotifyDescriptor.DEFAULT_OPTION,
+                NotifyDescriptor.WARNING_MESSAGE,
+                new Object[]{NotifyDescriptor.OK_OPTION},
+                null);
+        DialogDisplayer.getDefault().notify(not);
+        LOGGER.info("Cannot get websocket address.");
+        return null;
+    }
+
+    @Override
+    public void flush() {
+        flush=true;
+    }
+}
diff --git a/cordova.platforms.android/src/org/netbeans/modules/cordova/platforms/android/AndroidDevice.java b/cordova.platforms.android/src/org/netbeans/modules/cordova/platforms/android/AndroidDevice.java
new file mode 100644
index 0000000000..a7773ed6fe
--- /dev/null
+++ b/cordova.platforms.android/src/org/netbeans/modules/cordova/platforms/android/AndroidDevice.java
@@ -0,0 +1,188 @@
+/*
+ * 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.cordova.platforms.android;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Properties;
+import java.util.logging.Logger;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import org.netbeans.api.project.Project;
+import org.netbeans.modules.cordova.platforms.spi.Device;
+import org.netbeans.modules.cordova.platforms.spi.MobileDebugTransport;
+import org.netbeans.modules.cordova.platforms.spi.MobilePlatform;
+import org.netbeans.modules.cordova.platforms.api.ProcessUtilities;
+import org.netbeans.modules.cordova.platforms.spi.PropertyProvider;
+import org.netbeans.modules.web.clientproject.spi.platform.ProjectConfigurationCustomizer;
+import org.netbeans.spi.project.ActionProvider;
+import org.openide.util.EditableProperties;
+import org.openide.util.Exceptions;
+
+/**
+ *
+ * @author Jan Becicka
+ */
+public class AndroidDevice implements Device {
+    
+    public static Collection<org.netbeans.modules.cordova.platforms.spi.Device> parse(String output) throws IOException {
+        BufferedReader r = new BufferedReader(new StringReader(output));
+
+        Pattern pattern = Pattern.compile("([-\\w]+)\\s+([\\w]+) *"); //NOI18N
+
+        ArrayList<org.netbeans.modules.cordova.platforms.spi.Device> result = new ArrayList<org.netbeans.modules.cordova.platforms.spi.Device>();
+        //ignore first line
+
+        String line = r.readLine();
+
+        while (((line = r.readLine()) != null)) {
+            Matcher m = pattern.matcher(line);
+            if (m.matches()) {
+                final String name = m.group(1);
+                AndroidDevice device = new AndroidDevice(name, Browser.DEFAULT, name.startsWith("emulator")); // NOI18N
+                result.add(device);
+            }
+        }
+        return result;
+    }
+    
+    private Browser browser;
+
+    @Override
+    public void openUrl(String url) {
+        try {
+            if (browser == browser.DEFAULT) {
+            ProcessUtilities.callProcess(
+                    ((AndroidPlatform) getPlatform()).getAdbCommand(), 
+                    true,
+                    AndroidPlatform.DEFAULT_TIMEOUT,
+                    isEmulator() ? "-e" : "-d", // NOI18N
+                    "wait-for-device", // NOI18N
+                    "shell", // NOI18N
+                    "am", // NOI18N
+                    "start", // NOI18N
+                    "-e", // NOI18N
+                    "com.android.browser.application_id", // NOI18N
+                    "org.netbeans.modules.cordova", // NOI18N
+                    "-a", // NOI18N
+                    "android.intent.action.VIEW", // NOI18N
+                    url); //NOI18N
+            } else {
+            ProcessUtilities.callProcess(
+                    ((AndroidPlatform) getPlatform()).getAdbCommand(), 
+                    true, 
+                    AndroidPlatform.DEFAULT_TIMEOUT,
+                    isEmulator() ? "-e" : "-d", // NOI18N
+                    "wait-for-device", // NOI18N
+                    "shell", // NOI18N
+                    "am", // NOI18N
+                    "start", // NOI18N
+                    "-e", // NOI18N
+                    "com.android.browser.application_id", // NOI18N
+                    "org.netbeans.modules.cordova", // NOI18N
+                    "-a", // NOI18N
+                    "android.intent.action.VIEW", // NOI18N
+                    "-n", // NOI18N
+                    getPrefferedBrowser(), 
+                    url); //NOI18N
+            }
+        } catch (IOException ex) {
+            Exceptions.printStackTrace(ex);
+        }
+    }
+    
+    static Device get(String name, EditableProperties props) {
+        final String property = props.getProperty(Device.DEVICE_PROP);
+        final boolean b = Device.EMULATOR.equals(property);
+        String property1 = props.getProperty(Device.BROWSER_PROP);
+        if (property1!=null && property1.equals(Browser.CHROME.getName())) {
+            return new AndroidDevice(name, Browser.CHROME, b);
+        }
+
+        return new AndroidDevice(name, Browser.DEFAULT, b);
+    }
+    
+    private final String name;
+    private boolean emulator;
+
+    public AndroidDevice(String name, Browser browser, boolean emulator) {
+        this.name = name;
+        this.browser = browser;
+        this.emulator = emulator;
+    }
+    
+    public boolean isEmulator() {
+        return emulator; //NOI18N
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    @Override
+    public String toString() {
+        return "Device{" + "name=" + name + ", emulator: " + isEmulator() + '}'; //NOI18N
+    }
+
+    @Override
+    public MobilePlatform getPlatform() {
+        return AndroidPlatform.getDefault();
+    }
+    
+    @Override
+    public MobileDebugTransport getDebugTransport() {
+        return new AndroidDebugTransport();
+    }
+
+    @Override
+    public void addProperties(Properties props) {
+        final MobilePlatform android = getPlatform();
+        if (android.isReady()) {
+            if (android.getPrefferedTarget() != null) {
+                props.put("android.build.target", android.getPrefferedTarget().getName());//NOI18N
+            }
+            props.put("android.sdk.home", android.getSdkLocation());//NOI18N
+            props.put("android.target.device.arg", isEmulator() ? "emulate" : "run");//NOI18N
+        } else {
+            Logger.getLogger(AndroidDevice.class.getName()).fine("Android not configured.");
+        }
+    }
+
+    @Override
+    public ActionProvider getActionProvider(Project p) {
+        return new AndroidActionProvider(p);
+    }
+
+    @Override
+    public ProjectConfigurationCustomizer getProjectConfigurationCustomizer(Project project, PropertyProvider aThis) {
+        return new AndroidConfigurationPanel.AndroidConfigurationCustomizer(project, aThis);
+    }
+
+    private String getPrefferedBrowser() {
+        return browser.getCommand();
+    }
+
+    @Override
+    public boolean isWebViewDebugSupported() {
+        return AndroidPlatform.getDefault().isWebViewDebugSupported(isEmulator());
+    }
+}
diff --git a/cordova.platforms.android/src/org/netbeans/modules/cordova/platforms/android/AndroidPlatform.java b/cordova.platforms.android/src/org/netbeans/modules/cordova/platforms/android/AndroidPlatform.java
new file mode 100644
index 0000000000..cb5345c754
--- /dev/null
+++ b/cordova.platforms.android/src/org/netbeans/modules/cordova/platforms/android/AndroidPlatform.java
@@ -0,0 +1,416 @@
+/*
+ * 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.cordova.platforms.android;
+
+import java.io.BufferedReader;
+import org.netbeans.modules.cordova.platforms.spi.MobilePlatform;
+import java.io.File;
+import java.io.IOException;
+import java.io.StringReader;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import javax.swing.SwingUtilities;
+import org.apache.tools.ant.module.api.support.ActionUtils;
+import org.netbeans.modules.cordova.platforms.spi.Device;
+import org.netbeans.modules.cordova.platforms.api.PlatformManager;
+import org.netbeans.modules.cordova.platforms.api.ProcessUtilities;
+import org.netbeans.modules.cordova.platforms.spi.ProvisioningProfile;
+import org.netbeans.modules.cordova.platforms.spi.SDK;
+import org.openide.execution.ExecutorTask;
+import org.openide.filesystems.FileObject;
+import org.openide.filesystems.FileUtil;
+import org.openide.util.EditableProperties;
+import org.openide.util.Exceptions;
+import org.openide.util.NbPreferences;
+import org.openide.util.RequestProcessor;
+import org.openide.util.Utilities;
+import org.openide.util.lookup.ServiceProvider;
+
+/**
+ *
+ * @author Jan Becicka
+ */
+@ServiceProvider(service=MobilePlatform.class)
+public class AndroidPlatform implements MobilePlatform {
+    
+    private static String ANDROID_SDK_ROOT_PREF = "android.sdk.home"; //NOI18N
+    
+    public static int DEFAULT_TIMEOUT = 30000;
+
+    private transient final java.beans.PropertyChangeSupport propertyChangeSupport = new java.beans.PropertyChangeSupport(this);
+    
+    public AndroidPlatform() {
+    }
+    
+    public static AndroidPlatform getDefault() {
+        return (AndroidPlatform) PlatformManager.getPlatform(PlatformManager.ANDROID_TYPE);
+    }
+
+//    public void createProject(File dir, String targetId, String projectName, String activityName, String packageName) throws IOException {
+//        ProcessBuilder pb = ProcessBuilder.getLocal();
+//        pb.setExecutable(getSdkLocation() + "/tools/android");
+//        pb.setArguments(
+//        Arrays.asList(
+//                "create", "project", 
+//                "--target", targetId,
+//                "--name", projectName,
+//                "--path", dir.getPath(),
+//                "--activity", activityName,
+//                "--package", packageName
+//                ));
+//        pb.setWorkingDirectory(dir.getParentFile().getAbsolutePath());
+//        try {
+//            Process call = pb.call();
+//            call.waitFor();
+//            InputStreamReader inputStreamReader = new InputStreamReader(new BufferedInputStream(call.getErrorStream()));
+//            if (call.exitValue() != 0) {
+//                StringBuilder error = new StringBuilder();
+//                char[] ch = new char[1];
+//                while (inputStreamReader.ready()) {
+//                    inputStreamReader.read(ch);
+//                    error.append(ch);
+//                }
+//                throw new IOException(error.toString());
+//            }
+//        } catch (InterruptedException ex) {
+//            throw new IOException(ex);
+//        }
+//    }
+    
+    @Override
+    public Collection<Device> getVirtualDevices() throws IOException {
+        assert !SwingUtilities.isEventDispatchThread();
+        String avdString = ProcessUtilities.callProcess(getAndroidCommand(), true, AndroidPlatform.DEFAULT_TIMEOUT, "list", "avd"); //NOI18N
+        return AVD.parse(avdString);
+    }
+    
+    private String getAndroidCommand() {
+        if (Utilities.isWindows()) {
+            return getSdkLocation() + "\\tools\\android.bat"; // NOI18N
+        } else {
+            return getSdkLocation() + "/tools/android"; // NOI18N
+        }
+    }
+    
+    String getAdbCommand() {
+        if (Utilities.isWindows()) {
+            return getSdkLocation() + "\\platform-tools\\adb.exe"; // NOI18N
+        } else {
+            return getSdkLocation() + "/platform-tools/adb"; // NOI18N
+
+        }
+    }
+    
+
+    @Override
+    public Collection<SDK> getSDKs() throws IOException {
+        //assert !SwingUtilities.isEventDispatchThread();
+        String avdString = ProcessUtilities.callProcess(getAndroidCommand(), true, 30000, "list", "target");//NOI18N
+        return Target.parse(avdString);
+    }
+    
+    private final HashSet<String> targets = new HashSet<String>(Arrays.asList(new String[]{
+            "android-14", //NOI18N
+            "android-15", //NOI18N
+            "android-16", //NOI18N
+            "android-17", //NOI18N
+            "android-18", //NOI18N
+            "android-19", //NOI18N
+            "android-20", //NOI18N
+            "android-21", //NOI18N
+            "android-22"})); //NOI18N
+    
+    
+    @Override
+    public SDK getPrefferedTarget() {
+        try {
+            final Collection<SDK> targets1 = getSDKs();
+            for (SDK t: targets1) {
+                if (targets.contains(t.getName())) {
+                    return t;
+                }
+            }
+            if (targets1.iterator().hasNext()) {
+                return targets1.iterator().next();
+            }
+        } catch (IOException ex) {
+            Exceptions.printStackTrace(ex);
+        }
+        return null;
+    }
+    
+    
+    @Override
+    public Collection<org.netbeans.modules.cordova.platforms.spi.Device> getConnectedDevices() throws IOException {
+        //assert !SwingUtilities.isEventDispatchThread();
+        String avdString = ProcessUtilities.callProcess(getAdbCommand(), true, AndroidPlatform.DEFAULT_TIMEOUT, "devices"); //NOI18N
+        Collection<org.netbeans.modules.cordova.platforms.spi.Device> devices = AndroidDevice.parse(avdString);
+        if (devices.isEmpty()) {
+            //maybe adb is just down. try to restart adb
+            try {
+                ProcessUtilities.callProcess(getAdbCommand(), true, AndroidPlatform.DEFAULT_TIMEOUT, "kill-server"); //NOI18N
+                ProcessUtilities.callProcess(getAdbCommand(), true, AndroidPlatform.DEFAULT_TIMEOUT, "start-server"); //NOI18N
+            } catch (IOException ioe) {
+                //ignore
+            }
+        }
+        avdString = ProcessUtilities.callProcess(getAdbCommand(), true, AndroidPlatform.DEFAULT_TIMEOUT, "devices"); //NOI18N
+        devices = AndroidDevice.parse(avdString);
+        return devices;
+    }
+    
+    
+    public ExecutorTask buildProject(File dir, String... targets) throws IOException {
+        File build = new File(dir.getAbsolutePath() + File.separator + "build.xml"); //NOI18N
+        FileObject buildFo = FileUtil.toFileObject(build);
+        return ActionUtils.runTarget(buildFo, targets, null);
+    }
+    
+    /**
+     * Deletes dir and all subdirectories/files!
+     * @param dir
+     * @throws IOException 
+     */
+    public void cleanProject(File dir) throws IOException {
+        FileUtil.toFileObject(dir).delete();
+    }
+
+    @Override
+    public String getSdkLocation() {
+        String sdkLocation = NbPreferences.forModule(AndroidPlatform.class).get(ANDROID_SDK_ROOT_PREF, null);
+        if (sdkLocation != null && !sdkLocation.isEmpty()) {
+            return sdkLocation;
+        } else {
+            return getSdkFromAndroidHome();
+        }
+    }
+
+    @Override
+    public void setSdkLocation(String sdkLocation) {
+        NbPreferences.forModule(AndroidPlatform.class).put(ANDROID_SDK_ROOT_PREF, sdkLocation);
+        propertyChangeSupport.firePropertyChange("SDK", null, sdkLocation);//NOI18N
+    }
+    
+    @Override
+    public boolean waitEmulatorReady(int timeout) {
+        try {
+            return RequestProcessor.getDefault().invokeAny(Collections.singleton(new Callable<Boolean>() {
+
+                    @Override
+                    public Boolean call() throws Exception {
+                        return waitEmulatorReady();
+                    }
+                }), timeout, TimeUnit.SECONDS);
+        } catch (InterruptedException ex) {
+        } catch (ExecutionException ex) {
+        } catch (TimeoutException ex) {
+        }
+        return false;
+        
+    }
+    
+    private boolean waitEmulatorReady() {
+        try {
+            String value;
+            for(;;) {
+                value = ProcessUtilities.callProcess(
+                        getAdbCommand(), 
+                        true, 
+                        -1, 
+                        "-e", // NOI18N
+                        "wait-for-device", // NOI18N
+                        "shell", // NOI18N
+                        "getprop", // NOI18N
+                        "init.svc.bootanim"); //NOI18N
+                if ("stopped".equals(value.trim())) { //NOI18N
+                    return true;
+                }
+                try {
+                    Thread.sleep(1000);
+                } catch (InterruptedException ex) {
+                    Exceptions.printStackTrace(ex);
+                }
+            } 
+            
+        } catch (IOException ex) {
+            Exceptions.printStackTrace(ex);
+        }
+        return false;
+        
+    }
+
+    @Override
+    public void manageDevices() {
+        assert !SwingUtilities.isEventDispatchThread();
+        try {
+            ProcessUtilities.callProcess(getAndroidCommand(), true, -1, "avd"); //NOI18N
+        } catch (IOException ex) {
+            Exceptions.printStackTrace(ex);
+        }
+    }
+
+    @Override
+    public boolean isReady() {
+        return getSdkLocation() != null && !getSdkLocation().isEmpty();
+    }
+    
+    /**
+     * Add PropertyChangeListener.
+     *
+     * @param listener
+     */
+    @Override
+    public void addPropertyChangeListener(java.beans.PropertyChangeListener listener ) {
+        propertyChangeSupport.addPropertyChangeListener( listener );
+    }
+
+    /**
+     * Remove PropertyChangeListener.
+     *
+     * @param listener
+     */
+    @Override
+    public void removePropertyChangeListener(java.beans.PropertyChangeListener listener ) {
+        propertyChangeSupport.removePropertyChangeListener( listener );
+    }
+
+
+    @Override
+    public String getType() {
+        return PlatformManager.ANDROID_TYPE;
+    }
+
+    @Override
+    public String getSimulatorPath() {
+        throw new UnsupportedOperationException("Not supported yet."); // NOI18N
+    }
+
+    @Override
+    public Device getDevice(String name, EditableProperties props) {
+        return AndroidDevice.get(name, props);
+    }
+
+    @Override
+    public String getCodeSignIdentity() {
+        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. // NOI18N
+    }
+
+    @Override
+    public String getProvisioningProfilePath() {
+        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. // NOI18N
+    }
+
+    @Override
+    public void setCodeSignIdentity(String identity) {
+        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. // NOI18N
+    }
+
+    @Override
+    public void setProvisioningProfilePath(String path) {
+        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. // NOI18N
+    }
+
+    @Override
+    public Collection<? extends ProvisioningProfile> getProvisioningProfiles() {
+        return Collections.emptyList();
+    }
+
+    public String getProcessIdByName(String appName) {
+        try {
+            String result = ProcessUtilities.callProcess(getAdbCommand(), true, AndroidPlatform.DEFAULT_TIMEOUT, "shell", "ps"); //NOI18N
+            BufferedReader r = new BufferedReader(new StringReader(result));
+            String line;
+            while ((line = r.readLine()) != null) {
+                if (line.trim().endsWith(appName)) {
+                    Pattern column = Pattern.compile("(\\S+)(\\s+)(\\S+)(\\s+)(.+)");
+                    Matcher matcher = column.matcher(line);
+                    if (matcher.matches()) {
+                        return matcher.group(3);
+                    }
+                }
+            } 
+        } catch (IOException ex) {
+            Exceptions.printStackTrace(ex);
+        }
+        return null;
+    }
+
+    boolean isWebViewDebugSupported(boolean emulator) {
+        try {
+            String version = ProcessUtilities.callProcess(
+                    getAdbCommand(),
+                    true,
+                    -1,
+                    emulator?"-e":"-d", // NOI18N
+                    "wait-for-device", // NOI18N
+                    "shell", // NOI18N
+                    "getprop", //NOI18N
+                    "ro.build.version.release"); //NOI18N
+            
+            return version.compareTo("4.4") >= 0;
+        } catch (IOException ex) {
+            Exceptions.printStackTrace(ex);
+            return false;
+        }
+        
+        
+    }
+
+    /**
+     * Sets the Android SDK location from ANDROID_HOME environment variable, if
+     * available.
+     *
+     * @return Android SDK Location or <code>null</code> if Android SDK could
+     * not be found.
+     */
+    private String getSdkFromAndroidHome() {
+        String androidHomeValue = System.getenv("ANDROID_HOME"); //NOI18N
+        if (androidHomeValue != null && !androidHomeValue.isEmpty()) {
+            File androidLoc = new File(androidHomeValue);
+            File androidTools = new File(androidLoc, "platform-tools"); //NOI18N
+            boolean validSdk = androidLoc.exists() && androidLoc.isDirectory()
+                    && androidTools.exists() && androidTools.isDirectory();
+            if (validSdk) {
+                NbPreferences.forModule(AndroidPlatform.class).put(ANDROID_SDK_ROOT_PREF, androidHomeValue);
+                return androidHomeValue;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Performs a check whether adb executable is available
+     *
+     * @return <code>true</code> if adb command has been found,
+     * <code>false</code> otherwise
+     */
+    boolean adbCommandExists() {
+        return Files.exists(Paths.get(getAdbCommand()));
+    }
+}
diff --git a/cordova.platforms.android/src/org/netbeans/modules/cordova/platforms/android/Browser.java b/cordova.platforms.android/src/org/netbeans/modules/cordova/platforms/android/Browser.java
new file mode 100644
index 0000000000..f63bf5bb28
--- /dev/null
+++ b/cordova.platforms.android/src/org/netbeans/modules/cordova/platforms/android/Browser.java
@@ -0,0 +1,46 @@
+/*
+ * 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.cordova.platforms.android;
+
+/**
+ *
+ * @author Jan Becicka
+ */
+public enum Browser {
+    
+    DEFAULT("default", "com.android.browser/.BrowserActivity"), // NOI18N
+    CHROME("chrome", "com.android.chrome/com.google.android.apps.chrome.Main"); // NOI18N
+    
+    private String name;
+    private String command;
+    
+    private Browser (String name, String command) {
+        this.name = name;
+        this.command = command;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public String getCommand() {
+        return command;
+    }
+    
+}
diff --git a/cordova.platforms.android/src/org/netbeans/modules/cordova/platforms/android/Bundle.properties b/cordova.platforms.android/src/org/netbeans/modules/cordova/platforms/android/Bundle.properties
new file mode 100644
index 0000000000..cc0add8c94
--- /dev/null
+++ b/cordova.platforms.android/src/org/netbeans/modules/cordova/platforms/android/Bundle.properties
@@ -0,0 +1,32 @@
+# 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.
+build-ios=Build iOS
+build-android=Build Android
+OpenIDE-Module-Display-Category=HTML5
+OpenIDE-Module-Long-Description=\
+    Android Platform for Cordova
+OpenIDE-Module-Short-Description=Android Platform
+sim-ios=Run iOS
+sim-android=Run Android
+clean-ios=Clean iOS
+clean-android=Clean Android
+AndroidConfigurationPanel.manageButton.text=Manage...
+AndroidConfigurationPanel.deviceLabel.text=&Device:
+AndroidConfigurationPanel.avdLabel.text=&AVD:
+AndroidConfigurationPanel.debuggerCheckBox.text=&Enable Debugging
+OpenIDE-Module-Name=Android Platform
+AndroidConfigurationPanel.jLabel1.text=Browser:
diff --git a/cordova.platforms.android/src/org/netbeans/modules/cordova/platforms/android/EnhancedBrowserProviderImpl.java b/cordova.platforms.android/src/org/netbeans/modules/cordova/platforms/android/EnhancedBrowserProviderImpl.java
new file mode 100644
index 0000000000..d22dadd90c
--- /dev/null
+++ b/cordova.platforms.android/src/org/netbeans/modules/cordova/platforms/android/EnhancedBrowserProviderImpl.java
@@ -0,0 +1,66 @@
+/*
+ * 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.cordova.platforms.android;
+
+import org.netbeans.api.project.Project;
+import org.netbeans.modules.cordova.platforms.api.ClientProjectUtilities;
+import org.netbeans.modules.web.browser.api.BrowserFamilyId;
+import org.netbeans.modules.web.browser.api.BrowserSupport;
+import org.netbeans.modules.web.browser.api.WebBrowser;
+import org.netbeans.modules.web.clientproject.spi.platform.ClientProjectEnhancedBrowserImplementation;
+import org.netbeans.modules.web.clientproject.spi.platform.ClientProjectEnhancedBrowserProvider;
+import org.netbeans.spi.project.ActionProvider;
+import org.netbeans.spi.project.LookupProvider;
+import org.netbeans.spi.project.ProjectServiceProvider;
+import org.openide.util.Parameters;
+
+/**
+ * @author Jan Becicka
+ */
+@ProjectServiceProvider(
+       projectTypes = {
+           @LookupProvider.Registration.ProjectType(id = "org-netbeans-modules-web-clientproject")
+       },
+       service = ClientProjectEnhancedBrowserProvider.class)
+public class EnhancedBrowserProviderImpl implements ClientProjectEnhancedBrowserProvider {
+    private Project p;
+
+    public EnhancedBrowserProviderImpl(Project p) {
+        Parameters.notNull("Project", p);
+        this.p = p;
+    }
+    
+    @Override
+    public ClientProjectEnhancedBrowserImplementation getEnhancedBrowser(final WebBrowser webBrowser) {
+        if (webBrowser == null) {
+            return null;
+        }
+        if (BrowserFamilyId.ANDROID == webBrowser.getBrowserFamily()) {
+            BrowserSupport support = BrowserSupport.create(webBrowser);
+            return ClientProjectUtilities.createMobileBrowser(
+                    p, 
+                    webBrowser, 
+                    support, 
+                    new AndroidBrowserActionProvider(support, webBrowser.getId(), p));
+        }
+        return null;
+    }
+
+}
diff --git a/cordova.platforms.android/src/org/netbeans/modules/cordova/platforms/android/RefreshListener.java b/cordova.platforms.android/src/org/netbeans/modules/cordova/platforms/android/RefreshListener.java
new file mode 100644
index 0000000000..dad1c7065e
--- /dev/null
+++ b/cordova.platforms.android/src/org/netbeans/modules/cordova/platforms/android/RefreshListener.java
@@ -0,0 +1,41 @@
+/*
+ * 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.cordova.platforms.android;
+
+import org.netbeans.modules.web.clientproject.spi.platform.RefreshOnSaveListener;
+import org.openide.filesystems.FileObject;
+
+/**
+ * @author Jan Becicka
+ */
+public class RefreshListener implements RefreshOnSaveListener {
+
+    public RefreshListener() {
+    }
+    
+    @Override
+    public void fileChanged(FileObject fo) {
+    }
+
+    @Override
+    public void fileDeleted(FileObject fo) {
+    }
+
+}
diff --git a/cordova.platforms.android/src/org/netbeans/modules/cordova/platforms/android/Target.java b/cordova.platforms.android/src/org/netbeans/modules/cordova/platforms/android/Target.java
new file mode 100644
index 0000000000..641442765a
--- /dev/null
+++ b/cordova.platforms.android/src/org/netbeans/modules/cordova/platforms/android/Target.java
@@ -0,0 +1,99 @@
+/*
+ * 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.cordova.platforms.android;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.logging.Logger;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import org.netbeans.modules.cordova.platforms.spi.SDK;
+
+/**
+ *
+ * @author Jan Becicka
+ */
+public class Target implements SDK {
+
+    private String name;
+    private HashMap<String, String> props;
+    private int id;
+    private static final Logger LOG = Logger.getLogger(Target.class.getName());
+
+    private Target() {
+        this.props = new HashMap();
+    }
+    
+    public static Collection<SDK> parse(String output) throws IOException {
+        BufferedReader r = new BufferedReader(new StringReader(output));
+        
+        Pattern pattern = Pattern.compile("id: ([\\d]*) or \"([^\"]+)\" *"); //NOI18N
+        
+        ArrayList<SDK> result = new ArrayList<SDK>();
+        //ignore first 2 lines
+        r.readLine();
+        r.readLine();
+        
+        Target current = new Target();
+        String lastProp = null;
+        String line = r.readLine();
+        while (line != null) {
+            Matcher m = pattern.matcher(line);
+            if (m.matches()) {
+                current.id = Integer.parseInt(m.group(1));
+                current.name = m.group(2);
+            } else {
+                if (line.contains("---------")) { //NOI18N
+                    result.add(current);
+                    current = new Target();
+                } else {
+                    //current.props.put(lastProp, current.props.get(lastProp) + line);
+                }
+            }
+            line = r.readLine();
+            if (line == null) {
+                result.add(current);
+            }
+        }
+        if (result.isEmpty()) {
+            LOG.warning("no targets found");
+            LOG.warning("output:" + output);
+        }
+        return result;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    @Override
+    public String toString() {
+        return "Target{" + "id=" + id + ", name=" + name + '}'; //NOI18N
+    }
+
+    @Override
+    public String getIdentifier() {
+        return Integer.toString(id);
+    }
+}
diff --git a/cordova.platforms.android/src/org/netbeans/modules/cordova/platforms/android/androiddevice.png b/cordova.platforms.android/src/org/netbeans/modules/cordova/platforms/android/androiddevice.png
new file mode 100644
index 0000000000..d926e7b265
Binary files /dev/null and b/cordova.platforms.android/src/org/netbeans/modules/cordova/platforms/android/androiddevice.png differ
diff --git a/cordova.platforms.android/src/org/netbeans/modules/cordova/platforms/android/androiddevice16.png b/cordova.platforms.android/src/org/netbeans/modules/cordova/platforms/android/androiddevice16.png
new file mode 100644
index 0000000000..2bb55e7f4c
Binary files /dev/null and b/cordova.platforms.android/src/org/netbeans/modules/cordova/platforms/android/androiddevice16.png differ
diff --git a/cordova.platforms.android/src/org/netbeans/modules/cordova/platforms/android/androidemulator.png b/cordova.platforms.android/src/org/netbeans/modules/cordova/platforms/android/androidemulator.png
new file mode 100644
index 0000000000..67b0c633dd
Binary files /dev/null and b/cordova.platforms.android/src/org/netbeans/modules/cordova/platforms/android/androidemulator.png differ
diff --git a/cordova.platforms.android/src/org/netbeans/modules/cordova/platforms/android/androidemulator16.png b/cordova.platforms.android/src/org/netbeans/modules/cordova/platforms/android/androidemulator16.png
new file mode 100644
index 0000000000..f9e0586e84
Binary files /dev/null and b/cordova.platforms.android/src/org/netbeans/modules/cordova/platforms/android/androidemulator16.png differ
diff --git a/cordova.platforms.ios/build.xml b/cordova.platforms.ios/build.xml
new file mode 100644
index 0000000000..794af7c170
--- /dev/null
+++ b/cordova.platforms.ios/build.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    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.
+
+-->
+<project basedir="." default="netbeans" name="cordova.platforms.ios">
+    <description>Builds, tests, and runs the project org.netbeans.modules.cordova.platforms.ios</description>
+    <import file="../nbbuild/templates/projectized.xml"/>
+</project>
diff --git a/cordova.platforms.ios/external/binaries-list b/cordova.platforms.ios/external/binaries-list
new file mode 100644
index 0000000000..183c5c3d36
--- /dev/null
+++ b/cordova.platforms.ios/external/binaries-list
@@ -0,0 +1,5 @@
+7C4A82593A85524A3541E55A4A9C906B773ABAD6 ios-sim
+0929AC5F40B5A8667021408748D64F30F77B3165 libiDeviceNativeBinding.dylib
+480C9E376169E21EA3BDA5D5841425BD7CC054D7 libplist.1.dylib
+C1BB9FF4232248B0054E5A26A33474A251EA19CB libusbmuxd.2.dylib
+2A38DA3DB5D36DBBDC0B03990B46810F72430D5E libimobiledevice.4.dylib
diff --git a/cordova.platforms.ios/external/ios-sim-license.txt b/cordova.platforms.ios/external/ios-sim-license.txt
new file mode 100644
index 0000000000..0bc095e53b
--- /dev/null
+++ b/cordova.platforms.ios/external/ios-sim-license.txt
@@ -0,0 +1,37 @@
+Name: ios-sim
+Version: 
+Description: Command-line application launcher for the iOS Simulator
+License: MIT-sim
+Origin: https://github.com/phonegap/ios-sim
+Files: ios-sim
+
+Author: Landon Fuller <la...@plausiblelabs.com>
+Copyright (c) 2008-2011 Plausible Labs Cooperative, Inc.
+All rights reserved.
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Modifications made by the following entities are licensed as above:
+- Jeff Haynie, Appcelerator, Inc.
+- https://github.com/hborders
+- http://pivotallabs.com/users/scoward/blog
+- Eloy Duran, Fingertips <el...@fngtps.com>
diff --git a/cordova.platforms.ios/external/libimobiledevice-license.txt b/cordova.platforms.ios/external/libimobiledevice-license.txt
new file mode 100644
index 0000000000..00c57f9c0c
--- /dev/null
+++ b/cordova.platforms.ios/external/libimobiledevice-license.txt
@@ -0,0 +1,509 @@
+Name: imobiledevice
+Version: 1.1.5
+Description: A protocol library to access an iOS Devices
+License: LGPL-2.1
+Origin: http://cgit.sukimashita.com/libimobiledevice.git/
+Files: libimobiledevice.4.dylib
+
+GNU LESSER GENERAL PUBLIC LICENSE
+		       Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL.  It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+  This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it.  You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+  When we speak of free software, we are referring to freedom of use,
+not price.  Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+  To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights.  These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+  For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you.  You must make sure that they, too, receive or can get the source
+code.  If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it.  And you must show them these terms so they know their rights.
+
+  We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+  To protect each distributor, we want to make it very clear that
+there is no warranty for the free library.  Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+  Finally, software patents pose a constant threat to the existence of
+any free program.  We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder.  Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+  Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License.  This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License.  We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+  When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library.  The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom.  The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+  We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License.  It also provides other free software developers Less
+of an advantage over competing non-free programs.  These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries.  However, the Lesser license provides advantages in certain
+special circumstances.
+
+  For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard.  To achieve this, non-free programs must be
+allowed to use the library.  A more frequent case is that a free
+library does the same job as widely used non-free libraries.  In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+  In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software.  For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+  Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.  Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library".  The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+		  GNU LESSER GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+  A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+  The "Library", below, refers to any such software library or work
+which has been distributed under these terms.  A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language.  (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+  "Source code" for a work means the preferred form of the work for
+making modifications to it.  For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+  Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it).  Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+  
+  1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+  You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+  2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) The modified work must itself be a software library.
+
+    b) You must cause the files modified to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    c) You must cause the whole of the work to be licensed at no
+    charge to all third parties under the terms of this License.
+
+    d) If a facility in the modified Library refers to a function or a
+    table of data to be supplied by an application program that uses
+    the facility, other than as an argument passed when the facility
+    is invoked, then you must make a good faith effort to ensure that,
+    in the event an application does not supply such function or
+    table, the facility still operates, and performs whatever part of
+    its purpose remains meaningful.
+
+    (For example, a function in a library to compute square roots has
+    a purpose that is entirely well-defined independent of the
+    application.  Therefore, Subsection 2d requires that any
+    application-supplied function or table used by this function must
+    be optional: if the application does not supply it, the square
+    root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library.  To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License.  (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.)  Do not make any other change in
+these notices.
+
+  Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+  This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+  4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+  If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library".  Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+  However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library".  The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+  When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library.  The
+threshold for this to be true is not precisely defined by law.
+
+  If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work.  (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+  Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+  6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+  You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License.  You must supply a copy of this License.  If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License.  Also, you must do one
+of these things:
+
+    a) Accompany the work with the complete corresponding
+    machine-readable source code for the Library including whatever
+    changes were used in the work (which must be distributed under
+    Sections 1 and 2 above); and, if the work is an executable linked
+    with the Library, with the complete machine-readable "work that
+    uses the Library", as object code and/or source code, so that the
+    user can modify the Library and then relink to produce a modified
+    executable containing the modified Library.  (It is understood
+    that the user who changes the contents of definitions files in the
+    Library will not necessarily be able to recompile the application
+    to use the modified definitions.)
+
+    b) Use a suitable shared library mechanism for linking with the
+    Library.  A suitable mechanism is one that (1) uses at run time a
+    copy of the library already present on the user's computer system,
+    rather than copying library functions into the executable, and (2)
+    will operate properly with a modified version of the library, if
+    the user installs one, as long as the modified version is
+    interface-compatible with the version that the work was made with.
+
+    c) Accompany the work with a written offer, valid for at
+    least three years, to give the same user the materials
+    specified in Subsection 6a, above, for a charge no more
+    than the cost of performing this distribution.
+
+    d) If distribution of the work is made by offering access to copy
+    from a designated place, offer equivalent access to copy the above
+    specified materials from the same place.
+
+    e) Verify that the user has already received a copy of these
+    materials or that you have already sent this user a copy.
+
+  For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it.  However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+  It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system.  Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+  7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+    a) Accompany the combined library with a copy of the same work
+    based on the Library, uncombined with any other library
+    facilities.  This must be distributed under the terms of the
+    Sections above.
+
+    b) Give prominent notice with the combined library of the fact
+    that part of it is a work based on the Library, and explaining
+    where to find the accompanying uncombined form of the same work.
+
+  8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License.  Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License.  However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+  9. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Library or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+  10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+  11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded.  In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+  13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation.  If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+  14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission.  For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this.  Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+			    NO WARRANTY
+
+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+           How to Apply These Terms to Your New Libraries
+
+  If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change.  You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+  To apply these terms, attach the following notices to the library.  It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the library's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
+  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+  <signature of Ty Coon>, 1 April 1990
+  Ty Coon, President of Vice
+
+That's all there is to it!
\ No newline at end of file
diff --git a/cordova.platforms.ios/external/libplist-license.txt b/cordova.platforms.ios/external/libplist-license.txt
new file mode 100644
index 0000000000..fc13005086
--- /dev/null
+++ b/cordova.platforms.ios/external/libplist-license.txt
@@ -0,0 +1,509 @@
+Name: plist
+Version: 1.10
+Description: A library to handle Apple Property List format in binary or XML
+License: LGPL-2.1
+Origin: http://cgit.sukimashita.com/libplist.git/
+Files: libplist.1.dylib
+
+GNU LESSER GENERAL PUBLIC LICENSE
+		       Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL.  It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+  This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it.  You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+  When we speak of free software, we are referring to freedom of use,
+not price.  Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+  To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights.  These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+  For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you.  You must make sure that they, too, receive or can get the source
+code.  If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it.  And you must show them these terms so they know their rights.
+
+  We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+  To protect each distributor, we want to make it very clear that
+there is no warranty for the free library.  Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+  Finally, software patents pose a constant threat to the existence of
+any free program.  We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder.  Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+  Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License.  This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License.  We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+  When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library.  The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom.  The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+  We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License.  It also provides other free software developers Less
+of an advantage over competing non-free programs.  These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries.  However, the Lesser license provides advantages in certain
+special circumstances.
+
+  For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard.  To achieve this, non-free programs must be
+allowed to use the library.  A more frequent case is that a free
+library does the same job as widely used non-free libraries.  In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+  In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software.  For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+  Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.  Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library".  The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+		  GNU LESSER GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+  A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+  The "Library", below, refers to any such software library or work
+which has been distributed under these terms.  A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language.  (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+  "Source code" for a work means the preferred form of the work for
+making modifications to it.  For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+  Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it).  Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+  
+  1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+  You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+  2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) The modified work must itself be a software library.
+
+    b) You must cause the files modified to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    c) You must cause the whole of the work to be licensed at no
+    charge to all third parties under the terms of this License.
+
+    d) If a facility in the modified Library refers to a function or a
+    table of data to be supplied by an application program that uses
+    the facility, other than as an argument passed when the facility
+    is invoked, then you must make a good faith effort to ensure that,
+    in the event an application does not supply such function or
+    table, the facility still operates, and performs whatever part of
+    its purpose remains meaningful.
+
+    (For example, a function in a library to compute square roots has
+    a purpose that is entirely well-defined independent of the
+    application.  Therefore, Subsection 2d requires that any
+    application-supplied function or table used by this function must
+    be optional: if the application does not supply it, the square
+    root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library.  To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License.  (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.)  Do not make any other change in
+these notices.
+
+  Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+  This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+  4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+  If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library".  Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+  However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library".  The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+  When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library.  The
+threshold for this to be true is not precisely defined by law.
+
+  If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work.  (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+  Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+  6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+  You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License.  You must supply a copy of this License.  If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License.  Also, you must do one
+of these things:
+
+    a) Accompany the work with the complete corresponding
+    machine-readable source code for the Library including whatever
+    changes were used in the work (which must be distributed under
+    Sections 1 and 2 above); and, if the work is an executable linked
+    with the Library, with the complete machine-readable "work that
+    uses the Library", as object code and/or source code, so that the
+    user can modify the Library and then relink to produce a modified
+    executable containing the modified Library.  (It is understood
+    that the user who changes the contents of definitions files in the
+    Library will not necessarily be able to recompile the application
+    to use the modified definitions.)
+
+    b) Use a suitable shared library mechanism for linking with the
+    Library.  A suitable mechanism is one that (1) uses at run time a
+    copy of the library already present on the user's computer system,
+    rather than copying library functions into the executable, and (2)
+    will operate properly with a modified version of the library, if
+    the user installs one, as long as the modified version is
+    interface-compatible with the version that the work was made with.
+
+    c) Accompany the work with a written offer, valid for at
+    least three years, to give the same user the materials
+    specified in Subsection 6a, above, for a charge no more
+    than the cost of performing this distribution.
+
+    d) If distribution of the work is made by offering access to copy
+    from a designated place, offer equivalent access to copy the above
+    specified materials from the same place.
+
+    e) Verify that the user has already received a copy of these
+    materials or that you have already sent this user a copy.
+
+  For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it.  However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+  It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system.  Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+  7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+    a) Accompany the combined library with a copy of the same work
+    based on the Library, uncombined with any other library
+    facilities.  This must be distributed under the terms of the
+    Sections above.
+
+    b) Give prominent notice with the combined library of the fact
+    that part of it is a work based on the Library, and explaining
+    where to find the accompanying uncombined form of the same work.
+
+  8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License.  Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License.  However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+  9. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Library or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+  10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+  11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded.  In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+  13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation.  If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+  14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission.  For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this.  Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+			    NO WARRANTY
+
+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+           How to Apply These Terms to Your New Libraries
+
+  If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change.  You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+  To apply these terms, attach the following notices to the library.  It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the library's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
+  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+  <signature of Ty Coon>, 1 April 1990
+  Ty Coon, President of Vice
+
+That's all there is to it!
\ No newline at end of file
diff --git a/cordova.platforms.ios/external/libusbmuxd-license.txt b/cordova.platforms.ios/external/libusbmuxd-license.txt
new file mode 100644
index 0000000000..ddaa57ee8f
--- /dev/null
+++ b/cordova.platforms.ios/external/libusbmuxd-license.txt
@@ -0,0 +1,509 @@
+Name: usbmuxd
+Version: 1.0.8
+Description: A socket library to multiplex connections from and to an iOS Devices
+License: LGPL-2.1
+Origin: http://cgit.sukimashita.com/usbmuxd.git/
+Files: libusbmuxd.2.dylib
+
+GNU LESSER GENERAL PUBLIC LICENSE
+		       Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL.  It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+  This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it.  You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+  When we speak of free software, we are referring to freedom of use,
+not price.  Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+  To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights.  These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+  For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you.  You must make sure that they, too, receive or can get the source
+code.  If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it.  And you must show them these terms so they know their rights.
+
+  We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+  To protect each distributor, we want to make it very clear that
+there is no warranty for the free library.  Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+  Finally, software patents pose a constant threat to the existence of
+any free program.  We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder.  Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+  Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License.  This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License.  We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+  When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library.  The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom.  The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+  We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License.  It also provides other free software developers Less
+of an advantage over competing non-free programs.  These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries.  However, the Lesser license provides advantages in certain
+special circumstances.
+
+  For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard.  To achieve this, non-free programs must be
+allowed to use the library.  A more frequent case is that a free
+library does the same job as widely used non-free libraries.  In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+  In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software.  For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+  Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.  Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library".  The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+		  GNU LESSER GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+  A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+  The "Library", below, refers to any such software library or work
+which has been distributed under these terms.  A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language.  (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+  "Source code" for a work means the preferred form of the work for
+making modifications to it.  For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+  Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it).  Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+  
+  1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+  You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+  2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) The modified work must itself be a software library.
+
+    b) You must cause the files modified to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    c) You must cause the whole of the work to be licensed at no
+    charge to all third parties under the terms of this License.
+
+    d) If a facility in the modified Library refers to a function or a
+    table of data to be supplied by an application program that uses
+    the facility, other than as an argument passed when the facility
+    is invoked, then you must make a good faith effort to ensure that,
+    in the event an application does not supply such function or
+    table, the facility still operates, and performs whatever part of
+    its purpose remains meaningful.
+
+    (For example, a function in a library to compute square roots has
+    a purpose that is entirely well-defined independent of the
+    application.  Therefore, Subsection 2d requires that any
+    application-supplied function or table used by this function must
+    be optional: if the application does not supply it, the square
+    root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library.  To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License.  (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.)  Do not make any other change in
+these notices.
+
+  Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+  This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+  4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+  If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library".  Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+  However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library".  The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+  When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library.  The
+threshold for this to be true is not precisely defined by law.
+
+  If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work.  (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+  Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+  6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+  You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License.  You must supply a copy of this License.  If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License.  Also, you must do one
+of these things:
+
+    a) Accompany the work with the complete corresponding
+    machine-readable source code for the Library including whatever
+    changes were used in the work (which must be distributed under
+    Sections 1 and 2 above); and, if the work is an executable linked
+    with the Library, with the complete machine-readable "work that
+    uses the Library", as object code and/or source code, so that the
+    user can modify the Library and then relink to produce a modified
+    executable containing the modified Library.  (It is understood
+    that the user who changes the contents of definitions files in the
+    Library will not necessarily be able to recompile the application
+    to use the modified definitions.)
+
+    b) Use a suitable shared library mechanism for linking with the
+    Library.  A suitable mechanism is one that (1) uses at run time a
+    copy of the library already present on the user's computer system,
+    rather than copying library functions into the executable, and (2)
+    will operate properly with a modified version of the library, if
+    the user installs one, as long as the modified version is
+    interface-compatible with the version that the work was made with.
+
+    c) Accompany the work with a written offer, valid for at
+    least three years, to give the same user the materials
+    specified in Subsection 6a, above, for a charge no more
+    than the cost of performing this distribution.
+
+    d) If distribution of the work is made by offering access to copy
+    from a designated place, offer equivalent access to copy the above
+    specified materials from the same place.
+
+    e) Verify that the user has already received a copy of these
+    materials or that you have already sent this user a copy.
+
+  For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it.  However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+  It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system.  Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+  7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+    a) Accompany the combined library with a copy of the same work
+    based on the Library, uncombined with any other library
+    facilities.  This must be distributed under the terms of the
+    Sections above.
+
+    b) Give prominent notice with the combined library of the fact
+    that part of it is a work based on the Library, and explaining
+    where to find the accompanying uncombined form of the same work.
+
+  8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License.  Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License.  However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+  9. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Library or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+  10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+  11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded.  In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+  13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation.  If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+  14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission.  For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this.  Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+			    NO WARRANTY
+
+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+           How to Apply These Terms to Your New Libraries
+
+  If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change.  You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+  To apply these terms, attach the following notices to the library.  It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the library's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
+  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+  <signature of Ty Coon>, 1 April 1990
+  Ty Coon, President of Vice
+
+That's all there is to it!
\ No newline at end of file
diff --git a/cordova.platforms.ios/iDeviceNativeBinding/Makefile b/cordova.platforms.ios/iDeviceNativeBinding/Makefile
new file mode 100644
index 0000000000..4dda6db143
--- /dev/null
+++ b/cordova.platforms.ios/iDeviceNativeBinding/Makefile
@@ -0,0 +1,145 @@
+# 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.
+
+#
+#  There exist several targets which are by default empty and which can be 
+#  used for execution of your targets. These targets are usually executed 
+#  before and after some main targets. They are: 
+#
+#     .build-pre:              called before 'build' target
+#     .build-post:             called after 'build' target
+#     .clean-pre:              called before 'clean' target
+#     .clean-post:             called after 'clean' target
+#     .clobber-pre:            called before 'clobber' target
+#     .clobber-post:           called after 'clobber' target
+#     .all-pre:                called before 'all' target
+#     .all-post:               called after 'all' target
+#     .help-pre:               called before 'help' target
+#     .help-post:              called after 'help' target
+#
+#  Targets beginning with '.' are not intended to be called on their own.
+#
+#  Main targets can be executed directly, and they are:
+#  
+#     build                    build a specific configuration
+#     clean                    remove built files from a configuration
+#     clobber                  remove all built files
+#     all                      build all configurations
+#     help                     print help mesage
+#  
+#  Targets .build-impl, .clean-impl, .clobber-impl, .all-impl, and
+#  .help-impl are implemented in nbproject/makefile-impl.mk.
+#
+#  Available make variables:
+#
+#     CND_BASEDIR                base directory for relative paths
+#     CND_DISTDIR                default top distribution directory (build artifacts)
+#     CND_BUILDDIR               default top build directory (object files, ...)
+#     CONF                       name of current configuration
+#     CND_PLATFORM_${CONF}       platform name (current configuration)
+#     CND_ARTIFACT_DIR_${CONF}   directory of build artifact (current configuration)
+#     CND_ARTIFACT_NAME_${CONF}  name of build artifact (current configuration)
+#     CND_ARTIFACT_PATH_${CONF}  path to build artifact (current configuration)
+#     CND_PACKAGE_DIR_${CONF}    directory of package (current configuration)
+#     CND_PACKAGE_NAME_${CONF}   name of package (current configuration)
+#     CND_PACKAGE_PATH_${CONF}   path to package (current configuration)
+#
+# NOCDDL
+
+
+# Environment 
+MKDIR=mkdir
+CP=cp
+CCADMIN=CCadmin
+
+
+# build
+build: .build-post
+
+.build-pre:
+# Add your pre 'build' code here...
+
+.build-post: .build-impl
+# Add your post 'build' code here...
+
+
+# clean
+clean: .clean-post
+
+.clean-pre:
+# Add your pre 'clean' code here...
+
+.clean-post: .clean-impl
+# Add your post 'clean' code here...
+
+
+# clobber
+clobber: .clobber-post
+
+.clobber-pre:
+# Add your pre 'clobber' code here...
+
+.clobber-post: .clobber-impl
+# Add your post 'clobber' code here...
+
+
+# all
+all: .all-post
+
+.all-pre:
+# Add your pre 'all' code here...
+
+.all-post: .all-impl
+# Add your post 'all' code here...
+
+
+# build tests
+build-tests: .build-tests-post
+
+.build-tests-pre:
+# Add your pre 'build-tests' code here...
+
+.build-tests-post: .build-tests-impl
+# Add your post 'build-tests' code here...
+
+
+# run tests
+test: .test-post
+
+.test-pre: build-tests
+# Add your pre 'test' code here...
+
+.test-post: .test-impl
+# Add your post 'test' code here...
+
+
+# help
+help: .help-post
+
+.help-pre:
+# Add your pre 'help' code here...
+
+.help-post: .help-impl
+# Add your post 'help' code here...
+
+
+
+# include project implementation makefile
+include nbproject/Makefile-impl.mk
+
+# include project make variables
+include nbproject/Makefile-variables.mk
diff --git a/cordova.platforms.ios/iDeviceNativeBinding/nbproject/Makefile-Debug.mk b/cordova.platforms.ios/iDeviceNativeBinding/nbproject/Makefile-Debug.mk
new file mode 100644
index 0000000000..2d801a0217
--- /dev/null
+++ b/cordova.platforms.ios/iDeviceNativeBinding/nbproject/Makefile-Debug.mk
@@ -0,0 +1,86 @@
+#
+# Generated Makefile - do not edit!
+#
+# Edit the Makefile in the project folder instead (../Makefile). Each target
+# has a -pre and a -post target defined where you can add customized code.
+#
+# This makefile implements configuration specific macros and targets.
+
+
+# Environment
+MKDIR=mkdir
+CP=cp
+GREP=grep
+NM=nm
+CCADMIN=CCadmin
+RANLIB=ranlib
+CC=gcc
+CCC=g++
+CXX=g++
+FC=gfortran
+AS=as
+
+# Macros
+CND_PLATFORM=GNU-MacOSX
+CND_DLIB_EXT=dylib
+CND_CONF=Debug
+CND_DISTDIR=dist
+CND_BUILDDIR=build
+
+# Include project Makefile
+include Makefile
+
+# Object Directory
+OBJECTDIR=${CND_BUILDDIR}/${CND_CONF}/${CND_PLATFORM}
+
+# Object Files
+OBJECTFILES= \
+	${OBJECTDIR}/webinspectorjni.o
+
+
+# C Compiler Flags
+CFLAGS=
+
+# CC Compiler Flags
+CCFLAGS=
+CXXFLAGS=
+
+# Fortran Compiler Flags
+FFLAGS=
+
+# Assembler Flags
+ASFLAGS=
+
+# Link Libraries and Options
+LDLIBSOPTIONS=-L/usr/local/lib -limobiledevice /opt/local/lib/libplist.dylib
+
+# Build Targets
+.build-conf: ${BUILD_SUBPROJECTS}
+	"${MAKE}"  -f nbproject/Makefile-${CND_CONF}.mk ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/libiDeviceNativeBinding.${CND_DLIB_EXT}
+
+${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/libiDeviceNativeBinding.${CND_DLIB_EXT}: /opt/local/lib/libplist.dylib
+
+${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/libiDeviceNativeBinding.${CND_DLIB_EXT}: ${OBJECTFILES}
+	${MKDIR} -p ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}
+	${LINK.c} -o ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/libiDeviceNativeBinding.${CND_DLIB_EXT} ${OBJECTFILES} ${LDLIBSOPTIONS} -dynamiclib -install_name libiDeviceNativeBinding.${CND_DLIB_EXT} -fPIC
+
+${OBJECTDIR}/webinspectorjni.o: webinspectorjni.c 
+	${MKDIR} -p ${OBJECTDIR}
+	${RM} $@.d
+	$(COMPILE.c) -g -I/Library/Java/JavaVirtualMachines/jdk1.7.0_17.jdk/Contents/Home/include/ -I/opt/local/include -I/Library/Java/JavaVirtualMachines/jdk1.7.0_17.jdk/Contents/Home/include/darwin -fPIC  -MMD -MP -MF $@.d -o ${OBJECTDIR}/webinspectorjni.o webinspectorjni.c
+
+# Subprojects
+.build-subprojects:
+
+# Clean Targets
+.clean-conf: ${CLEAN_SUBPROJECTS}
+	${RM} -r ${CND_BUILDDIR}/${CND_CONF}
+	${RM} ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/libiDeviceNativeBinding.${CND_DLIB_EXT}
+
+# Subprojects
+.clean-subprojects:
+
+# Enable dependency checking
+.dep.inc: .depcheck-impl
+
+include .dep.inc
diff --git a/cordova.platforms.ios/iDeviceNativeBinding/nbproject/Makefile-Release.mk b/cordova.platforms.ios/iDeviceNativeBinding/nbproject/Makefile-Release.mk
new file mode 100644
index 0000000000..2ad667ce3b
--- /dev/null
+++ b/cordova.platforms.ios/iDeviceNativeBinding/nbproject/Makefile-Release.mk
@@ -0,0 +1,86 @@
+#
+# Generated Makefile - do not edit!
+#
+# Edit the Makefile in the project folder instead (../Makefile). Each target
+# has a -pre and a -post target defined where you can add customized code.
+#
+# This makefile implements configuration specific macros and targets.
+
+
+# Environment
+MKDIR=mkdir
+CP=cp
+GREP=grep
+NM=nm
+CCADMIN=CCadmin
+RANLIB=ranlib
+CC=gcc
+CCC=g++
+CXX=g++
+FC=gfortran
+AS=as
+
+# Macros
+CND_PLATFORM=GNU-MacOSX
+CND_DLIB_EXT=dylib
+CND_CONF=Release
+CND_DISTDIR=dist
+CND_BUILDDIR=build
+
+# Include project Makefile
+include Makefile
+
+# Object Directory
+OBJECTDIR=${CND_BUILDDIR}/${CND_CONF}/${CND_PLATFORM}
+
+# Object Files
+OBJECTFILES= \
+	${OBJECTDIR}/webinspectorjni.o
+
+
+# C Compiler Flags
+CFLAGS=
+
+# CC Compiler Flags
+CCFLAGS=
+CXXFLAGS=
+
+# Fortran Compiler Flags
+FFLAGS=
+
+# Assembler Flags
+ASFLAGS=
+
+# Link Libraries and Options
+LDLIBSOPTIONS=-L/usr/local/lib -limobiledevice /opt/local/lib/libplist.dylib
+
+# Build Targets
+.build-conf: ${BUILD_SUBPROJECTS}
+	"${MAKE}"  -f nbproject/Makefile-${CND_CONF}.mk ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/libiDeviceNativeBinding.${CND_DLIB_EXT}
+
+${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/libiDeviceNativeBinding.${CND_DLIB_EXT}: /opt/local/lib/libplist.dylib
+
+${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/libiDeviceNativeBinding.${CND_DLIB_EXT}: ${OBJECTFILES}
+	${MKDIR} -p ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}
+	${LINK.c} -o ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/libiDeviceNativeBinding.${CND_DLIB_EXT} ${OBJECTFILES} ${LDLIBSOPTIONS} -dynamiclib -install_name libiDeviceNativeBinding.${CND_DLIB_EXT} -fPIC
+
+${OBJECTDIR}/webinspectorjni.o: webinspectorjni.c 
+	${MKDIR} -p ${OBJECTDIR}
+	${RM} $@.d
+	$(COMPILE.c) -O2 -I/Library/Java/JavaVirtualMachines/jdk1.7.0_17.jdk/Contents/Home/include -I/opt/local/include -I/Library/Java/JavaVirtualMachines/jdk1.7.0_17.jdk/Contents/Home/include/darwin -fPIC  -MMD -MP -MF $@.d -o ${OBJECTDIR}/webinspectorjni.o webinspectorjni.c
+
+# Subprojects
+.build-subprojects:
+
+# Clean Targets
+.clean-conf: ${CLEAN_SUBPROJECTS}
+	${RM} -r ${CND_BUILDDIR}/${CND_CONF}
+	${RM} ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/libiDeviceNativeBinding.${CND_DLIB_EXT}
+
+# Subprojects
+.clean-subprojects:
+
+# Enable dependency checking
+.dep.inc: .depcheck-impl
+
+include .dep.inc
diff --git a/cordova.platforms.ios/iDeviceNativeBinding/nbproject/Makefile-impl.mk b/cordova.platforms.ios/iDeviceNativeBinding/nbproject/Makefile-impl.mk
new file mode 100644
index 0000000000..2c0ac75ec3
--- /dev/null
+++ b/cordova.platforms.ios/iDeviceNativeBinding/nbproject/Makefile-impl.mk
@@ -0,0 +1,133 @@
+# 
+# Generated Makefile - do not edit! 
+# 
+# Edit the Makefile in the project folder instead (../Makefile). Each target
+# has a pre- and a post- target defined where you can add customization code.
+#
+# This makefile implements macros and targets common to all configurations.
+#
+# NOCDDL
+
+
+# Building and Cleaning subprojects are done by default, but can be controlled with the SUB
+# macro. If SUB=no, subprojects will not be built or cleaned. The following macro
+# statements set BUILD_SUB-CONF and CLEAN_SUB-CONF to .build-reqprojects-conf
+# and .clean-reqprojects-conf unless SUB has the value 'no'
+SUB_no=NO
+SUBPROJECTS=${SUB_${SUB}}
+BUILD_SUBPROJECTS_=.build-subprojects
+BUILD_SUBPROJECTS_NO=
+BUILD_SUBPROJECTS=${BUILD_SUBPROJECTS_${SUBPROJECTS}}
+CLEAN_SUBPROJECTS_=.clean-subprojects
+CLEAN_SUBPROJECTS_NO=
+CLEAN_SUBPROJECTS=${CLEAN_SUBPROJECTS_${SUBPROJECTS}}
+
+
+# Project Name
+PROJECTNAME=iDeviceNativeBinding
+
+# Active Configuration
+DEFAULTCONF=Debug
+CONF=${DEFAULTCONF}
+
+# All Configurations
+ALLCONFS=Debug Release 
+
+
+# build
+.build-impl: .build-pre .validate-impl .depcheck-impl
+	@#echo "=> Running $@... Configuration=$(CONF)"
+	"${MAKE}" -f nbproject/Makefile-${CONF}.mk QMAKE=${QMAKE} SUBPROJECTS=${SUBPROJECTS} .build-conf
+
+
+# clean
+.clean-impl: .clean-pre .validate-impl .depcheck-impl
+	@#echo "=> Running $@... Configuration=$(CONF)"
+	"${MAKE}" -f nbproject/Makefile-${CONF}.mk QMAKE=${QMAKE} SUBPROJECTS=${SUBPROJECTS} .clean-conf
+
+
+# clobber 
+.clobber-impl: .clobber-pre .depcheck-impl
+	@#echo "=> Running $@..."
+	for CONF in ${ALLCONFS}; \
+	do \
+	    "${MAKE}" -f nbproject/Makefile-$${CONF}.mk QMAKE=${QMAKE} SUBPROJECTS=${SUBPROJECTS} .clean-conf; \
+	done
+
+# all 
+.all-impl: .all-pre .depcheck-impl
+	@#echo "=> Running $@..."
+	for CONF in ${ALLCONFS}; \
+	do \
+	    "${MAKE}" -f nbproject/Makefile-$${CONF}.mk QMAKE=${QMAKE} SUBPROJECTS=${SUBPROJECTS} .build-conf; \
+	done
+
+# build tests
+.build-tests-impl: .build-impl .build-tests-pre
+	@#echo "=> Running $@... Configuration=$(CONF)"
+	"${MAKE}" -f nbproject/Makefile-${CONF}.mk SUBPROJECTS=${SUBPROJECTS} .build-tests-conf
+
+# run tests
+.test-impl: .build-tests-impl .test-pre
+	@#echo "=> Running $@... Configuration=$(CONF)"
+	"${MAKE}" -f nbproject/Makefile-${CONF}.mk SUBPROJECTS=${SUBPROJECTS} .test-conf
+
+# dependency checking support
+.depcheck-impl:
+	@echo "# This code depends on make tool being used" >.dep.inc
+	@if [ -n "${MAKE_VERSION}" ]; then \
+	    echo "DEPFILES=\$$(wildcard \$$(addsuffix .d, \$${OBJECTFILES}))" >>.dep.inc; \
+	    echo "ifneq (\$${DEPFILES},)" >>.dep.inc; \
+	    echo "include \$${DEPFILES}" >>.dep.inc; \
+	    echo "endif" >>.dep.inc; \
+	else \
+	    echo ".KEEP_STATE:" >>.dep.inc; \
+	    echo ".KEEP_STATE_FILE:.make.state.\$${CONF}" >>.dep.inc; \
+	fi
+
+# configuration validation
+.validate-impl:
+	@if [ ! -f nbproject/Makefile-${CONF}.mk ]; \
+	then \
+	    echo ""; \
+	    echo "Error: can not find the makefile for configuration '${CONF}' in project ${PROJECTNAME}"; \
+	    echo "See 'make help' for details."; \
+	    echo "Current directory: " `pwd`; \
+	    echo ""; \
+	fi
+	@if [ ! -f nbproject/Makefile-${CONF}.mk ]; \
+	then \
+	    exit 1; \
+	fi
+
+
+# help
+.help-impl: .help-pre
+	@echo "This makefile supports the following configurations:"
+	@echo "    ${ALLCONFS}"
+	@echo ""
+	@echo "and the following targets:"
+	@echo "    build  (default target)"
+	@echo "    clean"
+	@echo "    clobber"
+	@echo "    all"
+	@echo "    help"
+	@echo ""
+	@echo "Makefile Usage:"
+	@echo "    make [CONF=<CONFIGURATION>] [SUB=no] build"
+	@echo "    make [CONF=<CONFIGURATION>] [SUB=no] clean"
+	@echo "    make [SUB=no] clobber"
+	@echo "    make [SUB=no] all"
+	@echo "    make help"
+	@echo ""
+	@echo "Target 'build' will build a specific configuration and, unless 'SUB=no',"
+	@echo "    also build subprojects."
+	@echo "Target 'clean' will clean a specific configuration and, unless 'SUB=no',"
+	@echo "    also clean subprojects."
+	@echo "Target 'clobber' will remove all built files from all configurations and,"
+	@echo "    unless 'SUB=no', also from subprojects."
+	@echo "Target 'all' will will build all configurations and, unless 'SUB=no',"
+	@echo "    also build subprojects."
+	@echo "Target 'help' prints this message."
+	@echo ""
+
diff --git a/cordova.platforms.ios/iDeviceNativeBinding/nbproject/Makefile-variables.mk b/cordova.platforms.ios/iDeviceNativeBinding/nbproject/Makefile-variables.mk
new file mode 100644
index 0000000000..e8e5e9b79f
--- /dev/null
+++ b/cordova.platforms.ios/iDeviceNativeBinding/nbproject/Makefile-variables.mk
@@ -0,0 +1,35 @@
+#
+# Generated - do not edit!
+#
+# NOCDDL
+#
+CND_BASEDIR=`pwd`
+CND_BUILDDIR=build
+CND_DISTDIR=dist
+# Debug configuration
+CND_PLATFORM_Debug=GNU-MacOSX
+CND_ARTIFACT_DIR_Debug=dist/Debug/GNU-MacOSX
+CND_ARTIFACT_NAME_Debug=libiDeviceNativeBinding.dylib
+CND_ARTIFACT_PATH_Debug=dist/Debug/GNU-MacOSX/libiDeviceNativeBinding.dylib
+CND_PACKAGE_DIR_Debug=dist/Debug/GNU-MacOSX/package
+CND_PACKAGE_NAME_Debug=libiDeviceNativeBinding.dylib.tar
+CND_PACKAGE_PATH_Debug=dist/Debug/GNU-MacOSX/package/libiDeviceNativeBinding.dylib.tar
+# Release configuration
+CND_PLATFORM_Release=GNU-MacOSX
+CND_ARTIFACT_DIR_Release=dist/Release/GNU-MacOSX
+CND_ARTIFACT_NAME_Release=libiDeviceNativeBinding.dylib
+CND_ARTIFACT_PATH_Release=dist/Release/GNU-MacOSX/libiDeviceNativeBinding.dylib
+CND_PACKAGE_DIR_Release=dist/Release/GNU-MacOSX/package
+CND_PACKAGE_NAME_Release=libiDeviceNativeBinding.dylib.tar
+CND_PACKAGE_PATH_Release=dist/Release/GNU-MacOSX/package/libiDeviceNativeBinding.dylib.tar
+#
+# include compiler specific variables
+#
+# dmake command
+ROOT:sh = test -f nbproject/private/Makefile-variables.mk || \
+	(mkdir -p nbproject/private && touch nbproject/private/Makefile-variables.mk)
+#
+# gmake command
+.PHONY: $(shell test -f nbproject/private/Makefile-variables.mk || (mkdir -p nbproject/private && touch nbproject/private/Makefile-variables.mk))
+#
+include nbproject/private/Makefile-variables.mk
diff --git a/cordova.platforms.ios/iDeviceNativeBinding/nbproject/Package-Debug.bash b/cordova.platforms.ios/iDeviceNativeBinding/nbproject/Package-Debug.bash
new file mode 100644
index 0000000000..f4bccace8a
--- /dev/null
+++ b/cordova.platforms.ios/iDeviceNativeBinding/nbproject/Package-Debug.bash
@@ -0,0 +1,76 @@
+#!/bin/bash -x
+
+#
+# Generated - do not edit!
+#
+
+# Macros
+TOP=`pwd`
+CND_PLATFORM=GNU-MacOSX
+CND_CONF=Debug
+CND_DISTDIR=dist
+CND_BUILDDIR=build
+CND_DLIB_EXT=dylib
+NBTMPDIR=${CND_BUILDDIR}/${CND_CONF}/${CND_PLATFORM}/tmp-packaging
+TMPDIRNAME=tmp-packaging
+OUTPUT_PATH=${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/libiDeviceNativeBinding.${CND_DLIB_EXT}
+OUTPUT_BASENAME=libiDeviceNativeBinding.${CND_DLIB_EXT}
+PACKAGE_TOP_DIR=libiDeviceNativeBinding.dylib/
+
+# Functions
+function checkReturnCode
+{
+    rc=$?
+    if [ $rc != 0 ]
+    then
+        exit $rc
+    fi
+}
+function makeDirectory
+# $1 directory path
+# $2 permission (optional)
+{
+    mkdir -p "$1"
+    checkReturnCode
+    if [ "$2" != "" ]
+    then
+      chmod $2 "$1"
+      checkReturnCode
+    fi
+}
+function copyFileToTmpDir
+# $1 from-file path
+# $2 to-file path
+# $3 permission
+{
+    cp "$1" "$2"
+    checkReturnCode
+    if [ "$3" != "" ]
+    then
+        chmod $3 "$2"
+        checkReturnCode
+    fi
+}
+
+# Setup
+cd "${TOP}"
+mkdir -p ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/package
+rm -rf ${NBTMPDIR}
+mkdir -p ${NBTMPDIR}
+
+# Copy files and create directories and links
+cd "${TOP}"
+makeDirectory "${NBTMPDIR}/libiDeviceNativeBinding.dylib/lib"
+copyFileToTmpDir "${OUTPUT_PATH}" "${NBTMPDIR}/${PACKAGE_TOP_DIR}lib/${OUTPUT_BASENAME}" 0644
+
+
+# Generate tar file
+cd "${TOP}"
+rm -f ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/package/libiDeviceNativeBinding.dylib.tar
+cd ${NBTMPDIR}
+tar -vcf ../../../../${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/package/libiDeviceNativeBinding.dylib.tar *
+checkReturnCode
+
+# Cleanup
+cd "${TOP}"
+rm -rf ${NBTMPDIR}
diff --git a/cordova.platforms.ios/iDeviceNativeBinding/nbproject/Package-Release.bash b/cordova.platforms.ios/iDeviceNativeBinding/nbproject/Package-Release.bash
new file mode 100644
index 0000000000..7a6248d0a8
--- /dev/null
+++ b/cordova.platforms.ios/iDeviceNativeBinding/nbproject/Package-Release.bash
@@ -0,0 +1,76 @@
+#!/bin/bash -x
+
+#
+# Generated - do not edit!
+#
+
+# Macros
+TOP=`pwd`
+CND_PLATFORM=GNU-MacOSX
+CND_CONF=Release
+CND_DISTDIR=dist
+CND_BUILDDIR=build
+CND_DLIB_EXT=dylib
+NBTMPDIR=${CND_BUILDDIR}/${CND_CONF}/${CND_PLATFORM}/tmp-packaging
+TMPDIRNAME=tmp-packaging
+OUTPUT_PATH=${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/libiDeviceNativeBinding.${CND_DLIB_EXT}
+OUTPUT_BASENAME=libiDeviceNativeBinding.${CND_DLIB_EXT}
+PACKAGE_TOP_DIR=libiDeviceNativeBinding.dylib/
+
+# Functions
+function checkReturnCode
+{
+    rc=$?
+    if [ $rc != 0 ]
+    then
+        exit $rc
+    fi
+}
+function makeDirectory
+# $1 directory path
+# $2 permission (optional)
+{
+    mkdir -p "$1"
+    checkReturnCode
+    if [ "$2" != "" ]
+    then
+      chmod $2 "$1"
+      checkReturnCode
+    fi
+}
+function copyFileToTmpDir
+# $1 from-file path
+# $2 to-file path
+# $3 permission
+{
+    cp "$1" "$2"
+    checkReturnCode
+    if [ "$3" != "" ]
+    then
+        chmod $3 "$2"
+        checkReturnCode
+    fi
+}
+
+# Setup
+cd "${TOP}"
+mkdir -p ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/package
+rm -rf ${NBTMPDIR}
+mkdir -p ${NBTMPDIR}
+
+# Copy files and create directories and links
+cd "${TOP}"
+makeDirectory "${NBTMPDIR}/libiDeviceNativeBinding.dylib/lib"
+copyFileToTmpDir "${OUTPUT_PATH}" "${NBTMPDIR}/${PACKAGE_TOP_DIR}lib/${OUTPUT_BASENAME}" 0644
+
+
+# Generate tar file
+cd "${TOP}"
+rm -f ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/package/libiDeviceNativeBinding.dylib.tar
+cd ${NBTMPDIR}
+tar -vcf ../../../../${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/package/libiDeviceNativeBinding.dylib.tar *
+checkReturnCode
+
+# Cleanup
+cd "${TOP}"
+rm -rf ${NBTMPDIR}
diff --git a/cordova.platforms.ios/iDeviceNativeBinding/nbproject/configurations.xml b/cordova.platforms.ios/iDeviceNativeBinding/nbproject/configurations.xml
new file mode 100644
index 0000000000..af40ba221f
--- /dev/null
+++ b/cordova.platforms.ios/iDeviceNativeBinding/nbproject/configurations.xml
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    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.
+
+-->
+<configurationDescriptor version="88">
+  <logicalFolder name="root" displayName="root" projectFiles="true" kind="ROOT">
+    <logicalFolder name="HeaderFiles"
+                   displayName="Header Files"
+                   projectFiles="true">
+    </logicalFolder>
+    <logicalFolder name="ResourceFiles"
+                   displayName="Resource Files"
+                   projectFiles="true">
+    </logicalFolder>
+    <logicalFolder name="SourceFiles"
+                   displayName="Source Files"
+                   projectFiles="true">
+      <itemPath>webinspectorjni.c</itemPath>
+    </logicalFolder>
+    <logicalFolder name="TestFiles"
+                   displayName="Test Files"
+                   projectFiles="false"
+                   kind="TEST_LOGICAL_FOLDER">
+    </logicalFolder>
+    <logicalFolder name="ExternalFiles"
+                   displayName="Important Files"
+                   projectFiles="false"
+                   kind="IMPORTANT_FILES_FOLDER">
+      <itemPath>Makefile</itemPath>
+    </logicalFolder>
+  </logicalFolder>
+  <projectmakefile>Makefile</projectmakefile>
+  <confs>
+    <conf name="Debug" type="2">
+      <toolsSet>
+        <remote-sources-mode>LOCAL_SOURCES</remote-sources-mode>
+        <compilerSet>default</compilerSet>
+      </toolsSet>
+      <compileType>
+        <cTool>
+          <incDir>
+            <pElem>/Library/Java/JavaVirtualMachines/jdk1.7.0_17.jdk/Contents/Home/include/</pElem>
+            <pElem>/opt/local/include</pElem>
+            <pElem>/Library/Java/JavaVirtualMachines/jdk1.7.0_17.jdk/Contents/Home/include/darwin</pElem>
+          </incDir>
+        </cTool>
+        <linkerTool>
+          <linkerAddLib>
+            <pElem>/usr/local/lib</pElem>
+          </linkerAddLib>
+          <linkerLibItems>
+            <linkerLibLibItem>imobiledevice</linkerLibLibItem>
+            <linkerLibFileItem>/opt/local/lib/libplist.dylib</linkerLibFileItem>
+          </linkerLibItems>
+        </linkerTool>
+      </compileType>
+      <item path="webinspectorjni.c" ex="false" tool="0" flavor2="0">
+      </item>
+    </conf>
+    <conf name="Release" type="2">
+      <toolsSet>
+        <remote-sources-mode>LOCAL_SOURCES</remote-sources-mode>
+        <compilerSet>default</compilerSet>
+      </toolsSet>
+      <compileType>
+        <cTool>
+          <developmentMode>5</developmentMode>
+          <incDir>
+            <pElem>/Library/Java/JavaVirtualMachines/jdk1.7.0_17.jdk/Contents/Home/include</pElem>
+            <pElem>/opt/local/include</pElem>
+            <pElem>/Library/Java/JavaVirtualMachines/jdk1.7.0_17.jdk/Contents/Home/include/darwin</pElem>
+          </incDir>
+        </cTool>
+        <ccTool>
+          <developmentMode>5</developmentMode>
+        </ccTool>
+        <fortranCompilerTool>
+          <developmentMode>5</developmentMode>
+        </fortranCompilerTool>
+        <asmTool>
+          <developmentMode>5</developmentMode>
+        </asmTool>
+        <linkerTool>
+          <linkerAddLib>
+            <pElem>/usr/local/lib</pElem>
+          </linkerAddLib>
+          <linkerLibItems>
+            <linkerLibLibItem>imobiledevice</linkerLibLibItem>
+            <linkerLibFileItem>/opt/local/lib/libplist.dylib</linkerLibFileItem>
+          </linkerLibItems>
+        </linkerTool>
+      </compileType>
+      <item path="webinspectorjni.c" ex="false" tool="0" flavor2="0">
+      </item>
+    </conf>
+  </confs>
+</configurationDescriptor>
diff --git a/cordova.platforms.ios/iDeviceNativeBinding/nbproject/project.xml b/cordova.platforms.ios/iDeviceNativeBinding/nbproject/project.xml
new file mode 100644
index 0000000000..2d6a8d65bd
--- /dev/null
+++ b/cordova.platforms.ios/iDeviceNativeBinding/nbproject/project.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    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.
+
+-->
+<project xmlns="http://www.netbeans.org/ns/project/1">
+    <type>org.netbeans.modules.cnd.makeproject</type>
+    <configuration>
+        <data xmlns="http://www.netbeans.org/ns/make-project/1">
+            <name>iDeviceNativeBinding</name>
+            <c-extensions>c</c-extensions>
+            <cpp-extensions/>
+            <header-extensions/>
+            <sourceEncoding>UTF-8</sourceEncoding>
+            <make-dep-projects/>
+            <sourceRootList/>
+            <confList>
+                <confElem>
+                    <name>Debug</name>
+                    <type>2</type>
+                </confElem>
+                <confElem>
+                    <name>Release</name>
+                    <type>2</type>
+                </confElem>
+            </confList>
+        </data>
+    </configuration>
+</project>
diff --git a/cordova.platforms.ios/iDeviceNativeBinding/webinspectorjni.c b/cordova.platforms.ios/iDeviceNativeBinding/webinspectorjni.c
new file mode 100644
index 0000000000..915113b7cf
--- /dev/null
+++ b/cordova.platforms.ios/iDeviceNativeBinding/webinspectorjni.c
@@ -0,0 +1,126 @@
+/*
+ * 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.
+ */
+#include <jni.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <libimobiledevice/libimobiledevice.h>
+#include <libimobiledevice/webinspector.h>
+
+static webinspector_client_t client = NULL;
+static idevice_t device = NULL;
+
+JNIEXPORT void JNICALL Java_org_netbeans_modules_cordova_platforms_ios_WebInspectorJNIBinding_nstart(JNIEnv * env, jobject thiz) {
+    if (IDEVICE_E_SUCCESS != idevice_new(&device, NULL)) {
+        throwException(env, "No device found");
+        return;
+    }
+
+    webinspector_error_t error = webinspector_client_start_service(device, &client, "webinspector");
+    if (error != WEBINSPECTOR_E_SUCCESS) {
+        throwException(env, "Could not connect to the webinspector", error);
+        return;
+    }
+
+    return;
+}
+
+JNIEXPORT jboolean JNICALL Java_org_netbeans_modules_cordova_platforms_ios_WebInspectorJNIBinding_nisDeviceConnected(JNIEnv * env, jobject thiz) {
+    idevice_t dev = NULL;
+    
+    if (IDEVICE_E_SUCCESS != idevice_new(&dev, NULL)) {
+        return JNI_FALSE;
+    }
+    if (dev != NULL) {
+        idevice_free(dev);
+        dev = NULL;
+    }
+    return JNI_TRUE;
+}
+
+JNIEXPORT void JNICALL Java_org_netbeans_modules_cordova_platforms_ios_WebInspectorJNIBinding_nstop(JNIEnv * env, jobject thiz) {
+    if (client != NULL) {
+        webinspector_client_free(client);
+        client = NULL;
+    }
+    if (device != NULL) {
+        idevice_free(device);
+        device = NULL;
+    }
+    return;
+}
+
+JNIEXPORT jstring JNICALL Java_org_netbeans_modules_cordova_platforms_ios_WebInspectorJNIBinding_nreceiveMessage(JNIEnv * env, jobject thiz, jint timeout_ms) {
+    plist_t plist = NULL;
+
+    webinspector_error_t res = webinspector_receive_with_timeout(client, &plist, timeout_ms);
+    if (res != WEBINSPECTOR_E_SUCCESS || plist == NULL) {
+        char str[100];
+        sprintf(str, "Error receiving message: %d", res);
+        //throwException(env, str);
+        if (plist != NULL) {
+            plist_free(plist);
+        }
+        return NULL;
+    }
+
+    char * xml = NULL;
+    int xmllength = 0;
+    plist_to_xml(plist, &xml, &xmllength);
+    plist_free(plist);
+
+    if (xml == NULL) {
+        throwException(env, "Error converting plist to xml.");
+        return NULL;
+    }
+
+    jstring retval = (*env)->NewStringUTF(env, xml);
+    free(xml);
+
+    return retval;
+}
+
+JNIEXPORT void JNICALL Java_org_netbeans_modules_cordova_platforms_ios_WebInspectorJNIBinding_nsendMessage(JNIEnv * env, jobject thiz, jstring command) {
+    char const * const xml = (*env)->GetStringUTFChars(env, command, 0);
+    int const xmllength = strlen(xml);
+
+    plist_t plist = NULL;
+    plist_from_xml(xml, xmllength, &plist);
+    if (!plist) {
+        throwException(env, "Failed to create plist from xml.");
+        return;
+    }
+
+    webinspector_send(client, plist);
+    plist_free(plist);
+
+    (*env)->ReleaseStringUTFChars(env, command, xml);
+    return;
+}
+
+jint throwException(JNIEnv *env, char *message) {
+    jclass exClass;
+    char *className = "java/lang/IllegalStateException";
+
+    exClass = (*env)->FindClass(env, className);
+    return (*env)->ThrowNew(env, exClass, message);
+}
+
+
+
diff --git a/cordova.platforms.ios/manifest.mf b/cordova.platforms.ios/manifest.mf
new file mode 100644
index 0000000000..c863513994
--- /dev/null
+++ b/cordova.platforms.ios/manifest.mf
@@ -0,0 +1,6 @@
+Manifest-Version: 1.0
+AutoUpdate-Show-In-Client: false
+OpenIDE-Module: org.netbeans.modules.cordova.platforms.ios
+OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/cordova/platforms/ios/Bundle.properties
+OpenIDE-Module-Specification-Version: 1.29
+
diff --git a/cordova.platforms.ios/nbproject/project.properties b/cordova.platforms.ios/nbproject/project.properties
new file mode 100644
index 0000000000..0c7fce5961
--- /dev/null
+++ b/cordova.platforms.ios/nbproject/project.properties
@@ -0,0 +1,25 @@
+# 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.
+javac.source=1.7
+javac.compilerargs=-Xlint -Xlint:-serial
+release.external/ios-sim=bin/ios-sim
+release.external/libiDeviceNativeBinding.dylib=bin/libiDeviceNativeBinding.dylib
+release.external/libimobiledevice.4.dylib=bin/libimobiledevice.4.dylib
+release.external/libplist.1.dylib=bin/libplist.1.dylib
+release.external/libusbmuxd.2.dylib=bin/libusbmuxd.2.dylib
+nbm.executable.files=bin/ios-sim
+
diff --git a/cordova.platforms.ios/nbproject/project.xml b/cordova.platforms.ios/nbproject/project.xml
new file mode 100644
index 0000000000..776dd38cf0
--- /dev/null
+++ b/cordova.platforms.ios/nbproject/project.xml
@@ -0,0 +1,200 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    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.
+
+-->
+<project xmlns="http://www.netbeans.org/ns/project/1">
+    <type>org.netbeans.modules.apisupport.project</type>
+    <configuration>
+        <data xmlns="http://www.netbeans.org/ns/nb-module-project/3">
+            <code-name-base>org.netbeans.modules.cordova.platforms.ios</code-name-base>
+            <module-dependencies>
+                <dependency>
+                    <code-name-base>org.netbeans.api.progress</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>1</release-version>
+                        <specification-version>1.40</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.api.progress.nb</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.40</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.libs.json_simple</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>1</release-version>
+                        <specification-version>0.4</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.libs.plist</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.0</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.modules.cordova.platforms</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.31</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.modules.netserver</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.2</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.modules.options.api</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>1</release-version>
+                        <specification-version>1.34</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.modules.projectapi</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>1</release-version>
+                        <specification-version>1.49</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.modules.web.browser.api</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.30</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.modules.web.clientproject.api</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.40</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.modules.web.webkit.debugging</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.2</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.awt</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>7.54</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.dialogs</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>7.29</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.execution</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>9.0</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.filesystems</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>9.0</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.modules</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>7.30</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.util.ui</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>9.3</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.util</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>9.3</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.18</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.projectapi.nb</code-name-base>
+                    </test-dependency>
+                </test-type>
+            </test-dependencies>
+            <public-packages/>
+        </data>
+    </configuration>
+</project>
diff --git a/cordova.platforms.ios/src/org/netbeans/modules/cordova/platforms/ios/Bundle.properties b/cordova.platforms.ios/src/org/netbeans/modules/cordova/platforms/ios/Bundle.properties
new file mode 100644
index 0000000000..69241e4d55
--- /dev/null
+++ b/cordova.platforms.ios/src/org/netbeans/modules/cordova/platforms/ios/Bundle.properties
@@ -0,0 +1,26 @@
+# 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.
+
+IOSConfigurationPanel.sdkLabel.text=Select &SDK:
+IOSConfigurationPanel.virtualDeviceLabel.text=&Virtual Device:
+IOSConfigurationPanel.deviceLabel.text=Device:
+IOSConfigurationPanel.debuggerCheckBox.text=&Enable Debugging
+OpenIDE-Module-Display-Category=HTML5
+OpenIDE-Module-Long-Description=\
+    iOS Mobile Platform for Cordova
+OpenIDE-Module-Name=iOS Platform
+OpenIDE-Module-Short-Description=iOS Platform
diff --git a/cordova.platforms.ios/src/org/netbeans/modules/cordova/platforms/ios/Command.properties b/cordova.platforms.ios/src/org/netbeans/modules/cordova/platforms/ios/Command.properties
new file mode 100644
index 0000000000..9ad91e61ba
--- /dev/null
+++ b/cordova.platforms.ios/src/org/netbeans/modules/cordova/platforms/ios/Command.properties
@@ -0,0 +1,84 @@
+# 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.
+setSenderKey=<?xml version="1.0" encoding="UTF-8"?>\n\
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">\n\
+<plist version="1.0">\n\
+    <dict>\n\
+        <key>__argument</key>\n\
+        <dict>\n\
+            <key>WIRApplicationIdentifierKey</key>\n\
+            <string>$bundleId</string>\n\
+            <key>WIRConnectionIdentifierKey</key>\n\
+            <string>7B7C5BD2-3027-4010-9CAA-21DAF8D48C63</string>\n\
+            <key>WIRPageIdentifierKey</key>\n\
+            <integer>$tabIdentifier</integer>\n\
+            <key>WIRSenderKey</key>\n\
+            <string>50ECDF4F-EC2D-4CF8-9A43-0252F7CB2973</string>\n\
+        </dict>\n\
+        <key>__selector</key>\n\
+        <string>_rpc_forwardSocketSetup:</string>\n\
+    </dict>\n\
+</plist>
+setConnectionKey=<?xml version="1.0" encoding="UTF-8"?>\n\
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">\n\
+<plist version="1.0">\n\
+    <dict>\n\
+        <key>__argument</key>\n\
+        <dict>\n\
+            <key>WIRConnectionIdentifierKey</key>\n\
+            <string>7B7C5BD2-3027-4010-9CAA-21DAF8D48C63</string>\n\
+        </dict>\n\
+        <key>__selector</key>\n\
+        <string>_rpc_reportIdentifier:</string>\n\
+    </dict>\n\
+</plist>
+sendJSONCommand=<?xml version="1.0" encoding="UTF-8"?>\n\
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">\n\
+<plist version="1.0">\n\
+    <dict>\n\
+        <key>__argument</key>\n\
+        <dict>\n\
+            <key>WIRApplicationIdentifierKey</key>\n\
+            <string>$bundleId</string>\n\
+            <key>WIRConnectionIdentifierKey</key>\n\
+            <string>7B7C5BD2-3027-4010-9CAA-21DAF8D48C63</string>\n\
+            <key>WIRPageIdentifierKey</key>\n\
+            <integer>$tabIdentifier</integer>\n\
+            <key>WIRSenderKey</key>\n\
+            <string>50ECDF4F-EC2D-4CF8-9A43-0252F7CB2973</string>\n\
+            <key>WIRSocketDataKey</key>\n\
+            <data>$json_encoded</data>\n\
+        </dict>\n\
+        <key>__selector</key>\n\
+        <string>_rpc_forwardSocketData:</string>\n\
+    </dict>\n\
+</plist>
+connectToApp=<?xml version="1.0" encoding="UTF-8"?>\n\
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">\n\
+<plist version="1.0">\n\
+    <dict>\n\
+        <key>__argument</key>\n\
+        <dict>\n\
+            <key>WIRApplicationIdentifierKey</key>\n\
+            <string>$bundleId</string>\n\
+            <key>WIRConnectionIdentifierKey</key>\n\
+            <string>7B7C5BD2-3027-4010-9CAA-21DAF8D48C63</string>\n\
+        </dict>\n\
+        <key>__selector</key>\n\
+        <string>_rpc_forwardGetListing:</string>\n\
+    </dict>\n\
+</plist>\n
diff --git a/cordova.platforms.ios/src/org/netbeans/modules/cordova/platforms/ios/DeviceDebugTransport.java b/cordova.platforms.ios/src/org/netbeans/modules/cordova/platforms/ios/DeviceDebugTransport.java
new file mode 100644
index 0000000000..404e3daa57
--- /dev/null
+++ b/cordova.platforms.ios/src/org/netbeans/modules/cordova/platforms/ios/DeviceDebugTransport.java
@@ -0,0 +1,89 @@
+/*
+ * 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.cordova.platforms.ios;
+
+import com.dd.plist.NSObject;
+import com.dd.plist.XMLPropertyListParser;
+import org.json.simple.JSONObject;
+import org.netbeans.modules.web.webkit.debugging.spi.TransportImplementation;
+
+/**
+ *
+ * @author Jan Becicka
+ */
+public class DeviceDebugTransport extends IOSDebugTransport implements TransportImplementation {
+    
+    private WebInspectorJNIBinding nativeCall;
+
+    public DeviceDebugTransport() {
+        super();
+        nativeCall = WebInspectorJNIBinding.getDefault();
+    }
+    
+    @Override
+    protected void init() throws Exception {
+        nativeCall.start();
+    }
+
+    @Override
+    public void sendCommand(JSONObject command) throws Exception {
+        sendMessage(createJSONCommand(command));
+    }
+
+    @Override
+    public void sendCommand(String command) throws Exception {
+        //System.out.println("sending " + command);
+        sendMessage(command);
+    }
+    
+    private void sendMessage(String message) {
+        if (keepGoing) {
+            nativeCall.sendMessage(message);
+        }
+    }
+
+    @Override
+    protected NSObject readData() throws Exception {
+        String content = nativeCall.receiveMessage();
+        if (content==null) {
+            Thread.sleep(100);
+            return null;
+        }
+
+        NSObject object = XMLPropertyListParser.parse(fromString(content));
+        return object;
+    }
+    
+    @Override
+    protected void stop() {
+        super.stop();
+        nativeCall.stop();
+   }
+
+    @Override
+    public String getConnectionName() {
+        return "iOS Device"; // NOI18N
+    }
+
+    @Override
+    public String getVersion() {
+        return "1.0"; // NOI18N
+    }
+}
+         
diff --git a/cordova.platforms.ios/src/org/netbeans/modules/cordova/platforms/ios/EnhancedBrowserProviderImpl.java b/cordova.platforms.ios/src/org/netbeans/modules/cordova/platforms/ios/EnhancedBrowserProviderImpl.java
new file mode 100644
index 0000000000..438de47911
--- /dev/null
+++ b/cordova.platforms.ios/src/org/netbeans/modules/cordova/platforms/ios/EnhancedBrowserProviderImpl.java
@@ -0,0 +1,66 @@
+/*
+ * 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.cordova.platforms.ios;
+
+import org.netbeans.api.project.Project;
+import org.netbeans.modules.cordova.platforms.api.ClientProjectUtilities;
+import org.netbeans.modules.web.browser.api.BrowserFamilyId;
+import org.netbeans.modules.web.browser.api.BrowserSupport;
+import org.netbeans.modules.web.browser.api.WebBrowser;
+import org.netbeans.modules.web.clientproject.spi.platform.ClientProjectEnhancedBrowserImplementation;
+import org.netbeans.modules.web.clientproject.spi.platform.ClientProjectEnhancedBrowserProvider;
+import org.netbeans.spi.project.ActionProvider;
+import org.netbeans.spi.project.LookupProvider;
+import org.netbeans.spi.project.ProjectServiceProvider;
+import org.openide.util.Parameters;
+
+/**
+ * @author Jan Becicka
+ */
+@ProjectServiceProvider(
+       projectTypes = {
+           @LookupProvider.Registration.ProjectType(id = "org-netbeans-modules-web-clientproject")
+       },
+       service = ClientProjectEnhancedBrowserProvider.class)
+public class EnhancedBrowserProviderImpl implements ClientProjectEnhancedBrowserProvider {
+    private Project p;
+
+    public EnhancedBrowserProviderImpl(Project p) {
+        Parameters.notNull("Project", p);
+        this.p = p;
+    }
+    
+    @Override
+    public ClientProjectEnhancedBrowserImplementation getEnhancedBrowser(final WebBrowser webBrowser) {
+        if (webBrowser == null) {
+            return null;
+        }
+        if (BrowserFamilyId.IOS == webBrowser.getBrowserFamily()) {
+            BrowserSupport support = BrowserSupport.create(webBrowser);
+            return ClientProjectUtilities.createMobileBrowser(
+                    p, 
+                    webBrowser, 
+                    support, 
+                    new IOSBrowserActionProvider(support, webBrowser.getId(), p));
+        }
+        return null;
+    }
+
+}
diff --git a/cordova.platforms.ios/src/org/netbeans/modules/cordova/platforms/ios/IOSActionProvider.java b/cordova.platforms.ios/src/org/netbeans/modules/cordova/platforms/ios/IOSActionProvider.java
new file mode 100644
index 0000000000..0f8f92425a
--- /dev/null
+++ b/cordova.platforms.ios/src/org/netbeans/modules/cordova/platforms/ios/IOSActionProvider.java
@@ -0,0 +1,121 @@
+/*
+ * 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.cordova.platforms.ios;
+
+import org.netbeans.api.project.Project;
+import org.netbeans.modules.cordova.platforms.api.PlatformManager;
+import org.netbeans.modules.cordova.platforms.api.WebKitDebuggingSupport;
+import org.netbeans.modules.cordova.platforms.spi.BuildPerformer;
+import org.netbeans.spi.project.ActionProvider;
+import org.openide.DialogDescriptor;
+import org.openide.DialogDisplayer;
+import org.openide.NotifyDescriptor;
+import org.openide.util.Lookup;
+import org.openide.util.NbBundle;
+import org.openide.util.Utilities;
+
+/**
+ * Cordova build action
+ * @author Jan Becicka
+ * 
+ */
+public class IOSActionProvider implements ActionProvider {
+    private final Project p;
+
+    public IOSActionProvider(Project p) {
+        this.p = p;
+    }
+    
+    @Override
+    public String[] getSupportedActions() {
+        return new String[]{
+                    COMMAND_BUILD,
+                    COMMAND_CLEAN,
+                    COMMAND_RUN,
+                    COMMAND_RUN_SINGLE,
+                    COMMAND_REBUILD
+                };
+    }
+
+    @NbBundle.Messages({
+        "ERR_NotMac=iOS Development is available only on Mac OS X",
+        "ERR_Title=Error",
+        "LBL_Opening=Connecting to iOS Simulator.\n Please start Mobile Safari if it is not already running.",
+        "ERR_NO_Xcode=Supported version of Xcode and Command Line Tools for Xcode not found.\n"
+            + "Make sure, that you have latest version of Xcode and iOS SDK installed from Mac App Store."
+    })
+    @Override
+    public void invokeAction(String command, final Lookup context) throws IllegalArgumentException {
+        if (!Utilities.isMac()) {
+            NotifyDescriptor not = new NotifyDescriptor(
+                    Bundle.LBL_NoMac(),
+                    Bundle.ERR_Title(),
+                    NotifyDescriptor.DEFAULT_OPTION,
+                    NotifyDescriptor.ERROR_MESSAGE,
+                    null,
+                    null);
+            DialogDisplayer.getDefault().notify(not);
+            return;
+        }
+
+        if (!PlatformManager.getPlatform(PlatformManager.IOS_TYPE).isReady()) {
+            NotifyDescriptor not = new NotifyDescriptor(
+                    Bundle.ERR_NO_Xcode(),
+                    Bundle.ERR_Title(),
+                    NotifyDescriptor.DEFAULT_OPTION,
+                    NotifyDescriptor.ERROR_MESSAGE,
+                    null,
+                    null);
+            DialogDisplayer.getDefault().notify(not);
+            return;
+        }
+        
+        final BuildPerformer build = Lookup.getDefault().lookup(BuildPerformer.class);
+        assert build != null;
+        try {
+            switch (command) {
+                case COMMAND_BUILD:
+                    build.perform(BuildPerformer.BUILD_IOS, p);
+                    break;
+                case COMMAND_CLEAN:
+                    build.perform(BuildPerformer.CLEAN_IOS, p);
+                    break;
+                case COMMAND_RUN:
+                case COMMAND_RUN_SINGLE:
+                    WebKitDebuggingSupport.getDefault().stopDebugging(true);
+                    build.perform(BuildPerformer.RUN_IOS, p);
+                    break;
+                case COMMAND_REBUILD:
+                    build.perform(BuildPerformer.REBUILD_IOS, p);
+            }
+        } catch (UnsupportedOperationException | IllegalStateException ex) {
+                NotifyDescriptor.Message not = new DialogDescriptor.Message(
+                        ex.getMessage(),
+                        DialogDescriptor.ERROR_MESSAGE);
+                Object value = DialogDisplayer.getDefault().notify(not);
+            return;
+        }
+    }
+
+    @Override
+    public boolean isActionEnabled(String command, Lookup context) throws IllegalArgumentException {
+        return Utilities.isMac();
+    }
+    
+}
diff --git a/cordova.platforms.ios/src/org/netbeans/modules/cordova/platforms/ios/IOSBrowser.java b/cordova.platforms.ios/src/org/netbeans/modules/cordova/platforms/ios/IOSBrowser.java
new file mode 100644
index 0000000000..f376575ff9
--- /dev/null
+++ b/cordova.platforms.ios/src/org/netbeans/modules/cordova/platforms/ios/IOSBrowser.java
@@ -0,0 +1,243 @@
+/*
+ * 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.cordova.platforms.ios;
+
+import java.awt.Component;
+import java.beans.PropertyChangeListener;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.swing.SwingUtilities;
+import org.netbeans.api.progress.ProgressUtils;
+import org.netbeans.api.project.Project;
+import org.netbeans.modules.cordova.platforms.api.WebKitDebuggingSupport;
+import org.netbeans.modules.web.browser.api.BrowserSupport;
+import org.netbeans.modules.web.browser.api.WebBrowserFeatures;
+import org.netbeans.modules.web.browser.spi.EnhancedBrowser;
+import org.openide.DialogDisplayer;
+import org.openide.NotifyDescriptor;
+import org.openide.awt.HtmlBrowser;
+import org.openide.filesystems.FileObject;
+import org.openide.util.Exceptions;
+import org.openide.util.ImageUtilities;
+import org.openide.util.Lookup;
+import org.openide.util.NbBundle;
+import org.openide.util.RequestProcessor;
+import org.openide.util.Utilities;
+import org.openide.util.lookup.Lookups;
+import org.openide.util.lookup.ProxyLookup;
+
+/**
+ *
+ * @author Jan Becicka
+ */
+public class IOSBrowser extends HtmlBrowser.Impl implements EnhancedBrowser {
+    private final Kind kind;
+    private Lookup projectContext;
+    private static final Logger LOGGER = Logger.getLogger(IOSBrowser.class.getName());
+
+    @Override
+    public void initialize(WebBrowserFeatures browserFeatures) {
+    }
+
+    @Override
+    public void close(boolean closeTab) {
+        RequestProcessor.getDefault().post(new Runnable() {
+            @Override
+            public void run() {
+                WebKitDebuggingSupport.getDefault().stopDebugging(true);
+            }
+        });
+    }
+
+    @Override
+    public void setProjectContext(Lookup projectContext) {
+        this.projectContext = projectContext;
+    }
+
+    @Override
+    public boolean canReloadPage() {
+        return false;
+    }
+    
+    @Override
+    public boolean ignoreChange(FileObject fo) {
+        return BrowserSupport.ignoreChangeDefaultImpl(fo);
+    }
+
+    public static enum Kind {
+        IOS_DEVICE_DEFAULT,
+        IOS_SIMULATOR_DEFAULT
+    }
+    
+
+    public IOSBrowser(Kind kind) {
+        this.kind = kind;
+    }
+    
+    private URL url;
+
+    @Override
+    public Component getComponent() {
+        return null;
+    }
+
+    @Override
+    public void reloadDocument() {
+        WebKitDebuggingSupport.getDefault().reload();
+    }
+
+    @Override
+    public void stopLoading() {
+    }
+
+    @NbBundle.Messages({
+            "LBL_DeviceNotConnected=iOS Device Not Connected.",
+            "TTL_DeviceNotConnected=Cannot Connect to Device"
+    })
+    @Override
+    public void setURL(final URL url) {
+        if (!Utilities.isMac()) {
+            NotifyDescriptor not = new NotifyDescriptor(
+                    Bundle.LBL_NoMac(),
+                    Bundle.ERR_Title(),
+                    NotifyDescriptor.DEFAULT_OPTION,
+                    NotifyDescriptor.ERROR_MESSAGE,
+                    null,
+                    null);
+            DialogDisplayer.getDefault().notify(not);
+            return;
+        }
+        final WebKitDebuggingSupport build = WebKitDebuggingSupport.getDefault();
+
+        this.url = url;
+        final IOSDevice dev = kind == Kind.IOS_DEVICE_DEFAULT ? IOSDevice.CONNECTED : IOSDevice.IPHONE;
+        dev.openUrl(url.toExternalForm());
+        final Project project = projectContext.lookup(Project.class);
+        if (project == null) {
+            //dont start debugging session for non project files
+            return;
+        }
+        try {
+            ProgressUtils.runOffEventDispatchThread(new Runnable() {
+                @Override
+                public void run() {
+                    if (kind == Kind.IOS_DEVICE_DEFAULT) {
+                        try {
+                            build.startDebugging(dev, project, new ProxyLookup(projectContext, Lookups.fixed(ImageUtilities.loadImage("org/netbeans/modules/cordova/platforms/ios/iosdevice16.png"), url)), true);
+                        } catch (IllegalStateException ise) {
+                            build.stopDebugging(true);
+                            SwingUtilities.invokeLater(new Runnable() {
+                                @Override
+                                public void run() {
+                                    NotifyDescriptor not = new NotifyDescriptor(
+                                            Bundle.LBL_DeviceNotConnected(),
+                                            Bundle.TTL_DeviceNotConnected(),
+                                            NotifyDescriptor.DEFAULT_OPTION,
+                                            NotifyDescriptor.ERROR_MESSAGE,
+                                            null,
+                                            null);
+                                    DialogDisplayer.getDefault().notify(not);
+                                }
+                            });
+                        }
+                    } else {
+                        build.startDebugging(dev, project, new ProxyLookup(projectContext, Lookups.fixed(ImageUtilities.loadImage("org/netbeans/modules/cordova/platforms/ios/iossimulator16.png"), url)), true);
+                    }
+                }
+            }, kind == Kind.IOS_DEVICE_DEFAULT ? Bundle.LBL_OpeningiOS() : Bundle.LBL_Opening(), new AtomicBoolean(), true);
+        } catch (IllegalStateException ise) {
+            LOGGER.log(Level.FINE, "Stopping debugging.", ise);         //NOI18N
+            WebKitDebuggingSupport.getDefault().stopDebugging(true);
+        }
+    }
+
+    @NbBundle.Messages(
+            "LBL_OpeningiOS=Connecting to iOS Device.\nMake sure, that:\n"
+            + "\u2022 Device is attached\n"
+            + "\u2022 Web Inspector is enabled on your device (Settings | Safari | Advanced)\n"
+            + "\u2022 Mobile Safari is running\n"
+            + "\u2022 Your computer and iOS device are connected to the same WiFi network")
+    public static void openBrowser(String command, final Lookup context, final IOSBrowser.Kind kind, final Project project, final BrowserSupport browserSupport) throws IllegalArgumentException {
+        final WebKitDebuggingSupport build = WebKitDebuggingSupport.getDefault();
+        assert project != null && build != null;
+        final IOSDevice dev = kind == Kind.IOS_DEVICE_DEFAULT ? IOSDevice.CONNECTED : IOSDevice.IPHONE;
+        final String url1 = build.getUrl(project, context);
+        FileObject f = build.getFile(project, context);
+        try {
+            browserSupport.load(new URL(url1), f);
+        } catch (MalformedURLException ex) {
+            Exceptions.printStackTrace(ex);
+        }
+    }
+
+    @Override
+    public URL getURL() {
+        return url;
+    }
+
+    @Override
+    public String getStatusMessage() {
+        return "";
+    }
+
+    @Override
+    @NbBundle.Messages("LBL_SafariTitle=Safari")
+    public String getTitle() {
+        return Bundle.LBL_SafariTitle();
+    }
+
+    @Override
+    public boolean isForward() {
+        return false;
+    }
+
+    @Override
+    public void forward() {
+    }
+
+    @Override
+    public boolean isBackward() {
+        return false;
+    }
+
+    @Override
+    public void backward() {
+    }
+
+    @Override
+    public boolean isHistory() {
+        return false;
+    }
+
+    @Override
+    public void showHistory() {
+    }
+
+    @Override
+    public void addPropertyChangeListener(PropertyChangeListener l) {
+    }
+
+    @Override
+    public void removePropertyChangeListener(PropertyChangeListener l) {
+    }
+    
+}
diff --git a/cordova.platforms.ios/src/org/netbeans/modules/cordova/platforms/ios/IOSBrowserActionProvider.java b/cordova.platforms.ios/src/org/netbeans/modules/cordova/platforms/ios/IOSBrowserActionProvider.java
new file mode 100644
index 0000000000..9b5bf1b652
--- /dev/null
+++ b/cordova.platforms.ios/src/org/netbeans/modules/cordova/platforms/ios/IOSBrowserActionProvider.java
@@ -0,0 +1,73 @@
+/*
+ * 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.cordova.platforms.ios;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+import org.netbeans.api.progress.ProgressUtils;
+import org.netbeans.api.project.Project;
+import org.netbeans.modules.cordova.platforms.api.WebKitDebuggingSupport;
+import org.netbeans.modules.web.browser.api.BrowserSupport;
+import org.netbeans.spi.project.ActionProvider;
+import org.openide.util.Lookup;
+import org.openide.util.Utilities;
+
+/**
+ *
+ * @author Jan Becicka
+ */
+public class IOSBrowserActionProvider implements ActionProvider {
+
+    private BrowserSupport browserSupport;
+    private final Project project;
+    private final String browserId;
+
+    public IOSBrowserActionProvider(BrowserSupport support, String browserId, Project project) {
+        this.browserSupport = support;
+        this.project = project;
+        this.browserId = browserId;
+    }
+
+    @Override
+    public String[] getSupportedActions() {
+        return new String[]{
+            COMMAND_RUN,
+            COMMAND_RUN_SINGLE
+        };
+    }
+
+    @Override
+    public void invokeAction(final String command, final Lookup context) throws IllegalArgumentException {
+        try {
+            ProgressUtils.runOffEventDispatchThread(new Runnable() {
+                @Override
+                public void run() {
+                    WebKitDebuggingSupport.getDefault().stopDebugging(true);
+                    IOSBrowser.openBrowser(command, context, IOSBrowser.Kind.valueOf(browserId), project, browserSupport);
+                }
+            }, IOSBrowser.Kind.valueOf(browserId) == IOSBrowser.Kind.IOS_DEVICE_DEFAULT ? Bundle.LBL_OpeningiOS() : Bundle.LBL_Opening(), new AtomicBoolean(), true);
+        } catch (IllegalStateException ise) {
+            WebKitDebuggingSupport.getDefault().stopDebugging(true);
+        }
+    }
+
+    @Override
+    public boolean isActionEnabled(String command, Lookup context) throws IllegalArgumentException {
+        return Utilities.isMac();
+    }
+}
diff --git a/cordova.platforms.ios/src/org/netbeans/modules/cordova/platforms/ios/IOSBrowserFactory.java b/cordova.platforms.ios/src/org/netbeans/modules/cordova/platforms/ios/IOSBrowserFactory.java
new file mode 100644
index 0000000000..b6fea6edd6
--- /dev/null
+++ b/cordova.platforms.ios/src/org/netbeans/modules/cordova/platforms/ios/IOSBrowserFactory.java
@@ -0,0 +1,123 @@
+/*
+ * 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.cordova.platforms.ios;
+
+import java.awt.Image;
+import org.netbeans.modules.cordova.platforms.api.ClientProjectUtilities;
+import org.netbeans.modules.web.browser.api.BrowserFamilyId;
+import org.netbeans.modules.web.browser.spi.BrowserURLMapperImplementation;
+import org.netbeans.modules.web.browser.spi.BrowserURLMapperProvider;
+import org.netbeans.modules.web.browser.spi.EnhancedBrowserFactory;
+import org.openide.awt.HtmlBrowser;
+import org.openide.util.ImageUtilities;
+import org.openide.util.NbBundle;
+import org.openide.util.Utilities;
+import org.openide.util.lookup.ServiceProvider;
+
+
+/**
+ *
+ * @author Jan Becicka
+ */
+@NbBundle.Messages({
+    "LBL_DeviceDefault=iOS Device",
+    "LBL_SimulatorDefault=iOS Simulator"
+})
+public abstract class IOSBrowserFactory implements EnhancedBrowserFactory, HtmlBrowser.Factory, BrowserURLMapperProvider {
+    
+    private BrowserURLMapperImplementation urlMapper;
+
+    public IOSBrowserFactory() {
+        urlMapper = ClientProjectUtilities.createMobileBrowserURLMapper();
+    }
+
+    @Override
+    public BrowserFamilyId getBrowserFamilyId() {
+        return BrowserFamilyId.IOS;
+    }
+
+    @Override
+    public boolean canCreateHtmlBrowserImpl() {
+        return Utilities.isMac();
+    }
+
+    @Override
+    public BrowserURLMapperImplementation getBrowserURLMapper() {
+        return urlMapper;
+    }
+
+    @ServiceProvider(service = HtmlBrowser.Factory.class, path = "Services/Browsers2")
+    public static class EmulatorDefault extends IOSBrowserFactory {
+
+        @Override
+        public String getDisplayName() {
+            return Bundle.LBL_SimulatorDefault();
+        }
+
+        @Override
+        public HtmlBrowser.Impl createHtmlBrowserImpl() {
+            return new IOSBrowser(IOSBrowser.Kind.IOS_SIMULATOR_DEFAULT);
+        }
+
+        @Override
+        public String getId() {
+            return IOSBrowser.Kind.IOS_SIMULATOR_DEFAULT.toString(); // NOI18N
+        }
+
+        @Override
+        public boolean hasNetBeansIntegration() {
+            return true;
+        }
+        
+        @Override
+        public Image getIconImage(boolean small) {
+            return ImageUtilities.loadImage("org/netbeans/modules/cordova/platforms/ios/iossimulator" + (small?"16.png":".png"), false);
+        }
+    }
+
+    @ServiceProvider(service = HtmlBrowser.Factory.class, path = "Services/Browsers2")
+    public static class DeviceDefault extends IOSBrowserFactory {
+
+        @Override
+        public String getDisplayName() {
+            return Bundle.LBL_DeviceDefault();
+        }
+
+        @Override
+        public HtmlBrowser.Impl createHtmlBrowserImpl() {
+            return new IOSBrowser(IOSBrowser.Kind.IOS_DEVICE_DEFAULT);
+        }
+
+        @Override
+        public String getId() {
+            return IOSBrowser.Kind.IOS_DEVICE_DEFAULT.toString(); // NOI18N
+        }
+
+        @Override
+        public boolean hasNetBeansIntegration() {
+            return true;
+        }
+
+        @Override
+        public Image getIconImage(boolean small) {
+            return ImageUtilities.loadImage("org/netbeans/modules/cordova/platforms/ios/iosdevice" + (small?"16.png":".png"), false);
+        }
+        
+    }
+}
diff --git a/cordova.platforms.ios/src/org/netbeans/modules/cordova/platforms/ios/IOSConfigurationPanel.form b/cordova.platforms.ios/src/org/netbeans/modules/cordova/platforms/ios/IOSConfigurationPanel.form
new file mode 100644
index 0000000000..7870e7d127
--- /dev/null
+++ b/cordova.platforms.ios/src/org/netbeans/modules/cordova/platforms/ios/IOSConfigurationPanel.form
@@ -0,0 +1,126 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<Form version="1.5" maxVersion="1.8" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
+  <AuxValues>
+    <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
+    <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
+    <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
+    <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
+    <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
+    <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
+    <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
+    <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
+    <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
+  </AuxValues>
+
+  <Layout>
+    <DimensionLayout dim="0">
+      <Group type="103" groupAlignment="0" attributes="0">
+          <Group type="102" attributes="0">
+              <Group type="103" groupAlignment="0" attributes="0">
+                  <Component id="virtualDeviceLabel" alignment="0" min="-2" max="-2" attributes="0"/>
+                  <Component id="sdkLabel" alignment="0" min="-2" max="-2" attributes="0"/>
+                  <Component id="deviceLabel" alignment="0" min="-2" max="-2" attributes="0"/>
+              </Group>
+              <EmptySpace max="-2" attributes="0"/>
+              <Group type="103" groupAlignment="0" attributes="0">
+                  <Component id="virtualDeviceCombo" max="32767" attributes="0"/>
+                  <Component id="sdkCombo" max="32767" attributes="0"/>
+                  <Component id="deviceCombo" alignment="0" pref="372" max="32767" attributes="0"/>
+              </Group>
+          </Group>
+          <Group type="102" attributes="0">
+              <Component id="debuggerCheckBox" min="-2" max="-2" attributes="0"/>
+              <EmptySpace min="0" pref="0" max="32767" attributes="0"/>
+          </Group>
+      </Group>
+    </DimensionLayout>
+    <DimensionLayout dim="1">
+      <Group type="103" groupAlignment="0" attributes="0">
+          <Group type="102" alignment="0" attributes="0">
+              <Group type="103" groupAlignment="3" attributes="0">
+                  <Component id="deviceLabel" alignment="3" min="-2" max="-2" attributes="0"/>
+                  <Component id="deviceCombo" alignment="3" min="-2" max="-2" attributes="0"/>
+              </Group>
+              <EmptySpace max="-2" attributes="0"/>
+              <Group type="103" groupAlignment="3" attributes="0">
+                  <Component id="sdkLabel" alignment="3" min="-2" max="-2" attributes="0"/>
+                  <Component id="sdkCombo" alignment="3" min="-2" max="-2" attributes="0"/>
+              </Group>
+              <EmptySpace max="-2" attributes="0"/>
+              <Group type="103" groupAlignment="3" attributes="0">
+                  <Component id="virtualDeviceLabel" alignment="3" min="-2" max="-2" attributes="0"/>
+                  <Component id="virtualDeviceCombo" alignment="3" min="-2" max="-2" attributes="0"/>
+              </Group>
+              <EmptySpace max="-2" attributes="0"/>
+              <Component id="debuggerCheckBox" min="-2" pref="36" max="-2" attributes="0"/>
+              <EmptySpace max="-2" attributes="0"/>
+          </Group>
+      </Group>
+    </DimensionLayout>
+  </Layout>
+  <SubComponents>
+    <Component class="javax.swing.JLabel" name="sdkLabel">
+      <Properties>
+        <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
+          <ComponentRef name="sdkCombo"/>
+        </Property>
+        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+          <ResourceString bundle="org/netbeans/modules/cordova/platforms/ios/Bundle.properties" key="IOSConfigurationPanel.sdkLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+        </Property>
+      </Properties>
+    </Component>
+    <Component class="javax.swing.JComboBox" name="sdkCombo">
+      <Properties>
+        <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
+          <Connection code="new javax.swing.DefaultComboBoxModel(new String[] { Bundle.LBL_PleaseWait() })" type="code"/>
+        </Property>
+      </Properties>
+      <Events>
+        <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="sdkComboActionPerformed"/>
+      </Events>
+    </Component>
+    <Component class="javax.swing.JLabel" name="virtualDeviceLabel">
+      <Properties>
+        <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
+          <ComponentRef name="virtualDeviceCombo"/>
+        </Property>
+        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+          <ResourceString bundle="org/netbeans/modules/cordova/platforms/ios/Bundle.properties" key="IOSConfigurationPanel.virtualDeviceLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+        </Property>
+      </Properties>
+    </Component>
+    <Component class="javax.swing.JComboBox" name="virtualDeviceCombo">
+      <Events>
+        <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="virtualDeviceComboActionPerformed"/>
+      </Events>
+    </Component>
+    <Component class="javax.swing.JLabel" name="deviceLabel">
+      <Properties>
+        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+          <ResourceString bundle="org/netbeans/modules/cordova/platforms/ios/Bundle.properties" key="IOSConfigurationPanel.deviceLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+        </Property>
+      </Properties>
+    </Component>
+    <Component class="javax.swing.JComboBox" name="deviceCombo">
+      <Properties>
+        <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
+          <Connection code="new javax.swing.DefaultComboBoxModel(new String[] { Bundle.LBL_Simulator(), Bundle.LBL_ConnectedDevice() })" type="code"/>
+        </Property>
+      </Properties>
+      <Events>
+        <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="deviceComboActionPerformed"/>
+      </Events>
+    </Component>
+    <Component class="javax.swing.JCheckBox" name="debuggerCheckBox">
+      <Properties>
+        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+          <ResourceString bundle="org/netbeans/modules/cordova/platforms/ios/Bundle.properties" key="IOSConfigurationPanel.debuggerCheckBox.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+        </Property>
+      </Properties>
+      <Events>
+        <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="debuggerCheckBoxActionPerformed"/>
+      </Events>
+    </Component>
+  </SubComponents>
+</Form>
diff --git a/cordova.platforms.ios/src/org/netbeans/modules/cordova/platforms/ios/IOSConfigurationPanel.java b/cordova.platforms.ios/src/org/netbeans/modules/cordova/platforms/ios/IOSConfigurationPanel.java
new file mode 100644
index 0000000000..587471f097
--- /dev/null
+++ b/cordova.platforms.ios/src/org/netbeans/modules/cordova/platforms/ios/IOSConfigurationPanel.java
@@ -0,0 +1,305 @@
+/*
+ * 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.cordova.platforms.ios;
+
+import java.awt.BorderLayout;
+import java.awt.Component;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.EnumSet;
+import javax.swing.DefaultComboBoxModel;
+import javax.swing.DefaultListCellRenderer;
+import javax.swing.JLabel;
+import javax.swing.JList;
+import javax.swing.JPanel;
+import org.netbeans.api.project.Project;
+import org.netbeans.modules.cordova.platforms.spi.Device;
+import org.netbeans.modules.cordova.platforms.spi.MobilePlatform;
+import org.netbeans.modules.cordova.platforms.api.PlatformManager;
+import org.netbeans.modules.cordova.platforms.spi.PropertyProvider;
+import org.netbeans.modules.cordova.platforms.spi.SDK;
+import org.netbeans.modules.web.clientproject.spi.platform.ProjectConfigurationCustomizer;
+import org.openide.util.Exceptions;
+import org.openide.util.NbBundle;
+import org.openide.util.RequestProcessor;
+import org.openide.util.Utilities;
+
+/**
+ *
+ * @author Jan Becicka
+ */
+public class IOSConfigurationPanel extends javax.swing.JPanel {
+
+    private PropertyProvider config;
+    final RequestProcessor RP = new RequestProcessor(IOSConfigurationPanel.class);
+    
+    private void refreshDeviceCombo(Collection sdKs) {
+        final IOSSDK[] sdks = (IOSSDK[]) sdKs.toArray(new IOSSDK[sdKs.size()]);
+        sdkCombo.setEnabled(true);
+        sdkCombo.setRenderer(new SDKRenderer());
+        sdkCombo.setModel(new DefaultComboBoxModel(sdks));
+        for (IOSSDK sdk : sdks) {
+            final String sdkProp = config.getProperty(IOSSDK.IOS_BUILD_SDK_PROP);
+            if (sdk.getName().equals(sdkProp)) {
+                sdkCombo.setSelectedItem(sdk);
+                break;
+            }
+        }
+        final String deviceProp = config.getProperty(Device.VIRTUAL_DEVICE_PROP); //NOI18N
+        if (deviceProp !=null)
+            virtualDeviceCombo.setSelectedItem(IOSDevice.valueOf(deviceProp));
+    }
+
+    private void initControls(PropertyProvider config) {
+        initComponents();
+        virtualDeviceCombo.setModel(new DefaultComboBoxModel(new Object[]{IOSDevice.IPHONE, IOSDevice.IPHONE_RETINA, IOSDevice.IPAD, IOSDevice.IPAD_RETINA}));
+        virtualDeviceCombo.setRenderer(new DeviceRenderer());
+        String device = config.getProperty(Device.DEVICE_PROP); //NOI18N
+        if (Device.DEVICE.equals(device)) { //NOI18N
+            deviceCombo.setSelectedIndex(Device.DEVICE.equals(device)?1:0); //NOI18N
+        }
+        setCombosVisible(!Device.DEVICE.equals(device)); //NOI18N
+        debuggerCheckBox.setVisible(false);
+        deviceCombo.setVisible(false);
+        deviceLabel.setVisible(false);
+        validate();
+    }
+
+    public static class IOSConfigurationCustomizer implements ProjectConfigurationCustomizer {
+        
+        private final Project p;
+        private PropertyProvider config;
+        
+        public IOSConfigurationCustomizer(Project p, PropertyProvider config) {
+            this.p = p;
+            this.config = config;
+        }
+        
+        
+
+        @Override
+        public JPanel createPanel() {
+            return new IOSConfigurationPanel(config);
+        }
+
+        @Override
+        public EnumSet<HiddenProperties> getHiddenProperties() {
+            return EnumSet.of(HiddenProperties.WEB_SERVER);
+        }
+
+    }
+    
+    private static class SDKRenderer extends DefaultListCellRenderer {
+
+        @Override
+        public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
+            super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
+            if (value instanceof IOSSDK) {
+                setText(((IOSSDK) value).getName());
+            }
+            return this;
+        }
+    }
+    
+    private static class DeviceRenderer extends DefaultListCellRenderer {
+
+        @Override
+        public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
+            super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
+            if (value instanceof IOSDevice) {
+                setText(((IOSDevice) value).getDisplayName());
+            }
+            return this;
+        }
+    }
+    
+    
+    /**
+     * Creates new form AndroidConfigurationCustomizer
+     */
+    @NbBundle.Messages({
+        "LBL_NoMac=iOS Development is supported only on Mac.",
+        "LBL_NoXcode=Please install Xcode and iOS SDK."})
+    public IOSConfigurationPanel(PropertyProvider config) {
+        this.config = config;
+        if (!Utilities.isMac()) {
+            setLayout(new BorderLayout());
+            add(new JLabel(Bundle.LBL_NoMac()));
+            validate();
+        } else if (!org.netbeans.modules.cordova.platforms.api.PlatformManager.getPlatform(PlatformManager.IOS_TYPE).isReady()) {
+            setLayout(new BorderLayout());
+            add(new JLabel(Bundle.LBL_NoXcode()));
+            validate();
+        } else {
+            initControls(config);
+        }
+    }
+
+    @NbBundle.Messages("LBL_PleaseWait=Please Wait...")
+    private void setCombosVisible(boolean visible) {
+        if (visible) {
+        sdkCombo.setModel(new DefaultComboBoxModel(new Object[]{Bundle.LBL_PleaseWait()}));
+        sdkCombo.setEnabled(false);
+        RP.post(new Runnable() {
+            @Override
+            public void run() {
+                try {
+                    final Collection<? extends SDK> sdKs = PlatformManager.getPlatform(PlatformManager.IOS_TYPE).getSDKs();
+                    refreshDeviceCombo(sdKs);
+                } catch (IOException ex) {
+                    Exceptions.printStackTrace(ex);
+                }
+            }
+        });
+        }
+        virtualDeviceCombo.setVisible(visible);
+        virtualDeviceLabel.setVisible(visible);
+        sdkCombo.setVisible(visible);
+        sdkLabel.setVisible(visible);
+    }
+    
+    
+    /**
+     * This method is called from within the constructor to initialize the form.
+     * WARNING: Do NOT modify this code. The content of this method is always
+     * regenerated by the Form Editor.
+     */
+    @SuppressWarnings("unchecked")
+    @NbBundle.Messages({
+        "LBL_Simulator=Simulator",
+        "LBL_ConnectedDevice=Connected Device"
+    })
+    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
+    private void initComponents() {
+
+        sdkLabel = new javax.swing.JLabel();
+        sdkCombo = new javax.swing.JComboBox();
+        virtualDeviceLabel = new javax.swing.JLabel();
+        virtualDeviceCombo = new javax.swing.JComboBox();
+        deviceLabel = new javax.swing.JLabel();
+        deviceCombo = new javax.swing.JComboBox();
+        debuggerCheckBox = new javax.swing.JCheckBox();
+
+        sdkLabel.setLabelFor(sdkCombo);
+        org.openide.awt.Mnemonics.setLocalizedText(sdkLabel, org.openide.util.NbBundle.getMessage(IOSConfigurationPanel.class, "IOSConfigurationPanel.sdkLabel.text")); // NOI18N
+
+        sdkCombo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { Bundle.LBL_PleaseWait() }));
+        sdkCombo.addActionListener(new java.awt.event.ActionListener() {
+            public void actionPerformed(java.awt.event.ActionEvent evt) {
+                sdkComboActionPerformed(evt);
+            }
+        });
+
+        virtualDeviceLabel.setLabelFor(virtualDeviceCombo);
+        org.openide.awt.Mnemonics.setLocalizedText(virtualDeviceLabel, org.openide.util.NbBundle.getMessage(IOSConfigurationPanel.class, "IOSConfigurationPanel.virtualDeviceLabel.text")); // NOI18N
+
+        virtualDeviceCombo.addActionListener(new java.awt.event.ActionListener() {
+            public void actionPerformed(java.awt.event.ActionEvent evt) {
+                virtualDeviceComboActionPerformed(evt);
+            }
+        });
+
+        org.openide.awt.Mnemonics.setLocalizedText(deviceLabel, org.openide.util.NbBundle.getMessage(IOSConfigurationPanel.class, "IOSConfigurationPanel.deviceLabel.text")); // NOI18N
+
+        deviceCombo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { Bundle.LBL_Simulator(), Bundle.LBL_ConnectedDevice() }));
+        deviceCombo.addActionListener(new java.awt.event.ActionListener() {
+            public void actionPerformed(java.awt.event.ActionEvent evt) {
+                deviceComboActionPerformed(evt);
+            }
+        });
+
+        org.openide.awt.Mnemonics.setLocalizedText(debuggerCheckBox, org.openide.util.NbBundle.getMessage(IOSConfigurationPanel.class, "IOSConfigurationPanel.debuggerCheckBox.text")); // NOI18N
+        debuggerCheckBox.addActionListener(new java.awt.event.ActionListener() {
+            public void actionPerformed(java.awt.event.ActionEvent evt) {
+                debuggerCheckBoxActionPerformed(evt);
+            }
+        });
+
+        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
+        this.setLayout(layout);
+        layout.setHorizontalGroup(
+            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addGroup(layout.createSequentialGroup()
+                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+                    .addComponent(virtualDeviceLabel)
+                    .addComponent(sdkLabel)
+                    .addComponent(deviceLabel))
+                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+                    .addComponent(virtualDeviceCombo, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+                    .addComponent(sdkCombo, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+                    .addComponent(deviceCombo, 0, 372, Short.MAX_VALUE)))
+            .addGroup(layout.createSequentialGroup()
+                .addComponent(debuggerCheckBox)
+                .addGap(0, 0, Short.MAX_VALUE))
+        );
+        layout.setVerticalGroup(
+            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addGroup(layout.createSequentialGroup()
+                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+                    .addComponent(deviceLabel)
+                    .addComponent(deviceCombo, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+                    .addComponent(sdkLabel)
+                    .addComponent(sdkCombo, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+                    .addComponent(virtualDeviceLabel)
+                    .addComponent(virtualDeviceCombo, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                .addComponent(debuggerCheckBox, javax.swing.GroupLayout.PREFERRED_SIZE, 36, javax.swing.GroupLayout.PREFERRED_SIZE)
+                .addContainerGap())
+        );
+    }// </editor-fold>//GEN-END:initComponents
+
+    private void sdkComboActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_sdkComboActionPerformed
+        config.putProperty(IOSSDK.IOS_BUILD_SDK_PROP, ((IOSSDK)sdkCombo.getSelectedItem()).getIdentifier());
+    }//GEN-LAST:event_sdkComboActionPerformed
+
+    private void virtualDeviceComboActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_virtualDeviceComboActionPerformed
+        final IOSDevice val = (IOSDevice)virtualDeviceCombo.getSelectedItem();
+        if (val != null)
+            config.putProperty(Device.VIRTUAL_DEVICE_PROP, val.name()); //NOI18N
+    }//GEN-LAST:event_virtualDeviceComboActionPerformed
+
+    private void deviceComboActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_deviceComboActionPerformed
+        if (deviceCombo.getSelectedIndex() == 0) {
+            config.putProperty(Device.DEVICE_PROP, Device.EMULATOR); //NOI18N
+            setCombosVisible(true);
+        } else {
+            config.putProperty(Device.DEVICE_PROP, Device.DEVICE); //NOI18N
+            setCombosVisible(false);
+        }
+    }//GEN-LAST:event_deviceComboActionPerformed
+
+    private void debuggerCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_debuggerCheckBoxActionPerformed
+        config.putProperty("debug.enabled", Boolean.toString(debuggerCheckBox.isSelected())); //NOI18N
+    }//GEN-LAST:event_debuggerCheckBoxActionPerformed
+
+    // Variables declaration - do not modify//GEN-BEGIN:variables
+    private javax.swing.JCheckBox debuggerCheckBox;
+    private javax.swing.JComboBox deviceCombo;
+    private javax.swing.JLabel deviceLabel;
+    private javax.swing.JComboBox sdkCombo;
+    private javax.swing.JLabel sdkLabel;
+    private javax.swing.JComboBox virtualDeviceCombo;
+    private javax.swing.JLabel virtualDeviceLabel;
+    // End of variables declaration//GEN-END:variables
+}
diff --git a/cordova.platforms.ios/src/org/netbeans/modules/cordova/platforms/ios/IOSDebugTransport.java b/cordova.platforms.ios/src/org/netbeans/modules/cordova/platforms/ios/IOSDebugTransport.java
new file mode 100644
index 0000000000..b3d3cdd51b
--- /dev/null
+++ b/cordova.platforms.ios/src/org/netbeans/modules/cordova/platforms/ios/IOSDebugTransport.java
@@ -0,0 +1,568 @@
+/*
+ * 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.cordova.platforms.ios;
+
+import com.dd.plist.Base64;
+import com.dd.plist.BinaryPropertyListWriter;
+import com.dd.plist.NSData;
+import com.dd.plist.NSDictionary;
+import com.dd.plist.NSObject;
+import com.dd.plist.NSString;
+import com.dd.plist.XMLPropertyListParser;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.net.SocketException;
+import java.nio.charset.Charset;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import org.json.simple.JSONObject;
+import org.json.simple.JSONValue;
+import org.netbeans.modules.cordova.platforms.spi.MobileDebugTransport;
+import org.netbeans.modules.cordova.platforms.api.WebKitDebuggingSupport;
+import org.netbeans.modules.web.webkit.debugging.spi.Command;
+import org.netbeans.modules.web.webkit.debugging.spi.Response;
+import org.netbeans.modules.web.webkit.debugging.spi.TransportImplementation;
+import org.openide.util.Exceptions;
+import org.openide.util.RequestProcessor;
+
+/**
+ *
+ * @author Jan Becicka
+ */
+public abstract class IOSDebugTransport extends MobileDebugTransport implements TransportImplementation {
+    
+    private final RequestProcessor RP = new RequestProcessor(IOSDebugTransport.class);
+    private RequestProcessor.Task socketListener;
+    protected volatile boolean keepGoing = true;
+    private Tabs tabs = new IOSDebugTransport.Tabs();
+    private final Object init = new Object();
+    private static final Logger LOGGER = Logger.getLogger(IOSDebugTransport.class.getName());
+    private final AtomicBoolean flush = new AtomicBoolean();
+    
+    
+
+    public IOSDebugTransport() {
+        setBundleIdentifier("com.apple.mobilesafari"); // NOI18N
+    }
+    
+    @Override
+    public boolean attach() {
+        try {
+            init();
+            socketListener = RP.post(new Runnable() {
+                @Override
+                public void run() {
+                    while (keepGoing) {
+                        try {
+                            process();
+                        } catch (SocketException e) {
+                            Logger.getLogger(IOSDebugTransport.class.getName()).log(Level.FINE, "Debugging Connection Closed", e);
+                            return;
+                        } catch (Exception exception) {
+                            Exceptions.printStackTrace(exception);
+                        }
+                    }
+                }
+            });
+            sendInitCommands();
+
+            return true;
+        } catch (IllegalStateException ise) {
+            synchronized(tabs.monitor) {
+                if (!flush.get()) {
+                    throw ise;
+                }
+            }
+            return false;
+        } catch (Exception ex) {
+            Exceptions.printStackTrace(ex);
+            return false;
+        }
+    }
+
+    @Override
+    public void flush() {
+        synchronized(tabs.monitor) {
+            flush.set(true);
+            tabs.monitor.notifyAll();
+        }
+    }
+    
+    
+    
+    private void process() throws Exception {
+        NSObject object = readData();
+        if (LOGGER.isLoggable(Level.FINEST)) {
+            LOGGER.log(Level.FINEST, "\nReceived: {0}",                 //NOI18N
+                    nsObjectToString(object));
+        }
+        if (object == null) {
+            return;
+        }
+
+        JSONObject jmessage = extractResponse(object);
+        if (jmessage != null) {
+            if (callBack == null) {
+                LOGGER.info("callBack is null. Ignoring response: " + jmessage.toString());
+            } else {
+                callBack.handleResponse(new Response(jmessage));
+            }
+        } else {
+            if (!tabs.update(object)) {
+                checkClose(object);
+            }
+        }
+    }
+
+    /**
+     * Fix application identifier key when it is available. Before knowing the
+     * application listing, incorrect identifier key is used (set in
+     * WebKitDebuggingSupport#startDebugging(...). When the listing for our
+     * application (or web browser with our page) is received, we should fix it
+     * and use WIRApplicationIdentifierKey in form PID:XXXX.
+     *
+     * See bug #247400.
+     *
+     * @param object
+     */
+    private void fixApplicationIdentifierKey(NSObject object) {
+        String appId = stringInNSObject(object,
+                "__argument", "WIRApplicationIdentifierKey");           //NOI18N
+        setBundleIdentifier(appId);
+    }
+
+    /**
+     * Convert complex (nested dictionaries) NS object to string. Used mainly
+     * for debugging.
+     *
+     * @param o
+     * @return
+     */
+    String nsObjectToString(NSObject o) {
+        return nsObjectToString(o, 0);
+    }
+
+    private String nsObjectToString(NSObject o, int lvl) {
+        String basicIndent = "    ";                                    //NOI18N
+        String levelIndent = "";                                        //NOI18N
+        for (int i = 0; i < lvl; i++) {
+            levelIndent += basicIndent;
+        }
+        if (o instanceof NSDictionary) {
+            String[] allKeys = ((NSDictionary) o).allKeys();
+            StringBuilder sb = new StringBuilder(lvl == 0 ? "\n" : ""); //NOI18N
+            sb.append("{\n");                                           //NOI18N
+            for (String key: allKeys) {
+                NSObject objectForKey = ((NSDictionary) o).objectForKey(key);
+                sb.append(levelIndent);
+                sb.append(basicIndent);
+                sb.append("\"");                                        //NOI18N
+                sb.append(key);
+                sb.append("\": ");                                      //NOI18N
+                sb.append(nsObjectToString(objectForKey, lvl + 1));
+                sb.append("\n");                                        //NOI18N
+            }
+            sb.append(levelIndent);
+            sb.append("}\n");                                           //NOI18N
+            return sb.toString();
+        } else if (o instanceof NSString) {
+            return "\"" + ((NSString) o).toString() + "\"";             //NOI18N
+        } else if (o instanceof NSData) {
+            NSData data = (NSData) o;
+            String asStr = new String(data.bytes(), Charset.forName("UTF-8"));
+            return "Data: " + asStr;
+        } else if (o != null) {
+            return o.toString();
+        } else {
+            return "null";                                              //NOI18N
+        }
+    }
+
+    protected abstract NSObject readData() throws Exception;
+    
+    private String getCommand(String name, boolean replace) {
+        try {
+            Properties props = new Properties();
+            props.load(IOSDebugTransport.class.getResourceAsStream("Command.properties"));
+            final String cmd = props.getProperty(name).replace("$bundleId", getBundleIdentifier());
+            if (!replace) {
+                return cmd;
+            }
+            return cmd.replace("$tabIdentifier", getBundleIdentifier().equals("com.apple.mobilesafari") ? tabs.getActive() : "1"); // NOI18N
+        } catch (java.util.NoSuchElementException nse) {
+            LOGGER.log(Level.INFO, nse.getMessage(), nse);
+            throw new IllegalStateException(nse);
+        } catch (IOException | InterruptedException ex) {
+            throw new RuntimeException(ex);
+        }
+    }
+
+    protected final String createJSONCommand(JSONObject command) throws IOException {
+        String json = translate(command.toString());
+        String s = Base64.encodeBytes(json.getBytes());
+        String res = getCommand("sendJSONCommand", true).replace("$json_encoded", s); // NOI18N
+        return res;
+    }
+
+    protected final byte[] plistXmlToBinary(String msg) throws Exception {
+        NSObject object = XMLPropertyListParser.parse(msg.getBytes());
+        return BinaryPropertyListWriter.writeToArray(object);
+
+    }
+    
+    private void checkClose(NSObject r) throws Exception {
+        if (!(r instanceof NSDictionary)) {
+            return;
+        }
+        String selector = stringInNSObject(r, "__selector");            //NOI18N
+        if (selector == null) {
+            return;
+        }
+        switch (selector) {
+            case "_rpc_reportConnectedApplicationList:":                //NOI18N
+                NSDictionary applications = dictInNSObject(r,
+                        "__argument", //NOI18N
+                        "WIRApplicationDictionaryKey");                 //NOI18N
+                if (applications != null && applications.count() == 0) {
+                    WebKitDebuggingSupport.getDefault().stopDebugging(false);
+                }
+                break;
+            case "_rpc_applicationDisconnected:":                       //NOI18N
+                String appId = stringInNSObject(r,
+                        "__argument", //NOI18N
+                        "WIRApplicationIdentifierKey");                 //NOI18N
+                if (appId != null
+                        && appId.equals(getBundleIdentifier())) {
+                    WebKitDebuggingSupport.getDefault().stopDebugging(false);
+                }
+                break;
+        }
+    }
+
+    private JSONObject extractResponse(NSObject r) throws Exception {
+        if (r == null) {
+            return null;
+        }
+        if (!(r instanceof NSDictionary)) {
+            return null;
+        }
+        NSDictionary root = (NSDictionary) r;
+        NSDictionary argument = (NSDictionary) root.objectForKey("__argument"); // NOI18N
+        if (argument == null) {
+            return null;
+        }
+        NSData data = (NSData) argument.objectForKey("WIRMessageDataKey"); // NOI18N
+        if (data == null) {
+            return null;
+        }
+        byte[] bytes = data.bytes();
+        String s = new String(bytes);
+        JSONObject o = (JSONObject) JSONValue.parseWithException(s);
+        return o;
+    }
+
+    protected static InputStream fromString(String str) {
+        try {
+            byte[] bytes = str.getBytes("UTF-8"); // NOI18N
+            return new ByteArrayInputStream(bytes);
+        } catch (UnsupportedEncodingException ex) {
+            Exceptions.printStackTrace(ex);
+            return null;
+        }
+    }
+
+    protected void stop() {
+        keepGoing = false;
+        synchronized (init) {
+            init.notifyAll();
+        }
+        if (socketListener != null) {
+            socketListener.cancel();
+        }
+    }
+
+    @Override
+    public boolean detach() {
+        stop();
+        return true;
+    }
+
+    @Override
+    public final void sendCommandImpl(Command command) {
+        try {
+            sendCommand(command.getCommand());
+            JSONObject o = command.getCommand();
+            if (o != null) {
+                Object methodO = o.get("method");                       //NOI18N
+                if (methodO instanceof String) {
+                    String method = (String) methodO;
+                    // iOS sends no reposonse for some of the methods. Calling
+                    // callbacks directly here as workaround.
+                    if (callBack != null && (method.endsWith(".enable") //NOI18N
+                            || method.endsWith(".disable")              //NOI18N
+                            || method.endsWith(".navigate"))) {         //NOI18N
+                        JSONObject resp = new JSONObject();
+                        JSONObject empty = new JSONObject();
+                        resp.put("id", command.getID());
+                        resp.put("result", empty);                      //NOI18N
+                        callBack.handleResponse(new Response(resp));
+                    }
+                }
+            }
+        } catch (Exception ex) {
+            boolean s = keepGoing;
+            stop();
+            if (s) {
+                WebKitDebuggingSupport.getDefault().stopDebugging(false);
+            }
+        }
+    }
+
+    protected void sendInitCommands() throws Exception {
+        sendCommand(getCommand("setConnectionKey", false)); // NOI18N
+        synchronized (init) {
+            init.wait();
+        }
+        sendCommand(getCommand("connectToApp", false)); // NOI18N
+        sendCommand(getCommand("setSenderKey", true)); // NOI18N
+    }
+    
+    protected abstract void sendCommand(String command) throws Exception;
+    protected abstract void sendCommand(JSONObject command) throws Exception;
+
+    protected abstract void init() throws Exception;
+
+    private class Tabs {
+
+        private HashMap<String, TabDescriptor> map = new HashMap();
+        private Object monitor = new Object();
+        private boolean inited = false;
+
+        public boolean update(NSObject r) throws Exception {
+            if (!(r instanceof NSDictionary)) {
+                return false;
+            }
+            NSDictionary listing = dictInNSObject(r,
+                    "__argument", "WIRListingKey");                     //NOI18N
+            if (listing == null) {
+                return false;
+            }
+            boolean wasEmpty = map.isEmpty();
+            boolean connectionUrlFound = false;
+            HashMap<String, TabDescriptor> currentMap = new HashMap();
+            for (String s : listing.allKeys()) {
+                NSDictionary o = (NSDictionary) listing.objectForKey(s);
+                NSObject identifier = o.objectForKey("WIRPageIdentifierKey"); // NOI18N
+                NSObject url = o.objectForKey("WIRURLKey"); // NOI18N
+                if (url == null) {
+                    continue;
+                }
+                String urlString = url.toString().trim();
+                if(urlString.isEmpty()) {
+                    continue;
+                }
+                NSObject title = o.objectForKey("WIRTitleKey"); // NOI18N
+                if (getConnectionURL()==null) {
+                    //auto setup for phonegap. There is always on tab
+                    setBaseUrl(url.toString());
+                }
+                currentMap.put(s, new TabDescriptor(urlString, title.toString(), identifier.toString()));
+                if (checkUrlMatchesConnectionUrl(urlString)) {
+                    connectionUrlFound = true;
+                    fixApplicationIdentifierKey(r);
+                }
+            }
+            if (!connectionUrlFound) {
+                return false;
+            }
+            map.clear();
+            map.putAll(currentMap);
+            if (map.isEmpty()) {
+                return !wasEmpty; // was not empty and now is empty -> updated
+            } else {
+                synchronized (init) {
+                    init.notifyAll();
+                }
+                synchronized (monitor) {
+                    inited = true;
+                    monitor.notifyAll();
+                }
+                if (getTabForUrl() == null) {
+                    WebKitDebuggingSupport.getDefault().stopDebugging(false);
+                }
+                return true;
+            }
+        }
+
+        public TabDescriptor get(String key) {
+            return map.get(key);
+        }
+
+        private String getActive() throws InterruptedException {
+            synchronized (monitor) {
+                if (!inited) {
+                    monitor.wait(2 * 60 * 1000);
+                }
+            }
+            final String tabForUrl = getTabForUrl();
+            if (tabForUrl != null) {
+                return tabForUrl;
+            }
+            return map.entrySet().iterator().next().getKey();
+        }
+
+        private String lastTab = null;
+
+        private boolean checkUrlMatchesConnectionUrl(String url) {
+
+            String normUrl = url;
+            int hash = normUrl.indexOf("#"); // NOI18N
+            if (hash != -1) {
+                normUrl = normUrl.substring(0, hash);
+            }
+            if (normUrl.endsWith("/")) { // NOI18N
+                normUrl = normUrl.substring(0, normUrl.length() - 1);
+            }
+            return getConnectionURL().toString().equals(normUrl.replaceAll("file:///", "file:/"));
+        }
+
+        private String getTabForUrl() {
+            for (Map.Entry<String, TabDescriptor> entry : map.entrySet()) {
+                String urlFromBrowser = entry.getValue().getUrl();
+                if (urlFromBrowser.startsWith("file:/")) { // NOI18N
+                    //phonegap
+                    return lastTab="1"; // NOI18N
+                }
+                if (checkUrlMatchesConnectionUrl(urlFromBrowser)) {
+                    return lastTab = entry.getKey();
+                }
+            }
+            for (Map.Entry<String, TabDescriptor> entry : map.entrySet()) {
+                if (entry.getValue().getIdentifier().equals(lastTab)) {
+                    return lastTab;
+                }
+            }
+            return null;
+        }
+
+        private class TabDescriptor {
+
+            String url;
+            String title;
+            String identifier;
+
+            public TabDescriptor(String url, String title, String identifier) {
+                this.url = url;
+                this.title = title;
+                this.identifier = identifier;
+            }
+
+            public String getUrl() {
+                return url;
+            }
+
+            public String getTitle() {
+                return title;
+            }
+
+            public String getIdentifier() {
+                return identifier;
+            }
+
+            @Override
+            public String toString() {
+                return "TabDescriptor{" + "url=" + url + ", title=" + title + ", identifier=" + identifier + '}'; // NOI18N
+            }
+        }
+    }
+
+    /**
+     * Helper method for accessing keys deeper in NSObject hierarchy.
+     *
+     * @param obj Root object.
+     * @param path Path to contained object.
+     *
+     * @return Object found under specified key {@code path}, or null some of
+     * its path elements is not available.
+     */
+    static NSObject findInNSObject(NSObject obj, String... path) {
+        return findInNSObject(0, obj, path);
+    }
+
+    private static NSObject findInNSObject(int pos, NSObject obj, String... path) {
+        if (obj == null) {
+            throw new NullPointerException("obj is null");
+        } else if (path == null) {
+            throw new NullPointerException("path is null");
+        } else if (path.length == pos) {
+            return obj;
+        } else if (obj instanceof NSDictionary) {
+            NSDictionary dict = (NSDictionary) obj;
+            NSObject next = dict.objectForKey(path[pos]);
+            if (next == null) {
+                return null;
+            } else {
+                return findInNSObject(pos + 1, next, path);
+            }
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Get string contained in NSObject hierarchy.
+     *
+     * @param obj Root object.
+     * @param path Path to string value.
+     *
+     * @return String value, or null if not fount or if data type is not string.
+     */
+    static String stringInNSObject(NSObject obj, String... path) {
+        NSObject res = findInNSObject(obj, path);
+        if (res instanceof NSString) {
+            return ((NSString) res).toString();
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Get dictionary contained in NSObject hierarchy.
+     *
+     * @param obj Root object.
+     * @param path Path to the dictionary.
+     *
+     * @return The dictionary, or null if not found or if data type is not
+     * dictionary.
+     */
+    static NSDictionary dictInNSObject(NSObject obj, String... path) {
+        NSObject res = findInNSObject(obj, path);
+        if (res instanceof NSDictionary) {
+            return (NSDictionary) res;
+        } else {
+            return null;
+        }
+    }
+}
diff --git a/cordova.platforms.ios/src/org/netbeans/modules/cordova/platforms/ios/IOSDevice.java b/cordova.platforms.ios/src/org/netbeans/modules/cordova/platforms/ios/IOSDevice.java
new file mode 100644
index 0000000000..37fc49f1d4
--- /dev/null
+++ b/cordova.platforms.ios/src/org/netbeans/modules/cordova/platforms/ios/IOSDevice.java
@@ -0,0 +1,143 @@
+/*
+ * 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.cordova.platforms.ios;
+
+import java.io.IOException;
+import java.util.Properties;
+import java.util.logging.Logger;
+import org.netbeans.api.project.Project;
+import org.netbeans.modules.cordova.platforms.spi.Device;
+import org.netbeans.modules.cordova.platforms.spi.MobileDebugTransport;
+import org.netbeans.modules.cordova.platforms.spi.MobilePlatform;
+import org.netbeans.modules.cordova.platforms.api.PlatformManager;
+import org.netbeans.modules.cordova.platforms.api.ProcessUtilities;
+import org.netbeans.modules.cordova.platforms.spi.PropertyProvider;
+import org.netbeans.modules.web.clientproject.spi.platform.ProjectConfigurationCustomizer;
+import org.netbeans.spi.project.ActionProvider;
+import org.openide.modules.InstalledFileLocator;
+import org.openide.util.Exceptions;
+
+/**
+ *
+ * @author Jan Becicka
+ */
+public enum IOSDevice implements Device {
+    
+    IPHONE("iPhone", "--family iphone", true), //NOI18N
+    IPHONE_RETINA("iPhone (Retina)", "--family iphone --retina", true), //NOI18N
+    IPAD("iPad", "--family ipad", true), //NOI18N
+    IPAD_RETINA("iPad (Retina)", "--family ipad --retina", true), //NOI18N
+    CONNECTED("Connected Device", "", false); // NOI18N
+    
+    String displayName;
+    String args;
+    private boolean simulator;
+    private static boolean ios_sim_bug;
+    
+    private Logger LOG = Logger.getLogger(IOSDevice.class.getName());
+
+    IOSDevice(String name, String args, boolean simulator) {
+        this.displayName = name;
+        this.args = args;
+        this.simulator = simulator;
+    }
+
+    public String getDisplayName() {
+        return displayName;
+    }
+
+    public String getArgs() {
+        return args;
+    }
+
+    @Override
+    public boolean isEmulator() {
+        return simulator;
+    }
+
+    @Override
+    public MobilePlatform getPlatform() {
+        return PlatformManager.getPlatform(PlatformManager.IOS_TYPE);
+    }
+
+    @Override
+    public void addProperties(Properties props) {
+        props.put("ios.sim.exec", getPlatform().getSimulatorPath());//NOI18N
+        props.put("ios.device.args", getArgs());//NOI18N
+    }
+
+    @Override
+    public ActionProvider getActionProvider(Project p) {
+        return new IOSActionProvider(p);
+    }
+
+    @Override
+    public ProjectConfigurationCustomizer getProjectConfigurationCustomizer(Project project, PropertyProvider aThis) {
+        return new IOSConfigurationPanel.IOSConfigurationCustomizer(project, aThis);
+    }
+    
+    @Override
+    public void openUrl(final String url) {
+        if (!simulator) {
+            //do nothing for device. Don't know how to open Safari on device.
+            return;
+        }
+        try {
+            if (ios_sim_bug) {
+                return;
+            }
+            try {
+                ProcessUtilities.callProcess("killall", true, IOSPlatform.DEFAULT_TIMEOUT, "MobileSafari"); // NOI18N
+            } catch (IOException ex) {
+            }
+            String simctlList = ProcessUtilities.callProcess("xcrun", true, IOSPlatform.DEFAULT_TIMEOUT, "simctl", "list"); //NOI18N
+            if (!simctlList.contains("Booted")) { //NOI18N
+                // boot the simulator and wait until it is ready
+                String sim = InstalledFileLocator.getDefault().locate("bin/ios-sim", "org.netbeans.modules.cordova.platforms.ios", false).getPath(); // NOI18N
+                ProcessUtilities.callProcess(sim, true, IOSPlatform.DEFAULT_TIMEOUT, "start", "--exit"); //NOI18N
+                Thread.sleep(10000); // try to wait for the simulator before loading the URL
+            }
+            String retVal = ProcessUtilities.callProcess("xcrun", true, IOSPlatform.DEFAULT_TIMEOUT, "simctl", "openurl", "booted", url); //NOI18N
+            LOG.finest(retVal);
+        } catch (IOException | InterruptedException ex) {
+            Exceptions.printStackTrace(ex);
+        } catch (IllegalStateException ex) {
+            //MobileSafari failed to load
+            ios_sim_bug = true;
+        }
+    }
+
+    private String getIPhoneSimName() {
+        return getPlatform().getPrefferedTarget().getIdentifier().replace("p","P").replace("s", "S"); // NOI18N
+    }
+
+    @Override
+    public MobileDebugTransport getDebugTransport() {
+        if (simulator) {
+            return new SimulatorDebugTransport();
+        } else {
+            return new DeviceDebugTransport();
+        }
+    }
+
+    @Override
+    public boolean isWebViewDebugSupported() {
+        return true;
+    }
+}
diff --git a/cordova.platforms.ios/src/org/netbeans/modules/cordova/platforms/ios/IOSPlatform.java b/cordova.platforms.ios/src/org/netbeans/modules/cordova/platforms/ios/IOSPlatform.java
new file mode 100644
index 0000000000..1aa99a7b34
--- /dev/null
+++ b/cordova.platforms.ios/src/org/netbeans/modules/cordova/platforms/ios/IOSPlatform.java
@@ -0,0 +1,249 @@
+/*
+ * 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.cordova.platforms.ios;
+
+import java.io.File;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.Iterator;
+import org.netbeans.modules.cordova.platforms.spi.Device;
+import org.netbeans.modules.cordova.platforms.spi.MobilePlatform;
+import org.netbeans.modules.cordova.platforms.api.PlatformManager;
+import org.netbeans.modules.cordova.platforms.api.ProcessUtilities;
+import org.netbeans.modules.cordova.platforms.spi.ProvisioningProfile;
+import org.netbeans.modules.cordova.platforms.spi.SDK;
+import org.openide.modules.InstalledFileLocator;
+import org.openide.util.EditableProperties;
+import org.openide.util.Exceptions;
+import org.openide.util.NbPreferences;
+import org.openide.util.Parameters;
+import org.openide.util.Utilities;
+import org.openide.util.lookup.ServiceProvider;
+
+/**
+ *
+ * @author Jan Becicka
+ * 
+ */
+@ServiceProvider(service=MobilePlatform.class)
+public class IOSPlatform implements MobilePlatform {
+    
+    private static String IOS_SIGN_IDENTITY_PREF = "ios.sign.identity"; //NOI18N
+    private static String IOS_PROVISIONING_PROFILE_PREF = "ios.provisioning.profile"; //NOI18N
+    public static final int DEFAULT_TIMEOUT = 30000;
+    
+    private boolean isReady = false;
+    
+    private transient final java.beans.PropertyChangeSupport propertyChangeSupport = new java.beans.PropertyChangeSupport(this);
+    private String sdkLocation;
+    private SDK DEFAULT = new IOSSDK("Simulator - iOS 6.0", "iphonesimulator6.0"); // NOI18N
+    
+    public String getType() {
+        return PlatformManager.IOS_TYPE;
+    }
+    
+    public IOSPlatform() {
+    }
+    
+    @Override
+    public Collection<SDK> getSDKs()  {
+        try {
+            String listSdks = ProcessUtilities.callProcess("xcodebuild", true, 60*1000, "-showsdks"); //NOI18N
+            return IOSSDK.parse(listSdks);
+        } catch (IOException ex) {
+            Exceptions.printStackTrace(ex);
+        }
+        return Collections.emptyList();
+    }
+    
+    @Override
+    public synchronized boolean isReady() {
+        if (!isReady) {
+            try {
+                String path = ProcessUtilities.callProcess("xcode-select", true, DEFAULT_TIMEOUT, "--print-path");
+                if (!"/Applications/Xcode.app/Contents/Developer".equals(path.trim())) {
+                    return false;
+                }
+                File f = new File("/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform"); // NOI18N
+                if (!f.exists()) {
+                    return false;
+                }
+                String version = ProcessUtilities.callProcess("xcodebuild", true, DEFAULT_TIMEOUT, "-version");
+                String[] lines = version.split(System.getProperty("line.separator"));
+                if (lines.length<1) {
+                    return false;
+                }
+                if (!lines[0].startsWith("Xcode")) {
+                    return false;
+                }
+            } catch (IOException ex) {
+                return false;
+            }
+            isReady = true;
+        }
+        return isReady;
+    }
+    
+    @Override
+    public String getSimulatorPath() {
+        return InstalledFileLocator.getDefault().locate("bin/ios-sim", "org.netbeans.modules.cordova.platforms.ios", false).getPath(); // NOI18N
+    }
+
+    @Override
+    public Collection<? extends Device> getConnectedDevices() throws IOException {
+        final WebInspectorJNIBinding inspector = WebInspectorJNIBinding.getDefault();
+        if (inspector.isDeviceConnected()) {
+            return Collections.singleton(IOSDevice.CONNECTED);
+        } else {
+            return Collections.emptyList();
+        }
+    }
+    
+    @Override
+    public SDK getPrefferedTarget() {
+        String preffered = System.getProperty("ios.preffered.sdk");
+        if (preffered != null ) {
+            return new IOSSDK(preffered, preffered);
+        }
+        if (Utilities.isMac()) {
+            final Collection<SDK> sDKs = getSDKs();
+            if (!sDKs.isEmpty()) {
+                return (SDK) sDKs.toArray()[sDKs.size()-1];
+            }
+        }
+        return DEFAULT;
+    }
+
+    @Override
+    public String getSdkLocation() {
+        return sdkLocation;
+    }
+
+
+    @Override
+    public void manageDevices() {
+        throw new UnsupportedOperationException("Not supported yet."); // NOI18N
+    }
+
+    /**
+     * Add PropertyChangeListener.
+     *
+     * @param listener
+     */
+    @Override
+    public void addPropertyChangeListener(java.beans.PropertyChangeListener listener ) {
+        propertyChangeSupport.addPropertyChangeListener( listener );
+    }
+
+    /**
+     * Remove PropertyChangeListener.
+     *
+     * @param listener
+     */
+    @Override
+    public void removePropertyChangeListener(java.beans.PropertyChangeListener listener ) {
+        propertyChangeSupport.removePropertyChangeListener( listener );
+    }
+    
+ 
+    @Override
+    public void setSdkLocation(String sdkLocation) {
+    }
+
+    @Override
+    public boolean waitEmulatorReady(int timeout) {
+        return true;
+    }
+
+    @Override
+    public Device getDevice(String name, EditableProperties props) {
+        Parameters.notNull("name", name);
+        Parameters.notNull("props", props);
+        if (Device.DEVICE.equals(props.getProperty(Device.DEVICE_PROP))) {
+            return IOSDevice.CONNECTED;
+        } else {
+            return IOSDevice.IPHONE;
+        }
+    }
+
+    @Override
+    public Collection<? extends Device> getVirtualDevices() throws IOException {
+        return EnumSet.allOf(IOSDevice.class);
+    }
+
+    @Override
+    public String getCodeSignIdentity() {
+        return NbPreferences.forModule(IOSPlatform.class).get(IOS_SIGN_IDENTITY_PREF, "iPhone Developer"); // NOI18N
+    }
+
+    @Override
+    public String getProvisioningProfilePath() {
+        String def = null;
+        File f = new File(System.getProperty("user.home") + "/Library/MobileDevice/Provisioning Profiles/");
+        if (f.exists() && f.isDirectory()) {
+            File[] listFiles = f.listFiles(new FilenameFilter() {
+
+                @Override
+                public boolean accept(File dir, String name) {
+                    return name.endsWith(".mobileprovision"); // NOI18N

  (This diff was longer than 20,000 lines, and has been truncated...)


 

----------------------------------------------------------------
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