/******************************************************************************* * Copyright (c) 2014 Zend Technologies Ltd. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html *******************************************************************************/ package org.zend.php.zendserver.deployment.core.sdk; import java.io.File; import java.io.IOException; import org.apache.commons.io.FileUtils; import org.eclipse.core.runtime.FileLocator; import org.eclipse.core.runtime.Platform; import org.eclipse.osgi.util.NLS; import org.eclipse.php.internal.debug.core.preferences.PHPexeItem; import org.eclipse.php.internal.debug.core.preferences.PHPexes; import org.osgi.framework.Bundle; import org.zend.php.zendserver.deployment.core.DeploymentCore; import org.zend.sdklib.application.PackageBuilder; import org.zend.sdklib.internal.utils.CommandExecutor; import org.zend.sdklib.mapping.IMappingLoader; /** * Provides ability to create ZPK application package for production. It * executes the ZF Deploy tool as additional step of exporting the project to a * ZPK file. * * @author Kaloyan Raev */ public class ProductionPackageBuilder extends PackageBuilder { private static final String BUILD_COMMAND = "build"; //$NON-NLS-1$ private static final String TARGET_OPTION = "--target"; //$NON-NLS-1$ private static final String ZPK_DATA_OPTION = "--zpkdata"; //$NON-NLS-1$ private static final String CONFIGS_OPTION = "--configs"; //$NON-NLS-1$ private static final String GITIGNORE = ".gitignore"; //$NON-NLS-1$ private static final String ZPK_DATA_DIR = "zpkdata"; //$NON-NLS-1$ private static final String PHP = "php"; //$NON-NLS-1$ private static final String DEPLOY_PHAR = "lib/zfdeploy.phar"; //$NON-NLS-1$ private static final String TEMP_FILE_PREFIX = "zpk"; //$NON-NLS-1$ /** * The temporary directory to export the project before calling the ZF * Deploy tool. */ private File zpkTempDir; /** * The path to the directory with application configuration files to pack in * the ZPK file. */ private String appConfigsPath; /** * Constructor for the production package builder. * * @param container * the root of the project to export * @param loader * a mapping loader * @param appConfigsPath * a path to the directory with application configuration files */ public ProductionPackageBuilder(File container, IMappingLoader loader, String appConfigsPath) { super(container, container, loader); this.appConfigsPath = appConfigsPath; } /** * Creates the temporary directory for exporting the project. * * <p>After resolving all mappings this folder will be passed to the ZF Deploy tool.</p> */ @Override protected void prepareOutputFile(File zpkFile) throws IOException { // create the temporary directory for exporting the project zpkTempDir = createTempDirectory(); } /** * Executes the ZF Deploy tool on the temporary directory. */ @Override protected void finishOutputFile(File zpkFile) throws IOException { File appDir = new File(zpkTempDir, getAppdirName(configLocation)); // make sure the .gitignore file is copied if any File srcGitIgnore = new File(container, GITIGNORE); File destGitIgnore = new File(appDir, GITIGNORE); if (srcGitIgnore.exists() && !destGitIgnore.exists()) { FileUtils.copyFile(srcGitIgnore, destGitIgnore); } // move everything but the app dir into the zpkdata directory File zpkDataDir = new File(zpkTempDir, ZPK_DATA_DIR); for (File file : zpkTempDir.listFiles()) { if (!file.getName().equals(getAppdirName(configLocation))) { FileUtils.moveToDirectory(file, zpkDataDir, true); } } // construct the command to execute the zf-deploy tool String zpkFilePath = zpkFile.getPath(); String projectPath = appDir.getPath(); String zpkDataPath = zpkDataDir.getPath(); String[] command = new String[] { findPhpExePath(), getDeployPharPath(), BUILD_COMMAND, zpkFilePath, TARGET_OPTION, projectPath, ZPK_DATA_OPTION, zpkDataPath, CONFIGS_OPTION, appConfigsPath }; // delete any previous instance of the result ZPK file new File(zpkFilePath).delete(); // execute the ZF Deploy tool CommandExecutor cmdExecutor = new CommandExecutor(); cmdExecutor.setCommand(command); int exitCode = cmdExecutor.run(); if(exitCode != 0){ String message = NLS.bind( Messages.ProductionPackageBuilder_ErrorZFDeployTool, exitCode, cmdExecutor.getCommandOutput()); throw new IOException(message); } // delete the temporary directory FileUtils.deleteDirectory(zpkTempDir); } /** * Copies a file from a resolved mapping to the temporary directory. */ @Override protected void addFileToOutput(File file, String relativePath) throws IOException { FileUtils.copyFile(file, new File(zpkTempDir, relativePath)); } /** * Creates an empty directory in the temporary directory. */ @Override protected void addEmptyDirectoryToOutput(File directory) throws IOException { directory.mkdirs(); } /** * Creates a temporary directory in the system temp directory. * * @return a {@link File} reference to the created temporary directory * * @throws IOException * if the temporary directory cannot be created */ private File createTempDirectory() throws IOException { final File tmp; tmp = File.createTempFile(TEMP_FILE_PREFIX, Long.toString(System.nanoTime())); if (!(tmp.delete())) { throw new IOException( Messages.ProductionPackageBuilder_ErrorDeleteTempFile + tmp.getAbsolutePath()); } if (!(tmp.mkdir())) { throw new IOException( Messages.ProductionPackageBuilder_ErrorDeleteTempDirectory + tmp.getAbsolutePath()); } return tmp; } /** * Returns the path to the zfdeploy.phar packed in this OSGi bundle. * * @return the path to the zfdeploy.phar * * @throws IOException * if the path cannot be determined */ private String getDeployPharPath() throws IOException { Bundle bundle = Platform.getBundle(DeploymentCore.PLUGIN_ID); File bundleFile = FileLocator.getBundleFile(bundle); return new File(bundleFile, DEPLOY_PHAR).getPath(); } /** * Returns the path to the PHP executable. * * <p> * This method first checks if there are any PHP binaries packed in the IDE. * If yes, then returns the first found. Otherwise returns "php" with the * hope that there is PHP executable available on the executable path. * </p> * * @return the path to the PHP executable */ private String findPhpExePath() { PHPexeItem[] items = PHPexes.getInstance().getCLIItems(); if (items.length > 0) { return items[0].getExecutable().getPath(); } else { // no PHP binaries are available in IDE return PHP; } } }