/*******************************************************************************
* Copyright (c) 2012-2017 Codenvy, S.A.
* 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:
* Codenvy, S.A. - initial API and implementation
*******************************************************************************/
package org.eclipse.che.ide.sdk.tools;
import org.eclipse.che.commons.lang.IoUtil;
import org.eclipse.che.ide.commons.GwtXmlUtils;
import org.eclipse.che.ide.maven.tools.Dependency;
import org.eclipse.che.ide.maven.tools.MavenUtils;
import org.eclipse.che.ide.maven.tools.Model;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
/**
* Tool to integrate 3rd-party extensions to existing Codenvy IDE.
* <p/>
* This tool looks up all 3rd-party extensions in a special folder.
* For every found extension:
* <p/>
* - get GWT-module name from gwt.xml descriptor;
* <p/>
* - get Maven artifact coordinates;
* <p/>
* - add collected info in IDE.gwt.xml and pom.xml.
*
* @author Artem Zatsarynnyi
*/
public class InstallExtension {
public static final String IDE_GWT_XML_FILE_NAME = "IDE.gwt.xml";
/** CLI argument specifies the location of the directory that contains extensions to add. */
public static final String EXT_DIR_PARAMETER = "--extDir=";
/** CLI argument specifies the location of the directory that contains resource files to re-build Codenvy IDE. */
public static final String EXT_RESOURCES_DIR_PARAMETER = "--extResourcesDir=";
/** Location of the directory that contains 3rd-party extensions. */
public static Path extDirPath = null;
/** Location of the directory that contains resource files to re-build Codenvy IDE. */
public static Path extResourcesWorkDirPath = null;
public static void main(String[] args) throws IOException {
for (String arg : args) {
if (arg.startsWith(EXT_DIR_PARAMETER)) {
extDirPath = Paths.get(arg.substring(EXT_DIR_PARAMETER.length()));
} else if (arg.startsWith(EXT_RESOURCES_DIR_PARAMETER)) {
final Path extResourcesDirPath = Paths.get(arg.substring(EXT_RESOURCES_DIR_PARAMETER.length()));
final String tempDirName = "temp";
extResourcesWorkDirPath = extResourcesDirPath.resolve(tempDirName);
// delete working directory from previous build if it exist
IoUtil.deleteRecursive(extResourcesWorkDirPath.toFile());
Files.createDirectory(extResourcesWorkDirPath);
IoUtil.copy(extResourcesDirPath.toFile(), extResourcesWorkDirPath.toFile(), new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return !(tempDirName.equals(name));
}
});
} else {
System.err.println("Unknown flag: " + arg);
System.exit(1);
}
}
List<Extension> extensions = findExtensionsByPath(extDirPath);
for (Extension extension : extensions) {
final File pom = extResourcesWorkDirPath.resolve("pom.xml").toFile();
final Model model = Model.readFrom(pom);
model.dependencies()
.add(new Dependency(extension.groupId,
extension.artifactId,
extension.artifactVersion));
model.writeTo(pom);
// Add GWT module if there is one
if (extension.gwtModuleName != null) {
final Path ideGwtXmlPath = IoUtil.findFile(IDE_GWT_XML_FILE_NAME, extResourcesWorkDirPath.toFile()).toPath();
GwtXmlUtils.inheritGwtModule(ideGwtXmlPath, extension.gwtModuleName);
}
}
}
private static List<Extension> findExtensionsByPath(Path extDirPath) throws IOException {
File[] files = extDirPath.toFile().listFiles(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return name.endsWith(".jar");
}
});
List<Extension> extensions = new ArrayList<>();
for (File file : files) {
Extension extension = getExtensionFromFile(file.toPath());
if (extension != null) {
extensions.add(extension);
System.out.println(String.format("Extension found %s:%s:%s", extension.groupId, extension.artifactId, extension.artifactVersion));
if (extension.gwtModuleName != null) {
System.out.println(String.format(" Including GWT module %s", extension.gwtModuleName));
}
} else {
System.err.println(
String.format("Rejecting file %s it doesn't contain a pom.xml file", file.toPath().toString()));
}
}
System.out.println(String.format("Found: %d extension(s)", extensions.size()));
return extensions;
}
private static Extension getExtensionFromFile(Path zipPath) throws IOException {
try (ZipFile zipFile = new ZipFile(zipPath.toString())) {
Enumeration<? extends ZipEntry> entries = zipFile.entries();
ZipEntry gwtXmlEntry = null;
ZipEntry pomEntry = null;
while (entries.hasMoreElements()) {
ZipEntry entry = entries.nextElement();
if (!entry.isDirectory()) {
if (entry.getName().endsWith(GwtXmlUtils.GWT_MODULE_XML_SUFFIX)) {
gwtXmlEntry = entry;
} else if (entry.getName().endsWith("pom.xml")) {
pomEntry = entry;
}
}
// have both entries
if (pomEntry != null && gwtXmlEntry != null) {
break;
}
}
// TODO consider Codenvy extension validator
if (pomEntry == null) {
return null;
}
String gwtModuleName = null;
if (gwtXmlEntry != null) {
gwtModuleName = gwtXmlEntry.getName().replace(File.separatorChar, '.');
gwtModuleName = gwtModuleName.substring(0, gwtModuleName.length() - GwtXmlUtils.GWT_MODULE_XML_SUFFIX.length());
}
Model pom = Model.readFrom(zipFile.getInputStream(pomEntry));
return new Extension(gwtModuleName, MavenUtils.getGroupId(pom), pom.getArtifactId(), MavenUtils.getVersion(pom));
}
}
private static class Extension {
String gwtModuleName;
String groupId;
String artifactId;
String artifactVersion;
Extension(String gwtModuleName, String groupId, String artifactId, String artifactVersion) {
this.gwtModuleName = gwtModuleName;
this.groupId = groupId;
this.artifactId = artifactId;
this.artifactVersion = artifactVersion;
}
@Override
public String toString() {
return "Extension{" +
"gwtModuleName='" + gwtModuleName + '\'' +
", groupId='" + groupId + '\'' +
", artifactId='" + artifactId + '\'' +
", artifactVersion='" + artifactVersion + '\'' +
'}';
}
}
}