/*******************************************************************************
* 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.ide.project.core.modules.templates;
import com.liferay.ide.core.ILiferayProject;
import com.liferay.ide.core.LiferayCore;
import com.liferay.ide.core.util.CoreUtil;
import com.liferay.ide.core.util.FileUtil;
import com.liferay.ide.project.core.IProjectBuilder;
import com.liferay.ide.project.core.ProjectCore;
import com.liferay.ide.project.core.modules.IComponentTemplate;
import com.liferay.ide.project.core.modules.NewLiferayComponentOp;
import com.liferay.ide.project.core.modules.PropertyKey;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.jdt.core.IClasspathAttribute;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.sapphire.ElementList;
import org.eclipse.sapphire.java.JavaPackageName;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import freemarker.template.TemplateExceptionHandler;
/**
* @author Simon Jiang
*/
@SuppressWarnings( "rawtypes" )
public abstract class AbstractLiferayComponentTemplate implements IComponentTemplate<NewLiferayComponentOp>, Comparable<IComponentTemplate>
{
protected String displayName;
protected String shortName;
protected final static String TEMPLATE_DIR = "com/liferay/ide/project/core/modules/templates";
protected File[] bndTemplateFiles;
protected Configuration cfg = new Configuration();
protected String componentClassName;
protected File[] dependenciesTemplateFiles;
protected ILiferayProject liferayProject;
protected JavaPackageName packageName;
protected IProject project;
protected String projectName;
protected List<String> properties = new ArrayList<String>();
protected String serviceName;
protected File[] sourceTemplateFiles;
protected String templateName;
protected String componentNameWithoutTemplateName;
protected String modelClass;
protected String simpleModelClass;
private final static String[][] DEPENDENCY=
{
{ "com.liferay.portal", "com.liferay.portal.kernel", "2.0.0"},
{ "org.osgi", "org.osgi.service.component.annotations", "1.3.0"}
};
public AbstractLiferayComponentTemplate()
{
super();
}
public void setDisplayName( final String displayName )
{
this.displayName = displayName;
}
public void setShortName( final String shortName )
{
this.shortName = shortName;
}
@Override
public String getDisplayName()
{
return this.displayName;
}
@Override
public String getShortName()
{
return this.shortName;
}
public int compareTo( IComponentTemplate componentTemplate )
{
if( componentTemplate != null )
{
return this.displayName.compareTo( componentTemplate.getDisplayName() );
}
return 0;
}
protected void createFile( IFile newFile, final byte[] input ) throws CoreException
{
if( newFile.getParent() instanceof IFolder )
{
CoreUtil.prepareFolder( (IFolder) newFile.getParent() );
}
newFile.create( new ByteArrayInputStream( input ), true, null );
}
protected void createFileInResouceFolder( IFolder sourceFolder, String filePath, File resourceFile )
throws CoreException
{
final IFile projectFile = getProjectFile( sourceFolder, filePath );
if( !projectFile.exists() )
{
String readContents = FileUtil.readContents( resourceFile, true );
createFile( projectFile, readContents.getBytes() );
}
}
protected final IPackageFragment createJavaPackage( IJavaProject javaProject, final String packageName )
{
IPackageFragmentRoot packRoot = getSourceFolder( javaProject );
if( packRoot == null )
{
//IFolder resourceFolder = liferayProject.getSourceFolder( "src/main/java" );
//packRoot = javaProject.getPackageFragmentRoot(resourceFolder);
//return packRoot.getPackageFragment( packageName );
return null;
}
IPackageFragment pack = packRoot.getPackageFragment( packageName );
if( pack == null )
{
pack = packRoot.getPackageFragment( "" );
}
if( !pack.exists() )
{
String packName = pack.getElementName();
try
{
pack = packRoot.createPackageFragment( packName, true, null );
}
catch( CoreException e )
{
ProjectCore.logError( e );
}
}
return pack;
}
protected void createResorcesFolder( IProject project ) throws CoreException
{
IFolder resourceFolder = liferayProject.getSourceFolder( "resources" );
if( resourceFolder == null || !resourceFolder.exists() )
{
IJavaProject javaProject = JavaCore.create( project );
List<IClasspathEntry> existingRawClasspath = Arrays.asList( javaProject.getRawClasspath() );
List<IClasspathEntry> newRawClasspath = new ArrayList<IClasspathEntry>();
IClasspathAttribute[] attributes =
new IClasspathAttribute[] { JavaCore.newClasspathAttribute( "FROM_GRADLE_MODEL", "true" ) }; //$NON-NLS-1$ //$NON-NLS-2$
IClasspathEntry resourcesEntry = JavaCore.newSourceEntry(
project.getFullPath().append( "src/main/resources" ), new IPath[0], new IPath[0], null, attributes );
newRawClasspath.add( resourcesEntry );
for( IClasspathEntry entry : existingRawClasspath )
{
newRawClasspath.add( entry );
}
javaProject.setRawClasspath( newRawClasspath.toArray( new IClasspathEntry[0] ), new NullProgressMonitor() );
project.refreshLocal( IResource.DEPTH_INFINITE, new NullProgressMonitor() );
}
}
public void createSampleFile( IFile newFile, final String srcFileName ) throws CoreException
{
try
{
URL sampleFileURL = getClass().getClassLoader().getResource( TEMPLATE_DIR + "/" + srcFileName );
final String sampleContent =
FileUtil.readContents( new File( FileLocator.toFileURL( sampleFileURL ).getFile() ), true );
if( newFile.getParent() instanceof IFolder )
{
CoreUtil.prepareFolder( (IFolder) newFile.getParent() );
}
newFile.create( new ByteArrayInputStream( sampleContent.getBytes() ), true, null );
}
catch( IOException e )
{
throw new CoreException( ProjectCore.createErrorStatus( e ) );
}
}
public void createSampleFile( IFile newFile, final String srcFileName, final String oldReplaceConent, final String newReplaceContent) throws CoreException
{
try
{
URL sampleFileURL = getClass().getClassLoader().getResource( TEMPLATE_DIR + "/" + srcFileName );
final String sampleContent =
FileUtil.readContents( new File( FileLocator.toFileURL( sampleFileURL ).getFile() ), true );
final String newCoentent = sampleContent.replace( oldReplaceConent, newReplaceContent );
if( newFile.getParent() instanceof IFolder )
{
CoreUtil.prepareFolder( (IFolder) newFile.getParent() );
}
newFile.create( new ByteArrayInputStream( newCoentent.getBytes() ), true, null );
}
catch( IOException e )
{
throw new CoreException( ProjectCore.createErrorStatus( e ) );
}
}
protected void initializeOperation( final NewLiferayComponentOp op )
{
this.projectName = op.getProjectName().content( true );
this.packageName = op.getPackageName().content( true );
this.componentClassName = op.getComponentClassName().content( true );
this.templateName = op.getComponentClassTemplateName().content( true ).getShortName();
this.serviceName = op.getServiceName().content( true );
this.modelClass = op.getModelClass().content( true );
this.componentNameWithoutTemplateName = componentClassName.replace( templateName, "" );
if( modelClass != null )
{
int modeClassPos = modelClass.lastIndexOf( "." );
simpleModelClass = modelClass.substring( modeClassPos + 1 );
}
ElementList<PropertyKey> propertyKeys = op.getPropertyKeys();
for( int i = 0; i < propertyKeys.size(); i++ )
{
PropertyKey propertyKey = propertyKeys.get( i );
this.properties.add(
propertyKey.getName().content( true ) + "=" + propertyKey.getValue().content( true ) +
( i != ( propertyKeys.size() - 1 ) ? "," : "" ) );
}
}
public void doExecute( NewLiferayComponentOp op, IProgressMonitor monitor ) throws CoreException
{
try
{
initializeOperation( op );
this.project = CoreUtil.getProject( projectName );
if( project != null )
{
liferayProject = LiferayCore.create( project );
if( liferayProject != null )
{
initFreeMarker();
IFile srcFile = prepareClassFile( this.componentClassName );
doSourceCodeOperation( srcFile );
doNewPropertiesOperation();
doMergeResourcesOperation();
doMergeBndOperation();
doMergeDependencyOperation();
project.refreshLocal( IResource.DEPTH_INFINITE, new NullProgressMonitor() );
}
}
}
catch( Exception e )
{
throw new CoreException( ProjectCore.createErrorStatus( e ) );
}
}
protected void initBndProperties( File bndFile, BndProperties bndProperty)
{
try
{
bndProperty.load( bndFile );
}
catch( IOException e )
{
e.printStackTrace();
}
}
protected void setBndProperties( BndProperties bndProperty )
{
}
protected void doMergeBndOperation() throws CoreException
{
BndProperties bndProperty = new BndProperties();
IFile iBndFile = project.getFile( "bnd.bnd" );
if ( iBndFile.exists() )
{
File bndFile = iBndFile.getLocation().toFile();
initBndProperties( bndFile, bndProperty );
try( OutputStream out = new FileOutputStream( bndFile ) )
{
setBndProperties( bndProperty );
bndProperty.store( out, null );
}
catch( Exception e )
{
ProjectCore.logError( e );
}
}
}
protected void doMergeResourcesOperation() throws CoreException
{
}
protected void doNewPropertiesOperation() throws CoreException
{
}
protected List<String[]> getComponentDependency() throws CoreException
{
List<String[]> dependencyList = new ArrayList<String[]>();
for( String[] dependency : DEPENDENCY)
{
dependencyList.add( dependency );
}
return dependencyList;
}
protected void doMergeDependencyOperation() throws CoreException
{
final IProjectBuilder builder = liferayProject.adapt( IProjectBuilder.class );
builder.updateProjectDependency( project, getComponentDependency() );
}
protected void doSourceCodeOperation( IFile srcFile ) throws CoreException
{
try(OutputStream fos = new FileOutputStream( srcFile.getLocation().toFile() ))
{
Template temp = cfg.getTemplate( getTemplateFile() );
Map<String, Object> root = getTemplateMap();
Writer out = new OutputStreamWriter( fos );
temp.process( root, out );
fos.flush();
}
catch( IOException | TemplateException e )
{
throw new CoreException( ProjectCore.createErrorStatus( e ) );
}
}
protected String getExtensionClass()
{
return null;
}
protected List<String> getImports()
{
List<String> imports = new ArrayList<String>();
imports.add( "org.osgi.service.component.annotations.Component" );
return imports;
}
protected IProject getProject()
{
return CoreUtil.getProject( projectName );
}
protected IFile getProjectFile( IFolder sourceFolder, String filePath )
{
IFile retval = null;
if( sourceFolder != null )
{
retval = sourceFolder.getFile( new Path( filePath ) );
}
return retval;
}
protected List<String> getProperties()
{
return properties;
}
protected IPackageFragmentRoot getSourceFolder( IJavaProject javaProject )
{
try
{
for( IPackageFragmentRoot root : javaProject.getPackageFragmentRoots() )
{
if( root.getKind() == IPackageFragmentRoot.K_SOURCE )
{
return root;
}
}
}
catch( Exception e )
{
ProjectCore.logError( e );
}
return null;
}
protected String getSuperClass()
{
return null;
}
protected abstract String getTemplateFile();
protected Map<String, Object> getTemplateMap()
{
Map<String, Object> root = new HashMap<String, Object>();
root.put( "importlibs", getImports() );
root.put( "properties", getProperties() );
root.put( "packagename", packageName );
root.put( "classname", componentClassName );
root.put( "projectname", projectName );
root.put( "supperclass", getSuperClass() );
root.put( "extensionclass", getExtensionClass() );
root.put( "simplemodelclass", simpleModelClass );
root.put( "componentNameWithoutTemplateName", componentNameWithoutTemplateName );
root.put( "componentfolder", componentClassName.toLowerCase() );
return root;
}
protected void initFreeMarker() throws CoreException
{
try
{
URL templateURL = getClass().getClassLoader().getResource( TEMPLATE_DIR );
cfg.setDirectoryForTemplateLoading( new File( FileLocator.toFileURL( templateURL ).getFile() ) );
cfg.setDefaultEncoding( "UTF-8" );
cfg.setTemplateExceptionHandler( TemplateExceptionHandler.RETHROW_HANDLER );
}
catch( IOException e )
{
throw new CoreException( ProjectCore.createErrorStatus( e ) );
}
}
protected IFile prepareClassFile( final String className ) throws CoreException
{
IFile file = null;
try
{
IFolder sourceFolder = liferayProject.getSourceFolder( "java" );
IJavaProject javaProject = JavaCore.create( project );
if( packageName != null )
{
IPackageFragment pack = createJavaPackage( javaProject, packageName.toString() );
if( pack == null )
{
throw new CoreException( ProjectCore.createErrorStatus( "Can't create package folder" ) );
}
String fileName = className + ".java";
IPath packageFullPath = new Path( packageName.toString().replace( '.', IPath.SEPARATOR ) );
if( !packageFullPath.toFile().exists() )
{
CoreUtil.prepareFolder( sourceFolder.getFolder( packageFullPath ) );
}
IPath javaFileFullPath = packageFullPath.append( fileName );
file = sourceFolder.getFile( javaFileFullPath );
}
}
catch( Exception e )
{
throw new CoreException( ProjectCore.createErrorStatus( e ) );
}
return file;
}
}