/******************************************************************************* * 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.gradle.core; import com.liferay.blade.gradle.model.CustomModel; import com.liferay.ide.core.LiferayCore; import com.liferay.ide.core.LiferayNature; import com.liferay.ide.core.util.CoreUtil; import com.liferay.ide.project.core.util.LiferayWorkspaceUtil; import com.liferay.ide.project.core.util.ProjectUtil; import com.liferay.ide.server.core.portal.PortalRuntime; import com.liferay.ide.server.util.ServerUtil; import java.io.File; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import org.eclipse.buildship.core.configuration.GradleProjectNature; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IProjectDescription; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IResourceChangeEvent; import org.eclipse.core.resources.IResourceChangeListener; import org.eclipse.core.resources.IResourceDelta; import org.eclipse.core.resources.IResourceDeltaVisitor; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.resources.WorkspaceJob; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Plugin; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.Job; import org.osgi.framework.BundleContext; /** * The activator class controls the plugin life cycle * * @author Gregory Amerson * @author Terry Jia * @author Andy Wu */ public class GradleCore extends Plugin { // The shared instance private static GradleCore plugin; // The plugin ID public static final String PLUGIN_ID = "com.liferay.ide.gradle.core"; public static final String JobFamilyId = "CheckingGradleConfiguration"; public static final File customModelCache = LiferayCore.GLOBAL_SETTINGS_PATH.toFile(); public static IStatus createErrorStatus( Exception ex ) { return new Status( IStatus.ERROR, PLUGIN_ID, ex.getMessage(), ex ); } public static IStatus createErrorStatus( String msg ) { return new Status( IStatus.ERROR, PLUGIN_ID, msg ); } public static IStatus createErrorStatus( String msg, Exception e ) { return new Status( IStatus.ERROR, PLUGIN_ID, msg, e ); } public static IStatus createWarningStatus( String msg ) { return new Status( IStatus.WARNING, PLUGIN_ID, msg ); } /** * Returns the shared instance * * @return the shared instance */ public static GradleCore getDefault() { return plugin; } public static <T> T getToolingModel( GradleCore gradleCore, Class<T> modelClass, File projectDir ) { T retval = null; try { retval = GradleTooling.getModel( modelClass, customModelCache, projectDir ); } catch( Exception e ) { logError( "Error getting tooling model", e ); } return retval; } public static <T> T getToolingModel( GradleCore gradleCore, Class<T> modelClass, IProject gradleProject ) { return getToolingModel( gradleCore, modelClass, gradleProject.getLocation().toFile() ); } public static void logError( Exception ex ) { getDefault().getLog().log( createErrorStatus( ex ) ); } public static void logError( String msg ) { getDefault().getLog().log( createErrorStatus( msg ) ); } public static void logError( String msg, Exception e ) { getDefault().getLog().log( createErrorStatus( msg, e ) ); } /** * The constructor */ public GradleCore() { } private static void configureIfLiferayProject( final IProject project, final GradleCore gradleCore ) throws CoreException { if( project.hasNature( GradleProjectNature.ID ) && !LiferayNature.hasNature( project ) ) { final boolean[] needAddNature = new boolean[1]; needAddNature[0] = false; IFile bndFile = project.getFile( "bnd.bnd" ); // case 1: has bnd file if( bndFile != null && bndFile.exists() ) { needAddNature[0] = true; } else if( ProjectUtil.isWorkspaceWars( project ) ) { needAddNature[0] = true; } else { IFile gulpFile = project.getFile( "gulpfile.js" ); if( gulpFile != null && gulpFile.exists() ) { String gulpFileContent; try { gulpFileContent = new String( Files.readAllBytes( gulpFile.getLocation().toFile().toPath() ), StandardCharsets.UTF_8 ); // case 2: has gulpfile.js with some content if( gulpFileContent.contains( "require('liferay-theme-tasks')" ) ) { needAddNature[0] = true; } } catch( IOException e ) { logError( "read gulpfile.js file fail", e ); } } } Job job = new WorkspaceJob( "Checking gradle configuration" ) { @Override public IStatus runInWorkspace( IProgressMonitor monitor ) throws CoreException { try { if( needAddNature[0] ) { LiferayNature.addLiferayNature( project, monitor ); return Status.OK_STATUS; } final CustomModel customModel = getToolingModel( gradleCore, CustomModel.class, project ); if( customModel == null ) { throw new CoreException( GradleCore.createErrorStatus( "Unable to get read gradle configuration" ) ); } if( customModel.isLiferayModule() || customModel.hasPlugin( "org.gradle.api.plugins.WarPlugin" ) || customModel.hasPlugin( "com.liferay.gradle.plugins.theme.builder.ThemeBuilderPlugin" ) ) { LiferayNature.addLiferayNature( project, monitor ); } } catch( Exception e ) { logError( "Unable to get tooling model", e ); } return Status.OK_STATUS; } @Override public boolean belongsTo( Object family ) { if( family != null && family.toString().equals( JobFamilyId ) ) { return true; } return false; } }; job.setRule( CoreUtil.getWorkspaceRoot() ); job.schedule(); } } /* * (non-Javadoc) * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext) */ public void start( BundleContext context ) throws Exception { super.start( context ); plugin = this; CoreUtil.getWorkspace().addResourceChangeListener( new IResourceChangeListener() { @Override public void resourceChanged( IResourceChangeEvent event ) { try { event.getDelta().accept( new IResourceDeltaVisitor() { @Override public boolean visit( IResourceDelta delta ) throws CoreException { try { IResource resource = delta.getResource(); if( delta.getKind() == IResourceDelta.ADDED && resource.getName().equals( IProjectDescription.DESCRIPTION_FILE_NAME ) ) { IProjectDescription projectDescription = ResourcesPlugin.getWorkspace().loadProjectDescription( resource.getLocation() ); String projectName = projectDescription.getName(); IProject project = CoreUtil.getProject( projectName ); if( project != null && project.isAccessible() ) { configureIfLiferayProject( CoreUtil.getProject( projectName ), GradleCore.this ); } } } catch( Exception e ) { GradleCore.logError( e ); } return true; } } ); } catch( CoreException e ) { GradleCore.logError( e ); } } }, IResourceChangeEvent.POST_CHANGE ); CoreUtil.getWorkspace().addResourceChangeListener( new IResourceChangeListener() { @Override public void resourceChanged( IResourceChangeEvent event ) { try { if( event.getType() == IResourceChangeEvent.PRE_DELETE ) { // for the event of delete project IProject project = (IProject) event.getResource(); if( LiferayWorkspaceUtil.isValidWorkspace( project ) ) { IFolder bundlesFolder = project.getFolder( LiferayWorkspaceUtil.loadConfiguredHomeDir( project.getLocation().toOSString() ) ); if( bundlesFolder.exists() ) { File portalBundle = bundlesFolder.getLocation().toFile().getCanonicalFile(); ServerUtil.deleteRuntimeAndServer( PortalRuntime.ID , portalBundle ); } } return; } else { event.getDelta().accept( new IResourceDeltaVisitor() { @Override public boolean visit( IResourceDelta delta ) throws CoreException { try { // for only delete bundles dir if( delta.getKind() == IResourceDelta.REMOVED ) { IResource deletedRes = delta.getResource(); IProject project = deletedRes.getProject(); if( LiferayWorkspaceUtil.isValidWorkspace( project ) ) { IPath bundlesPath = project.getFullPath().append( LiferayWorkspaceUtil.loadConfiguredHomeDir( project.getLocation().toOSString() ) ); if( delta.getFullPath().equals( bundlesPath ) ) { try { File portalBundle = deletedRes.getLocation().toFile().getCanonicalFile(); ServerUtil.deleteRuntimeAndServer( PortalRuntime.ID, portalBundle ); } catch( Exception e ) { GradleCore.logError( "delete related runtime and server error", e ); } } } } } catch( Exception e ) { GradleCore.logError( e ); } return true; } } ); } } catch( Exception e ) { GradleCore.logError( "delete related runtime and server error", e ); } return; } }, IResourceChangeEvent.POST_CHANGE | IResourceChangeEvent.PRE_DELETE ); } /* * (non-Javadoc) * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext) */ public void stop( BundleContext context ) throws Exception { plugin = null; super.stop( context ); } }