/******************************************************************************* * 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; import com.liferay.ide.core.util.CoreUtil; import com.liferay.ide.core.util.MarkerUtil; import com.liferay.ide.project.core.util.ClasspathUtil; import com.liferay.ide.sdk.core.SDK; import com.liferay.ide.sdk.core.SDKUtil; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IMarker; import org.eclipse.core.resources.IProject; 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.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.Status; import org.eclipse.core.runtime.jobs.Job; /** * @author Simon Jiang */ public class SDKBuildPropertiesResourceListener implements IResourceChangeListener, IResourceDeltaVisitor { private final static String MARKER_ID_SDK_PROPERTIES_INVALID = "sdk-properties-invalid"; private final static String ID_WORKSPACE_SDK_INVALID = "workspace-sdk-invalid"; private final static Pattern PATTERN_BUILD_PROPERTIES = Pattern.compile("build.[\\w|\\W.]*properties"); private boolean checkMultipleSDK( final IProgressMonitor monitor ) throws CoreException { boolean hasMultipleSDK = false; boolean findSDK = false; final IProject[] projects = CoreUtil.getAllProjects(); for( final IProject existProject : projects ) { if ( SDKUtil.isValidSDKLocation( existProject.getLocation().toPortableString() ) ) { final IMarker[] problemMarkers = MarkerUtil.findMarkers( existProject, IMarker.PROBLEM, ID_WORKSPACE_SDK_INVALID ); if ( findSDK == false ) { if ( problemMarkers != null && problemMarkers.length > 0) { MarkerUtil.clearMarkers( existProject, IMarker.PROBLEM, ID_WORKSPACE_SDK_INVALID ); } findSDK = true; } else { if ( problemMarkers == null || problemMarkers.length < 1 ) { MarkerUtil.setMarker(existProject, IMarker.PROBLEM, IMarker.SEVERITY_ERROR, "Workspace has more than one SDK", existProject.getFullPath().toPortableString(),ID_WORKSPACE_SDK_INVALID); } hasMultipleSDK = true; } existProject.refreshLocal( IResource.DEPTH_INFINITE, monitor ); } } return hasMultipleSDK; } protected void processPropertiesFileChanged( final IFile deltaFile ) throws CoreException { final IProject deltaProject = deltaFile.getProject(); final SDK sdk = SDKUtil.createSDKFromLocation( deltaProject.getLocation() ); if ( sdk != null ) { final IMarker[] problemMarkers = MarkerUtil.findMarkers( deltaFile.getProject(), IMarker.PROBLEM, MARKER_ID_SDK_PROPERTIES_INVALID ); final IStatus sdkStatus = sdk.validate( true ); if( sdkStatus.isOK() ) { if ( problemMarkers != null && problemMarkers.length > 0) { MarkerUtil.clearMarkers( deltaFile.getProject(), IMarker.PROBLEM, MARKER_ID_SDK_PROPERTIES_INVALID ); } for( final IProject project : CoreUtil.getAllProjects() ) { if( SDKUtil.isSDKProject( project ) && sdk.getLocation().isPrefixOf( project.getLocation() ) ) { Job job = new WorkspaceJob( "Updating dependencies " + project.getName() ) { @Override public IStatus runInWorkspace( final IProgressMonitor monitor ) throws CoreException { ClasspathUtil.updateRequestContainer( project ); return Status.OK_STATUS; } }; job.schedule(); } } } else { final IStatus[] statuses = sdkStatus.getChildren(); for( IMarker marker : problemMarkers ) { boolean canDelete = true; String message = ( String ) marker.getAttribute( IMarker.MESSAGE ); for( final IStatus status : statuses ) { if ( status.getMessage().equals( message )) { canDelete = false; break; } } if ( canDelete ) { marker.delete(); } } for( final IStatus status : statuses ) { boolean canAdd = true; for( IMarker marker : problemMarkers ) { String message = ( String ) marker.getAttribute( IMarker.MESSAGE ); if ( status.getMessage().equals( message )) { canAdd = false; break; } } if ( canAdd ) { MarkerUtil.setMarker( deltaFile, IMarker.PROBLEM, IMarker.SEVERITY_ERROR, status.getMessage(), deltaFile.getFullPath().toPortableString(), MARKER_ID_SDK_PROPERTIES_INVALID ); } } } } } @Override public void resourceChanged( final IResourceChangeEvent event ) { if( event == null ) { return; } try { final IResourceDelta delta = event.getDelta(); if( delta != null ) { for( IResourceDelta child : delta.getAffectedChildren() ) { IResource resource = child.getResource(); if( resource != null ) { IProject[] sdkProjects = SDKUtil.getWorkspaceSDKs(); for( IProject sdkProject : sdkProjects ) { IPath sdkProjectLocation = sdkProject.getLocation(); if( sdkProjectLocation != null ) { final IResourceDelta[] sdkChangedFiles = child.getAffectedChildren( IResourceDelta.CHANGED | IResourceDelta.ADDED | IResourceDelta.REMOVED ); for( IResourceDelta sdkDelta : sdkChangedFiles ) { IResource sdkDeltaResource = sdkDelta.getResource(); if( sdkDeltaResource != null && sdkDeltaResource.getLocation() != null ) { if( sdkProjectLocation.isPrefixOf( sdkDeltaResource.getLocation() ) ) { final String deltaLastSegment = sdkDelta.getFullPath().lastSegment(); final Matcher propertiesMatcher = PATTERN_BUILD_PROPERTIES.matcher( deltaLastSegment ); if( propertiesMatcher.matches() ) { sdkDelta.accept( this ); break; } } } } } } } } } } catch( Throwable e ) { ProjectCore.logError( "build.properties resource listener failed.", e ); } } @Override public boolean visit( final IResourceDelta delta ) throws CoreException { switch( delta.getResource().getType() ) { case IResource.ROOT: case IResource.PROJECT: case IResource.FOLDER: return true; case IResource.FILE: { final IFile deltaFile = (IFile)delta.getResource(); Job job = new WorkspaceJob( "Processing SDK build properties file" ) { @Override public IStatus runInWorkspace( final IProgressMonitor monitor ) throws CoreException { try { final boolean hasMultipleSDK = checkMultipleSDK( monitor ); if ( !hasMultipleSDK ) { final IPath deltaLocation = deltaFile.getLocation(); if( deltaLocation != null ) { final SDK sdk = SDKUtil.getWorkspaceSDK(); if( sdk.getLocation().isPrefixOf( deltaLocation ) ) { processPropertiesFileChanged( deltaFile ); } } } } catch(CoreException e) { ProjectCore.logError( e ); } return Status.OK_STATUS; } }; job.schedule(); } return false; } return false; } }