/*******************************************************************************
* Copyright (c) 2014, 2015 IBH SYSTEMS GmbH.
* 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:
* IBH SYSTEMS GmbH - initial API and implementation
*******************************************************************************/
package org.eclipse.packagedrone.repo.utils.osgi.feature;
import java.io.IOException;
import java.io.InputStream;
import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import org.eclipse.packagedrone.repo.XmlHelper;
import org.eclipse.packagedrone.repo.utils.osgi.ParserHelper;
import org.eclipse.packagedrone.repo.utils.osgi.feature.FeatureInformation.FeatureInclude;
import org.eclipse.packagedrone.repo.utils.osgi.feature.FeatureInformation.PluginInclude;
import org.eclipse.packagedrone.repo.utils.osgi.feature.FeatureInformation.Qualifiers;
import org.eclipse.packagedrone.repo.utils.osgi.feature.FeatureInformation.Requirement;
import org.eclipse.packagedrone.repo.utils.osgi.feature.FeatureInformation.Requirement.MatchRule;
import org.osgi.framework.Version;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
public class FeatureInformationParser
{
private final static Logger logger = LoggerFactory.getLogger ( FeatureInformationParser.class );
private final ZipFile file;
private final XmlHelper xml;
public FeatureInformationParser ( final ZipFile file )
{
this.xml = new XmlHelper ();
this.file = file;
}
public FeatureInformation parse () throws IOException
{
final ZipEntry ze = this.file.getEntry ( "feature.xml" );
if ( ze == null )
{
logger.debug ( "There is no feature.xml in the archive" );
return null;
}
Document doc;
try ( InputStream is = this.file.getInputStream ( ze ) )
{
try
{
doc = this.xml.parse ( is );
}
catch ( final Exception e )
{
logger.info ( "Failed to parse feature.xml", e );
return null;
}
}
final Element root = doc.getDocumentElement ();
final String id = makeNull ( root.getAttribute ( "id" ) );
if ( id == null )
{
logger.info ( "Feature ID is not set" );
return null;
}
final String version = makeNull ( root.getAttribute ( "version" ) );
if ( version == null )
{
logger.info ( "Feature version is not set" );
return null;
}
final FeatureInformation result = new FeatureInformation ();
result.setId ( id );
result.setVersion ( new Version ( version ) );
result.setProvider ( makeNull ( root.getAttribute ( "provider-name" ) ) );
result.setLabel ( makeNull ( root.getAttribute ( "label" ) ) );
result.setPlugin ( makeNull ( root.getAttribute ( "plugin" ) ) );
result.setQualifiers ( Qualifiers.parse ( root ) );
for ( final Node node : XmlHelper.iter ( root.getChildNodes () ) )
{
if ( ! ( node instanceof Element ) )
{
continue;
}
final Element ele = (Element)node;
if ( "description".equals ( node.getNodeName () ) )
{
result.setDescriptionUrl ( makeNull ( ele.getAttribute ( "url" ) ) );
result.setDescription ( trim ( ele.getTextContent () ) );
}
if ( "copyright".equals ( node.getNodeName () ) )
{
result.setCopyrightUrl ( makeNull ( ele.getAttribute ( "url" ) ) );
result.setCopyright ( trim ( ele.getTextContent () ) );
}
if ( "license".equals ( node.getNodeName () ) )
{
result.setLicenseUrl ( makeNull ( ele.getAttribute ( "url" ) ) );
result.setLicense ( trim ( ele.getTextContent () ) );
}
if ( "includes".equals ( node.getNodeName () ) )
{
processFeatureInclude ( result, ele );
}
if ( "requires".equals ( node.getNodeName () ) )
{
processRequirements ( result, ele );
}
if ( "plugin".equals ( node.getNodeName () ) )
{
processPluginInclude ( result, ele );
}
}
attachLocalization ( result );
return result;
}
private String trim ( final String text )
{
if ( text == null )
{
return text;
}
return text.trim ();
}
private String makeNull ( final String value )
{
if ( value == null || value.isEmpty () )
{
return null;
}
return value;
}
private void processRequirements ( final FeatureInformation result, final Element ele )
{
final Set<Requirement> reqs = result.getRequirements ();
for ( final Element im : XmlHelper.iterElement ( ele, "import" ) )
{
final String feature = im.getAttribute ( "feature" );
final String plugin = im.getAttribute ( "plugin" );
final String vs = makeNull ( im.getAttribute ( "version" ) );
final MatchRule match = makeMatch ( im.getAttribute ( "match" ) );
Version version = null;
if ( vs != null )
{
version = new Version ( vs );
}
Requirement req;
if ( feature != null && !feature.isEmpty () )
{
req = new Requirement ( Requirement.Type.FEATURE, feature, version, match );
}
else
{
req = new Requirement ( Requirement.Type.PLUGIN, plugin, version, match );
}
reqs.add ( req );
}
}
private MatchRule makeMatch ( final String matchString )
{
if ( matchString == null )
{
return MatchRule.DEFAULT;
}
final MatchRule mr = MatchRule.findById ( matchString );
if ( mr != null )
{
return mr;
}
else
{
return MatchRule.DEFAULT;
}
}
private void processPluginInclude ( final FeatureInformation result, final Element ele )
{
final String id = ele.getAttribute ( "id" );
final String vs = makeNull ( ele.getAttribute ( "version" ) );
final Version version = new Version ( vs == null ? "0.0.0" : vs );
final String unpackAttr = ele.getAttribute ( "unpack" );
final boolean unpack = unpackAttr == null || unpackAttr.isEmpty () ? true : Boolean.parseBoolean ( unpackAttr );
final Qualifiers q = Qualifiers.parse ( ele );
result.getIncludedPlugins ().add ( new PluginInclude ( id, version, unpack, q ) );
}
private void processFeatureInclude ( final FeatureInformation result, final Element ele )
{
final String id = ele.getAttribute ( "id" );
final String vs = makeNull ( ele.getAttribute ( "version" ) );
final Version version = new Version ( vs == null ? "0.0.0" : vs );
final String name = makeNull ( ele.getAttribute ( "name" ) );
final boolean optional = Boolean.parseBoolean ( ele.getAttribute ( "optional" ) );
final Qualifiers q = Qualifiers.parse ( ele );
result.getIncludedFeatures ().add ( new FeatureInclude ( id, version, name, optional, q ) );
}
private void attachLocalization ( final FeatureInformation result ) throws IOException
{
result.setLocalization ( ParserHelper.loadLocalization ( this.file, "feature" ) );
}
}