/****************************************************************************** * Copyright (c) 2005, 2007 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 ******************************************************************************/ package org.eclipse.jst.j2ee.internal.archive; import static org.eclipse.jst.j2ee.internal.archive.ArchiveExportParticipantsExtensionPoint.PluginUtil.findExtensions; import static org.eclipse.jst.j2ee.internal.archive.ArchiveExportParticipantsExtensionPoint.PluginUtil.findOptionalElement; import static org.eclipse.jst.j2ee.internal.archive.ArchiveExportParticipantsExtensionPoint.PluginUtil.findRequiredAttribute; import static org.eclipse.jst.j2ee.internal.archive.ArchiveExportParticipantsExtensionPoint.PluginUtil.findRequiredElement; import static org.eclipse.jst.j2ee.internal.archive.ArchiveExportParticipantsExtensionPoint.PluginUtil.getTopLevelElements; import static org.eclipse.jst.j2ee.internal.archive.ArchiveExportParticipantsExtensionPoint.PluginUtil.instantiate; import static org.eclipse.jst.j2ee.internal.plugin.J2EEPlugin.PLUGIN_ID; import static org.eclipse.jst.j2ee.internal.plugin.J2EEPlugin.createErrorStatus; import static org.eclipse.jst.j2ee.internal.plugin.J2EEPlugin.log; import static org.eclipse.jst.j2ee.internal.plugin.J2EEPlugin.logError; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; import org.eclipse.core.expressions.EvaluationContext; import org.eclipse.core.expressions.EvaluationResult; import org.eclipse.core.expressions.Expression; import org.eclipse.core.expressions.ExpressionConverter; import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IConfigurationElement; import org.eclipse.core.runtime.IExtension; import org.eclipse.core.runtime.IExtensionPoint; import org.eclipse.core.runtime.IExtensionRegistry; import org.eclipse.core.runtime.Platform; import org.eclipse.jst.j2ee.archive.IArchiveExportParticipant; import org.eclipse.jst.j2ee.internal.archive.ArchiveExportParticipantsExtensionPoint.PluginUtil.InvalidExtensionException; import org.eclipse.osgi.util.NLS; import org.eclipse.wst.common.project.facet.core.runtime.IRuntime; import org.eclipse.wst.common.project.facet.core.runtime.IRuntimeComponent; import org.eclipse.wst.common.project.facet.core.runtime.IRuntimeComponentType; import org.eclipse.wst.common.project.facet.core.runtime.IRuntimeComponentVersion; import org.eclipse.wst.common.project.facet.core.runtime.RuntimeManager; import org.osgi.framework.Bundle; /** * Contains the logic for processing the <code>org.eclipse.jst.j2ee.archiveExportParticipants</code> * extension point. * * @author <a href="mailto:kosta@bea.com">Konstantin Komissarchik</a> */ public final class ArchiveExportParticipantsExtensionPoint { public static final String EXTENSION_POINT_ID = "archiveExportParticipants"; //$NON-NLS-1$ private static final String EL_PARTICIPANT = "participant"; //$NON-NLS-1$ private static final String EL_RUNTIME_COMPONENT = "runtime-component"; //$NON-NLS-1$ private static final String EL_FACTORY = "factory"; //$NON-NLS-1$ private static final String EL_ENABLEMENT = "enablement"; //$NON-NLS-1$ private static final String ATTR_ID = "id"; //$NON-NLS-1$ private static final String ATTR_TYPE = "type"; //$NON-NLS-1$ private static final String ATTR_VERSION = "version"; //$NON-NLS-1$ private static final String ATTR_CLASS = "class"; //$NON-NLS-1$ private static List<ParticipantInfo> extensions = null; public static class ParticipantInfo { private String id; private String pluginId = null; private String className = null; private IRuntimeComponentType runtimeComponentType = null; private String runtimeComponentVersionExpr = null; private Expression enablementCondition = null; public String getId() { return this.id; } public IArchiveExportParticipant loadParticipant() { try { return instantiate( this.pluginId, this.className, IArchiveExportParticipant.class ); } catch( CoreException e ) { log( e.getStatus() ); return null; } } } public static List<ParticipantInfo> getExtensions( final IProject project, final IRuntime runtime ) { readExtensions(); final List<ParticipantInfo> result = new ArrayList<ParticipantInfo>(); for( ParticipantInfo partInfo : extensions ) { boolean match = false; for( IRuntimeComponent rc : runtime.getRuntimeComponents() ) { final IRuntimeComponentType rct = rc.getRuntimeComponentType(); if( rct == partInfo.runtimeComponentType ) { final IRuntimeComponentVersion rcv = rc.getRuntimeComponentVersion(); try { if( rct.getVersions( partInfo.runtimeComponentVersionExpr ).contains( rcv ) ) { match = true; break; } } catch( CoreException e ) { logError( -1, e.getMessage(), e ); } } } if( match && partInfo.enablementCondition != null ) { final EvaluationContext evalContext = new EvaluationContext( null, project ); evalContext.setAllowPluginActivation( true ); try { final EvaluationResult evalResult = partInfo.enablementCondition.evaluate( evalContext ); if( evalResult != EvaluationResult.TRUE ) { match = false; } } catch( CoreException e ) { logError( -1, e.getMessage(), e ); } } if( match ) { result.add( partInfo ); } } return Collections.unmodifiableList( result ); } private static synchronized void readExtensions() { if( extensions != null ) { return; } extensions = new ArrayList<ParticipantInfo>(); for( IConfigurationElement element : getTopLevelElements( findExtensions( PLUGIN_ID, EXTENSION_POINT_ID ) ) ) { if( element.getName().equals( EL_PARTICIPANT ) ) { try { readExtension( element ); } catch( InvalidExtensionException e ) { // Continue. The problem has been reported to the user via the log. } } } } private static void readExtension( final IConfigurationElement config ) throws InvalidExtensionException { final ParticipantInfo info = new ParticipantInfo(); info.pluginId = config.getContributor().getName(); info.id = info.pluginId + "." + findRequiredAttribute( config, ATTR_ID ); //$NON-NLS-1$ final IConfigurationElement elFactory = findRequiredElement( config, EL_FACTORY ); info.className = findRequiredAttribute( elFactory, ATTR_CLASS ); final IConfigurationElement elRuntimeComponent = findRequiredElement( config, EL_RUNTIME_COMPONENT ); final String rcTypeString = findRequiredAttribute( elRuntimeComponent, ATTR_TYPE ); if( ! RuntimeManager.isRuntimeComponentTypeDefined( rcTypeString ) ) { // TODO: Log the problem throw new InvalidExtensionException(); } info.runtimeComponentType = RuntimeManager.getRuntimeComponentType( rcTypeString ); info.runtimeComponentVersionExpr = elRuntimeComponent.getAttribute( ATTR_VERSION ); final IConfigurationElement elEnablement = findOptionalElement( config, EL_ENABLEMENT ); try { info.enablementCondition = ExpressionConverter.getDefault().perform( elEnablement ); } catch( CoreException e ) { logError( -1, e.getMessage(), e ); throw new InvalidExtensionException(); } extensions.add( info ); } /** * Utility methods that are helpful for implementing extension points. * * @author <a href="mailto:kosta@bea.com">Konstantin Komissarchik</a> */ public static final class PluginUtil { public static final class InvalidExtensionException extends Exception { private static final long serialVersionUID = 1L; } private PluginUtil() {} public static Collection<IExtension> findExtensions( final String pluginId, final String extensionPointId ) { final IExtensionRegistry registry = Platform.getExtensionRegistry(); final IExtensionPoint point = registry.getExtensionPoint( pluginId, extensionPointId ); if( point == null ) { throw new RuntimeException(); } final List<IExtension> extensions = new ArrayList<IExtension>(); for( IExtension extension : point.getExtensions() ) { extensions.add( extension ); } return extensions; } public static Collection<IConfigurationElement> getTopLevelElements( final Collection<IExtension> extensions ) { final List<IConfigurationElement> elements = new ArrayList<IConfigurationElement>(); for( IExtension extension : extensions ) { for( IConfigurationElement element : extension.getConfigurationElements() ) { elements.add( element ); } } return elements; } public static void reportMissingAttribute( final IConfigurationElement el, final String attribute ) { final String pluginId = el.getContributor().getName(); final String extPointId = el.getDeclaringExtension().getExtensionPointUniqueIdentifier(); final String msg = Resources.bind( Resources.missingAttribute, pluginId, extPointId, el.getName(), attribute ); log( createErrorStatus( -1, msg, null ) ); } public static void reportMissingElement( final IConfigurationElement el, final String element ) { final String pluginId = el.getContributor().getName(); final String extPointId = el.getDeclaringExtension().getExtensionPointUniqueIdentifier(); final String msg = Resources.bind( Resources.missingElement, pluginId, extPointId, el.getName(), element ); log( createErrorStatus( -1, msg, null ) ); } public static String findRequiredAttribute( final IConfigurationElement el, final String attribute ) throws InvalidExtensionException { final String val = el.getAttribute( attribute ); if( val == null ) { reportMissingAttribute( el, attribute ); throw new InvalidExtensionException(); } return val; } public static IConfigurationElement findRequiredElement( final IConfigurationElement el, final String childElement ) throws InvalidExtensionException { final IConfigurationElement[] children = el.getChildren( childElement ); if( children.length == 0 ) { reportMissingElement( el, childElement ); throw new InvalidExtensionException(); } return children[ 0 ]; } public static IConfigurationElement findOptionalElement( final IConfigurationElement el, final String childElement ) { final IConfigurationElement[] children = el.getChildren( childElement ); if( children.length == 0 ) { return null; } return children[ 0 ]; } public static String getElementValue( final IConfigurationElement el, final String defaultValue ) { if( el != null ) { String text = el.getValue(); if( text != null ) { text = text.trim(); if( text.length() > 0 ) { return text; } } } return defaultValue; } @SuppressWarnings( "unchecked" ) public static <T> T instantiate( final String pluginId, final String clname, final Class<T> interfc ) throws CoreException { final Bundle bundle = Platform.getBundle( pluginId ); final Object obj; try { final Class cl = bundle.loadClass( clname ); obj = cl.newInstance(); } catch( Exception e ) { final String msg = NLS.bind( Resources.failedToCreate, clname ); throw new CoreException( createErrorStatus( -1, msg, e ) ); } if( ! interfc.isAssignableFrom( obj.getClass() ) ) { final String msg = NLS.bind( Resources.doesNotImplement, clname, interfc.getClass().getName() ); throw new CoreException( createErrorStatus( -1, msg, null ) ); } return (T) obj; } private static final class Resources extends NLS { public static String missingAttribute; public static String missingElement; public static String failedToCreate; public static String doesNotImplement; static { initializeMessages( PluginUtil.class.getName(), Resources.class ); } public static String bind( final String message, final String arg1, final String arg2, final String arg3, final String arg4 ) { return bind( message, new Object[] { arg1, arg2, arg3, arg4 } ); } } } }