blob: a2a37d9e33d75908647cb184705b13f7d90aa4e3 [file] [log] [blame]
/******************************************************************************
* Copyright (c) 2010 Oracle
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* Contributors:
* Konstantin Komissarchik - initial implementation and ongoing maintenance
******************************************************************************/
package org.eclipse.jst.common.project.facet.core.libprov.user;
import static org.eclipse.jst.common.project.facet.core.internal.FacetedProjectFrameworkJavaPlugin.createErrorStatus;
import static org.eclipse.jst.common.project.facet.core.internal.FacetedProjectFrameworkJavaPlugin.log;
import static org.eclipse.wst.common.project.facet.core.util.internal.PluginUtil.instantiate;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.internal.core.JavaModelManager;
import org.eclipse.jdt.internal.core.UserLibrary;
import org.eclipse.jdt.internal.core.UserLibraryManager;
import org.eclipse.jst.common.project.facet.core.internal.ClasspathUtil;
import org.eclipse.jst.common.project.facet.core.libprov.ILibraryProvider;
import org.eclipse.jst.common.project.facet.core.libprov.LibraryProviderFramework;
import org.eclipse.jst.common.project.facet.core.libprov.LibraryProviderInstallOperationConfig;
import org.eclipse.osgi.util.NLS;
import org.eclipse.wst.common.project.facet.core.FacetedProjectFramework;
import org.eclipse.wst.common.project.facet.core.IFacetedProjectBase;
import org.eclipse.wst.common.project.facet.core.IProjectFacet;
import org.eclipse.wst.common.project.facet.core.IProjectFacetVersion;
import org.osgi.service.prefs.BackingStoreException;
import org.osgi.service.prefs.Preferences;
/**
* The install operation config corresponding to the user-library-provider that uses JDT user library facility
* for managing libraries. This class can be subclassed by those wishing to extend the base implementation
* supplied by the framework.
*
* @author <a href="mailto:konstantin.komissarchik@oracle.com">Konstantin Komissarchik</a>
* @since 1.4
*/
@SuppressWarnings( "restriction" )
public class UserLibraryProviderInstallOperationConfig
extends LibraryProviderInstallOperationConfig
{
private static final String CLASS_NAME
= UserLibraryProviderInstallOperationConfig.class.getName();
/**
* The preferences path (in the workspace-level facet preferences) where information about
* user libraries that were last used for a particular facet are stored. Beneath this path,
* content is organized by facet version.
*/
public static final String PREFS_LAST_USED_LIBRARIES
= "user.library.provider/last.used.libraries"; //$NON-NLS-1$
/**
* The property corresponding to the list of selected user libraries.
*/
public static final String PROP_LIBRARY_NAMES
= CLASS_NAME + ".LIBRARY_NAMES"; //$NON-NLS-1$
private static final String PARAM_VALIDATOR = "validator"; //$NON-NLS-1$
private static final String PARAM_VALIDATOR_PARAM = "validator.param"; //$NON-NLS-1$
private List<String> libraryNames;
private List<String> libraryNamesReadOnly;
private UserLibraryValidator validator;
/**
* Constructs the user library provider install operation config.
*/
public UserLibraryProviderInstallOperationConfig()
{
this.libraryNames = Collections.emptyList();
this.libraryNamesReadOnly = Collections.emptyList();
this.validator = null;
}
/**
* Initializes the operation config. This method is called soon after the provider
* is instantiated. Extenders can override in order to add to the initialization, but
* have make sure to forward the init call up the inheritance chain.
*
* @param fpj the faceted project (or a working copy)
* @param fv the project facet that is making the request for libraries
* @param provider the library provider (useful if the same operation config class
* is re-used between multiple providers)
*/
@Override
public synchronized void init( final IFacetedProjectBase fproj,
final IProjectFacetVersion fv,
final ILibraryProvider provider )
{
super.init( fproj, fv, provider );
final Map<String,String> params = provider.getParams();
final String validatorClassName = params.get( PARAM_VALIDATOR );
if( validatorClassName != null )
{
this.validator = instantiate( provider.getPluginId(), validatorClassName, UserLibraryValidator.class );
if( this.validator != null )
{
final List<String> keyClassNames = new ArrayList<String>();
int i = 0;
String paramName = PARAM_VALIDATOR_PARAM + "." + String.valueOf( i ); //$NON-NLS-1$
String paramValue = params.get( paramName );
while( paramValue != null )
{
keyClassNames.add( paramValue );
i++;
paramName = PARAM_VALIDATOR_PARAM + "." + String.valueOf( i ); //$NON-NLS-1$
paramValue = params.get( paramName );
}
try
{
this.validator.init( keyClassNames );
}
catch( Exception e )
{
log( e );
this.validator = null;
}
}
}
reset();
}
/**
* Returns the list of user libraries that are currently selected. To listen for changes
* to this list use PROP_LIBRARY_NAMES.
*
* @return the list of user libraries that are currently selected
*/
public synchronized final List<String> getLibraryNames()
{
return this.libraryNamesReadOnly;
}
/**
* Sets the list of user libraries.
*
* @param libraryNames the list of user library names
*/
public synchronized final void setLibraryNames( final List<String> libraryNames )
{
final List<String> oldLibraryNames = this.libraryNamesReadOnly;
this.libraryNames = new ArrayList<String>( libraryNames );
this.libraryNamesReadOnly = Collections.unmodifiableList( this.libraryNames );
notifyListeners( PROP_LIBRARY_NAMES, oldLibraryNames, this.libraryNamesReadOnly );
}
/**
* Adds a library to the list of selected user libraries.
*
* @param libraryName the name of the library
*/
public synchronized final void addLibraryName( final String libraryName )
{
if( ! this.libraryNamesReadOnly.contains( libraryName ) )
{
final List<String> oldLibraryNames = this.libraryNamesReadOnly;
this.libraryNames = new ArrayList<String>( oldLibraryNames );
this.libraryNamesReadOnly = Collections.unmodifiableList( this.libraryNames );
this.libraryNames.add( libraryName );
notifyListeners( PROP_LIBRARY_NAMES, oldLibraryNames, this.libraryNamesReadOnly );
}
}
/**
* Resolve the referenced user libraries into a collection of classpath entries that reference
* physical libraries.
*
* @return the classpath entries contributed by the referenced user libraries
*/
public synchronized Collection<IClasspathEntry> resolve()
{
final List<IClasspathEntry> entries = new ArrayList<IClasspathEntry>();
final UserLibraryManager userLibraryManager = JavaModelManager.getUserLibraryManager();
for( String libraryName : this.libraryNames )
{
final UserLibrary userLibrary = userLibraryManager.getUserLibrary( libraryName );
if( userLibrary != null )
{
for( IClasspathEntry cpe : userLibrary.getEntries() )
{
entries.add( cpe );
}
}
}
return Collections.unmodifiableCollection( entries );
}
/**
* Validates the state of this operation config object and returns a status object
* describing any problems. If no problems are detected, this should return OK
* status.
*
* @return the result of validating this operation config
*/
@Override
public synchronized IStatus validate()
{
IStatus st = Status.OK_STATUS;
if( this.libraryNames.size() == 0 )
{
st = createErrorStatus( Resources.libraryNeedsToBeSelected );
}
else
{
if( this.validator != null )
{
try
{
st = this.validator.validate( this );
}
catch( Exception e )
{
log( e );
this.validator = null;
}
}
}
return st;
}
/**
* Resets this operation config to its initial state (prior to any user changes).
*/
@Override
public synchronized void reset()
{
final IProject project = getFacetedProject().getProject();
final IProjectFacet f = getProjectFacet();
final IProjectFacetVersion fv = getProjectFacetVersion();
List<String> newLibraryNames = null;
if( project != null )
{
final ILibraryProvider currentProvider
= LibraryProviderFramework.getCurrentProvider( project, f );
if( currentProvider == getLibraryProvider() )
{
final List<IClasspathEntry> entries;
try
{
entries = ClasspathUtil.getClasspathEntries( project, f );
}
catch( CoreException e )
{
throw new RuntimeException( e );
}
final List<String> libraryNamesList = new ArrayList<String>();
for( IClasspathEntry cpe : entries )
{
if( cpe.getEntryKind() == IClasspathEntry.CPE_CONTAINER )
{
final IPath path = cpe.getPath();
if( path.segmentCount() >= 2 && path.segment( 0 ).equals( JavaCore.USER_LIBRARY_CONTAINER_ID ) )
{
libraryNamesList.add( path.segment( 1 ) );
}
}
}
newLibraryNames = libraryNamesList;
}
}
if( newLibraryNames == null )
{
newLibraryNames = new ArrayList<String>();
try
{
Preferences prefs = FacetedProjectFramework.getPreferences( f );
if( prefs.nodeExists( PREFS_LAST_USED_LIBRARIES ) )
{
prefs = prefs.node( PREFS_LAST_USED_LIBRARIES );
if( prefs.nodeExists( fv.getVersionString() ) )
{
prefs = prefs.node( fv.getVersionString() );
for( String libraryName : prefs.childrenNames() )
{
newLibraryNames.add( libraryName );
}
}
}
}
catch( BackingStoreException e )
{
log( e );
}
}
setLibraryNames( newLibraryNames );
}
private static final class Resources
extends NLS
{
public static String libraryNeedsToBeSelected;
static
{
initializeMessages( UserLibraryProviderInstallOperationConfig.class.getName(),
Resources.class );
}
}
}