/*******************************************************************************
* Copyright (c) 2014, 2015 IBM Corporation and others
* 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
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.orion.server.cf.ds;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import org.eclipse.core.filesystem.EFS;
import org.eclipse.core.filesystem.IFileStore;
import org.eclipse.core.runtime.Path;
import org.eclipse.orion.server.cf.ds.objects.Plan;
import org.eclipse.orion.server.cf.ds.objects.Procfile;
import org.eclipse.orion.server.cf.manifest.v2.InvalidAccessException;
import org.eclipse.orion.server.cf.manifest.v2.ManifestParseTree;
import org.eclipse.orion.server.cf.manifest.v2.utils.ManifestConstants;
import org.eclipse.orion.server.cf.manifest.v2.utils.ManifestUtils;
import org.eclipse.orion.server.core.IOUtilities;
import org.eclipse.orion.server.core.OrionConfiguration;
import org.eclipse.osgi.util.NLS;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public final class GenericDeploymentPlanner implements IDeploymentPlanner {
protected final Logger logger = LoggerFactory.getLogger("org.eclipse.orion.server.cf"); //$NON-NLS-1$
public static String TYPE = "generic"; //$NON-NLS-1$
@Override
public String getId() {
return getClass().getCanonicalName();
}
@Override
public String getWizardId() {
return "org.eclipse.orion.client.cf.wizard.generic"; //$NON-NLS-1$
}
protected String getApplicationName(IFileStore contentLocation) throws UnsupportedEncodingException {
IFileStore rootStore = OrionConfiguration.getRootLocation();
Path relativePath = new Path(URLDecoder.decode(contentLocation.toURI().toString(), "UTF8").substring(rootStore.toURI().toString().length()));
if (relativePath.segmentCount() < 4) {
// not a change to a file in a project
return null;
}
String projectDirectory = relativePath.segment(3);
projectDirectory = projectDirectory.replaceFirst(" \\| ", " --- ");
String[] folderNameParts = projectDirectory.split(" --- ", 2);
if (folderNameParts.length > 1)
return folderNameParts[1];
return folderNameParts[0];
}
protected String getApplicationHost(IFileStore contentLocation) throws UnsupportedEncodingException {
IFileStore rootStore = OrionConfiguration.getRootLocation();
Path relativePath = new Path(URLDecoder.decode(contentLocation.toURI().toString(), "UTF8").substring(rootStore.toURI().toString().length()));
if (relativePath.segmentCount() < 4) {
// not a change to a file in a project
return null;
}
String folderName = relativePath.segment(3);
folderName = folderName.replaceFirst(" \\| ", " --- ");
return ManifestUtils.slugify(folderName);
}
private void set(ManifestParseTree application, String property, String defaultValue) {
if (application.has(property))
return;
else
application.put(property, defaultValue);
}
/**
* Looks for a Procfile and parses the web command.
* @return <code>null</code> iff there is no Procfile present or it does not contain a web command.
*/
private String getProcfileCommand(IFileStore contentLocation) {
IFileStore procfileStore = contentLocation.getChild(ManifestConstants.PROCFILE);
if (!procfileStore.fetchInfo().exists())
return null;
InputStream is = null;
try {
is = procfileStore.openInputStream(EFS.NONE, null);
Procfile procfile = Procfile.load(is);
return procfile.get(ManifestConstants.WEB);
} catch (Exception ex) {
/* can't parse the file, fail */
return null;
} finally {
IOUtilities.safeClose(is);
}
}
@Override
public Plan getDeploymentPlan(IFileStore contentLocation, ManifestParseTree manifest, IFileStore manifestStore) {
IFileStore appStore = contentLocation;
try {
if (manifest != null) {
ManifestParseTree application = manifest.get(ManifestConstants.APPLICATIONS).get(0);
if (application.has(ManifestConstants.PATH)) {
appStore = contentLocation.getFileStore(new Path(application.get(ManifestConstants.PATH).getValue()));
}
}
} catch (InvalidAccessException e) {
logger.error("Problem while reading manifest", e);
}
try {
String applicationName = getApplicationName(contentLocation);
String manifestPath;
if (manifest == null) {
manifest = ManifestUtils.createBoilerplate(applicationName);
manifestPath = null;
} else {
manifestPath = contentLocation.toURI().relativize(manifestStore.toURI()).toString();
}
/* set up generic defaults */
ManifestParseTree application = manifest.get(ManifestConstants.APPLICATIONS).get(0);
set(application, ManifestConstants.HOST, getApplicationHost(contentLocation));
set(application, ManifestConstants.MEMORY, ManifestUtils.DEFAULT_MEMORY);
set(application, ManifestConstants.INSTANCES, ManifestUtils.DEFAULT_INSTANCES);
set(application, ManifestConstants.PATH, ManifestUtils.DEFAULT_PATH);
String procfileCommand = getProcfileCommand(appStore);
if (procfileCommand != null)
set(application, ManifestConstants.COMMAND, procfileCommand);
return new Plan(getId(), getWizardId(), TYPE, manifest, manifestPath);
} catch (Exception ex) {
/* Nobody expected the Spanish inquisition */
String msg = NLS.bind("Failed to handle generic deployment plan for {0}", contentLocation.toString()); //$NON-NLS-1$
logger.error(msg, ex);
return null;
}
}
}