/*******************************************************************************
* Copyright (c) 2006-2013, 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.
*
* Contributors:
* Lorenzo Bettini - https://bugs.eclipse.org/bugs/show_bug.cgi?id=428301
******************************************************************************/
package org.eclipse.buckminster.pde.mapfile;
import static org.eclipse.buckminster.core.helpers.MapUtils.getString;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.eclipse.buckminster.core.CorePlugin;
import org.eclipse.buckminster.core.common.model.ExpandingProperties;
import org.eclipse.buckminster.core.common.model.Replace;
import org.eclipse.buckminster.core.cspec.model.ComponentIdentifier;
import org.eclipse.buckminster.core.ctype.IComponentType;
import org.eclipse.buckminster.core.reader.IReaderType;
import org.eclipse.buckminster.pde.Messages;
import org.eclipse.buckminster.runtime.Logger;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.equinox.p2.metadata.Version;
import org.eclipse.osgi.util.NLS;
import org.eclipse.pde.build.IFetchFactory;
import org.eclipse.pde.internal.build.FetchTaskFactoriesRegistry;
/**
* @author Thomas Hallgren
*/
@SuppressWarnings("restriction")
public class MapFile {
private static final Pattern pattern = Pattern.compile("^" + "\\s*([^@=,\\s]+)\\s*@" // The type, i.e. bundle, //$NON-NLS-1$ //$NON-NLS-2$
// feature, plugin, or
// fragment
+ "\\s*([^@,=\\s]+)\\s*" // Element ID //$NON-NLS-1$
+ "(?:,\\s*([^@,=\\s]+)\\s*)?=" // Optional version //$NON-NLS-1$
+ "(?:\\s*([A-Za-z_][A-Za-z0-9_-]*)\\s*,)?\\s*" // Optional fetch type specifier (default is CVS) //$NON-NLS-1$
+ "\\s*([^\\s]+)\\s*$"); // Fetch type specific field //$NON-NLS-1$
private static FetchTaskFactoriesRegistry fetchTaskFactories;
public static void parse(InputStream inputStream, String streamName, Replace replace, Map<String, ? extends Object> queryProps,
List<MapFileEntry> receivingList) throws IOException {
CorePlugin core = CorePlugin.getDefault();
Logger logger = CorePlugin.getLogger();
if (fetchTaskFactories == null)
fetchTaskFactories = new FetchTaskFactoriesRegistry();
BufferedReader input = new BufferedReader(new InputStreamReader(inputStream));
String line;
nextLine: while ((line = input.readLine()) != null) {
// find first non-whitespace character on the line
int len = line.length();
int idx;
for (idx = 0; idx < len; ++idx) {
char c = line.charAt(idx);
if (Character.isWhitespace(c))
continue;
if (c == '!' || c == '#')
//
// Comment
//
continue nextLine;
break;
}
if (idx == len)
// Just whitespace
continue;
if (replace != null) {
line = replace.replace(line);
// Expand since the replacement might have introduced
// property expansion constructs.
line = ExpandingProperties.expand(queryProps, line, 0);
}
Matcher m = pattern.matcher(line);
if (!m.matches())
continue;
String fetchType = m.group(4);
String fetchTypeSpecific = m.group(5);
if (fetchType == null)
fetchType = "CVS"; //$NON-NLS-1$
else if (fetchType.equals("COPY")) //$NON-NLS-1$
{
logger.warning(NLS.bind(Messages.fetch_type_COPY_not_supported_map_0, streamName));
continue;
}
IFetchFactory ff = fetchTaskFactories.getFactory(fetchType);
if (ff == null) {
// Assume that the fetchType that we encountered is part of the
// fetchTypeSpecific string and that the real fetchType is CVS.
//
fetchTypeSpecific = fetchType + ',' + fetchTypeSpecific;
fetchType = "CVS"; //$NON-NLS-1$
ff = fetchTaskFactories.getFactory(fetchType);
if (ff == null) {
logger.warning(NLS.bind(Messages.no_factory_found_for_0_in_PDEmap_1, fetchType, streamName));
continue;
}
}
String type = m.group(1);
String ctypeId;
if ("plugin".equals(type) || "bundle".equals(type) || "fragment".equals(type)) //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
ctypeId = IComponentType.OSGI_BUNDLE;
else if ("feature".equals(type)) //$NON-NLS-1$
ctypeId = IComponentType.ECLIPSE_FEATURE;
else {
// We don't recognize this type
//
logger.warning(NLS.bind(Messages.unrecognized_component_type_0_in_PDEmap_1, type, streamName));
continue;
}
String vstr = m.group(3);
Version version;
try {
version = vstr == null ? null : Version.parseVersion(vstr);
} catch (IllegalArgumentException e) {
// Version is corrupt. Skip this line
//
logger.warning(NLS.bind(Messages.badly_formatted_version_0_in_PDEmap_1, vstr, streamName));
continue;
}
String identifier = m.group(2);
Map<String, Object> props = new HashMap<String, Object>();
try {
ff.parseMapFileEntry(fetchTypeSpecific, null, props);
} catch (Exception e) {
logger.warning(NLS.bind(Messages.fetch_factory_0_unable_to_parse_1_in_PDEmap_2, new Object[] { fetchType, fetchTypeSpecific,
streamName }));
continue;
}
String readerTypeID = fetchType.toLowerCase(Locale.ENGLISH);
if ("get".equals(readerTypeID)) //$NON-NLS-1$
{
readerTypeID = "url"; //$NON-NLS-1$
// Extract a more exact version from the file name if possible
//
String src = getString(props, "src"); //$NON-NLS-1$
if (src.endsWith(".jar") || src.endsWith(".zip")) //$NON-NLS-1$ //$NON-NLS-2$
{
int lastSlash = src.lastIndexOf('/');
if (lastSlash < 0)
lastSlash = 0;
String vcName = src.substring(lastSlash + 1, src.length() - 4);
if (vcName.startsWith(identifier + '_')) {
try {
version = Version.parseVersion(vcName.substring(identifier.length() + 1));
} catch (IllegalArgumentException e) {
// Ignore. For some reason this version was not a
// valid OSGi version
}
}
}
} else if (readerTypeID.equals("p2iu")) //$NON-NLS-1$
readerTypeID = "p2"; //$NON-NLS-1$
ComponentIdentifier cid = new ComponentIdentifier(identifier, ctypeId, version);
IReaderType readerType;
try {
readerType = core.getReaderType(readerTypeID);
} catch (CoreException e) {
logger.warning(NLS.bind(Messages.Unable_to_obtain_readertype_for_fetchtype_0_in_PDEmap_1, fetchType, streamName));
continue;
}
receivingList.add(new MapFileEntry(cid, readerType, props));
}
}
}