com.sap.prd.mobile.ios.mios.PreDeployMojo.java Source code

Java tutorial

Introduction

Here is the source code for com.sap.prd.mobile.ios.mios.PreDeployMojo.java

Source

package com.sap.prd.mobile.ios.mios;

/*
 * #%L
 * Xcode Maven Plugin
 * %%
 * Copyright (C) 2012 SAP AG
 * %%
 * Licensed 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.
 * #L%
 */

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

import org.apache.commons.io.IOUtils;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.project.MavenProject;
import org.sonatype.aether.transfer.TransferCancelledException;
import org.sonatype.aether.transfer.TransferEvent;
import org.sonatype.aether.transfer.TransferListener;

/**
 * Registers a TransferListener on Aether that reacts on successful deployments. For each ipa file
 * deployed successfully a pointer file is written. This pointer file redirects to XXX
 * 
 * 
 * @goal pre-deploy
 * 
 */
public class PreDeployMojo extends AbstractDeployMojo {

    /**
     * The folder used for hudson archiving
     * 
     * @parameter expression="${archive.dir}" default-value="${project.build.directory}"
     */
    private File archiveFolder;

    private final static String HTML_TEMPLATE = "<html><head><meta http-equiv=\"refresh\" content=\"0; URL=$LOCATION\">"
            + "<body>You will be redirected within the next few seconds.<br />"
            + "In case this does not work click <a href=\"$LOCATION\">here</a></body></html>";

    /**
     * Returns the unique archive folder for this specific project (containing folders with groupId
     * and artifactId)
     * 
     * @param rootArchiveFolder
     * @param project
     * @return
     */
    static File getProjectArchiveFolder(File rootArchiveFolder, MavenProject project) {
        return new File(new File(new File(rootArchiveFolder, "artifacts"), project.getGroupId()),
                project.getArtifactId());
    }

    @Override
    public void execute() throws MojoExecutionException, MojoFailureException {
        try {
            archiveFolder = archiveFolder.getCanonicalFile();
        } catch (IOException ex) {
            throw new MojoExecutionException(ex.getMessage(), ex);
        }

        createArchiveFolder(archiveFolder);

        getLog().info("Using archive directory: '" + archiveFolder + "'.");

        try {

            //
            // [Q] Why do we use reflection here? What about a simple downcast to DefaultRepositorySystemSession?
            // [A] We cannot downcast since the downcast fails. The DefaultRepositorySystemSession that is available
            //     here is loaded by another class loader than the DefaultRepositorySystemSession used by the actual class.
            //     Hence we are in different runtime packages and the downcast is not possible.

            final TransferListener transferListener = getTransferListener();

            final TransferListener prepareIpaPointerFileTransferListener = new PrepareIpaPointerFileTransferListener(
                    transferListener);

            setTransferListener(prepareIpaPointerFileTransferListener);

            getLog().info("The previously used transfer listener was: '" + toString(transferListener) + "'.");
        } catch (RuntimeException e) {
            throw e;
        } catch (Exception e) {
            throw new MojoExecutionException(
                    "Cannot set transfer listener for creating artifact redirect HTML files: " + e.getMessage(), e);
        }
    }

    private static void createArchiveFolder(File archiveFolder) throws MojoExecutionException {
        if (archiveFolder.isFile())
            throw new MojoExecutionException(
                    "Archive folder '" + archiveFolder + "' is a file rather than a directory.");

        if (!archiveFolder.exists() && !archiveFolder.mkdirs())
            throw new MojoExecutionException("Cannot create archive folder '" + archiveFolder + "'.");
    }

    class PrepareIpaPointerFileTransferListener implements TransferListener {
        private TransferListener forward;

        PrepareIpaPointerFileTransferListener(TransferListener forward) {
            this.forward = forward;
        }

        TransferListener getForward() {
            return this.forward;
        }

        @Override
        public void transferSucceeded(TransferEvent event) {
            if (forward != null)
                forward.transferSucceeded(event);

            if (event.getRequestType().equals(TransferEvent.RequestType.GET))
                return;

            if (event.getResource().getResourceName().endsWith("maven-metadata.xml")) {

                getLog().debug("No redirect html file will be created for '" + event.getResource().getResourceName()
                        + "'.");
                return;
            }

            try {

                final String url = event.getResource().getRepositoryUrl() + event.getResource().getResourceName();
                final String html = HTML_TEMPLATE.replaceAll("\\$LOCATION", url);

                final File projectArchiveFolder = getProjectArchiveFolder(archiveFolder, project);
                final File redirect = new File(projectArchiveFolder, getArtifactRedirectHtmlFileName(url));

                writeArtifactRedirectHtmlFile(redirect, url, html);

                getLog().info("Redirect file '" + redirect + "' written for '" + url + "'.");

            } catch (RuntimeException ex) {

                getLog().error("Could not create artifact redirect HTML file for '"
                        + event.getResource().getResourceName(), ex);
            }
        }

        @Override
        public void transferStarted(TransferEvent event) throws TransferCancelledException {
            if (forward != null)
                forward.transferStarted(event);
        }

        @Override
        public void transferProgressed(TransferEvent event) throws TransferCancelledException {
            if (forward != null)
                forward.transferProgressed(event);
        }

        @Override
        public void transferInitiated(TransferEvent event) throws TransferCancelledException {
            if (forward != null)
                forward.transferInitiated(event);
        }

        @Override
        public void transferFailed(TransferEvent event) {
            if (forward != null)
                forward.transferFailed(event);
        }

        @Override
        public void transferCorrupted(TransferEvent event) throws TransferCancelledException {
            if (forward != null)
                forward.transferCorrupted(event);
        }

        private void writeArtifactRedirectHtmlFile(final File redirect, final String url, final String html) {
            FileOutputStream fos = null;

            try {

                if (!redirect.getParentFile().exists() && !redirect.getParentFile().mkdirs())
                    throw new IOException("Cannot create folder '" + redirect.getParentFile() + "'.");

                fos = new FileOutputStream(redirect);

                IOUtils.write(html, fos, "UTF-8");
            } catch (IOException ex) {
                throw new RuntimeException(ex);
            } finally {
                IOUtils.closeQuietly(fos);
            }
        }

        private String getArtifactRedirectHtmlFileName(final String url) {
            //E.g. MyApp-1.0.0-20120821.132955-1-Release-iphoneos-ota.htm 
            String artifactFileName = url.substring(url.lastIndexOf("/") + 1);
            return getRedirectHtmlFilename(artifactFileName, project.getArtifactId());
        }

    }

    static String getRedirectHtmlFilename(String artifactFileName, String artifactId) {
        String search = "-";
        int nthElement = 0;
        if (artifactFileName.endsWith(XCodeOtaHtmlGeneratorMojo.OTA_CLASSIFIER_APPENDIX + "."
                + XCodeOtaHtmlGeneratorMojo.OTA_HTML_FILE_APPENDIX)) {
            nthElement = 3;
        } else if (artifactFileName.endsWith("-AppStoreMetaData.zip")) {
            nthElement = 1;
        } else if (artifactFileName.endsWith("-app.dSYM.zip")) {
            nthElement = 3;
        } else if (artifactFileName.endsWith("-app.zip")) {
            nthElement = 3;
        } else if (artifactFileName.endsWith(".ipa")) {
            nthElement = 2;
        } else if (artifactFileName.endsWith("versions.xml")) {
            nthElement = 1;
        } else if (artifactFileName.endsWith(".pom")) {
            nthElement = 1;
            search = ".";
        } else if (artifactFileName.endsWith("-fat-binary.a")) {
            nthElement = 3;
        } else if (artifactFileName.endsWith(".a")) {
            nthElement = 2;
        } else if (artifactFileName.endsWith(".headers.tar")) {
            nthElement = 2;
        } else if (artifactFileName.endsWith(".tar")) {
            nthElement = 1;
            search = ".";
        }

        int idx = getNthIndexFromBack(artifactFileName, search, nthElement);
        if (idx >= 0) {
            String name = artifactId + artifactFileName.substring(idx);
            if (!name.endsWith(".htm")) {
                name = name + ".htm";
            }
            return name;
        }
        return artifactId + "-" + artifactFileName + ".htm";
    }

    static int getNthIndexFromBack(String string, String searchString, int countFromBack) {
        if (countFromBack <= 0)
            return -1;
        int idx = string.length();
        for (int i = 0; i < countFromBack; i++) {
            idx = string.substring(0, idx).lastIndexOf(searchString);
            if (idx <= 0)
                return idx;
        }
        return idx;
    }

}