blob: 8d5935336d820a654da44143e04496b1cbf2b753 [file] [log] [blame]
/******************************************************************************
* Copyright (c) 2005 BEA Systems, Inc.
* 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:
* Konstantin Komissarchik - initial API and implementation
******************************************************************************/
package org.eclipse.jst.j2ee.project.facet;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.ProjectScope;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.jdt.core.IClasspathAttribute;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jst.common.project.facet.core.ClasspathHelper;
import org.eclipse.jst.common.project.facet.core.IClasspathProvider;
import org.eclipse.jst.common.project.facet.core.internal.FacetCorePlugin;
import org.eclipse.wst.common.componentcore.ComponentCore;
import org.eclipse.wst.common.componentcore.resources.IVirtualComponent;
import org.eclipse.wst.common.componentcore.resources.IVirtualReference;
import org.eclipse.wst.common.project.facet.core.IDelegate;
import org.eclipse.wst.common.project.facet.core.IFacetedProject;
import org.eclipse.wst.common.project.facet.core.IProjectFacetVersion;
import org.eclipse.wst.common.project.facet.core.IRuntimeChangedEvent;
import org.eclipse.wst.common.project.facet.core.ProjectFacetsManager;
import org.eclipse.wst.common.project.facet.core.runtime.IRuntime;
import org.osgi.service.prefs.BackingStoreException;
/**
* @author <a href="mailto:kosta@bea.com">Konstantin Komissarchik</a>
*/
public final class J2EEFacetRuntimeChangedDelegate
implements IDelegate
{
public static final String LEGACY_METADATA_FILE_NAME
= ".settings/org.eclipse.jst.common.project.facet.core.prefs"; //$NON-NLS-1$
private static final String OWNER_PROJECT_FACETS_ATTR = "owner.project.facets"; //$NON-NLS-1$
public void execute( final IProject project,
final IProjectFacetVersion fv,
final Object cfg,
final IProgressMonitor monitor )
throws CoreException
{
if( monitor != null )
{
monitor.beginTask( "", 11 ); //$NON-NLS-1$
}
try
{
IRuntimeChangedEvent event = (IRuntimeChangedEvent)cfg;
// Using our remove Utility to first check for missing preferences
removeClasspathEntries( project, fv, event.getOldRuntime());
if( ! ClasspathHelper.addClasspathEntries( project, fv ) )
{
// TODO: Support the no runtime case.
// ClasspathHelper.addClasspathEntries( project, fv, <something> );
}
if( monitor != null )
{
monitor.worked( 1 );
}
// Cascade this runtime change to projects referenced by this project
// Compile the list of projects referenced by this project.
final Set<IProject> childProjects = new HashSet<IProject>();
final IVirtualComponent projectVC = ComponentCore.createComponent( project );
Map<String, Object> options = new HashMap<String, Object>();
options.put(IVirtualComponent.REQUESTED_REFERENCE_TYPE, IVirtualComponent.HARD_REFERENCES);
final IVirtualReference[] vrefs = projectVC.getReferences(options);
for( int i = 0; i < vrefs.length; i++ ) {
final IVirtualReference vref = vrefs[ i ];
final IVirtualComponent vc = vref.getReferencedComponent();
childProjects.add( vc.getProject() );
}
if( monitor != null ) {
monitor.worked( 1 );
}
// Attempt to change the runtime for each of the referenced projects.
updateProjectRuntime( project, childProjects, submon( monitor, 9 ) );
}
finally
{
if( monitor != null )
{
monitor.done();
}
}
}
private void removeClasspathEntries(IProject project, IProjectFacetVersion fv, IRuntime oldRuntime) throws CoreException {
IJavaProject jproj = JavaCore.create(project);
List cp = getClasspath(jproj);
boolean hasPrefs = hasClasspathPreferencesNode(project);
// In the case where no prefs exists... make sure the entries of the
// oldRuntime are removed before continuing
if (!hasPrefs) {
removeOnlyCPEntries(project, fv, jproj, cp, oldRuntime);
} else
ClasspathHelper.removeClasspathEntries(project, fv);
}
private boolean hasClasspathPreferencesNode(IProject project) {
IProject pj = project.getProject();
IFile legacyMetadataFile = pj.getFile( LEGACY_METADATA_FILE_NAME );
// First check if file exists
if( legacyMetadataFile.exists() ) {
ProjectScope scope = new ProjectScope(project);
IEclipsePreferences pluginRoot = scope.getNode(FacetCorePlugin.PLUGIN_ID);
try {
return pluginRoot.nodeExists("classpath.helper"); //$NON-NLS-1$
} catch (BackingStoreException e) {
org.eclipse.jst.j2ee.internal.plugin.J2EEPlugin.logError(e);
}
}
//Now check classpath entries for new attributes
IJavaProject jproj = JavaCore.create( project );
return hasClasspathPreferencesNode(jproj);
}
private boolean hasClasspathPreferencesNode(IJavaProject jproj) {
boolean attributeFound = false;
IClasspathEntry[] entries = null;
try {
entries = jproj.getRawClasspath();
} catch (JavaModelException e) {
org.eclipse.jst.j2ee.internal.plugin.J2EEPlugin.logError(e);
}
int i = 0;
if (entries != null) {
while (!attributeFound && i < entries.length) {
IClasspathEntry cpe = entries[i];
attributeFound = hasOwnerAttribute( cpe );
i++;
}
}
return attributeFound;
}
private boolean hasOwnerAttribute(IClasspathEntry cpe) {
if( cpe != null )
{
for( IClasspathAttribute attr : cpe.getExtraAttributes() )
{
if( attr.getName().equals( OWNER_PROJECT_FACETS_ATTR ) )
return true;
}
}
return false;
}
private void removeOnlyCPEntries(final IProject project, final IProjectFacetVersion fv, final IJavaProject jproj, final List cp,
IRuntime oldRuntime) throws CoreException {
IFacetedProject fproj = ProjectFacetsManager.create(project);
IRuntime runtime = (oldRuntime != null) ? oldRuntime : fproj.getPrimaryRuntime();
if (runtime != null) {
IClasspathProvider cpprov = (IClasspathProvider) runtime.getAdapter(IClasspathProvider.class);
List cpentries = cpprov.getClasspathEntries(fv);
boolean realCPChanged = false;
if (cpentries != null) {
for (Iterator itr = cpentries.iterator(); itr.hasNext();) {
IClasspathEntry cpentry = (IClasspathEntry) itr.next();
IPath path = cpentry.getPath();
boolean contains = cp.contains(cpentry);
if (contains) {
for (Iterator itr2 = cp.iterator(); itr2.hasNext();) {
final IClasspathEntry realEntry = (IClasspathEntry) itr2.next();
if (realEntry.getPath().equals(path)) {
itr2.remove();
realCPChanged = true;
break;
}
}
}
}
}
if (realCPChanged) {
IClasspathEntry[] newcp = (IClasspathEntry[]) cp.toArray(new IClasspathEntry[cp.size()]);
jproj.setRawClasspath(newcp, null);
}
}
}
private List getClasspath(final IJavaProject jproj)
throws CoreException
{
ArrayList list = new ArrayList();
IClasspathEntry[] cp = jproj.getRawClasspath();
for (int i = 0; i < cp.length; i++) {
list.add(cp[i]);
}
return list;
}
private static IProgressMonitor submon( final IProgressMonitor parent, final int ticks ) {
return ( parent == null ? null : new SubProgressMonitor( parent, ticks ) );
}
public static void updateProjectRuntime( final IProject project,
final IProject childProject,
final IProgressMonitor monitor ) throws CoreException {
if( monitor != null ) {
monitor.beginTask( "", 1 ); //$NON-NLS-1$
}
try
{
final IFacetedProject facetedProject = ProjectFacetsManager.create( project );
final IRuntime projectRuntime = facetedProject.getRuntime();
final IFacetedProject childFacetedProject = ProjectFacetsManager.create( childProject );
if( childFacetedProject != null &&
! equals(projectRuntime, childFacetedProject.getRuntime()))
{
boolean supports = true;
if( projectRuntime != null )
{
for( Iterator itr = childFacetedProject.getProjectFacets().iterator(); itr.hasNext(); ) {
final IProjectFacetVersion fver = (IProjectFacetVersion) itr.next();
if(!projectRuntime.supports(fver)) {
supports = false;
break;
}
}
}
if( supports ) {
childFacetedProject.setRuntime(projectRuntime, submon( monitor, 1 ) );
}
}
}
finally {
if( monitor != null ) {
monitor.done();
}
}
}
public static void updateProjectRuntime( final IProject project,
final Set<IProject> childProjects,
final IProgressMonitor monitor ) throws CoreException {
if( monitor != null ) {
monitor.beginTask( "", childProjects.size() ); //$NON-NLS-1$
}
try {
for(final IProject childProject : childProjects) {
updateProjectRuntime( project, childProject,
submon( monitor, 1 ) );
}
}
finally {
if( monitor != null ) {
monitor.done();
}
}
}
private static boolean equals( final Object obj1, final Object obj2 ) {
if( obj1 == obj2 ) {
return true;
} else if( obj1 == null || obj2 == null ) {
return false;
} else {
return obj1.equals( obj2 );
}
}
}