/******************************************************************************* * Copyright (c) 2010, Cloudsmith Inc. * The code, documentation and other materials contained herein have been * licensed under the Eclipse Public License - v 1.0 by the copyright holder * listed above, as the Initial Contributor under such license. The text of * such license is available at www.eclipse.org. ******************************************************************************/ package org.eclipse.buckminster.team; import java.io.PrintStream; import java.util.ArrayList; import java.util.Map; import java.util.TreeMap; import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; import org.eclipse.buckminster.core.actor.IActionContext; import org.eclipse.buckminster.core.common.model.ExpandingProperties; import org.eclipse.buckminster.core.reader.ITeamReaderType; import org.eclipse.buckminster.runtime.BuckminsterException; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.osgi.util.NLS; import org.eclipse.team.core.RepositoryProvider; /** * Implementation of the Workspace Resolution Tagging actor. When invoked on a * component this actor finds all its dependencies (even transitive) present in * the workspace and tags them with a tag according to the actor properties. * * @author michal.ruzicka@cloudsmith.com */ public class TagTeamActor extends AbstractTeamActor<TagTeamActor.TagContext> { protected static class TagContext extends TeamPerformContext { private String tag; private Pattern[] includes, excludes; public TagContext(IActionContext actionContext) throws CoreException { super(actionContext); TreeMap<Integer, Map.Entry<String, ?>> sortedIncludes = new TreeMap<Integer, Map.Entry<String, ?>>(); TreeMap<Integer, Map.Entry<String, ?>> sortedExcludes = new TreeMap<Integer, Map.Entry<String, ?>>(); StringBuilder message = null; // walk through the supplied actor properties and process those of // interest for (Map.Entry<String, ?> property : actionContext.getAction().getActorProperties().entrySet()) { String name = property.getKey(); if (name.startsWith(EXCLUDE_PROPERTY_PREFIX)) { try { int key = Integer.parseInt(name.substring(EXCLUDE_PROPERTY_PREFIX.length())); if (key >= 0) { sortedExcludes.put(Integer.valueOf(key), property); continue; } } catch (NumberFormatException e) { // fall through } } else if (name.startsWith(INCLUDE_PROPERTY_PREFIX)) { try { int key = Integer.parseInt(name.substring(INCLUDE_PROPERTY_PREFIX.length())); if (key >= 0) { sortedIncludes.put(Integer.valueOf(key), property); continue; } } catch (NumberFormatException e) { // fall through } } else if (name.equals(TAG_PROPERTY_NAME)) { tag = ExpandingProperties.expand(actionContext.getProperties(), (String) property.getValue(), 0); continue; } if (message == null) message = new StringBuilder(); else message.append(Messages.list_separator); message.append(name); } if (tag == null || tag.length() == 0) throw new CoreException(createStatus(NLS.bind(Messages.required_properties_not_supplied_0, TAG_PROPERTY_NAME))); if (message != null) throw new CoreException(createStatus(NLS.bind(Messages.unrecognized_properties_supplied_0, message.toString()) + '\n' + NLS.bind(Messages.recognized_properties_0, TAG_PROPERTY_NAME + Messages.list_separator // + INCLUDE_PROPERTY_PREFIX + "<n>" + Messages.list_separator//$NON-NLS-1$ + EXCLUDE_PROPERTY_PREFIX + "<n>"))); //$NON-NLS-1$ ArrayList<Pattern> patternList = new ArrayList<Pattern>(Math.max(sortedIncludes.size(), sortedExcludes.size())); for (Map.Entry<String, ?> include : sortedIncludes.values()) { String includeString = ExpandingProperties.expand(actionContext.getProperties(), (String) include.getValue(), 0); Pattern includePattern; try { includePattern = Pattern.compile(includeString); } catch (PatternSyntaxException e) { if (message == null) message = new StringBuilder(); else message.append('\n'); message.append(NLS.bind( Messages._0_entry_1_invalid_2, new Object[] { Messages.include_label, include.getKey(), NLS.bind(Messages.specified_pattern_is_invalid_0, e.getMessage()) })); continue; } patternList.add(includePattern); } includes = patternList.toArray(new Pattern[patternList.size()]); patternList.clear(); for (Map.Entry<String, ?> exclude : sortedExcludes.values()) { String excludeString = ExpandingProperties.expand(actionContext.getProperties(), (String) exclude.getValue(), 0); Pattern excludePattern; try { excludePattern = Pattern.compile(excludeString); } catch (PatternSyntaxException e) { if (message == null) message = new StringBuilder(); else message.append('\n'); message.append(NLS.bind( Messages._0_entry_1_invalid_2, new Object[] { Messages.exclude_label, exclude.getKey(), NLS.bind(Messages.specified_pattern_is_invalid_0, e.getMessage()) })); continue; } patternList.add(excludePattern); } if (message != null) throw new CoreException(createStatus(NLS.bind(Messages.property_settings_problems_0, message.toString()))); excludes = patternList.toArray(new Pattern[patternList.size()]); } public String getTag() { return tag; } public boolean shouldExclude(String name) { for (Pattern include : includes) { if (include.matcher(name).find()) return false; } for (Pattern exclude : excludes) { if (exclude.matcher(name).find()) return true; } return false; } } public static final String TAG_PROPERTY_NAME = "tag"; //$NON-NLS-1$ public static final String INCLUDE_PROPERTY_PREFIX = "include."; //$NON-NLS-1$ public static final String EXCLUDE_PROPERTY_PREFIX = "exclude."; //$NON-NLS-1$ @Override public String getActionName(IActionContext actionContext) { return NLS.bind(Messages.workspace_resolution_tagging_of_0, actionContext.getAction().getCSpec().getComponentIdentifier().toString()); } @Override protected TagContext createTeamPerformContext(IActionContext actionContext) throws CoreException { return new TagContext(actionContext); } @Override protected String getTaskName(RepositoryProvider provider) { return NLS.bind(Messages.tagging_project_0, provider.getProject().getName()); } @Override protected void processResources(TagContext tagContext, RepositoryProvider provider, IResource[] resources, boolean recurse, IProgressMonitor monitor) throws CoreException, InterruptedException { ITeamReaderType readerType = tagContext.getCachedReaderTypeForRepositoryProvider(provider.getID()); String tag = tagContext.getTag(); IStatus status = readerType.tag(provider, resources, tag, recurse, monitor); if (status.matches(IStatus.INFO | IStatus.WARNING)) { PrintStream outputPrintStream = tagContext.getActionContext().getOutputStream(); BuckminsterException.deeplyPrint(new CoreException(status), outputPrintStream, false); } else tagContext.collectStatus(status); } @Override protected boolean shouldExclude(TagContext tagContext, IResource resource) { return tagContext.shouldExclude(resource.getName()); } }