Merge commit 'f77ed26a33fcb38eb99d52e73d1629b3519939c8'
diff --git a/mavenizer/src/main/java/SDKGenerator.java b/mavenizer/src/main/java/SDKGenerator.java
new file mode 100644
index 0000000..c69eda6
--- /dev/null
+++ b/mavenizer/src/main/java/SDKGenerator.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.
+ */
+import java.io.*;
+import javax.xml.parsers.*;
+
+import air.AirCompilerGenerator;
+import common.ConversionPlan;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.xml.sax.SAXException;
+import air.AirFrameworkGenerator;
+import air.AirRuntimeGenerator;
+import flex.FlexCompilerGenerator;
+import flex.FlexFrameworkGenerator;
+import flex.FlexRuntimeGenerator;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: cdutz
+ * Date: 11.05.12
+ * Time: 12:03
+ */
+public class SDKGenerator {
+
+    protected void buildAirConversionPlan(ConversionPlan plan, File sdkSourceDirectory) {
+        final File sdkDirectories[] = sdkSourceDirectory.listFiles(new FileFilter() {
+            public boolean accept(File pathname) {
+                return pathname.isDirectory();
+            }
+        });
+        if (sdkDirectories != null) {
+            for (final File sdkDirectory : sdkDirectories) {
+                final String sdkVersion = getAirSdkVersion(sdkDirectory);
+                if(sdkVersion != null) {
+                    plan.addVersion(sdkVersion, sdkDirectory, false);
+                }
+            }
+        }
+    }
+
+    /**
+     * All this little helper does is list up all directories in the given base directory and
+     * trigger the actual import on that. If a flex sdk comes with an air runtime, the structure
+     * is identical to that of an ordinary air sdk. Therefore the import works if a flex sdk or
+     * an air sdk directory is passed to this method.
+     *
+     * @param plan conversion plan for converting the air sdks containing the air content
+     * @param sdkTargetDirectory directory where to copy the content
+     * @throws Exception
+     */
+    public void generateAllAir(ConversionPlan plan, File sdkTargetDirectory) throws Exception {
+        for(final String airVersion : plan.getVersionIterator()) {
+            final File airDirectory = plan.getDirectory(airVersion);
+
+            System.out.println("---------------------------------------------");
+            System.out.println("-- Generating Air SDK version: " + airVersion);
+            System.out.println("---------------------------------------------");
+
+            generateAir(airDirectory, sdkTargetDirectory, airVersion);
+        }
+    }
+
+    public void generateAir(final File sdkSourceDirectory, final File sdkTargetDirectory, final String sdkVersion) throws Exception {
+        // Generate the artifacts, needed by the air compiler.
+        new AirCompilerGenerator().process(sdkSourceDirectory, false, sdkTargetDirectory, sdkVersion, false);
+
+        // Generate the artifacts, needed by the flex application.
+        new AirFrameworkGenerator().process(sdkSourceDirectory, false, sdkTargetDirectory, sdkVersion, false);
+
+        // Deploy the FlashPlayer and AIR runtime binaries.
+        new AirRuntimeGenerator().process(sdkSourceDirectory, false, sdkTargetDirectory, sdkVersion, false);
+    }
+
+    protected void buildFlexConversionPlan(ConversionPlan plan, File sdkSourceDirectory) {
+        final File sdkDirectories[] = sdkSourceDirectory.listFiles(new FileFilter() {
+            public boolean accept(File pathname) {
+                return pathname.isDirectory();
+            }
+        });
+        if (sdkDirectories != null) {
+            // Build a sorted set of versions as well as maps for the additional information
+            // to allow sorted conversion of the Flex SDKs.
+            for (final File sdkDirectory : sdkDirectories) {
+                String fdkVersion = getFlexSdkVersion(sdkDirectory);
+                // Apache FDKs have the version prefix "Apache-"
+                // So this is what we use in order to determine what type of FDK it is.
+                final boolean isApache = fdkVersion.startsWith("Apache-");
+                if (isApache) {
+                    fdkVersion = fdkVersion.substring("Apache-".length());
+                }
+                plan.addVersion(fdkVersion, sdkDirectory, isApache);
+            }
+        }
+    }
+
+    public void generateAllFlex(ConversionPlan plan, File sdkTargetDirectory, boolean useApache) throws Exception {
+        for(final String fdkVersion : plan.getVersionIterator()) {
+            final File fdkDirectory = plan.getDirectory(fdkVersion);
+            final boolean isApache = plan.getApacheFlag(fdkVersion);
+
+            System.out.println("---------------------------------------------");
+            System.out.println("-- Generating Flex SDK version: " + fdkVersion);
+            System.out.println("---------------------------------------------");
+
+            generateFlex(fdkDirectory, isApache, sdkTargetDirectory, fdkVersion, useApache);
+        }
+    }
+
+    public void generateFlex(final File sdkSourceDirectory, final boolean isApache, final File sdkTargetDirectory,
+                             final String sdkVersion, final boolean useApache) throws Exception {
+        // Generate the artifacts, needed by the flex compiler.
+        new FlexCompilerGenerator().process(sdkSourceDirectory, isApache, sdkTargetDirectory, sdkVersion, useApache);
+
+        // Generate the artifacts, needed by the flex application.
+        new FlexFrameworkGenerator().process(sdkSourceDirectory, isApache, sdkTargetDirectory, sdkVersion, useApache);
+
+        // Deploy the FlashPlayer and AIR runtime binaries.
+        new FlexRuntimeGenerator().process(sdkSourceDirectory, isApache, sdkTargetDirectory, sdkVersion, useApache);
+    }
+
+    public static void main(String[] args) throws Exception {
+
+        if (args.length != 3) {
+            System.out.println("Usage: SDKGenerator {source-directory} {target-directory} {use-apache-gid}");
+            System.exit(0);
+        }
+
+        final String sdkSourceDirectoryName = args[0];
+        final String sdkTargetDirectoryName = args[1];
+        final boolean useApache = Boolean.valueOf(args[2]);
+
+        final File sdkSourceDirectory = new File(sdkSourceDirectoryName);
+        final File sdkTargetDirectory = new File(sdkTargetDirectoryName);
+
+        // When generating the fdks the generator tries to figure out the flashplayer-version and air-version
+        // by comparing the hash of the playerglobal.swc and airglobal.swc with some hashes. This list of
+        // hashes has to be created first. Therefore the Generator generates air artifacts by processing air
+        // sdk directories and then by extracting the needed artifacts from the flex fdks.
+        final SDKGenerator generator = new SDKGenerator();
+        final ConversionPlan airPlan = new ConversionPlan();
+        generator.buildAirConversionPlan(airPlan, new File(sdkSourceDirectory, "air"));
+        generator.buildAirConversionPlan(airPlan, new File(sdkSourceDirectory, "flex"));
+        generator.generateAllAir(airPlan, sdkTargetDirectory);
+
+        // After the air artifacts are generated and
+        final ConversionPlan flexPlan = new ConversionPlan();
+        generator.buildFlexConversionPlan(flexPlan, new File(sdkSourceDirectory, "flex"));
+        generator.generateAllFlex(flexPlan, sdkTargetDirectory, useApache);
+    }
+
+    /**
+     * The only place I found where to extract the version of an Air SDK was the "AIR SDK Readme.txt" file.
+     * In order to get the version we need to cut out the version-part from the title-row of that text file.
+     * This file is present in the root of a pure air sdk or in the root of a flex sdk, therefore the same
+     * algorithm works if sdkSourceDirectory points to a flex sdk or an air sdk.
+     *
+     * @param sdkSourceDirectory directory in which to look for the sdk descriptor file of an air sdk
+     * @return version of the sdk in th given directory
+     */
+    public static String getAirSdkVersion(final File sdkSourceDirectory) {
+        final File sdkDescriptor = new File(sdkSourceDirectory, "AIR SDK Readme.txt");
+
+        if (sdkDescriptor.exists()) {
+            DataInputStream in = null;
+            try {
+                final FileInputStream fstream = new FileInputStream(sdkDescriptor);
+                in = new DataInputStream(fstream);
+                final BufferedReader br = new BufferedReader(new InputStreamReader(in));
+                final String strLine = br.readLine();
+                return strLine.substring("Adobe AIR ".length(), strLine.indexOf(" ", "Adobe AIR ".length()));
+            } catch (Exception e) {
+                e.printStackTrace();
+            } finally {
+                if (in != null) {
+                    try {
+                        in.close();
+                    } catch (IOException ioe) {
+                        // Ignore.
+                    }
+                }
+            }
+        }
+        return null;
+    }
+
+    /**
+     * The Flex SDK version is contained in the flex-sdk-description.xml file.
+     *
+     * @param sdkSourceDirectory directory where to look for the fdk descriptor file
+     * @return version string of the fdk
+     */
+    public static String getFlexSdkVersion(final File sdkSourceDirectory) {
+        final File sdkDescriptor = new File(sdkSourceDirectory, "flex-sdk-description.xml");
+
+        final DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+        try {
+            // Parse the document
+            final DocumentBuilder db = dbf.newDocumentBuilder();
+            final Document dom = db.parse(sdkDescriptor);
+
+            // Get name, version and build nodes
+            final Element root = dom.getDocumentElement();
+            final String name = root.getElementsByTagName("name").item(0).getTextContent();
+            final String version = root.getElementsByTagName("version").item(0).getTextContent();
+            final String build = root.getElementsByTagName("build").item(0).getTextContent();
+
+            // In general the version consists of the content of the version element with an appended build-number.
+            String sdkVersion = (build.equals("0")) ? version + "-SNAPSHOT" : version + "." + build;
+
+            // Deal with the patched re-releases of all older SDKs:
+            // The patched versions have A or B appended to their name and not a modified version or build number.
+            // In order to differentiate the patched versions from the un-patched ones, we appnd A or B to the
+            // version string.
+            if (name.endsWith("A")) {
+                sdkVersion += "A";
+            } else if (name.endsWith("B")) {
+                sdkVersion += "B";
+            }
+
+            // If the name contains "Apache", we prefix the version with "Apache-". This is cut off
+            // again later on.
+            if (name.contains("Apache")) {
+                sdkVersion = "Apache-" + sdkVersion;
+            }
+
+            return sdkVersion;
+        } catch (ParserConfigurationException pce) {
+            throw new RuntimeException(pce);
+        } catch (SAXException se) {
+            throw new RuntimeException(se);
+        } catch (IOException ioe) {
+            throw new RuntimeException(ioe);
+        }
+    }
+}
diff --git a/mavenizer/src/main/java/SDKInVMDeployer.java b/mavenizer/src/main/java/SDKInVMDeployer.java
new file mode 100644
index 0000000..d1643ab
--- /dev/null
+++ b/mavenizer/src/main/java/SDKInVMDeployer.java
@@ -0,0 +1,241 @@
+/*
+ * 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.
+ */
+
+import org.apache.maven.model.Model;
+import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
+import org.apache.maven.repository.internal.DefaultArtifactDescriptorReader;
+import org.apache.maven.repository.internal.DefaultVersionRangeResolver;
+import org.apache.maven.repository.internal.DefaultVersionResolver;
+import org.apache.maven.repository.internal.MavenRepositorySystemUtils;
+import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
+import org.eclipse.aether.DefaultRepositorySystemSession;
+import org.eclipse.aether.RepositorySystem;
+import org.eclipse.aether.RepositorySystemSession;
+import org.eclipse.aether.artifact.Artifact;
+import org.eclipse.aether.artifact.DefaultArtifact;
+import org.eclipse.aether.connector.basic.BasicRepositoryConnectorFactory;
+import org.eclipse.aether.deployment.DeployRequest;
+import org.eclipse.aether.deployment.DeploymentException;
+import org.eclipse.aether.impl.*;
+import org.eclipse.aether.installation.InstallationException;
+import org.eclipse.aether.internal.impl.DefaultDependencyCollector;
+import org.eclipse.aether.internal.impl.DefaultTransporterProvider;
+import org.eclipse.aether.repository.Authentication;
+import org.eclipse.aether.repository.LocalRepository;
+import org.eclipse.aether.repository.RemoteRepository;
+import org.eclipse.aether.spi.connector.RepositoryConnectorFactory;
+import org.eclipse.aether.spi.connector.transport.TransporterFactory;
+import org.eclipse.aether.spi.connector.transport.TransporterProvider;
+import org.eclipse.aether.transport.file.FileTransporterFactory;
+import org.eclipse.aether.transport.http.HttpTransporterFactory;
+import org.eclipse.aether.transport.wagon.WagonTransporterFactory;
+import org.eclipse.aether.util.repository.AuthenticationBuilder;
+
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.Reader;
+
+/**
+ * Updated Version of the SDKDeployer which no longer relies on an installed Maven
+ * system and which performs the deployment inside the VM without having to spawn new
+ * VMs for each artifact in order to deploy the files using a Maven commandline
+ * execution.
+ *
+ * Created with IntelliJ IDEA.
+ * User: cdutz
+ * Date: 03.11.13
+ *
+ * @author Christofer Dutz
+ */
+public class SDKInVMDeployer {
+
+    private String directory;
+    private String url;
+    private String username;
+    private String password;
+
+
+    public SDKInVMDeployer(String[] parameters) {
+        this.directory = parameters[0];
+        this.url = parameters[1];
+        if (parameters.length > 2) {
+            this.username = parameters[2];
+            this.password = parameters[3];
+        }
+    }
+
+    public static void main(String[] args) {
+        if ((args.length != 2) && (args.length != 4)) {
+            printUsage();
+            System.exit(0);
+        }
+
+        final SDKInVMDeployer deployer = new SDKInVMDeployer(args);
+        deployer.start();
+    }
+
+    private static void printUsage() {
+        System.out.println("\nUsage: java -cp flex-sdk-converter-1.0.jar SDKInVMDeployer \"directory\" \"url\" [\"username\", \"password\"]\n");
+        System.out.println("The SDKDeployer needs at least 2 ordered parameters separated by spaces:");
+        System.out.println("\t1- directory: The path to the directory containing the artifacts that should be deployed.");
+        System.out.println("\t2- url: URL where the artifacts will be deployed.");
+        System.out.println("If the targeted repository requires authentication two more parameters have to be provided:");
+        System.out.println("\t3- username: The username used to authenticate on the target repository.");
+        System.out.println("\t4- password: The password used to authenticate on the target repository.");
+    }
+
+    private void start() {
+        try {
+            final DefaultServiceLocator locator = new DefaultServiceLocator();
+            locator.addService(RepositoryConnectorFactory.class, BasicRepositoryConnectorFactory.class);
+            locator.addService(VersionResolver.class, DefaultVersionResolver.class);
+            locator.addService(VersionRangeResolver.class, DefaultVersionRangeResolver.class);
+            locator.addService(ArtifactDescriptorReader.class, DefaultArtifactDescriptorReader.class);
+            locator.addService(DependencyCollector.class, DefaultDependencyCollector.class);
+            locator.addService(RepositoryConnectorFactory.class, BasicRepositoryConnectorFactory.class);
+            locator.addService(TransporterProvider.class, DefaultTransporterProvider.class);
+            locator.addService(TransporterFactory.class, FileTransporterFactory.class);
+            locator.addService(TransporterFactory.class, HttpTransporterFactory.class);
+            locator.addService(TransporterFactory.class, WagonTransporterFactory.class);
+
+            final RepositorySystem repositorySystem = locator.getService(RepositorySystem.class);
+
+            if (repositorySystem == null) {
+                System.out.println("Couldn't initialize local maven repository system.");
+                System.exit(0);
+            } else {
+                // Setup the repository system session based upon the current maven settings.xml.
+                final DefaultRepositorySystemSession session = MavenRepositorySystemUtils.newSession();
+                final LocalRepository localRepo = new LocalRepository(directory);
+                RemoteRepository.Builder repoBuilder = new RemoteRepository.Builder("repo", "default", url);
+                if ((username != null) && (password != null)) {
+                    final Authentication authentication = new AuthenticationBuilder().addUsername(
+                            username).addPassword(password).build();
+                    repoBuilder.setAuthentication(authentication);
+                }
+                final RemoteRepository remoteRepository = repoBuilder.build();
+
+                session.setLocalRepositoryManager(repositorySystem.newLocalRepositoryManager(session, localRepo));
+
+                // Process all content of the mavenizer target directory.
+                final File rootDir = new File(directory);
+                processDir(rootDir, repositorySystem, session, remoteRepository);
+            }
+        } catch (Throwable e) {
+            e.printStackTrace();
+        }
+    }
+
+    private void processDir(File curDir, RepositorySystem repositorySystem, RepositorySystemSession session,
+                            RemoteRepository remoteRepository)
+            throws IOException, XmlPullParserException, InstallationException, DeploymentException {
+        // If the current directory contained any poms,
+        // process them as artifacts.
+        final File[] poms = curDir.listFiles(new PomFilter());
+        if (poms != null) {
+            for (File pom : poms) {
+                processArtifact(pom, repositorySystem, session, remoteRepository);
+            }
+        }
+
+        // If the current directory contained any directories,
+        // continue processing their content.
+        final File[] dirs = curDir.listFiles(new DirFilter());
+        if (dirs != null) {
+            for (File dir : dirs) {
+                processDir(dir, repositorySystem, session, remoteRepository);
+            }
+        }
+    }
+
+    private void processArtifact(File pomFile, RepositorySystem repositorySystem, RepositorySystemSession session,
+                                 RemoteRepository remoteRepository)
+            throws IOException, XmlPullParserException, InstallationException, DeploymentException {
+        final Reader reader = new FileReader(pomFile);
+        try {
+            final File artifactDirectory = pomFile.getParentFile();
+            final MavenXpp3Reader xpp3Reader = new MavenXpp3Reader();
+            final Model model = xpp3Reader.read(reader);
+
+            // Make the deployer deploy the pom itself.
+            final DeployRequest artifactInstallRequest = new DeployRequest();
+            artifactInstallRequest.setRepository(remoteRepository);
+            Artifact pomArtifact = new DefaultArtifact(
+                    model.getGroupId(), model.getArtifactId(), "pom", model.getVersion());
+            pomArtifact = pomArtifact.setFile(pomFile);
+            artifactInstallRequest.addArtifact(pomArtifact);
+
+            // Add any additional files to this installation.
+            final String artifactBaseName = model.getArtifactId() + "-" + model.getVersion();
+            final File artifactFiles[] = artifactDirectory.listFiles(new ArtifactFilter());
+            for (final File artifactFile : artifactFiles) {
+                final String fileName = artifactFile.getName();
+                final String classifier;
+                // This file has a classifier.
+                if (fileName.charAt(artifactBaseName.length()) == '-') {
+                    classifier = fileName.substring(artifactBaseName.length() + 1,
+                            fileName.indexOf(".", artifactBaseName.length()));
+                }
+                // This file doesn't have a classifier.
+                else {
+                    classifier = "";
+                }
+                final String extension = fileName.substring(
+                        artifactBaseName.length() + 1 + ((classifier.length() > 0) ? classifier.length() + 1 : 0));
+                Artifact fileArtifact = new DefaultArtifact(model.getGroupId(), model.getArtifactId(),
+                        classifier, extension, model.getVersion());
+                fileArtifact = fileArtifact.setFile(artifactFile);
+                artifactInstallRequest.addArtifact(fileArtifact);
+            }
+
+            // Actually install the artifact.
+            System.out.println("Installing Artifact: " + pomArtifact.getGroupId() + ":" +
+                    pomArtifact.getArtifactId() + ":" + pomArtifact.getVersion());
+            for (final Artifact artifact : artifactInstallRequest.getArtifacts()) {
+                System.out.println(" - File with extension " + artifact.getExtension() +
+                        ((artifact.getClassifier().length() > 0) ? " and classifier " + artifact.getClassifier() : ""));
+            }
+
+            repositorySystem.deploy(session, artifactInstallRequest);
+        } finally {
+            reader.close();
+        }
+    }
+
+    private class PomFilter implements java.io.FileFilter {
+        @Override
+        public boolean accept(File pathname) {
+            return pathname.getName().endsWith(".pom");
+        }
+    }
+
+    private class DirFilter implements java.io.FileFilter {
+        @Override
+        public boolean accept(File pathname) {
+            return pathname.isDirectory();
+        }
+    }
+
+    private class ArtifactFilter implements java.io.FileFilter {
+        @Override
+        public boolean accept(File pathname) {
+            return !pathname.getName().endsWith(".pom") && !pathname.isDirectory();
+        }
+    }
+
+}
diff --git a/mavenizer/src/main/java/common/ConversionPlan.java b/mavenizer/src/main/java/common/ConversionPlan.java
new file mode 100644
index 0000000..3897b0e
--- /dev/null
+++ b/mavenizer/src/main/java/common/ConversionPlan.java
@@ -0,0 +1,57 @@
+package common;
+
+import java.io.File;
+import java.util.*;
+
+/**
+ * Created by cdutz on 01.11.13.
+ */
+public class ConversionPlan {
+
+    private final Set<String> versions;
+    private final Map<String, File> directories;
+    private final Map<String, Boolean> apacheFlags;
+
+    public ConversionPlan() {
+        final Comparator<String> versionComparator = new Comparator<String>() {
+            public int compare(String o1, String o2) {
+                final String[] versionSegments1 = o1.split("\\.");
+                final String[] versionSegments2 = o2.split("\\.");
+                final int length = Math.min(versionSegments1.length, versionSegments2.length);
+                // Compare each of the segments.
+                for(int i = 0; i < length; i++) {
+                    final int result = new Integer(versionSegments1[i]).compareTo(Integer.parseInt(versionSegments2[i]));
+                    if(result != 0) {
+                        return result;
+                    }
+                }
+                // If all segments were equal, the string that has more segments wins.
+                return Integer.valueOf(versionSegments1.length).compareTo(versionSegments2.length);
+            }
+        };
+        versions = new TreeSet<String>(versionComparator);
+        directories = new HashMap<String, File>();
+        apacheFlags = new HashMap<String, Boolean>();
+    }
+
+    public void addVersion(String version, File directory, Boolean apacheFlag) {
+        if(!versions.contains(version)) {
+            versions.add(version);
+            directories.put(version, directory);
+            apacheFlags.put(version, apacheFlag);
+        }
+    }
+
+    public Set<String> getVersionIterator() {
+        return versions;
+    }
+
+    public File getDirectory(String version) {
+        return directories.get(version);
+    }
+
+    public Boolean getApacheFlag(String version) {
+        return apacheFlags.get(version);
+    }
+
+}