You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by ds...@apache.org on 2009/07/21 20:51:41 UTC
svn commit: r796467 [25/25] - in /felix/trunk/sigil:
common/core.tests/src/org/apache/felix/sigil/core/
common/core/src/org/apache/felix/sigil/bnd/
common/core/src/org/apache/felix/sigil/config/
common/core/src/org/apache/felix/sigil/core/ common/core/...
Modified: felix/trunk/sigil/ivy/resolver/src/org/apache/felix/sigil/ivy/SigilParser.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/ivy/resolver/src/org/apache/felix/sigil/ivy/SigilParser.java?rev=796467&r1=796466&r2=796467&view=diff
==============================================================================
--- felix/trunk/sigil/ivy/resolver/src/org/apache/felix/sigil/ivy/SigilParser.java (original)
+++ felix/trunk/sigil/ivy/resolver/src/org/apache/felix/sigil/ivy/SigilParser.java Tue Jul 21 18:51:33 2009
@@ -19,6 +19,7 @@
package org.apache.felix.sigil.ivy;
+
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
@@ -60,518 +61,636 @@
import org.apache.ivy.plugins.repository.url.URLResource;
import org.apache.ivy.plugins.resolver.DependencyResolver;
-public class SigilParser implements ModuleDescriptorParser {
- private static DelegateParser instance;
+public class SigilParser implements ModuleDescriptorParser
+{
+
+ private static DelegateParser instance;
+
- // used by ProjectRepository
- static DelegateParser instance() {
- if (instance == null)
- throw new IllegalStateException("SigilParser is not instantiated.");
- return instance;
- }
-
- public SigilParser() {
- if (instance == null) {
- instance = new DelegateParser();
- }
- }
-
- /**
- * In IvyDE, IvyContext is not available, so we can't find the SigilResolver.
- * This allows us to construct one.
- * @deprecated temporary to support IvyDE
- */
- public void setConfig(String config) {
- instance.config = config;
- }
-
- /**
- * sets delegate parser.
- * If not set, we delegate to the default Ivy parser.
- * @param type name returned by desired parser's getType() method.
- */
- public void setDelegateType(String type) {
- for (ModuleDescriptorParser parser : ModuleDescriptorParserRegistry.getInstance().getParsers()) {
- if (parser.getType().equals(type)) {
- instance.delegate = parser;
- break;
- }
- }
-
- if (instance.delegate == null) {
- throw new IllegalArgumentException("Can't find parser delegateType=" + type);
- }
- }
-
- /**
- * sets default file name the delegate parser accepts.
- * If not set, defaults to "ivy.xml".
- * @param name
- */
- public void setDelegateFile(String name) {
- instance.ivyFile = name;
- }
-
- /**
- * sets the dependencies to keep from the delegate parser.
- * If not set, all existing dependencies are dropped.
- * @param regex pattern matching dependency names to keep.
- */
- public void setKeepDependencies(String regex) {
- instance.keepDependencyPattern = Pattern.compile(regex);
- }
-
- /**
- * reduce level of info logging.
- * @param quiet
- */
- public void setQuiet(String quiet) {
- instance.quiet = Boolean.parseBoolean(quiet);
- }
-
- /**
- * sets the SigilResolver we use.
- * If not set, we use the first SigilResolver we find.
- * @param name
- */
- public void setResolver(String name) {
- instance.resolverName = name;
- }
-
- /**
- * adds override element: <override name="X" pattern="Y" replace="Z"/>. Overrides
- * Ivy variables using a pattern substitution on the resource directory path.
- *
- * @deprecated
- * This is only needed when a delegate parser expects Ant variables to be set
- * during the ivy:buildlist task (or the ProjectRepository initialisation),
- * which they are not. The delegate parser should really be fixed, as otherwise
- * the ivy:buildlist task won't work without this workaround.
- */
- // e.g. <override name="ant.project.name" pattern=".*/([^/]+)/([^/]+)$" replace="$1-$2"/>
- public void addConfiguredOverride(Map<String, String> var) {
- final String name = var.get("name");
- final String regex = var.get("pattern");
- final String replace = var.get("replace");
-
- if (name == null || regex == null || replace == null)
- throw new IllegalArgumentException("override must contain name, pattern and replace attributes.");
-
- instance.varRegex.put(name, Pattern.compile(regex));
- instance.varReplace.put(name, replace);
- }
-
- // implement ModuleDescriptorParser interface by delegation to singleton instance.
-
- public boolean accept(Resource res) {
- return instance.accept(res);
- }
-
- public Artifact getMetadataArtifact(ModuleRevisionId mrid, Resource res) {
- return instance.getMetadataArtifact(mrid, res);
- }
-
- public String getType() {
- return instance.getType();
- }
-
- public ModuleDescriptor parseDescriptor(ParserSettings settings, URL xmlURL, boolean validate)
- throws ParseException, IOException {
- return instance.parseDescriptor(settings, xmlURL, validate);
- }
-
- public ModuleDescriptor parseDescriptor(ParserSettings settings, URL xmlURL, Resource res, boolean validate)
- throws ParseException, IOException {
- return instance.parseDescriptor(settings, xmlURL, res, validate);
- }
-
- public void toIvyFile(InputStream source, Resource res, File destFile, ModuleDescriptor md) throws ParseException,
- IOException {
- instance.toIvyFile(source, res, destFile, md);
- }
-
- /**
- * delegating parser.
- * (optionally) removes original dependencies and augments with sigil-determined dependencies.
- */
- static class DelegateParser extends XmlModuleDescriptorParser {
-
- private static final String SIGIL_BUILDLIST = IBldProject.PROJECT_FILE;
- private static final String KEEP_ALL = ".*";
-
- private IBldResolver resolver;
- private ParserSettings defaultSettings;
- private Map<String, DefaultModuleDescriptor> rawCache = new HashMap<String, DefaultModuleDescriptor>();
- private Map<String, DefaultModuleDescriptor> augmentedCache = new HashMap<String, DefaultModuleDescriptor>();
-
- private HashMap<String, String> varReplace = new HashMap<String, String>();
- private HashMap<String, Pattern> varRegex = new HashMap<String, Pattern>();
-
- private ModuleDescriptorParser delegate;
- private String ivyFile = "ivy.xml";
- private String resolverName;
- private Pattern keepDependencyPattern;
- private boolean quiet;
- private String config;
-
- @Override
- public boolean accept(Resource res) {
- boolean accept = (res instanceof SigilResolver.SigilIvy)
- || res.getName().endsWith("/" + SIGIL_BUILDLIST)
- || ((instance.getSigilURI(res) != null) &&
- ((instance.delegate != null ? instance.delegate.accept(res) : false) || super.accept(res)));
- if (accept)
- Log.verbose("accepted: " + res);
- return accept;
- }
-
- @Override
- public void toIvyFile(InputStream source, Resource res, File destFile, ModuleDescriptor md)
- throws ParseException, IOException {
- Log.verbose("writing resource: " + res + " toIvyFile: " + destFile);
- // source allows us to keep layout and comments,
- // but this doesn't work if source is not ivy.xml.
- // So just write file directly from descriptor.
- try {
- XmlModuleDescriptorWriter.write(md, destFile);
- } finally {
- if (source != null)
- source.close();
- }
- }
-
- @Override
- public ModuleDescriptor parseDescriptor(ParserSettings settings, URL xmlURL, boolean validate)
- throws ParseException, IOException {
- return parseDescriptor(settings, xmlURL, new URLResource(xmlURL), validate);
- }
-
- @Override
- public ModuleDescriptor parseDescriptor(ParserSettings settings, URL xmlURL, Resource res, boolean validate)
- throws ParseException, IOException {
- String cacheKey = xmlURL.toString() + settings.hashCode();
- DefaultModuleDescriptor dmd = augmentedCache.get(cacheKey);
-
- if (dmd == null) {
- dmd = rawCache.get(cacheKey);
- if (dmd == null) {
- dmd = delegateParse(settings, xmlURL, res, validate);
- }
-
- if (!quiet)
- Log.info("augmenting module=" + dmd.getModuleRevisionId().getName() +
- " ant.project.name=" + settings.substitute("${ant.project.name}"));
-
- addDependenciesToDescriptor(res, dmd);
- augmentedCache.put(cacheKey, dmd);
-
- Log.verbose("augmented dependencies: " + Arrays.asList(dmd.getDependencies()));
- }
-
- return dmd;
- }
-
- // used by ProjectRepository
- ModuleDescriptor parseDescriptor(URL projectURL) throws ParseException, IOException {
- if (defaultSettings == null) {
- Ivy ivy = IvyContext.getContext().peekIvy();
- if (ivy == null)
- throw new IllegalStateException("can't get default settings - no ivy context.");
- defaultSettings = ivy.getSettings();
- }
-
- URL ivyURL = new URL(projectURL, ivyFile);
- String cacheKey = ivyURL.toString() + defaultSettings.hashCode();
- DefaultModuleDescriptor dmd = rawCache.get(cacheKey);
-
- if (dmd == null) {
- URLResource res = new URLResource(ivyURL);
- // Note: this doesn't contain the augmented dependencies, which is OK,
- // since the ProjectRepository only needs the id and status.
- dmd = delegateParse(defaultSettings, ivyURL, res, false);
- rawCache.put(cacheKey, dmd);
- }
-
- return dmd;
- }
-
- private DefaultModuleDescriptor delegateParse(ParserSettings settings, URL xmlURL, Resource res,
- boolean validate) throws ParseException, IOException {
- String resName = res.getName();
-
- if (resName.endsWith("/" + SIGIL_BUILDLIST)) {
- String name = resName.substring(0, resName.length() - SIGIL_BUILDLIST.length());
- res = res.clone(name + ivyFile);
- xmlURL = new URL(xmlURL, ivyFile);
- }
-
- if (settings instanceof IvySettings) {
- IvySettings ivySettings = (IvySettings) settings;
- String dir = new File(res.getName()).getParent();
-
- for (String name : varRegex.keySet()) {
- Pattern regex = varRegex.get(name);
- String replace = varReplace.get(name);
-
- String value = regex.matcher(dir).replaceAll(replace);
-
- Log.debug("overriding variable " + name + "=" + value);
- ivySettings.setVariable(name, value);
- }
- }
-
- ModuleDescriptor md = null;
- if (delegate == null || !delegate.accept(res)) {
- md = super.parseDescriptor(settings, xmlURL, res, validate);
- } else {
- md = delegate.parseDescriptor(settings, xmlURL, res, validate);
- }
-
- return mungeDescriptor(md, res);
- }
-
- /**
- * clones descriptor and removes dependencies, as descriptor MUST have
- * 'this' as the parser given to its constructor.
- * Only dependency names matched by keepDependencyPattern are kept,
- * as we're going to add our own dependencies later.
- */
- private DefaultModuleDescriptor mungeDescriptor(ModuleDescriptor md, Resource res) {
-
- if ((md instanceof DefaultModuleDescriptor) &&
- (md.getParser() == this) &&
- (KEEP_ALL.equals(keepDependencyPattern))) {
- return (DefaultModuleDescriptor) md;
- }
-
- DefaultModuleDescriptor dmd = new DefaultModuleDescriptor(this, res);
-
- dmd.setModuleRevisionId(md.getModuleRevisionId());
- dmd.setPublicationDate(md.getPublicationDate());
-
- for (Configuration c : md.getConfigurations()) {
- String conf = c.getName();
-
- dmd.addConfiguration(c);
-
- for (Artifact a : md.getArtifacts(conf)) {
- dmd.addArtifact(conf, a);
- }
- }
-
- if (keepDependencyPattern != null) {
- for (DependencyDescriptor dependency : md.getDependencies()) {
- String name = dependency.getDependencyId().getName();
- if (keepDependencyPattern.matcher(name).matches()) {
- dmd.addDependency(dependency);
- }
- }
- }
-
- return dmd;
- }
-
- /*
- * find URI to Sigil project file. This assumes that it is in the same
- * directory as the ivy file.
- */
- private URI getSigilURI(Resource res) {
- URI uri = null;
-
- if (res instanceof URLResource) {
- URL url = ((URLResource) res).getURL();
- uri = URI.create(url.toString()).resolve(IBldProject.PROJECT_FILE);
- try {
- InputStream stream = uri.toURL().openStream(); // check file
- // exists
- stream.close();
- } catch (IOException e) {
- uri = null;
- }
- } else if (res instanceof FileResource) {
- uri = ((FileResource) res).getFile().toURI().resolve(IBldProject.PROJECT_FILE);
- if (!(new File(uri).exists()))
- uri = null;
- }
-
- return uri;
- }
-
- /*
- * add sigil dependencies to ModuleDescriptor.
- */
- private void addDependenciesToDescriptor(Resource res, DefaultModuleDescriptor md) throws IOException {
- // FIXME: transitive should be configurable
- final boolean transitive = true; // ivy default is true
- final boolean changing = false;
- final boolean force = false;
-
- URI uri = getSigilURI(res);
- if (uri == null)
- return;
-
- IBldProject project;
-
- project = BldFactory.getProject(uri);
-
- IBundleModelElement requirements = project.getDependencies();
- Log.verbose("requirements: " + Arrays.asList(requirements.children()));
-
- // preserve version range for Require-Bundle
- // XXX: synthesise bundle version range corresponding to package version ranges?
- HashMap<String, VersionRange> versions = new HashMap<String, VersionRange>();
- for (IModelElement child : requirements.children()) {
- if (child instanceof IRequiredBundle) {
- IRequiredBundle bundle = (IRequiredBundle) child;
- versions.put(bundle.getSymbolicName(), bundle.getVersions());
- }
- }
-
- IBldResolver resolver = findResolver();
- if (resolver == null) {
- // this can happen in IvyDE, but it retries and is OK next time.
- Log.warn("failed to find resolver - IvyContext not yet available.");
- return;
- }
-
- IResolution resolution = resolver.resolve(requirements, false);
- Log.verbose("resolution: " + resolution.getBundles());
-
- ModuleRevisionId masterMrid = md.getModuleRevisionId();
- DefaultDependencyDescriptor dd;
- ModuleRevisionId mrid;
-
- for (ISigilBundle bundle : resolution.getBundles()) {
- IBundleModelElement info = bundle.getBundleInfo();
- String name = info.getSymbolicName();
-
- if (name == null) {
- // e.g. SystemProvider with framework=null
- continue;
- }
-
- if (bundle instanceof ProjectRepository.ProjectBundle) {
- ProjectRepository.ProjectBundle pb = (ProjectRepository.ProjectBundle) bundle;
- String org = pb.getOrg();
- if (org == null)
- org = masterMrid.getOrganisation();
- String id = pb.getId();
- String module = pb.getModule();
- String rev = pb.getRevision();
-
- mrid = ModuleRevisionId.newInstance(org, module, rev);
- dd = new SigilDependencyDescriptor(md, mrid, force, changing, transitive);
-
- if (!id.equals(module)) { // non-default artifact
- dd.addDependencyArtifact(module,
- new DefaultDependencyArtifactDescriptor(dd, id, "jar", "jar", null, null));
- }
- } else {
- VersionRange version = versions.get(name);
- String rev = version != null ? version.toString() : info.getVersion().toString();
- mrid = ModuleRevisionId.newInstance(SigilResolver.ORG_SIGIL, name, rev);
- dd = new SigilDependencyDescriptor(md, mrid, force, changing, transitive);
- }
-
- int nDeps = 0;
- boolean foundDefault = false;
-
- // TODO: make dependency configurations configurable SIGIL-176
- for (String conf : md.getConfigurationsNames()) {
- if (conf.equals("default")) {
- foundDefault = true;
- } else if (md.getArtifacts(conf).length == 0) {
- dd.addDependencyConfiguration(conf, conf + "(default)");
- nDeps++;
- }
- }
-
- if (nDeps > 0) {
- if (foundDefault)
- dd.addDependencyConfiguration("default", "default");
- } else {
- dd.addDependencyConfiguration("*", "*"); // all configurations
- }
-
- md.addDependency(dd);
- }
-
- boolean resolved = true;
- for (IModelElement child : requirements.children()) {
- ISigilBundle provider = resolution.getProvider(child);
- if (provider == null) {
- resolved = false;
- // this is parse phase, so only log verbose message.
- // error is produced during resolution phase.
- Log.verbose("WARN: can't resolve: " + child);
-
- String name;
- String version;
- if (child instanceof IRequiredBundle) {
- IRequiredBundle rb = (IRequiredBundle) child;
- name = rb.getSymbolicName();
- version = rb.getVersions().toString();
- } else {
- IPackageImport pi = (IPackageImport) child;
- name = "import!" + pi.getPackageName();
- version = pi.getVersions().toString();
- }
-
- mrid = ModuleRevisionId.newInstance("!" + SigilResolver.ORG_SIGIL, name, version);
- dd = new SigilDependencyDescriptor(md, mrid, force, changing, transitive);
- dd.addDependencyConfiguration("*", "*"); // all
- // configurations
- md.addDependency(dd);
- }
- }
-
- if (!resolved) {
- // Ivy does not show warnings or errors logged from parse phase, until after resolution.
- // but <buildlist> ant task doesn't do resolution, so errors would be silently ignored.
- // Hence, we must use Message.info to ensure this failure is seen.
- if (!quiet)
- Log.info("WARN: resolution failed in: " + masterMrid.getName() + ". Use -v for details.");
- }
- }
-
- /*
- * find named resolver, or first resolver that implements IBldResolver.
- */
- private IBldResolver findResolver() {
- if (resolver == null) {
- Ivy ivy = IvyContext.getContext().peekIvy();
- if (ivy != null) {
- if (resolverName != null) {
- DependencyResolver r = ivy.getSettings().getResolver(resolverName);
- if (r == null) {
- throw new Error("SigilParser: resolver \"" + resolverName + "\" not defined.");
- } else if (r instanceof IBldResolver) {
- resolver = (IBldResolver) r;
- } else {
- throw new Error("SigilParser: resolver \"" + resolverName + "\" is not a SigilResolver.");
- }
- } else {
- for (Object r : ivy.getSettings().getResolvers()) {
- if (r instanceof IBldResolver) {
- resolver = (IBldResolver) r;
- break;
- }
- }
- }
-
- if (resolver == null) {
- throw new Error("SigilParser: can't find SigilResolver. Check ivysettings.xml.");
- }
- } else if (config != null) {
- Log.warn("creating duplicate resolver to support IvyDE.");
- resolver = new SigilResolver();
- ((SigilResolver)resolver).setConfig(config);
- }
- }
- return resolver;
- }
- }
+ // used by ProjectRepository
+ static DelegateParser instance()
+ {
+ if ( instance == null )
+ throw new IllegalStateException( "SigilParser is not instantiated." );
+ return instance;
+ }
+
+
+ public SigilParser()
+ {
+ if ( instance == null )
+ {
+ instance = new DelegateParser();
+ }
+ }
+
+
+ /**
+ * In IvyDE, IvyContext is not available, so we can't find the SigilResolver.
+ * This allows us to construct one.
+ * @deprecated temporary to support IvyDE
+ */
+ public void setConfig( String config )
+ {
+ instance.config = config;
+ }
+
+
+ /**
+ * sets delegate parser.
+ * If not set, we delegate to the default Ivy parser.
+ * @param type name returned by desired parser's getType() method.
+ */
+ public void setDelegateType( String type )
+ {
+ for ( ModuleDescriptorParser parser : ModuleDescriptorParserRegistry.getInstance().getParsers() )
+ {
+ if ( parser.getType().equals( type ) )
+ {
+ instance.delegate = parser;
+ break;
+ }
+ }
+
+ if ( instance.delegate == null )
+ {
+ throw new IllegalArgumentException( "Can't find parser delegateType=" + type );
+ }
+ }
+
+
+ /**
+ * sets default file name the delegate parser accepts.
+ * If not set, defaults to "ivy.xml".
+ * @param name
+ */
+ public void setDelegateFile( String name )
+ {
+ instance.ivyFile = name;
+ }
+
+
+ /**
+ * sets the dependencies to keep from the delegate parser.
+ * If not set, all existing dependencies are dropped.
+ * @param regex pattern matching dependency names to keep.
+ */
+ public void setKeepDependencies( String regex )
+ {
+ instance.keepDependencyPattern = Pattern.compile( regex );
+ }
+
+
+ /**
+ * reduce level of info logging.
+ * @param quiet
+ */
+ public void setQuiet( String quiet )
+ {
+ instance.quiet = Boolean.parseBoolean( quiet );
+ }
+
+
+ /**
+ * sets the SigilResolver we use.
+ * If not set, we use the first SigilResolver we find.
+ * @param name
+ */
+ public void setResolver( String name )
+ {
+ instance.resolverName = name;
+ }
+
+
+ /**
+ * adds override element: <override name="X" pattern="Y" replace="Z"/>. Overrides
+ * Ivy variables using a pattern substitution on the resource directory path.
+ *
+ * @deprecated
+ * This is only needed when a delegate parser expects Ant variables to be set
+ * during the ivy:buildlist task (or the ProjectRepository initialisation),
+ * which they are not. The delegate parser should really be fixed, as otherwise
+ * the ivy:buildlist task won't work without this workaround.
+ */
+ // e.g. <override name="ant.project.name" pattern=".*/([^/]+)/([^/]+)$" replace="$1-$2"/>
+ public void addConfiguredOverride( Map<String, String> var )
+ {
+ final String name = var.get( "name" );
+ final String regex = var.get( "pattern" );
+ final String replace = var.get( "replace" );
+
+ if ( name == null || regex == null || replace == null )
+ throw new IllegalArgumentException( "override must contain name, pattern and replace attributes." );
+
+ instance.varRegex.put( name, Pattern.compile( regex ) );
+ instance.varReplace.put( name, replace );
+ }
+
+
+ // implement ModuleDescriptorParser interface by delegation to singleton instance.
+
+ public boolean accept( Resource res )
+ {
+ return instance.accept( res );
+ }
+
+
+ public Artifact getMetadataArtifact( ModuleRevisionId mrid, Resource res )
+ {
+ return instance.getMetadataArtifact( mrid, res );
+ }
+
+
+ public String getType()
+ {
+ return instance.getType();
+ }
+
+
+ public ModuleDescriptor parseDescriptor( ParserSettings settings, URL xmlURL, boolean validate )
+ throws ParseException, IOException
+ {
+ return instance.parseDescriptor( settings, xmlURL, validate );
+ }
+
+
+ public ModuleDescriptor parseDescriptor( ParserSettings settings, URL xmlURL, Resource res, boolean validate )
+ throws ParseException, IOException
+ {
+ return instance.parseDescriptor( settings, xmlURL, res, validate );
+ }
+
+
+ public void toIvyFile( InputStream source, Resource res, File destFile, ModuleDescriptor md )
+ throws ParseException, IOException
+ {
+ instance.toIvyFile( source, res, destFile, md );
+ }
+
+ /**
+ * delegating parser.
+ * (optionally) removes original dependencies and augments with sigil-determined dependencies.
+ */
+ static class DelegateParser extends XmlModuleDescriptorParser
+ {
+
+ private static final String SIGIL_BUILDLIST = IBldProject.PROJECT_FILE;
+ private static final String KEEP_ALL = ".*";
+
+ private IBldResolver resolver;
+ private ParserSettings defaultSettings;
+ private Map<String, DefaultModuleDescriptor> rawCache = new HashMap<String, DefaultModuleDescriptor>();
+ private Map<String, DefaultModuleDescriptor> augmentedCache = new HashMap<String, DefaultModuleDescriptor>();
+
+ private HashMap<String, String> varReplace = new HashMap<String, String>();
+ private HashMap<String, Pattern> varRegex = new HashMap<String, Pattern>();
+
+ private ModuleDescriptorParser delegate;
+ private String ivyFile = "ivy.xml";
+ private String resolverName;
+ private Pattern keepDependencyPattern;
+ private boolean quiet;
+ private String config;
+
+
+ @Override
+ public boolean accept( Resource res )
+ {
+ boolean accept = ( res instanceof SigilResolver.SigilIvy )
+ || res.getName().endsWith( "/" + SIGIL_BUILDLIST )
+ || ( ( instance.getSigilURI( res ) != null ) && ( ( instance.delegate != null ? instance.delegate
+ .accept( res ) : false ) || super.accept( res ) ) );
+ if ( accept )
+ Log.verbose( "accepted: " + res );
+ return accept;
+ }
+
+
+ @Override
+ public void toIvyFile( InputStream source, Resource res, File destFile, ModuleDescriptor md )
+ throws ParseException, IOException
+ {
+ Log.verbose( "writing resource: " + res + " toIvyFile: " + destFile );
+ // source allows us to keep layout and comments,
+ // but this doesn't work if source is not ivy.xml.
+ // So just write file directly from descriptor.
+ try
+ {
+ XmlModuleDescriptorWriter.write( md, destFile );
+ }
+ finally
+ {
+ if ( source != null )
+ source.close();
+ }
+ }
+
+
+ @Override
+ public ModuleDescriptor parseDescriptor( ParserSettings settings, URL xmlURL, boolean validate )
+ throws ParseException, IOException
+ {
+ return parseDescriptor( settings, xmlURL, new URLResource( xmlURL ), validate );
+ }
+
+
+ @Override
+ public ModuleDescriptor parseDescriptor( ParserSettings settings, URL xmlURL, Resource res, boolean validate )
+ throws ParseException, IOException
+ {
+ String cacheKey = xmlURL.toString() + settings.hashCode();
+ DefaultModuleDescriptor dmd = augmentedCache.get( cacheKey );
+
+ if ( dmd == null )
+ {
+ dmd = rawCache.get( cacheKey );
+ if ( dmd == null )
+ {
+ dmd = delegateParse( settings, xmlURL, res, validate );
+ }
+
+ if ( !quiet )
+ Log.info( "augmenting module=" + dmd.getModuleRevisionId().getName() + " ant.project.name="
+ + settings.substitute( "${ant.project.name}" ) );
+
+ addDependenciesToDescriptor( res, dmd );
+ augmentedCache.put( cacheKey, dmd );
+
+ Log.verbose( "augmented dependencies: " + Arrays.asList( dmd.getDependencies() ) );
+ }
+
+ return dmd;
+ }
+
+
+ // used by ProjectRepository
+ ModuleDescriptor parseDescriptor( URL projectURL ) throws ParseException, IOException
+ {
+ if ( defaultSettings == null )
+ {
+ Ivy ivy = IvyContext.getContext().peekIvy();
+ if ( ivy == null )
+ throw new IllegalStateException( "can't get default settings - no ivy context." );
+ defaultSettings = ivy.getSettings();
+ }
+
+ URL ivyURL = new URL( projectURL, ivyFile );
+ String cacheKey = ivyURL.toString() + defaultSettings.hashCode();
+ DefaultModuleDescriptor dmd = rawCache.get( cacheKey );
+
+ if ( dmd == null )
+ {
+ URLResource res = new URLResource( ivyURL );
+ // Note: this doesn't contain the augmented dependencies, which is OK,
+ // since the ProjectRepository only needs the id and status.
+ dmd = delegateParse( defaultSettings, ivyURL, res, false );
+ rawCache.put( cacheKey, dmd );
+ }
+
+ return dmd;
+ }
+
+
+ private DefaultModuleDescriptor delegateParse( ParserSettings settings, URL xmlURL, Resource res,
+ boolean validate ) throws ParseException, IOException
+ {
+ String resName = res.getName();
+
+ if ( resName.endsWith( "/" + SIGIL_BUILDLIST ) )
+ {
+ String name = resName.substring( 0, resName.length() - SIGIL_BUILDLIST.length() );
+ res = res.clone( name + ivyFile );
+ xmlURL = new URL( xmlURL, ivyFile );
+ }
+
+ if ( settings instanceof IvySettings )
+ {
+ IvySettings ivySettings = ( IvySettings ) settings;
+ String dir = new File( res.getName() ).getParent();
+
+ for ( String name : varRegex.keySet() )
+ {
+ Pattern regex = varRegex.get( name );
+ String replace = varReplace.get( name );
+
+ String value = regex.matcher( dir ).replaceAll( replace );
+
+ Log.debug( "overriding variable " + name + "=" + value );
+ ivySettings.setVariable( name, value );
+ }
+ }
+
+ ModuleDescriptor md = null;
+ if ( delegate == null || !delegate.accept( res ) )
+ {
+ md = super.parseDescriptor( settings, xmlURL, res, validate );
+ }
+ else
+ {
+ md = delegate.parseDescriptor( settings, xmlURL, res, validate );
+ }
+
+ return mungeDescriptor( md, res );
+ }
+
+
+ /**
+ * clones descriptor and removes dependencies, as descriptor MUST have
+ * 'this' as the parser given to its constructor.
+ * Only dependency names matched by keepDependencyPattern are kept,
+ * as we're going to add our own dependencies later.
+ */
+ private DefaultModuleDescriptor mungeDescriptor( ModuleDescriptor md, Resource res )
+ {
+
+ if ( ( md instanceof DefaultModuleDescriptor ) && ( md.getParser() == this )
+ && ( KEEP_ALL.equals( keepDependencyPattern ) ) )
+ {
+ return ( DefaultModuleDescriptor ) md;
+ }
+
+ DefaultModuleDescriptor dmd = new DefaultModuleDescriptor( this, res );
+
+ dmd.setModuleRevisionId( md.getModuleRevisionId() );
+ dmd.setPublicationDate( md.getPublicationDate() );
+
+ for ( Configuration c : md.getConfigurations() )
+ {
+ String conf = c.getName();
+
+ dmd.addConfiguration( c );
+
+ for ( Artifact a : md.getArtifacts( conf ) )
+ {
+ dmd.addArtifact( conf, a );
+ }
+ }
+
+ if ( keepDependencyPattern != null )
+ {
+ for ( DependencyDescriptor dependency : md.getDependencies() )
+ {
+ String name = dependency.getDependencyId().getName();
+ if ( keepDependencyPattern.matcher( name ).matches() )
+ {
+ dmd.addDependency( dependency );
+ }
+ }
+ }
+
+ return dmd;
+ }
+
+
+ /*
+ * find URI to Sigil project file. This assumes that it is in the same
+ * directory as the ivy file.
+ */
+ private URI getSigilURI( Resource res )
+ {
+ URI uri = null;
+
+ if ( res instanceof URLResource )
+ {
+ URL url = ( ( URLResource ) res ).getURL();
+ uri = URI.create( url.toString() ).resolve( IBldProject.PROJECT_FILE );
+ try
+ {
+ InputStream stream = uri.toURL().openStream(); // check file
+ // exists
+ stream.close();
+ }
+ catch ( IOException e )
+ {
+ uri = null;
+ }
+ }
+ else if ( res instanceof FileResource )
+ {
+ uri = ( ( FileResource ) res ).getFile().toURI().resolve( IBldProject.PROJECT_FILE );
+ if ( !( new File( uri ).exists() ) )
+ uri = null;
+ }
+
+ return uri;
+ }
+
+
+ /*
+ * add sigil dependencies to ModuleDescriptor.
+ */
+ private void addDependenciesToDescriptor( Resource res, DefaultModuleDescriptor md ) throws IOException
+ {
+ // FIXME: transitive should be configurable
+ final boolean transitive = true; // ivy default is true
+ final boolean changing = false;
+ final boolean force = false;
+
+ URI uri = getSigilURI( res );
+ if ( uri == null )
+ return;
+
+ IBldProject project;
+
+ project = BldFactory.getProject( uri );
+
+ IBundleModelElement requirements = project.getDependencies();
+ Log.verbose( "requirements: " + Arrays.asList( requirements.children() ) );
+
+ // preserve version range for Require-Bundle
+ // XXX: synthesise bundle version range corresponding to package version ranges?
+ HashMap<String, VersionRange> versions = new HashMap<String, VersionRange>();
+ for ( IModelElement child : requirements.children() )
+ {
+ if ( child instanceof IRequiredBundle )
+ {
+ IRequiredBundle bundle = ( IRequiredBundle ) child;
+ versions.put( bundle.getSymbolicName(), bundle.getVersions() );
+ }
+ }
+
+ IBldResolver resolver = findResolver();
+ if ( resolver == null )
+ {
+ // this can happen in IvyDE, but it retries and is OK next time.
+ Log.warn( "failed to find resolver - IvyContext not yet available." );
+ return;
+ }
+
+ IResolution resolution = resolver.resolve( requirements, false );
+ Log.verbose( "resolution: " + resolution.getBundles() );
+
+ ModuleRevisionId masterMrid = md.getModuleRevisionId();
+ DefaultDependencyDescriptor dd;
+ ModuleRevisionId mrid;
+
+ for ( ISigilBundle bundle : resolution.getBundles() )
+ {
+ IBundleModelElement info = bundle.getBundleInfo();
+ String name = info.getSymbolicName();
+
+ if ( name == null )
+ {
+ // e.g. SystemProvider with framework=null
+ continue;
+ }
+
+ if ( bundle instanceof ProjectRepository.ProjectBundle )
+ {
+ ProjectRepository.ProjectBundle pb = ( ProjectRepository.ProjectBundle ) bundle;
+ String org = pb.getOrg();
+ if ( org == null )
+ org = masterMrid.getOrganisation();
+ String id = pb.getId();
+ String module = pb.getModule();
+ String rev = pb.getRevision();
+
+ mrid = ModuleRevisionId.newInstance( org, module, rev );
+ dd = new SigilDependencyDescriptor( md, mrid, force, changing, transitive );
+
+ if ( !id.equals( module ) )
+ { // non-default artifact
+ dd.addDependencyArtifact( module, new DefaultDependencyArtifactDescriptor( dd, id, "jar",
+ "jar", null, null ) );
+ }
+ }
+ else
+ {
+ VersionRange version = versions.get( name );
+ String rev = version != null ? version.toString() : info.getVersion().toString();
+ mrid = ModuleRevisionId.newInstance( SigilResolver.ORG_SIGIL, name, rev );
+ dd = new SigilDependencyDescriptor( md, mrid, force, changing, transitive );
+ }
+
+ int nDeps = 0;
+ boolean foundDefault = false;
+
+ // TODO: make dependency configurations configurable SIGIL-176
+ for ( String conf : md.getConfigurationsNames() )
+ {
+ if ( conf.equals( "default" ) )
+ {
+ foundDefault = true;
+ }
+ else if ( md.getArtifacts( conf ).length == 0 )
+ {
+ dd.addDependencyConfiguration( conf, conf + "(default)" );
+ nDeps++;
+ }
+ }
+
+ if ( nDeps > 0 )
+ {
+ if ( foundDefault )
+ dd.addDependencyConfiguration( "default", "default" );
+ }
+ else
+ {
+ dd.addDependencyConfiguration( "*", "*" ); // all configurations
+ }
+
+ md.addDependency( dd );
+ }
+
+ boolean resolved = true;
+ for ( IModelElement child : requirements.children() )
+ {
+ ISigilBundle provider = resolution.getProvider( child );
+ if ( provider == null )
+ {
+ resolved = false;
+ // this is parse phase, so only log verbose message.
+ // error is produced during resolution phase.
+ Log.verbose( "WARN: can't resolve: " + child );
+
+ String name;
+ String version;
+ if ( child instanceof IRequiredBundle )
+ {
+ IRequiredBundle rb = ( IRequiredBundle ) child;
+ name = rb.getSymbolicName();
+ version = rb.getVersions().toString();
+ }
+ else
+ {
+ IPackageImport pi = ( IPackageImport ) child;
+ name = "import!" + pi.getPackageName();
+ version = pi.getVersions().toString();
+ }
+
+ mrid = ModuleRevisionId.newInstance( "!" + SigilResolver.ORG_SIGIL, name, version );
+ dd = new SigilDependencyDescriptor( md, mrid, force, changing, transitive );
+ dd.addDependencyConfiguration( "*", "*" ); // all
+ // configurations
+ md.addDependency( dd );
+ }
+ }
+
+ if ( !resolved )
+ {
+ // Ivy does not show warnings or errors logged from parse phase, until after resolution.
+ // but <buildlist> ant task doesn't do resolution, so errors would be silently ignored.
+ // Hence, we must use Message.info to ensure this failure is seen.
+ if ( !quiet )
+ Log.info( "WARN: resolution failed in: " + masterMrid.getName() + ". Use -v for details." );
+ }
+ }
+
+
+ /*
+ * find named resolver, or first resolver that implements IBldResolver.
+ */
+ private IBldResolver findResolver()
+ {
+ if ( resolver == null )
+ {
+ Ivy ivy = IvyContext.getContext().peekIvy();
+ if ( ivy != null )
+ {
+ if ( resolverName != null )
+ {
+ DependencyResolver r = ivy.getSettings().getResolver( resolverName );
+ if ( r == null )
+ {
+ throw new Error( "SigilParser: resolver \"" + resolverName + "\" not defined." );
+ }
+ else if ( r instanceof IBldResolver )
+ {
+ resolver = ( IBldResolver ) r;
+ }
+ else
+ {
+ throw new Error( "SigilParser: resolver \"" + resolverName + "\" is not a SigilResolver." );
+ }
+ }
+ else
+ {
+ for ( Object r : ivy.getSettings().getResolvers() )
+ {
+ if ( r instanceof IBldResolver )
+ {
+ resolver = ( IBldResolver ) r;
+ break;
+ }
+ }
+ }
+
+ if ( resolver == null )
+ {
+ throw new Error( "SigilParser: can't find SigilResolver. Check ivysettings.xml." );
+ }
+ }
+ else if ( config != null )
+ {
+ Log.warn( "creating duplicate resolver to support IvyDE." );
+ resolver = new SigilResolver();
+ ( ( SigilResolver ) resolver ).setConfig( config );
+ }
+ }
+ return resolver;
+ }
+ }
}
@@ -579,9 +698,11 @@
* this is only needed so that we can distinguish sigil-added dependencies from
* existing ones.
*/
-class SigilDependencyDescriptor extends DefaultDependencyDescriptor {
- public SigilDependencyDescriptor(DefaultModuleDescriptor md, ModuleRevisionId mrid, boolean force,
- boolean changing, boolean transitive) {
- super(md, mrid, force, changing, transitive);
- }
+class SigilDependencyDescriptor extends DefaultDependencyDescriptor
+{
+ public SigilDependencyDescriptor( DefaultModuleDescriptor md, ModuleRevisionId mrid, boolean force,
+ boolean changing, boolean transitive )
+ {
+ super( md, mrid, force, changing, transitive );
+ }
}
Modified: felix/trunk/sigil/ivy/resolver/src/org/apache/felix/sigil/ivy/SigilResolver.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/ivy/resolver/src/org/apache/felix/sigil/ivy/SigilResolver.java?rev=796467&r1=796466&r2=796467&view=diff
==============================================================================
--- felix/trunk/sigil/ivy/resolver/src/org/apache/felix/sigil/ivy/SigilResolver.java (original)
+++ felix/trunk/sigil/ivy/resolver/src/org/apache/felix/sigil/ivy/SigilResolver.java Tue Jul 21 18:51:33 2009
@@ -19,6 +19,7 @@
package org.apache.felix.sigil.ivy;
+
import static java.lang.String.format;
import java.io.File;
@@ -54,359 +55,464 @@
import org.apache.ivy.plugins.resolver.util.ResolvedResource;
import org.apache.ivy.util.FileUtil;
+
/**
* This resolver is able to work with Sigil repositories.
* It does not allow publishing.
*/
-public class SigilResolver extends BasicResolver implements IBldResolver {
- /** the sigil-injected dependency organisation name */
- static final String ORG_SIGIL = "sigil";
-
- private IBldResolver resolver;
- private String config;
- private boolean extractBCP = false;
- private Map<String, Resource> resourcesCache = new HashMap<String, Resource>();
-
- /**
- * no-args constructor required by Ivy.
- *
- * XXX: It doesn't currently seem to matter that Ivy instantiates this many times,
- * since SigilParser caches it, and the ProjectRepositoryProvider static cache
- * prevents it being re-loaded unnecessarily.
- *
- * If this should become a problem, then we will need to delegate to a singleton instance,
- * as we have done in SigilParser.
- */
- public SigilResolver() {
- }
-
- public void setConfig(String config) {
- this.config = config;
- }
-
- /**
- * if true, resolver extracts any jars embedded in Bundle-ClassPath.
- */
- public void setExtractBCP(String extract) {
- this.extractBCP = Boolean.parseBoolean(extract);
- }
-
- private IBldResolver getResolver() {
- if (resolver == null) {
- if (config == null) {
- throw new Error("SigilResolver: not configured. Specify config=\"PATH\" in ivysettings.xml.");
- }
- try {
- URI uri;
- File file = new File(config);
-
- if (file.isAbsolute()) {
- uri = file.toURI();
- } else {
- URI cwd = new File(".").toURI();
- uri = cwd.resolve(config);
- }
-
- Map<String, Properties> repositories = BldFactory.getConfig(uri).getRepositoryConfig();
- resolver = new BldResolver(repositories);
- } catch (IOException e) {
- throw new Error("SigilResolver: failed to configure: " + e);
- }
- }
- return resolver;
- }
-
- public IResolution resolveOrFail(IModelElement element, boolean transitive) throws ResolutionException {
- return getResolver().resolveOrFail(element, transitive);
- }
-
- public IResolution resolve(IModelElement element, boolean transitive) {
- return getResolver().resolve(element, transitive);
- }
-
- public String getTypeName() {
- return "sigil";
- }
-
- /*
- * synthesize an ivy descriptor for a Sigil dependency. called after Sigil
- * resolution, so descriptor already contains resolved version.
- */
- public ResolvedResource findIvyFileRef(DependencyDescriptor dd, ResolveData data) {
- ResolvedResource ref = null;
-
- ModuleRevisionId id = dd.getDependencyRevisionId();
-
- if (!id.getOrganisation().equals(ORG_SIGIL)) {
- return null;
- }
-
- ISigilBundle bundle = resolve(id);
- if (bundle == null) {
- Log.error( "Failed to find bundle for module " + id );
- return null;
- }
-
- String symbolicName = id.getName();
- String version = bundle.getVersion().toString();
-
- Resource res = new SigilIvy(extractBCP ? bundle : null, symbolicName, version);
- ref = new ResolvedResource(res, version);
-
- Log.debug(format("findIvyFileRef: dd=%s => ref=%s", dd, ref));
- return ref;
- }
-
- @Override
- protected ResolvedResource findArtifactRef(Artifact artifact, Date date) {
- String name = artifact.getName();
- ModuleRevisionId id = artifact.getModuleRevisionId();
-
- if (!id.getOrganisation().equals(ORG_SIGIL)) {
- return null;
- }
-
- ISigilBundle bundle = resolve(id);
- if (bundle == null) {
- return null;
- }
-
- IBundleModelElement info = bundle.getBundleInfo();
- URI uri = info.getUpdateLocation();
- Resource res = null;
-
- try {
- URL url = (uri != null) ? uri.toURL() : bundle.getLocation().toFile().toURL();
- if (name.contains("!")) {
- String[] split = name.split("!");
- url = new URL("jar:" + url + "!/" + split[1] + "." + artifact.getExt());
- }
- res = new URLResource(url);
- } catch (MalformedURLException e) {
- System.out.println("Oops! " + e);
- }
-
- String version = bundle.getVersion().toString();
- ResolvedResource ref = new ResolvedResource(res, version);
-
- Log.debug(format("findArtifactRef: artifact=%s, date=%s => ref=%s", artifact, date, ref));
- return ref;
- }
-
- private ISigilBundle resolve(ModuleRevisionId id) {
- String revision = id.getRevision();
- String range = revision;
-
- if (revision.indexOf(',') < 0) {
- // SigilParser has already resolved the revision from the import
- // version range.
- // We now need to locate the same bundle to get its download URL.
- // We must use an OSGi version range to specify the exact version,
- // otherwise it will resolve to "specified version or above".
- range = "[" + revision + "," + revision + "]";
- }
-
- RequiredBundle bundle = new RequiredBundle();
- bundle.setSymbolicName(id.getName());
- bundle.setVersions(VersionRange.parseVersionRange(range));
-
- Log.verbose("searching for " + bundle);
-
- try {
- IResolution resolution = resolveOrFail(bundle, false);
- ISigilBundle[] bundles = resolution.getBundles().toArray(new ISigilBundle[0]);
- if (bundles.length == 1) {
- return bundles[0];
- }
- } catch (ResolutionException e) {
- Log.warn( e.getMessage() );
- return null;
- }
- return null;
- }
-
- /*
- * Implement BasicResolver abstract methods
- */
-
- @Override
- protected long get(Resource res, File dest) throws IOException {
- FileUtil.copy(res.openStream(), dest, null);
- long len = res.getContentLength();
- Log.debug(format("get(%s, %s) = %d", res, dest, len));
- return len;
- }
-
-
- @Override
- public Resource getResource(String source) throws IOException {
- source = encode(source);
- Resource res = resourcesCache.get(source);
- if (res == null) {
- res = new URLResource(new URL(source));
- resourcesCache.put(source, res);
- }
- Log.debug(format("SIGIL: getResource(%s) = %d", source, res));
- return res;
- }
-
- private static String encode(String source) {
- return source.trim().replaceAll(" ", "%20");
- }
-
- @SuppressWarnings("unchecked")
- @Override
- protected Collection findNames(Map tokenValues, String token) {
- throw new Error("SigilResolver: findNames not supported.");
- }
-
- public void publish(Artifact artifact, File src, boolean overwrite) throws IOException {
- throw new Error("SigilResolver: publish not supported.");
- }
-
- public void beginPublishTransaction(ModuleRevisionId module, boolean overwrite) throws IOException {
- // stop publish attempts being silently ignored.
- throw new Error("SigilResolver: publish not supported.");
- }
-
- /*
- * Synthesize a virtual ivy file for a Sigil dependency.
- */
- static class SigilIvy implements Resource {
- private StringBuilder content = new StringBuilder();
- private String name;
- private boolean exists = true;
-
- private SigilIvy() {
- }
-
- public SigilIvy(ISigilBundle bundle, String module, String rev) {
- this.name = "sigil!" + module + "#" + rev;
-
- String org = ORG_SIGIL;
- // FIXME: make status and pub configurable
- String status = "release";
- String pub = "20080912162859";
-
- content.append("<ivy-module version=\"1.0\">\n");
-
- content.append(format(
- "<info organisation=\"%s\" module=\"%s\" revision=\"%s\" status=\"%s\" publication=\"%s\"/>\n",
- org, module, rev, status, pub));
-
- String bcp = readBundleClassPath(bundle);
- if (bcp != null) {
- content.append("<publications>\n");
- for (String j : bcp.split(",\\s*")) {
- if (j.equals(".")) {
- content.append("<artifact/>\n");
- } else if (j.endsWith(".jar") && bundleContains(bundle, j)) {
- j = j.substring(0, j.length() - 4);
- content.append(format("<artifact name=\"%s!%s\"/>\n", module, j));
- }
- }
- content.append("</publications>\n");
- }
-
- // TODO: add dependencies?
- // <dependencies>
- // <dependency org="org.apache" name="log4j" rev="1.2.12"
- // revConstraint="[1.2,1.3)"/>
- // </dependencies>
-
- content.append("</ivy-module>\n");
- }
-
- private boolean bundleContains(ISigilBundle bundle, String j) {
- URI uri = bundle.getBundleInfo().getUpdateLocation();
+public class SigilResolver extends BasicResolver implements IBldResolver
+{
+ /** the sigil-injected dependency organisation name */
+ static final String ORG_SIGIL = "sigil";
+
+ private IBldResolver resolver;
+ private String config;
+ private boolean extractBCP = false;
+ private Map<String, Resource> resourcesCache = new HashMap<String, Resource>();
+
+
+ /**
+ * no-args constructor required by Ivy.
+ *
+ * XXX: It doesn't currently seem to matter that Ivy instantiates this many times,
+ * since SigilParser caches it, and the ProjectRepositoryProvider static cache
+ * prevents it being re-loaded unnecessarily.
+ *
+ * If this should become a problem, then we will need to delegate to a singleton instance,
+ * as we have done in SigilParser.
+ */
+ public SigilResolver()
+ {
+ }
+
+
+ public void setConfig( String config )
+ {
+ this.config = config;
+ }
+
+
+ /**
+ * if true, resolver extracts any jars embedded in Bundle-ClassPath.
+ */
+ public void setExtractBCP( String extract )
+ {
+ this.extractBCP = Boolean.parseBoolean( extract );
+ }
+
+
+ private IBldResolver getResolver()
+ {
+ if ( resolver == null )
+ {
+ if ( config == null )
+ {
+ throw new Error( "SigilResolver: not configured. Specify config=\"PATH\" in ivysettings.xml." );
+ }
+ try
+ {
+ URI uri;
+ File file = new File( config );
+
+ if ( file.isAbsolute() )
+ {
+ uri = file.toURI();
+ }
+ else
+ {
+ URI cwd = new File( "." ).toURI();
+ uri = cwd.resolve( config );
+ }
+
+ Map<String, Properties> repositories = BldFactory.getConfig( uri ).getRepositoryConfig();
+ resolver = new BldResolver( repositories );
+ }
+ catch ( IOException e )
+ {
+ throw new Error( "SigilResolver: failed to configure: " + e );
+ }
+ }
+ return resolver;
+ }
+
+
+ public IResolution resolveOrFail( IModelElement element, boolean transitive ) throws ResolutionException
+ {
+ return getResolver().resolveOrFail( element, transitive );
+ }
+
+
+ public IResolution resolve( IModelElement element, boolean transitive )
+ {
+ return getResolver().resolve( element, transitive );
+ }
+
+
+ public String getTypeName()
+ {
+ return "sigil";
+ }
+
+
+ /*
+ * synthesize an ivy descriptor for a Sigil dependency. called after Sigil
+ * resolution, so descriptor already contains resolved version.
+ */
+ public ResolvedResource findIvyFileRef( DependencyDescriptor dd, ResolveData data )
+ {
+ ResolvedResource ref = null;
+
+ ModuleRevisionId id = dd.getDependencyRevisionId();
+
+ if ( !id.getOrganisation().equals( ORG_SIGIL ) )
+ {
+ return null;
+ }
+
+ ISigilBundle bundle = resolve( id );
+ if ( bundle == null )
+ {
+ Log.error( "Failed to find bundle for module " + id );
+ return null;
+ }
+
+ String symbolicName = id.getName();
+ String version = bundle.getVersion().toString();
+
+ Resource res = new SigilIvy( extractBCP ? bundle : null, symbolicName, version );
+ ref = new ResolvedResource( res, version );
+
+ Log.debug( format( "findIvyFileRef: dd=%s => ref=%s", dd, ref ) );
+ return ref;
+ }
+
+
+ @Override
+ protected ResolvedResource findArtifactRef( Artifact artifact, Date date )
+ {
+ String name = artifact.getName();
+ ModuleRevisionId id = artifact.getModuleRevisionId();
+
+ if ( !id.getOrganisation().equals( ORG_SIGIL ) )
+ {
+ return null;
+ }
+
+ ISigilBundle bundle = resolve( id );
+ if ( bundle == null )
+ {
+ return null;
+ }
+
+ IBundleModelElement info = bundle.getBundleInfo();
+ URI uri = info.getUpdateLocation();
+ Resource res = null;
+
+ try
+ {
+ URL url = ( uri != null ) ? uri.toURL() : bundle.getLocation().toFile().toURL();
+ if ( name.contains( "!" ) )
+ {
+ String[] split = name.split( "!" );
+ url = new URL( "jar:" + url + "!/" + split[1] + "." + artifact.getExt() );
+ }
+ res = new URLResource( url );
+ }
+ catch ( MalformedURLException e )
+ {
+ System.out.println( "Oops! " + e );
+ }
+
+ String version = bundle.getVersion().toString();
+ ResolvedResource ref = new ResolvedResource( res, version );
+
+ Log.debug( format( "findArtifactRef: artifact=%s, date=%s => ref=%s", artifact, date, ref ) );
+ return ref;
+ }
+
+
+ private ISigilBundle resolve( ModuleRevisionId id )
+ {
+ String revision = id.getRevision();
+ String range = revision;
+
+ if ( revision.indexOf( ',' ) < 0 )
+ {
+ // SigilParser has already resolved the revision from the import
+ // version range.
+ // We now need to locate the same bundle to get its download URL.
+ // We must use an OSGi version range to specify the exact version,
+ // otherwise it will resolve to "specified version or above".
+ range = "[" + revision + "," + revision + "]";
+ }
+
+ RequiredBundle bundle = new RequiredBundle();
+ bundle.setSymbolicName( id.getName() );
+ bundle.setVersions( VersionRange.parseVersionRange( range ) );
+
+ Log.verbose( "searching for " + bundle );
+
+ try
+ {
+ IResolution resolution = resolveOrFail( bundle, false );
+ ISigilBundle[] bundles = resolution.getBundles().toArray( new ISigilBundle[0] );
+ if ( bundles.length == 1 )
+ {
+ return bundles[0];
+ }
+ }
+ catch ( ResolutionException e )
+ {
+ Log.warn( e.getMessage() );
+ return null;
+ }
+ return null;
+ }
+
+
+ /*
+ * Implement BasicResolver abstract methods
+ */
+
+ @Override
+ protected long get( Resource res, File dest ) throws IOException
+ {
+ FileUtil.copy( res.openStream(), dest, null );
+ long len = res.getContentLength();
+ Log.debug( format( "get(%s, %s) = %d", res, dest, len ) );
+ return len;
+ }
+
+
+ @Override
+ public Resource getResource( String source ) throws IOException
+ {
+ source = encode( source );
+ Resource res = resourcesCache.get( source );
+ if ( res == null )
+ {
+ res = new URLResource( new URL( source ) );
+ resourcesCache.put( source, res );
+ }
+ Log.debug( format( "SIGIL: getResource(%s) = %d", source, res ) );
+ return res;
+ }
+
+
+ private static String encode( String source )
+ {
+ return source.trim().replaceAll( " ", "%20" );
+ }
+
+
+ @SuppressWarnings("unchecked")
+ @Override
+ protected Collection findNames( Map tokenValues, String token )
+ {
+ throw new Error( "SigilResolver: findNames not supported." );
+ }
+
+
+ public void publish( Artifact artifact, File src, boolean overwrite ) throws IOException
+ {
+ throw new Error( "SigilResolver: publish not supported." );
+ }
+
+
+ public void beginPublishTransaction( ModuleRevisionId module, boolean overwrite ) throws IOException
+ {
+ // stop publish attempts being silently ignored.
+ throw new Error( "SigilResolver: publish not supported." );
+ }
+
+ /*
+ * Synthesize a virtual ivy file for a Sigil dependency.
+ */
+ static class SigilIvy implements Resource
+ {
+ private StringBuilder content = new StringBuilder();
+ private String name;
+ private boolean exists = true;
+
+
+ private SigilIvy()
+ {
+ }
+
+
+ public SigilIvy( ISigilBundle bundle, String module, String rev )
+ {
+ this.name = "sigil!" + module + "#" + rev;
+
+ String org = ORG_SIGIL;
+ // FIXME: make status and pub configurable
+ String status = "release";
+ String pub = "20080912162859";
+
+ content.append( "<ivy-module version=\"1.0\">\n" );
+
+ content.append( format(
+ "<info organisation=\"%s\" module=\"%s\" revision=\"%s\" status=\"%s\" publication=\"%s\"/>\n", org,
+ module, rev, status, pub ) );
+
+ String bcp = readBundleClassPath( bundle );
+ if ( bcp != null )
+ {
+ content.append( "<publications>\n" );
+ for ( String j : bcp.split( ",\\s*" ) )
+ {
+ if ( j.equals( "." ) )
+ {
+ content.append( "<artifact/>\n" );
+ }
+ else if ( j.endsWith( ".jar" ) && bundleContains( bundle, j ) )
+ {
+ j = j.substring( 0, j.length() - 4 );
+ content.append( format( "<artifact name=\"%s!%s\"/>\n", module, j ) );
+ }
+ }
+ content.append( "</publications>\n" );
+ }
+
+ // TODO: add dependencies?
+ // <dependencies>
+ // <dependency org="org.apache" name="log4j" rev="1.2.12"
+ // revConstraint="[1.2,1.3)"/>
+ // </dependencies>
+
+ content.append( "</ivy-module>\n" );
+ }
+
+
+ private boolean bundleContains( ISigilBundle bundle, String j )
+ {
+ URI uri = bundle.getBundleInfo().getUpdateLocation();
InputStream is = null;
- try {
- URL url = (uri != null) ? uri.toURL() : bundle.getLocation().toFile().toURL();
- is = url.openStream();
- JarInputStream js = new JarInputStream(is, false);
- JarEntry entry;
- while ( (entry = js.getNextJarEntry()) != null ) {
- if ( j.equals( entry.getName() ) ) {
- return true;
- }
- }
- } catch (IOException e) {
- } finally {
- if (is != null) {
- try {
- is.close();
- } catch (IOException e2) {
- }
- }
- }
- return false;
- }
-
- private String readBundleClassPath(ISigilBundle bundle) {
- if (bundle == null)
- return null;
-
- URI uri = bundle.getBundleInfo().getUpdateLocation();
+ try
+ {
+ URL url = ( uri != null ) ? uri.toURL() : bundle.getLocation().toFile().toURL();
+ is = url.openStream();
+ JarInputStream js = new JarInputStream( is, false );
+ JarEntry entry;
+ while ( ( entry = js.getNextJarEntry() ) != null )
+ {
+ if ( j.equals( entry.getName() ) )
+ {
+ return true;
+ }
+ }
+ }
+ catch ( IOException e )
+ {
+ }
+ finally
+ {
+ if ( is != null )
+ {
+ try
+ {
+ is.close();
+ }
+ catch ( IOException e2 )
+ {
+ }
+ }
+ }
+ return false;
+ }
+
+
+ private String readBundleClassPath( ISigilBundle bundle )
+ {
+ if ( bundle == null )
+ return null;
+
+ URI uri = bundle.getBundleInfo().getUpdateLocation();
InputStream is = null;
- try {
- URL url = (uri != null) ? uri.toURL() : bundle.getLocation().toFile().toURL();
- is = url.openStream();
- JarInputStream js = new JarInputStream(is, false);
+ try
+ {
+ URL url = ( uri != null ) ? uri.toURL() : bundle.getLocation().toFile().toURL();
+ is = url.openStream();
+ JarInputStream js = new JarInputStream( is, false );
Manifest m = js.getManifest();
- if (m != null)
- return (String) m.getMainAttributes().getValue("Bundle-ClassPath");
- } catch (IOException e) {
- } finally {
- if (is != null) {
- try {
- is.close();
- } catch (IOException e2) {
- }
- }
- }
-
+ if ( m != null )
+ return ( String ) m.getMainAttributes().getValue( "Bundle-ClassPath" );
+ }
+ catch ( IOException e )
+ {
+ }
+ finally
+ {
+ if ( is != null )
+ {
+ try
+ {
+ is.close();
+ }
+ catch ( IOException e2 )
+ {
+ }
+ }
+ }
+
return null;
}
- public String toString() {
- return "SigilIvy[" + name + "]";
- }
-
- // clone is used to read checksum files
- // so clone(getName() + ".sha1").exists() should be false
- public Resource clone(String cloneName) {
- Log.debug("SigilIvy: clone: " + cloneName);
- SigilIvy clone = new SigilIvy();
- clone.name = cloneName;
- clone.exists = false;
- return clone;
- }
-
- public boolean exists() {
- return exists;
- }
-
- public long getContentLength() {
- return content.length();
- }
-
- public long getLastModified() {
- // TODO Auto-generated method stub
- Log.debug("NOT IMPLEMENTED: getLastModified");
- return 0;
- }
-
- public String getName() {
- return name;
- }
-
- public boolean isLocal() {
- return false;
- }
-
- @SuppressWarnings("deprecation")
- public InputStream openStream() throws IOException {
- return new java.io.StringBufferInputStream(content.toString());
- }
- }
+
+ public String toString()
+ {
+ return "SigilIvy[" + name + "]";
+ }
+
+
+ // clone is used to read checksum files
+ // so clone(getName() + ".sha1").exists() should be false
+ public Resource clone( String cloneName )
+ {
+ Log.debug( "SigilIvy: clone: " + cloneName );
+ SigilIvy clone = new SigilIvy();
+ clone.name = cloneName;
+ clone.exists = false;
+ return clone;
+ }
+
+
+ public boolean exists()
+ {
+ return exists;
+ }
+
+
+ public long getContentLength()
+ {
+ return content.length();
+ }
+
+
+ public long getLastModified()
+ {
+ // TODO Auto-generated method stub
+ Log.debug( "NOT IMPLEMENTED: getLastModified" );
+ return 0;
+ }
+
+
+ public String getName()
+ {
+ return name;
+ }
+
+
+ public boolean isLocal()
+ {
+ return false;
+ }
+
+
+ @SuppressWarnings("deprecation")
+ public InputStream openStream() throws IOException
+ {
+ return new java.io.StringBufferInputStream( content.toString() );
+ }
+ }
}
Modified: felix/trunk/sigil/sigil-builder/src/org/apache/felix/sigil/build/Feature.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/sigil-builder/src/org/apache/felix/sigil/build/Feature.java?rev=796467&r1=796466&r2=796467&view=diff
==============================================================================
--- felix/trunk/sigil/sigil-builder/src/org/apache/felix/sigil/build/Feature.java (original)
+++ felix/trunk/sigil/sigil-builder/src/org/apache/felix/sigil/build/Feature.java Tue Jul 21 18:51:33 2009
@@ -21,7 +21,9 @@
*/
package org.apache.felix.sigil.build;
-class Feature {
- String id, version, url;
- String[] categories;
+
+class Feature
+{
+ String id, version, url;
+ String[] categories;
}
Modified: felix/trunk/sigil/sigil-builder/src/org/apache/felix/sigil/build/FindBundlesTask.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/sigil-builder/src/org/apache/felix/sigil/build/FindBundlesTask.java?rev=796467&r1=796466&r2=796467&view=diff
==============================================================================
--- felix/trunk/sigil/sigil-builder/src/org/apache/felix/sigil/build/FindBundlesTask.java (original)
+++ felix/trunk/sigil/sigil-builder/src/org/apache/felix/sigil/build/FindBundlesTask.java Tue Jul 21 18:51:33 2009
@@ -18,6 +18,7 @@
*/
package org.apache.felix.sigil.build;
+
import java.io.File;
import java.io.FilenameFilter;
@@ -25,77 +26,98 @@
import org.apache.tools.ant.Task;
import org.osgi.framework.Version;
-public class FindBundlesTask extends Task {
- private File dir;
- private String symbolicName;
- private String property;
-
- public File getDir() {
- return dir;
- }
-
- public void setDir(File dir) {
- this.dir = dir;
- }
-
- public String getSymbolicName() {
- return symbolicName;
- }
-
- public void setSymbolicName(String symbolicName) {
- this.symbolicName = symbolicName;
- }
-
- public String getProperty() {
- return property;
- }
-
- public void setProperty(String property) {
- this.property = property;
- }
-
- @Override
- public void execute() throws BuildException {
- System.out.println("Searching " + dir + " for bundle '" + symbolicName + "'");
- final String prefix = symbolicName + "_";
- String[] files = dir.list(new FilenameFilter() {
- public boolean accept(File dir, String name) {
- return name.startsWith(prefix);
- }
- });
- if (files == null)
- files = new String[0];
-
- System.out.println("Found " + files.length + " file(s) starting with " + symbolicName);
-
- Version highest = null;
- for (String filename : files) {
- System.out.println("Testing " + filename);
- // Drop the prefix
- int startIndex = prefix.length();
-
- // Drop the ".jar" suffix if present
- int endIndex = filename.length();
- if (filename.toLowerCase().endsWith(".jar")) {
- endIndex -= 4;
- }
-
- String versionString = filename.substring(startIndex, endIndex);
- System.out.println("Version string is '" + versionString + "'");
-
- Version version = new Version(versionString);
- if (highest == null || version.compareTo(highest) > 0) {
- highest = version;
- }
- }
-
- if (highest == null) {
- throw new BuildException("No matches for symbolic name '"
- + symbolicName + "'");
- }
+public class FindBundlesTask extends Task
+{
+
+ private File dir;
+ private String symbolicName;
+ private String property;
+
+
+ public File getDir()
+ {
+ return dir;
+ }
+
+
+ public void setDir( File dir )
+ {
+ this.dir = dir;
+ }
+
+
+ public String getSymbolicName()
+ {
+ return symbolicName;
+ }
+
+
+ public void setSymbolicName( String symbolicName )
+ {
+ this.symbolicName = symbolicName;
+ }
+
+
+ public String getProperty()
+ {
+ return property;
+ }
+
+
+ public void setProperty( String property )
+ {
+ this.property = property;
+ }
+
+
+ @Override
+ public void execute() throws BuildException
+ {
+ System.out.println( "Searching " + dir + " for bundle '" + symbolicName + "'" );
+ final String prefix = symbolicName + "_";
+ String[] files = dir.list( new FilenameFilter()
+ {
+ public boolean accept( File dir, String name )
+ {
+ return name.startsWith( prefix );
+ }
+ } );
+ if ( files == null )
+ files = new String[0];
+
+ System.out.println( "Found " + files.length + " file(s) starting with " + symbolicName );
+
+ Version highest = null;
+ for ( String filename : files )
+ {
+ System.out.println( "Testing " + filename );
+ // Drop the prefix
+ int startIndex = prefix.length();
+
+ // Drop the ".jar" suffix if present
+ int endIndex = filename.length();
+ if ( filename.toLowerCase().endsWith( ".jar" ) )
+ {
+ endIndex -= 4;
+ }
+
+ String versionString = filename.substring( startIndex, endIndex );
+ System.out.println( "Version string is '" + versionString + "'" );
+
+ Version version = new Version( versionString );
+ if ( highest == null || version.compareTo( highest ) > 0 )
+ {
+ highest = version;
+ }
+ }
+
+ if ( highest == null )
+ {
+ throw new BuildException( "No matches for symbolic name '" + symbolicName + "'" );
+ }
- getProject().setNewProperty(property, highest.toString());
- }
+ getProject().setNewProperty( property, highest.toString() );
+ }
}
Modified: felix/trunk/sigil/sigil-builder/src/org/apache/felix/sigil/build/SiteInsertFeatureContentHandler.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/sigil-builder/src/org/apache/felix/sigil/build/SiteInsertFeatureContentHandler.java?rev=796467&r1=796466&r2=796467&view=diff
==============================================================================
--- felix/trunk/sigil/sigil-builder/src/org/apache/felix/sigil/build/SiteInsertFeatureContentHandler.java (original)
+++ felix/trunk/sigil/sigil-builder/src/org/apache/felix/sigil/build/SiteInsertFeatureContentHandler.java Tue Jul 21 18:51:33 2009
@@ -18,6 +18,7 @@
*/
package org.apache.felix.sigil.build;
+
import java.util.List;
import org.xml.sax.Attributes;
@@ -26,79 +27,106 @@
import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;
-class SiteInsertFeatureContentHandler implements ContentHandler {
-
- private final ContentHandler output;
- private final List<org.apache.felix.sigil.build.Feature> featureList;
-
- public SiteInsertFeatureContentHandler(ContentHandler output,
- List<Feature> featureList) {
- this.output = output;
- this.featureList = featureList;
- }
-
- public void characters(char[] ch, int start, int length) throws SAXException {
- output.characters(ch, start, length);
- }
-
- public void endDocument() throws SAXException {
- output.endDocument();
- }
-
- public void endElement(String uri, String localName, String name) throws SAXException {
- output.endElement(uri, localName, name);
- }
-
- public void endPrefixMapping(String prefix) throws SAXException {
- output.endPrefixMapping(prefix);
- }
-
- public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException {
- //output.ignorableWhitespace(ch, start, length);
- }
-
- public void processingInstruction(String target, String data) throws SAXException {
- output.processingInstruction(target, data);
- }
-
- public void setDocumentLocator(Locator locator) {
- output.setDocumentLocator(locator);
- }
-
- public void skippedEntity(String name) throws SAXException {
- output.skippedEntity(name);
- }
-
- public void startDocument() throws SAXException {
- output.startDocument();
- }
-
- public void startElement(String uri, String localName, String name, Attributes atts)
- throws SAXException {
- output.startElement(uri, localName, name, atts);
-
- if("site".equals(name)) {
- for (Feature feature : featureList) {
- AttributesImpl featureAtts = new AttributesImpl();
- featureAtts.addAttribute("", "", "url", "CDATA", feature.url);
- featureAtts.addAttribute("", "", "id", "CDATA", feature.id);
- featureAtts.addAttribute("", "", "version", "CDATA", feature.version);
- output.startElement("", "", "feature", featureAtts);
-
- for (int i = 0; i < feature.categories.length; i++) {
- AttributesImpl categoryAtts = new AttributesImpl();
- categoryAtts.addAttribute("", "", "name", "CDATA", feature.categories[i]);
- output.startElement("", "", "category", categoryAtts);
- output.endElement("", "", "category");
- }
-
- output.endElement("", "", "feature");
- }
- }
- }
-
- public void startPrefixMapping(String prefix, String uri) throws SAXException {
- output.startPrefixMapping(prefix, uri);
- }
+
+class SiteInsertFeatureContentHandler implements ContentHandler
+{
+
+ private final ContentHandler output;
+ private final List<org.apache.felix.sigil.build.Feature> featureList;
+
+
+ public SiteInsertFeatureContentHandler( ContentHandler output, List<Feature> featureList )
+ {
+ this.output = output;
+ this.featureList = featureList;
+ }
+
+
+ public void characters( char[] ch, int start, int length ) throws SAXException
+ {
+ output.characters( ch, start, length );
+ }
+
+
+ public void endDocument() throws SAXException
+ {
+ output.endDocument();
+ }
+
+
+ public void endElement( String uri, String localName, String name ) throws SAXException
+ {
+ output.endElement( uri, localName, name );
+ }
+
+
+ public void endPrefixMapping( String prefix ) throws SAXException
+ {
+ output.endPrefixMapping( prefix );
+ }
+
+
+ public void ignorableWhitespace( char[] ch, int start, int length ) throws SAXException
+ {
+ //output.ignorableWhitespace(ch, start, length);
+ }
+
+
+ public void processingInstruction( String target, String data ) throws SAXException
+ {
+ output.processingInstruction( target, data );
+ }
+
+
+ public void setDocumentLocator( Locator locator )
+ {
+ output.setDocumentLocator( locator );
+ }
+
+
+ public void skippedEntity( String name ) throws SAXException
+ {
+ output.skippedEntity( name );
+ }
+
+
+ public void startDocument() throws SAXException
+ {
+ output.startDocument();
+ }
+
+
+ public void startElement( String uri, String localName, String name, Attributes atts ) throws SAXException
+ {
+ output.startElement( uri, localName, name, atts );
+
+ if ( "site".equals( name ) )
+ {
+ for ( Feature feature : featureList )
+ {
+ AttributesImpl featureAtts = new AttributesImpl();
+ featureAtts.addAttribute( "", "", "url", "CDATA", feature.url );
+ featureAtts.addAttribute( "", "", "id", "CDATA", feature.id );
+ featureAtts.addAttribute( "", "", "version", "CDATA", feature.version );
+ output.startElement( "", "", "feature", featureAtts );
+
+ for ( int i = 0; i < feature.categories.length; i++ )
+ {
+ AttributesImpl categoryAtts = new AttributesImpl();
+ categoryAtts.addAttribute( "", "", "name", "CDATA", feature.categories[i] );
+ output.startElement( "", "", "category", categoryAtts );
+ output.endElement( "", "", "category" );
+ }
+
+ output.endElement( "", "", "feature" );
+ }
+ }
+ }
+
+
+ public void startPrefixMapping( String prefix, String uri ) throws SAXException
+ {
+ output.startPrefixMapping( prefix, uri );
+ }
}
Modified: felix/trunk/sigil/sigil-builder/src/org/apache/felix/sigil/build/SiteInsertFeatures.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/sigil-builder/src/org/apache/felix/sigil/build/SiteInsertFeatures.java?rev=796467&r1=796466&r2=796467&view=diff
==============================================================================
--- felix/trunk/sigil/sigil-builder/src/org/apache/felix/sigil/build/SiteInsertFeatures.java (original)
+++ felix/trunk/sigil/sigil-builder/src/org/apache/felix/sigil/build/SiteInsertFeatures.java Tue Jul 21 18:51:33 2009
@@ -18,6 +18,7 @@
*/
package org.apache.felix.sigil.build;
+
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
@@ -42,138 +43,210 @@
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
-public class SiteInsertFeatures extends Task {
- private File siteXmlFile;
- private String features;
- private String versionPropPrefix;
- private String categoryPropPrefix;
-
- public File getSiteXmlFile() {
- return siteXmlFile;
- }
- public void setSiteXmlFile(File siteXmlFile) {
- this.siteXmlFile = siteXmlFile;
- }
- public String getFeatures() {
- return features;
- }
- public void setFeatures(String features) {
- this.features = features;
- }
- public String getVersionPropPrefix() {
- return versionPropPrefix;
- }
- public void setVersionPropPrefix(String versionPropPrefix) {
- this.versionPropPrefix = versionPropPrefix;
- }
- public String getCategoryPropPrefix() {
- return categoryPropPrefix;
- }
- public void setCategoryPropPrefix(String categoryPropPrefix) {
- this.categoryPropPrefix = categoryPropPrefix;
- }
-
- @Override
- public void execute() throws BuildException {
- Project project = getProject();
-
- List<Feature> featureList = new ArrayList<Feature>();
- StringTokenizer tokenizer = new StringTokenizer(features, ",");
- while(tokenizer.hasMoreTokens()) {
- Feature feature = new Feature();
- feature.id = tokenizer.nextToken().trim();
-
- // Find the version property
- String versionProp;
- if(versionPropPrefix == null) {
- versionProp = feature.id;
- } else {
- versionProp = versionPropPrefix + "." + feature.id;
- }
- feature.version = project.getProperty(versionProp);
-
- // Find the categories for this feature
- feature.categories = new String[0];
- if(categoryPropPrefix != null) {
- String categoriesStr = project.getProperty(categoryPropPrefix + "." + feature.id);
- if(categoriesStr != null) {
- StringTokenizer categoriesTokenizer = new StringTokenizer(categoriesStr, ",");
- feature.categories = new String[categoriesTokenizer.countTokens()];
- for(int i=0; i<feature.categories.length; i++) {
- feature.categories[i] = categoriesTokenizer.nextToken();
- }
- }
- }
-
- if(feature.version != null) {
- feature.url = "features/" + feature.id + "_" + feature.version + ".jar";
- featureList.add(feature);
- } else {
- System.out.println("Skipping feature " + feature.id);
- }
- }
-
- if(!siteXmlFile.isFile()) {
- throw new BuildException(siteXmlFile + " does not exist or is not a normal file");
- }
- try {
- // Generate new XML into a temporary file
- File tempFile = File.createTempFile("tmp", ".xml", siteXmlFile.getParentFile());
- tempFile.deleteOnExit();
-
- SAXTransformerFactory transformerFactory = (SAXTransformerFactory) SAXTransformerFactory.newInstance();
- TransformerHandler transformerHandler = transformerFactory.newTransformerHandler();
- transformerHandler.setResult(new StreamResult(tempFile));
-
- SAXParserFactory parserFactory = SAXParserFactory.newInstance();
- SAXParser parser = parserFactory.newSAXParser();
-
- SiteInsertFeatureContentHandler contentHandler = new SiteInsertFeatureContentHandler(transformerHandler, featureList);
-
- XMLReader reader = parser.getXMLReader();
- reader.setContentHandler(contentHandler);
- reader.parse(new InputSource(new FileInputStream(siteXmlFile)));
-
- // Backup original file
- File backup = new File(siteXmlFile.getParentFile(), siteXmlFile.getName() + ".bak");
- copyFile(siteXmlFile, backup);
-
- // Replace original file
- copyFile(tempFile, siteXmlFile);
-
- } catch (IOException e) {
- throw new BuildException(e);
- } catch (TransformerConfigurationException e) {
- throw new BuildException(e);
- } catch (IllegalArgumentException e) {
- throw new BuildException(e);
- } catch (TransformerFactoryConfigurationError e) {
- throw new BuildException(e);
- } catch (ParserConfigurationException e) {
- throw new BuildException(e);
- } catch (SAXException e) {
- throw new BuildException(e);
- }
- }
-
- private void copyFile(File source, File dest) throws IOException {
- FileInputStream in = null;
- FileOutputStream out = null;
- try {
- in = new FileInputStream(source);
- out = new FileOutputStream(dest);
-
- byte[] buffer = new byte[1024];
-
- int read;
- while((read = in.read(buffer, 0, 1024)) > -1) {
- out.write(buffer, 0, read);
- }
- } finally {
- try { if(in != null) in.close(); } catch(IOException e) {}
- try { if(out != null) out.close(); } catch(IOException e) {}
- }
-
- }
+public class SiteInsertFeatures extends Task
+{
+
+ private File siteXmlFile;
+ private String features;
+ private String versionPropPrefix;
+ private String categoryPropPrefix;
+
+
+ public File getSiteXmlFile()
+ {
+ return siteXmlFile;
+ }
+
+
+ public void setSiteXmlFile( File siteXmlFile )
+ {
+ this.siteXmlFile = siteXmlFile;
+ }
+
+
+ public String getFeatures()
+ {
+ return features;
+ }
+
+
+ public void setFeatures( String features )
+ {
+ this.features = features;
+ }
+
+
+ public String getVersionPropPrefix()
+ {
+ return versionPropPrefix;
+ }
+
+
+ public void setVersionPropPrefix( String versionPropPrefix )
+ {
+ this.versionPropPrefix = versionPropPrefix;
+ }
+
+
+ public String getCategoryPropPrefix()
+ {
+ return categoryPropPrefix;
+ }
+
+
+ public void setCategoryPropPrefix( String categoryPropPrefix )
+ {
+ this.categoryPropPrefix = categoryPropPrefix;
+ }
+
+
+ @Override
+ public void execute() throws BuildException
+ {
+ Project project = getProject();
+
+ List<Feature> featureList = new ArrayList<Feature>();
+ StringTokenizer tokenizer = new StringTokenizer( features, "," );
+ while ( tokenizer.hasMoreTokens() )
+ {
+ Feature feature = new Feature();
+ feature.id = tokenizer.nextToken().trim();
+
+ // Find the version property
+ String versionProp;
+ if ( versionPropPrefix == null )
+ {
+ versionProp = feature.id;
+ }
+ else
+ {
+ versionProp = versionPropPrefix + "." + feature.id;
+ }
+ feature.version = project.getProperty( versionProp );
+
+ // Find the categories for this feature
+ feature.categories = new String[0];
+ if ( categoryPropPrefix != null )
+ {
+ String categoriesStr = project.getProperty( categoryPropPrefix + "." + feature.id );
+ if ( categoriesStr != null )
+ {
+ StringTokenizer categoriesTokenizer = new StringTokenizer( categoriesStr, "," );
+ feature.categories = new String[categoriesTokenizer.countTokens()];
+ for ( int i = 0; i < feature.categories.length; i++ )
+ {
+ feature.categories[i] = categoriesTokenizer.nextToken();
+ }
+ }
+ }
+
+ if ( feature.version != null )
+ {
+ feature.url = "features/" + feature.id + "_" + feature.version + ".jar";
+ featureList.add( feature );
+ }
+ else
+ {
+ System.out.println( "Skipping feature " + feature.id );
+ }
+ }
+
+ if ( !siteXmlFile.isFile() )
+ {
+ throw new BuildException( siteXmlFile + " does not exist or is not a normal file" );
+ }
+ try
+ {
+ // Generate new XML into a temporary file
+ File tempFile = File.createTempFile( "tmp", ".xml", siteXmlFile.getParentFile() );
+ tempFile.deleteOnExit();
+
+ SAXTransformerFactory transformerFactory = ( SAXTransformerFactory ) SAXTransformerFactory.newInstance();
+ TransformerHandler transformerHandler = transformerFactory.newTransformerHandler();
+ transformerHandler.setResult( new StreamResult( tempFile ) );
+
+ SAXParserFactory parserFactory = SAXParserFactory.newInstance();
+ SAXParser parser = parserFactory.newSAXParser();
+
+ SiteInsertFeatureContentHandler contentHandler = new SiteInsertFeatureContentHandler( transformerHandler,
+ featureList );
+
+ XMLReader reader = parser.getXMLReader();
+ reader.setContentHandler( contentHandler );
+ reader.parse( new InputSource( new FileInputStream( siteXmlFile ) ) );
+
+ // Backup original file
+ File backup = new File( siteXmlFile.getParentFile(), siteXmlFile.getName() + ".bak" );
+ copyFile( siteXmlFile, backup );
+
+ // Replace original file
+ copyFile( tempFile, siteXmlFile );
+
+ }
+ catch ( IOException e )
+ {
+ throw new BuildException( e );
+ }
+ catch ( TransformerConfigurationException e )
+ {
+ throw new BuildException( e );
+ }
+ catch ( IllegalArgumentException e )
+ {
+ throw new BuildException( e );
+ }
+ catch ( TransformerFactoryConfigurationError e )
+ {
+ throw new BuildException( e );
+ }
+ catch ( ParserConfigurationException e )
+ {
+ throw new BuildException( e );
+ }
+ catch ( SAXException e )
+ {
+ throw new BuildException( e );
+ }
+ }
+
+
+ private void copyFile( File source, File dest ) throws IOException
+ {
+ FileInputStream in = null;
+ FileOutputStream out = null;
+ try
+ {
+ in = new FileInputStream( source );
+ out = new FileOutputStream( dest );
+
+ byte[] buffer = new byte[1024];
+
+ int read;
+ while ( ( read = in.read( buffer, 0, 1024 ) ) > -1 )
+ {
+ out.write( buffer, 0, read );
+ }
+ }
+ finally
+ {
+ try
+ {
+ if ( in != null )
+ in.close();
+ }
+ catch ( IOException e )
+ {
+ }
+ try
+ {
+ if ( out != null )
+ out.close();
+ }
+ catch ( IOException e )
+ {
+ }
+ }
+
+ }
}