blob: 18a187a19598e06a8090ab3f0630ecc7b2a033ff [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2006 IBM Corporation and others.
* 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:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.pde.tools.internal.versioning;
import java.io.*;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.eclipse.core.runtime.*;
import org.eclipse.osgi.util.NLS;
import org.eclipse.pde.tools.versioning.IVersionCompare;
import org.eclipse.update.core.IIncludedFeatureReference;
import org.eclipse.update.core.model.FeatureModel;
import org.eclipse.update.core.model.PluginEntryModel;
/**
* This class provides methods to process compare option property file, store the inclusive and exclusive
* information, check if a feature of plugin is need to be compared.
* <p>
* The properties in the compare option file are as following:
* <ul>
* <li>"exclude.os" - which indicates exclusive Operation Systems
* <li>"include.os" - which indicates inclusive Operation Systems
* <li>"exclude.ws" - which indicates exclusive windows system architecture specifications
* <li>"include.ws" - which indicates inclusive windows system architecture specifications
* <li>"exclude.arch" - which indicates exclusive optional system architecture specifications
* <li>"include.arch" - which indicates inclusive optional system architecture specifications
* <li>"exclude.nl" - which indicates exclusive optional locale language specifications
* <li>"include.nl" - which indicates inclusive optional locale language specifications
* <li>"exclude.features" - which indicates exclusive feature ids
* <li>"include.features" - which indicates inclusive feature ids
* <li>"exclude.plugins" - which indicates exclusive plugin ids
* <li>"include.plugins" - which indicates inclusive plugin ids
* </ul>
* </p>
*
*/
public class CompareOptionFileHelper implements VersionCompareConstants {
private Map optionTable = null;
/**
* constructor
* @param file compare option file
* @throws CoreException <p>if nested CoreException has been thrown
*/
public CompareOptionFileHelper(File file) throws CoreException {
if (file == null)
return;
processVersioningOptionFile(file);
}
/**
* processes the compare option file denoted by <code>file</code>, and put
* property key as key, List of property values of the property key as value
* into a map.
*
*
* @param file compare option file
* @throws CoreException if <code>file</code> does not exist or any IOException has been thrown
*/
private void processVersioningOptionFile(File file) throws CoreException {
Map table = new Hashtable();
InputStream inputStream = null;
Properties properties = new Properties();
try {
inputStream = new BufferedInputStream(new FileInputStream(file));
properties.load(inputStream);
} catch (FileNotFoundException fnfe) {
throw new CoreException(new Status(IStatus.ERROR, VersionCompareConstants.PLUGIN_ID, IStatus.ERROR, NLS.bind(Messages.VersionCompareDispatcher_fileNotFoundMsg, file.getAbsolutePath()), fnfe));
} catch (IOException ioe) {
throw new CoreException(new Status(IStatus.ERROR, VersionCompareConstants.PLUGIN_ID, IStatus.ERROR, NLS.bind(Messages.VersionCompareDispatcher_readPropertyFailedMsg, file.getAbsolutePath()), ioe));
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException ioe) {
throw new CoreException(new Status(IStatus.ERROR, VersionCompareConstants.PLUGIN_ID, IStatus.ERROR, NLS.bind(Messages.VersionCompareDispatcher_closeFileFailedMsg, file.getAbsolutePath()), ioe));
}
}
}
for (Iterator iterator = properties.keySet().iterator(); iterator.hasNext();) {
Object key = iterator.next();
String property = properties.getProperty((String) key);
if (property == null || property.trim().equals(VersionCompareConstants.EMPTY_STRING))
continue;
List propertyValueList;
// for feature or plugin inclusion, exclusion values, we convert them into Patterns
if (key.equals(IVersionCompare.INCLUDE_FEATURES_OPTION) || key.equals(IVersionCompare.EXCLUDE_FEATURES_OPTION) || key.equals(IVersionCompare.INCLUDE_PLUGINS_OPTION) || key.equals(IVersionCompare.EXCLUDE_PLUGINS_OPTION))
propertyValueList = generatePatternList(Arrays.asList(property.split(VersionCompareConstants.COMMA_MARK)));
else
propertyValueList = Arrays.asList(property.split(VersionCompareConstants.COMMA_MARK));
table.put(key, propertyValueList);
}
this.optionTable = table;
}
/*
* check the includes/excludes filters based on operating system
*/
private boolean filterOS(Object object) {
List inclusionValueList = (List) optionTable.get(IVersionCompare.INCLUDE_OS_OPTION);
String[] propertyValue;
if (object instanceof IIncludedFeatureReference)
propertyValue = ((IIncludedFeatureReference) object).getOS() == null ? null : ((IIncludedFeatureReference) object).getOS().split(COMMA_MARK);
else if (object instanceof PluginEntryModel)
propertyValue = ((PluginEntryModel) object).getOS() == null ? null : ((PluginEntryModel) object).getOS().split(COMMA_MARK);
else
propertyValue = ((FeatureModel) object).getOS() == null ? null : ((FeatureModel) object).getOS().split(COMMA_MARK);
if (!inclusionMatch(propertyValue, inclusionValueList))
return false;
// inclusionMatch is true, do exclusionMatch
return !exclusionMatch(propertyValue, (List) optionTable.get(IVersionCompare.EXCLUDE_OS_OPTION));
}
/*
* check the includes/excludes filters based on windowing system
*/
private boolean filterWS(Object object) {
List inclusionValueList = (List) optionTable.get(IVersionCompare.INCLUDE_WS_OPTION);
String[] propertyValue;
if (object instanceof IIncludedFeatureReference)
propertyValue = ((IIncludedFeatureReference) object).getWS() == null ? null : ((IIncludedFeatureReference) object).getWS().split(COMMA_MARK);
else if (object instanceof PluginEntryModel)
propertyValue = ((PluginEntryModel) object).getWS() == null ? null : ((PluginEntryModel) object).getWS().split(COMMA_MARK);
else
propertyValue = ((FeatureModel) object).getWS() == null ? null : ((FeatureModel) object).getWS().split(COMMA_MARK);
if (!inclusionMatch(propertyValue, inclusionValueList))
return false;
// inclusionMatch is true, do exclusionMatch
return !exclusionMatch(propertyValue, (List) optionTable.get(IVersionCompare.EXCLUDE_WS_OPTION));
}
/*
* check the includes/excludes filters based on system architecture
*/
private boolean filterArch(Object object) {
List inclusionValueList = (List) optionTable.get(IVersionCompare.INCLUDE_ARCH_OPTION);
String[] propertyValue;
if (object instanceof IIncludedFeatureReference)
propertyValue = ((IIncludedFeatureReference) object).getOSArch() == null ? null : ((IIncludedFeatureReference) object).getOSArch().split(COMMA_MARK);
else if (object instanceof PluginEntryModel)
propertyValue = ((PluginEntryModel) object).getOSArch() == null ? null : ((PluginEntryModel) object).getOSArch().split(COMMA_MARK);
else
propertyValue = ((FeatureModel) object).getOSArch() == null ? null : ((FeatureModel) object).getOSArch().split(COMMA_MARK);
if (!inclusionMatch(propertyValue, inclusionValueList))
return false;
// inclusionMatch is true, do exclusionMatch
return !exclusionMatch(propertyValue, (List) optionTable.get(IVersionCompare.EXCLUDE_ARCH_OPTION));
}
/*
* check the includes/excludes filters based on the language
*/
private boolean filterNL(Object object) {
List inclusionValueList = (List) optionTable.get(IVersionCompare.INCLUDE_NL_OPTION);
String[] propertyValue;
if (object instanceof IIncludedFeatureReference)
propertyValue = ((IIncludedFeatureReference) object).getNL() == null ? null : ((IIncludedFeatureReference) object).getNL().split(COMMA_MARK);
else if (object instanceof PluginEntryModel)
propertyValue = ((PluginEntryModel) object).getNL() == null ? null : ((PluginEntryModel) object).getNL().split(COMMA_MARK);
else
propertyValue = ((FeatureModel) object).getNL() == null ? null : ((FeatureModel) object).getNL().split(COMMA_MARK);
if (!inclusionMatch(propertyValue, inclusionValueList))
return false;
// inclusionMatch is true, do exclusionMatch
return !exclusionMatch(propertyValue, (List) optionTable.get(IVersionCompare.EXCLUDE_NL_OPTION));
}
/*
* check the includes/excludes filters based on feature identifiers
*/
private boolean filterFeatures(Object object) throws CoreException {
List inclusionPatternList = (List) optionTable.get(IVersionCompare.INCLUDE_FEATURES_OPTION);
String id;
if (object instanceof IIncludedFeatureReference)
id = ((IIncludedFeatureReference) object).getVersionedIdentifier().getIdentifier();
else
id = ((FeatureModel) object).getFeatureIdentifier();
if (inclusionPatternList != null) {
if (isMatch(id, inclusionPatternList)) {
// inclusion match, do exclusion match
List exclusionPatternList = (List) optionTable.get(IVersionCompare.EXCLUDE_FEATURES_OPTION);
if (exclusionPatternList != null && isMatch(id, exclusionPatternList))
return false;
} else
return false;
} else {
// do exclusion match
List exclusionPatternList = (List) optionTable.get(IVersionCompare.EXCLUDE_FEATURES_OPTION);
if (exclusionPatternList != null && isMatch(id, exclusionPatternList))
return false;
}
return true;
}
/*
* check the includes/excludes filters based on plugin identifiers
*/
private boolean filterPlugins(Object object) {
List inclusionPatternList = (List) optionTable.get(IVersionCompare.INCLUDE_PLUGINS_OPTION);
String id = ((PluginEntryModel) object).getPluginIdentifier();
if (inclusionPatternList != null) {
if (isMatch(id, inclusionPatternList)) {
// inclusion match, do exclusion match
List exclusionPatternList = (List) optionTable.get(IVersionCompare.EXCLUDE_PLUGINS_OPTION);
if (exclusionPatternList != null && isMatch(id, exclusionPatternList))
return false;
} else
return false;
} else {
// do exclusion match
List exclusionPatternList = (List) optionTable.get(IVersionCompare.EXCLUDE_PLUGINS_OPTION);
if (exclusionPatternList != null && isMatch(id, exclusionPatternList))
return false;
}
return true;
}
/**
* Returns a boolean value indicating whether or not the given object should be compared
* based on the includes and excludes filters.
* <p>
* The parameter can be of any of the following types:
* <ul>
* <li><code>IIncludedFeatureReference</code></li>
* <li><code>FeatureModel</code></li>
* <li><code>PluginEntryModel</code></li>
* </ul>
* </p>
*
* @param object the object to check
* @return <code>true</code> if we should compare and <code>false</code> otherwise
* @throws CoreException <p> if any nested CoreException has been thrown</p>
*/
public boolean shouldCompare(Object object) throws CoreException {
if (!((object instanceof IIncludedFeatureReference) || (object instanceof PluginEntryModel) || (object instanceof FeatureModel)))
return false;
if (optionTable == null || optionTable.size() == 0)
// if inclusionTable is null, means everything need to be compared
return true;
// check the includes/excludes filters based on operating system
if (!filterOS(object))
return false;
// check the includes/excludes filters based on windowing system
if (!filterWS(object))
return false;
// check the includes/excludes filters based on system architecture
if (!filterArch(object))
return false;
// check the includes/excludes filters based on the language
if (!filterNL(object))
return false;
// check the includes/excludes filters based on feature or plugin identifiers
if ((object instanceof IIncludedFeatureReference) || (object instanceof FeatureModel))
return filterFeatures(object);
else
return filterPlugins(object);
}
/**
* checks whether <code>list1</code> contains at least one element of <code>list2</code>
* @param list1 List
* @param list2 List
* @return <code>true</code>if <code>list1</code> contains at least one element of <code>list2</code>,
* <code>false</code> otherwise
*/
private boolean isIntersecting(List list1, List list2) {
for (Iterator iterator = list2.iterator(); iterator.hasNext();) {
Object key = iterator.next();
if (list1.contains(key))
return true;
}
return false;
}
/**
* check whether given <code>values</code> and <code>inclusionValueList</code> has an intersection
* @param values String array
* @param inclusionValueList inclusion value list
* @return <code>true</code> if given <code>values</code> and <code>inclusionValueList</code> has an intersection
* <code>false</code> otherwise
*/
private boolean inclusionMatch(String[] values, List inclusionValueList) {
if (values == null || inclusionValueList == null)
return true;
List propertyValue = Arrays.asList(values);
if (!isIntersecting(inclusionValueList, propertyValue))
// if propertyValue and inclusionValueList does not an intersection, return false
return false;
return true;
}
/**
* check whether given <code>values</code> are included the <code>exclusionValueList</code>
* @param values String array
* @param exclusionValueList exclusion value list
* @return <code>true</code> if given <code>values</code> are included the <code>exclusionValueList</code>
* <code>false</code> otherwise
*/
private boolean exclusionMatch(String[] values, List exclusionValueList) {
if (values == null || exclusionValueList == null)
return false;
List propertyValue = Arrays.asList(values);
if (!isIncluded(exclusionValueList, propertyValue))
// if propertyValue are not included in exclusionValuList, return false
return false;
return true;
}
/**
* checks whether <code>list1</code> contains all the elements of <code>list2</code>
* @param list1 List
* @param list2 List
* @return <code>true</code>if <code>list1</code> contains all the elements of <code>list2</code>,
* <code>false</code> otherwise
*/
private boolean isIncluded(List list1, List list2) {
for (Iterator iterator = list2.iterator(); iterator.hasNext();) {
Object key = iterator.next();
if (!list1.contains(key))
return false;
}
return true;
}
/**
* checks whether the <code>string</code> matches the <code>regex</code>
* @param string String need to be matched
* @param patternList List contains Patterns
* @return <code>true</code>if the <code>string</code> matches the <code>regex</code>
* <code>false</code>otherwise
*/
private boolean isMatch(String string, List patternList) {
for (Iterator iterator = patternList.iterator(); iterator.hasNext();) {
Pattern pattern = (Pattern) iterator.next();
Matcher matcher = pattern.matcher(string);
if (matcher.matches())
return true;
}
return false;
}
/**
* generates Pattern instances from each String in <code>list</code>
* @param list List contains Strings
* @return List contains Pattern instances
*/
private List generatePatternList(List list) {
List newList = new ArrayList();
for (Iterator iterator = list.iterator(); iterator.hasNext();) {
newList.add(Pattern.compile(generateRegex((String) iterator.next())));
}
return newList;
}
/**
* generates regular expression from <code>string</code>
* @param string
* @return regular expression
*/
private String generateRegex(String string) {
StringBuffer buffer = new StringBuffer();
for (int i = 0; i < string.length(); i++) {
char singleChar = string.charAt(i);
if (singleChar == START_CHAR)
// convert '*' to ".*"
buffer.append(WILD_CAST_STRING);
else if (singleChar == DOT_CHAR)
// convert '.' to "\."
buffer.append(DOT_QUOTE_STRING);
else
buffer.append(singleChar);
}
return buffer.toString();
}
}