/**
* Copyright (c) 2000-present Liferay, Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or (at your option)
* any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*/
package com.liferay.project.templates.internal;
import com.liferay.project.templates.ProjectTemplates;
import com.liferay.project.templates.ProjectTemplatesArgs;
import com.liferay.project.templates.internal.util.FileUtil;
import com.liferay.project.templates.internal.util.ReflectionUtil;
import com.liferay.project.templates.internal.util.Validator;
import com.liferay.project.templates.internal.util.WorkspaceUtil;
import java.io.File;
import java.lang.reflect.Field;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.util.Enumeration;
import java.util.List;
import java.util.Properties;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import org.apache.maven.archetype.ArchetypeGenerationRequest;
import org.apache.maven.archetype.ArchetypeGenerationResult;
import org.apache.maven.archetype.ArchetypeManager;
import org.apache.maven.archetype.DefaultArchetypeManager;
import org.apache.maven.archetype.common.ArchetypeArtifactManager;
import org.apache.maven.archetype.common.DefaultArchetypeArtifactManager;
import org.apache.maven.archetype.common.DefaultArchetypeFilesResolver;
import org.apache.maven.archetype.common.DefaultPomManager;
import org.apache.maven.archetype.exception.UnknownArchetype;
import org.apache.maven.archetype.generator.ArchetypeGenerator;
import org.apache.maven.archetype.generator.DefaultArchetypeGenerator;
import org.apache.maven.archetype.generator.DefaultFilesetArchetypeGenerator;
import org.apache.maven.archetype.generator.FilesetArchetypeGenerator;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.velocity.runtime.RuntimeConstants;
import org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader;
import org.codehaus.plexus.logging.AbstractLogEnabled;
import org.codehaus.plexus.logging.AbstractLogger;
import org.codehaus.plexus.logging.Logger;
import org.codehaus.plexus.velocity.DefaultVelocityComponent;
import org.codehaus.plexus.velocity.VelocityComponent;
/**
* @author Gregory Amerson
*/
public class Archetyper {
public ArchetypeGenerationResult generateProject(
ProjectTemplatesArgs projectTemplatesArgs, File destinationDir)
throws Exception {
String artifactId = projectTemplatesArgs.getName();
String author = projectTemplatesArgs.getAuthor();
String className = projectTemplatesArgs.getClassName();
String contributorType = projectTemplatesArgs.getContributorType();
String hostBundleSymbolicName =
projectTemplatesArgs.getHostBundleSymbolicName();
String hostBundleVersion = projectTemplatesArgs.getHostBundleVersion();
String packageName = projectTemplatesArgs.getPackageName();
File workspaceDir = WorkspaceUtil.getWorkspaceDir(destinationDir);
String projectType = "standalone";
if (workspaceDir != null) {
projectType = WorkspaceUtil.WORKSPACE;
}
String service = projectTemplatesArgs.getService();
String template = projectTemplatesArgs.getTemplate();
ArchetypeGenerationRequest archetypeGenerationRequest =
new ArchetypeGenerationRequest();
archetypeGenerationRequest.setArchetypeArtifactId(
ProjectTemplates.TEMPLATE_BUNDLE_PREFIX +
template.replace('-', '.'));
archetypeGenerationRequest.setArchetypeGroupId("com.liferay");
// archetypeVersion is ignored
archetypeGenerationRequest.setArchetypeVersion("0");
archetypeGenerationRequest.setArtifactId(artifactId);
archetypeGenerationRequest.setGroupId(packageName);
archetypeGenerationRequest.setInteractiveMode(false);
archetypeGenerationRequest.setOutputDirectory(destinationDir.getPath());
archetypeGenerationRequest.setPackage(packageName);
Properties properties = new Properties();
if (template.equals("service-builder")) {
String apiPath = ":" + artifactId + "-api";
if (workspaceDir != null) {
Path destinationDirPath = destinationDir.toPath();
Path workspaceDirPath = workspaceDir.toPath();
destinationDirPath = destinationDirPath.toAbsolutePath();
workspaceDirPath = workspaceDirPath.toAbsolutePath();
Path relativePath = workspaceDirPath.relativize(
destinationDirPath);
String path = relativePath.toString();
path = path.replace(File.separatorChar, ':');
apiPath = ":" + path + ":" + artifactId + apiPath;
}
_setProperty(properties, "apiPath", apiPath);
}
_setProperty(properties, "author", author);
_setProperty(properties, "buildType", "gradle");
_setProperty(properties, "className", className);
_setProperty(properties, "contributorType", contributorType);
_setProperty(
properties, "hostBundleSymbolicName", hostBundleSymbolicName);
_setProperty(properties, "hostBundleVersion", hostBundleVersion);
_setProperty(properties, "package", packageName);
_setProperty(properties, "projectType", projectType);
_setProperty(properties, "serviceClass", service);
_setProperty(properties, "serviceWrapperClass", service);
archetypeGenerationRequest.setProperties(properties);
archetypeGenerationRequest.setVersion("1.0.0");
ArchetypeManager archetypeManager = _createArchetypeManager();
return archetypeManager.generateProjectFromArchetype(
archetypeGenerationRequest);
}
private ArchetypeArtifactManager _createArchetypeArtifactManager()
throws Exception {
ArchetypeArtifactManager archetypeArtifactManager =
new ArchetyperArchetypeArtifactManager();
ReflectionUtil.setFieldValue(
_loggerField, archetypeArtifactManager, _logger);
return archetypeArtifactManager;
}
private ArchetypeGenerator _createArchetypeGenerator() throws Exception {
ArchetypeGenerator archetypeGenerator = new DefaultArchetypeGenerator();
ArchetypeArtifactManager archetypeArtifactManager =
_createArchetypeArtifactManager();
ReflectionUtil.setFieldValue(
DefaultArchetypeGenerator.class, "archetypeArtifactManager",
archetypeGenerator, archetypeArtifactManager);
ReflectionUtil.setFieldValue(
DefaultArchetypeGenerator.class, "filesetGenerator",
archetypeGenerator,
_createFilesetArchetypeGenerator(archetypeArtifactManager));
return archetypeGenerator;
}
private ArchetypeManager _createArchetypeManager() throws Exception {
DefaultArchetypeManager archetypeManager =
new DefaultArchetypeManager();
ReflectionUtil.setFieldValue(_loggerField, archetypeManager, _logger);
ReflectionUtil.setFieldValue(
DefaultArchetypeManager.class, "generator", archetypeManager,
_createArchetypeGenerator());
return archetypeManager;
}
private FilesetArchetypeGenerator _createFilesetArchetypeGenerator(
ArchetypeArtifactManager archetypeArtifactManager)
throws Exception {
FilesetArchetypeGenerator filesetArchetypeGenerator =
new DefaultFilesetArchetypeGenerator();
ReflectionUtil.setFieldValue(
_loggerField, filesetArchetypeGenerator, _logger);
ReflectionUtil.setFieldValue(
DefaultFilesetArchetypeGenerator.class, "archetypeArtifactManager",
filesetArchetypeGenerator, archetypeArtifactManager);
ReflectionUtil.setFieldValue(
DefaultFilesetArchetypeGenerator.class, "archetypeFilesResolver",
filesetArchetypeGenerator, new DefaultArchetypeFilesResolver());
ReflectionUtil.setFieldValue(
DefaultFilesetArchetypeGenerator.class, "pomManager",
filesetArchetypeGenerator, new DefaultPomManager());
ReflectionUtil.setFieldValue(
DefaultFilesetArchetypeGenerator.class, "velocity",
filesetArchetypeGenerator, _createVelocityComponent());
return filesetArchetypeGenerator;
}
private VelocityComponent _createVelocityComponent() throws Exception {
DefaultVelocityComponent defaultVelocityComponent =
new DefaultVelocityComponent();
ReflectionUtil.setFieldValue(
_loggerField, defaultVelocityComponent, _logger);
Properties properties = new Properties();
properties.setProperty(RuntimeConstants.RESOURCE_LOADER, "classpath");
properties.setProperty(
"classpath.resource.loader.class",
ClasspathResourceLoader.class.getName());
ReflectionUtil.setFieldValue(
DefaultVelocityComponent.class, "properties",
defaultVelocityComponent, properties);
defaultVelocityComponent.initialize();
return defaultVelocityComponent;
}
private void _setProperty(
Properties properties, String name, String value) {
if (Validator.isNotNull(value)) {
properties.setProperty(name, value);
}
}
private static final Field _loggerField;
static {
try {
_loggerField = ReflectionUtil.getField(
AbstractLogEnabled.class, "logger");
}
catch (Exception e) {
throw new ExceptionInInitializerError(e);
}
}
private final Logger _logger = new ArchetyperLogger();
private static class ArchetyperArchetypeArtifactManager
extends DefaultArchetypeArtifactManager {
@Override
public boolean exists(
String archetypeGroupId, String archetypeArtifactId,
String archetypeVersion, ArtifactRepository archetypeRepository,
ArtifactRepository localRepository,
List<ArtifactRepository> remoteRepositories) {
return true;
}
@Override
public File getArchetypeFile(
String groupId, String artifactId, String version,
ArtifactRepository archetypeRepository,
ArtifactRepository localRepository,
List<ArtifactRepository> repositories)
throws UnknownArchetype {
File archetypeFile = null;
try {
File file = FileUtil.getJarFile();
if (file.isDirectory()) {
Path archetypePath = FileUtil.getFile(
file.toPath(), artifactId + "-*.jar");
if (archetypePath != null) {
archetypeFile = archetypePath.toFile();
}
}
else {
try (JarFile jarFile = new JarFile(file)) {
Enumeration<JarEntry> enumeration = jarFile.entries();
while (enumeration.hasMoreElements()) {
JarEntry jarEntry = enumeration.nextElement();
if (jarEntry.isDirectory()) {
continue;
}
String name = jarEntry.getName();
if (!name.startsWith(artifactId + "-")) {
continue;
}
Path archetypePath = Files.createTempFile(
"temp-archetype", null);
Files.copy(
jarFile.getInputStream(jarEntry), archetypePath,
StandardCopyOption.REPLACE_EXISTING);
archetypeFile = archetypePath.toFile();
archetypeFile.deleteOnExit();
break;
}
}
}
}
catch (Exception e) {
throw new UnknownArchetype(e);
}
if (archetypeFile == null) {
throw new UnknownArchetype();
}
return archetypeFile;
}
@Override
public ClassLoader getArchetypeJarLoader(File archetypeFile)
throws UnknownArchetype {
try {
URI uri = archetypeFile.toURI();
return new URLClassLoader(new URL[] {uri.toURL()}, null);
}
catch (MalformedURLException murle) {
throw new UnknownArchetype(murle);
}
}
}
private static class ArchetyperLogger extends AbstractLogger {
public ArchetyperLogger() {
super(0, "archetyper");
}
@Override
public void debug(String message, Throwable throwable) {
}
@Override
public void error(String message, Throwable throwable) {
}
@Override
public void fatalError(String message, Throwable throwable) {
}
@Override
public Logger getChildLogger(String name) {
return this;
}
@Override
public void info(String message, Throwable throwable) {
}
@Override
public void warn(String message, Throwable throwable) {
}
}
}