Richard S. Hall | 85bafab | 2009-07-13 13:25:46 +0000 | [diff] [blame^] | 1 | /* |
| 2 | * Licensed to the Apache Software Foundation (ASF) under one |
| 3 | * or more contributor license agreements. See the NOTICE file |
| 4 | * distributed with this work for additional information |
| 5 | * regarding copyright ownership. The ASF licenses this file |
| 6 | * to you under the Apache License, Version 2.0 (the |
| 7 | * "License"); you may not use this file except in compliance |
| 8 | * with the License. You may obtain a copy of the License at |
| 9 | * |
| 10 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 11 | * |
| 12 | * Unless required by applicable law or agreed to in writing, |
| 13 | * software distributed under the License is distributed on an |
| 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| 15 | * KIND, either express or implied. See the License for the |
| 16 | * specific language governing permissions and limitations |
| 17 | * under the License. |
| 18 | */ |
| 19 | |
| 20 | package org.cauldron.bld.ivy; |
| 21 | |
| 22 | import java.io.File; |
| 23 | import java.io.IOException; |
| 24 | import java.io.InputStream; |
| 25 | import java.net.URI; |
| 26 | import java.net.URL; |
| 27 | import java.text.ParseException; |
| 28 | import java.util.Arrays; |
| 29 | import java.util.HashMap; |
| 30 | import java.util.Map; |
| 31 | import java.util.regex.Pattern; |
| 32 | |
| 33 | import org.apache.ivy.Ivy; |
| 34 | import org.apache.ivy.core.IvyContext; |
| 35 | import org.apache.ivy.core.module.descriptor.Artifact; |
| 36 | import org.apache.ivy.core.module.descriptor.Configuration; |
| 37 | import org.apache.ivy.core.module.descriptor.DefaultDependencyArtifactDescriptor; |
| 38 | import org.apache.ivy.core.module.descriptor.DefaultDependencyDescriptor; |
| 39 | import org.apache.ivy.core.module.descriptor.DefaultModuleDescriptor; |
| 40 | import org.apache.ivy.core.module.descriptor.DependencyDescriptor; |
| 41 | import org.apache.ivy.core.module.descriptor.ModuleDescriptor; |
| 42 | import org.apache.ivy.core.module.id.ModuleRevisionId; |
| 43 | import org.apache.ivy.core.settings.IvySettings; |
| 44 | import org.apache.ivy.plugins.parser.ModuleDescriptorParser; |
| 45 | import org.apache.ivy.plugins.parser.ModuleDescriptorParserRegistry; |
| 46 | import org.apache.ivy.plugins.parser.ParserSettings; |
| 47 | import org.apache.ivy.plugins.parser.xml.XmlModuleDescriptorParser; |
| 48 | import org.apache.ivy.plugins.parser.xml.XmlModuleDescriptorWriter; |
| 49 | import org.apache.ivy.plugins.repository.Resource; |
| 50 | import org.apache.ivy.plugins.repository.file.FileResource; |
| 51 | import org.apache.ivy.plugins.repository.url.URLResource; |
| 52 | import org.apache.ivy.plugins.resolver.DependencyResolver; |
| 53 | import org.cauldron.bld.config.BldFactory; |
| 54 | import org.cauldron.bld.config.IBldProject; |
| 55 | import org.cauldron.sigil.model.IModelElement; |
| 56 | import org.cauldron.sigil.model.common.VersionRange; |
| 57 | import org.cauldron.sigil.model.eclipse.ISigilBundle; |
| 58 | import org.cauldron.sigil.model.osgi.IBundleModelElement; |
| 59 | import org.cauldron.sigil.model.osgi.IPackageImport; |
| 60 | import org.cauldron.sigil.model.osgi.IRequiredBundle; |
| 61 | import org.cauldron.sigil.repository.IResolution; |
| 62 | |
| 63 | public class SigilParser implements ModuleDescriptorParser { |
| 64 | |
| 65 | private static DelegateParser instance; |
| 66 | |
| 67 | // used by ProjectRepository |
| 68 | static DelegateParser instance() { |
| 69 | if (instance == null) |
| 70 | throw new IllegalStateException("SigilParser is not instantiated."); |
| 71 | return instance; |
| 72 | } |
| 73 | |
| 74 | public SigilParser() { |
| 75 | if (instance == null) { |
| 76 | instance = new DelegateParser(); |
| 77 | } |
| 78 | } |
| 79 | |
| 80 | /** |
| 81 | * In IvyDE, IvyContext is not available, so we can't find the SigilResolver. |
| 82 | * This allows us to construct one. |
| 83 | * @deprecated temporary to support IvyDE |
| 84 | */ |
| 85 | public void setConfig(String config) { |
| 86 | instance.config = config; |
| 87 | } |
| 88 | |
| 89 | /** |
| 90 | * sets delegate parser. |
| 91 | * If not set, we delegate to the default Ivy parser. |
| 92 | * @param type name returned by desired parser's getType() method. |
| 93 | */ |
| 94 | public void setDelegateType(String type) { |
| 95 | for (ModuleDescriptorParser parser : ModuleDescriptorParserRegistry.getInstance().getParsers()) { |
| 96 | if (parser.getType().equals(type)) { |
| 97 | instance.delegate = parser; |
| 98 | break; |
| 99 | } |
| 100 | } |
| 101 | |
| 102 | if (instance.delegate == null) { |
| 103 | throw new IllegalArgumentException("Can't find parser delegateType=" + type); |
| 104 | } |
| 105 | } |
| 106 | |
| 107 | /** |
| 108 | * sets default file name the delegate parser accepts. |
| 109 | * If not set, defaults to "ivy.xml". |
| 110 | * @param name |
| 111 | */ |
| 112 | public void setDelegateFile(String name) { |
| 113 | instance.ivyFile = name; |
| 114 | } |
| 115 | |
| 116 | /** |
| 117 | * sets the dependencies to keep from the delegate parser. |
| 118 | * If not set, all existing dependencies are dropped. |
| 119 | * @param regex pattern matching dependency names to keep. |
| 120 | */ |
| 121 | public void setKeepDependencies(String regex) { |
| 122 | instance.keepDependencyPattern = Pattern.compile(regex); |
| 123 | } |
| 124 | |
| 125 | /** |
| 126 | * reduce level of info logging. |
| 127 | * @param quiet |
| 128 | */ |
| 129 | public void setQuiet(String quiet) { |
| 130 | instance.quiet = Boolean.parseBoolean(quiet); |
| 131 | } |
| 132 | |
| 133 | /** |
| 134 | * sets the SigilResolver we use. |
| 135 | * If not set, we use the first SigilResolver we find. |
| 136 | * @param name |
| 137 | */ |
| 138 | public void setResolver(String name) { |
| 139 | instance.resolverName = name; |
| 140 | } |
| 141 | |
| 142 | /** |
| 143 | * adds override element: <override name="X" pattern="Y" replace="Z"/>. Overrides |
| 144 | * Ivy variables using a pattern substitution on the resource directory path. |
| 145 | * |
| 146 | * @deprecated |
| 147 | * This is only needed when a delegate parser expects Ant variables to be set |
| 148 | * during the ivy:buildlist task (or the ProjectRepository initialisation), |
| 149 | * which they are not. The delegate parser should really be fixed, as otherwise |
| 150 | * the ivy:buildlist task won't work without this workaround. |
| 151 | */ |
| 152 | // e.g. <override name="ant.project.name" pattern=".*/([^/]+)/([^/]+)$" replace="$1-$2"/> |
| 153 | public void addConfiguredOverride(Map<String, String> var) { |
| 154 | final String name = var.get("name"); |
| 155 | final String regex = var.get("pattern"); |
| 156 | final String replace = var.get("replace"); |
| 157 | |
| 158 | if (name == null || regex == null || replace == null) |
| 159 | throw new IllegalArgumentException("override must contain name, pattern and replace attributes."); |
| 160 | |
| 161 | instance.varRegex.put(name, Pattern.compile(regex)); |
| 162 | instance.varReplace.put(name, replace); |
| 163 | } |
| 164 | |
| 165 | // implement ModuleDescriptorParser interface by delegation to singleton instance. |
| 166 | |
| 167 | public boolean accept(Resource res) { |
| 168 | return instance.accept(res); |
| 169 | } |
| 170 | |
| 171 | public Artifact getMetadataArtifact(ModuleRevisionId mrid, Resource res) { |
| 172 | return instance.getMetadataArtifact(mrid, res); |
| 173 | } |
| 174 | |
| 175 | public String getType() { |
| 176 | return instance.getType(); |
| 177 | } |
| 178 | |
| 179 | public ModuleDescriptor parseDescriptor(ParserSettings settings, URL xmlURL, boolean validate) |
| 180 | throws ParseException, IOException { |
| 181 | return instance.parseDescriptor(settings, xmlURL, validate); |
| 182 | } |
| 183 | |
| 184 | public ModuleDescriptor parseDescriptor(ParserSettings settings, URL xmlURL, Resource res, boolean validate) |
| 185 | throws ParseException, IOException { |
| 186 | return instance.parseDescriptor(settings, xmlURL, res, validate); |
| 187 | } |
| 188 | |
| 189 | public void toIvyFile(InputStream source, Resource res, File destFile, ModuleDescriptor md) throws ParseException, |
| 190 | IOException { |
| 191 | instance.toIvyFile(source, res, destFile, md); |
| 192 | } |
| 193 | |
| 194 | /** |
| 195 | * delegating parser. |
| 196 | * (optionally) removes original dependencies and augments with sigil-determined dependencies. |
| 197 | */ |
| 198 | static class DelegateParser extends XmlModuleDescriptorParser { |
| 199 | |
| 200 | private static final String SIGIL_BUILDLIST = IBldProject.PROJECT_FILE; |
| 201 | private static final String KEEP_ALL = ".*"; |
| 202 | |
| 203 | private IBldResolver resolver; |
| 204 | private ParserSettings defaultSettings; |
| 205 | private Map<String, DefaultModuleDescriptor> rawCache = new HashMap<String, DefaultModuleDescriptor>(); |
| 206 | private Map<String, DefaultModuleDescriptor> augmentedCache = new HashMap<String, DefaultModuleDescriptor>(); |
| 207 | |
| 208 | private HashMap<String, String> varReplace = new HashMap<String, String>(); |
| 209 | private HashMap<String, Pattern> varRegex = new HashMap<String, Pattern>(); |
| 210 | |
| 211 | private ModuleDescriptorParser delegate; |
| 212 | private String ivyFile = "ivy.xml"; |
| 213 | private String resolverName; |
| 214 | private Pattern keepDependencyPattern; |
| 215 | private boolean quiet; |
| 216 | private String config; |
| 217 | |
| 218 | @Override |
| 219 | public boolean accept(Resource res) { |
| 220 | boolean accept = (res instanceof SigilResolver.SigilIvy) |
| 221 | || res.getName().endsWith("/" + SIGIL_BUILDLIST) |
| 222 | || ((instance.getSigilURI(res) != null) && |
| 223 | ((instance.delegate != null ? instance.delegate.accept(res) : false) || super.accept(res))); |
| 224 | if (accept) |
| 225 | Log.verbose("accepted: " + res); |
| 226 | return accept; |
| 227 | } |
| 228 | |
| 229 | @Override |
| 230 | public void toIvyFile(InputStream source, Resource res, File destFile, ModuleDescriptor md) |
| 231 | throws ParseException, IOException { |
| 232 | Log.verbose("writing resource: " + res + " toIvyFile: " + destFile); |
| 233 | // source allows us to keep layout and comments, |
| 234 | // but this doesn't work if source is not ivy.xml. |
| 235 | // So just write file directly from descriptor. |
| 236 | try { |
| 237 | XmlModuleDescriptorWriter.write(md, destFile); |
| 238 | } finally { |
| 239 | if (source != null) |
| 240 | source.close(); |
| 241 | } |
| 242 | } |
| 243 | |
| 244 | @Override |
| 245 | public ModuleDescriptor parseDescriptor(ParserSettings settings, URL xmlURL, boolean validate) |
| 246 | throws ParseException, IOException { |
| 247 | return parseDescriptor(settings, xmlURL, new URLResource(xmlURL), validate); |
| 248 | } |
| 249 | |
| 250 | @Override |
| 251 | public ModuleDescriptor parseDescriptor(ParserSettings settings, URL xmlURL, Resource res, boolean validate) |
| 252 | throws ParseException, IOException { |
| 253 | String cacheKey = xmlURL.toString() + settings.hashCode(); |
| 254 | DefaultModuleDescriptor dmd = augmentedCache.get(cacheKey); |
| 255 | |
| 256 | if (dmd == null) { |
| 257 | dmd = rawCache.get(cacheKey); |
| 258 | if (dmd == null) { |
| 259 | dmd = delegateParse(settings, xmlURL, res, validate); |
| 260 | } |
| 261 | |
| 262 | if (!quiet) |
| 263 | Log.info("augmenting module=" + dmd.getModuleRevisionId().getName() + |
| 264 | " ant.project.name=" + settings.substitute("${ant.project.name}")); |
| 265 | |
| 266 | addDependenciesToDescriptor(res, dmd); |
| 267 | augmentedCache.put(cacheKey, dmd); |
| 268 | |
| 269 | Log.verbose("augmented dependencies: " + Arrays.asList(dmd.getDependencies())); |
| 270 | } |
| 271 | |
| 272 | return dmd; |
| 273 | } |
| 274 | |
| 275 | // used by ProjectRepository |
| 276 | ModuleDescriptor parseDescriptor(URL projectURL) throws ParseException, IOException { |
| 277 | if (defaultSettings == null) { |
| 278 | Ivy ivy = IvyContext.getContext().peekIvy(); |
| 279 | if (ivy == null) |
| 280 | throw new IllegalStateException("can't get default settings - no ivy context."); |
| 281 | defaultSettings = ivy.getSettings(); |
| 282 | } |
| 283 | |
| 284 | URL ivyURL = new URL(projectURL, ivyFile); |
| 285 | String cacheKey = ivyURL.toString() + defaultSettings.hashCode(); |
| 286 | DefaultModuleDescriptor dmd = rawCache.get(cacheKey); |
| 287 | |
| 288 | if (dmd == null) { |
| 289 | URLResource res = new URLResource(ivyURL); |
| 290 | // Note: this doesn't contain the augmented dependencies, which is OK, |
| 291 | // since the ProjectRepository only needs the id and status. |
| 292 | dmd = delegateParse(defaultSettings, ivyURL, res, false); |
| 293 | rawCache.put(cacheKey, dmd); |
| 294 | } |
| 295 | |
| 296 | return dmd; |
| 297 | } |
| 298 | |
| 299 | private DefaultModuleDescriptor delegateParse(ParserSettings settings, URL xmlURL, Resource res, |
| 300 | boolean validate) throws ParseException, IOException { |
| 301 | String resName = res.getName(); |
| 302 | |
| 303 | if (resName.endsWith("/" + SIGIL_BUILDLIST)) { |
| 304 | String name = resName.substring(0, resName.length() - SIGIL_BUILDLIST.length()); |
| 305 | res = res.clone(name + ivyFile); |
| 306 | xmlURL = new URL(xmlURL, ivyFile); |
| 307 | } |
| 308 | |
| 309 | if (settings instanceof IvySettings) { |
| 310 | IvySettings ivySettings = (IvySettings) settings; |
| 311 | String dir = new File(res.getName()).getParent(); |
| 312 | |
| 313 | for (String name : varRegex.keySet()) { |
| 314 | Pattern regex = varRegex.get(name); |
| 315 | String replace = varReplace.get(name); |
| 316 | |
| 317 | String value = regex.matcher(dir).replaceAll(replace); |
| 318 | |
| 319 | Log.debug("overriding variable " + name + "=" + value); |
| 320 | ivySettings.setVariable(name, value); |
| 321 | } |
| 322 | } |
| 323 | |
| 324 | ModuleDescriptor md = null; |
| 325 | if (delegate == null || !delegate.accept(res)) { |
| 326 | md = super.parseDescriptor(settings, xmlURL, res, validate); |
| 327 | } else { |
| 328 | md = delegate.parseDescriptor(settings, xmlURL, res, validate); |
| 329 | } |
| 330 | |
| 331 | return mungeDescriptor(md, res); |
| 332 | } |
| 333 | |
| 334 | /** |
| 335 | * clones descriptor and removes dependencies, as descriptor MUST have |
| 336 | * 'this' as the parser given to its constructor. |
| 337 | * Only dependency names matched by keepDependencyPattern are kept, |
| 338 | * as we're going to add our own dependencies later. |
| 339 | */ |
| 340 | private DefaultModuleDescriptor mungeDescriptor(ModuleDescriptor md, Resource res) { |
| 341 | |
| 342 | if ((md instanceof DefaultModuleDescriptor) && |
| 343 | (md.getParser() == this) && |
| 344 | (KEEP_ALL.equals(keepDependencyPattern))) { |
| 345 | return (DefaultModuleDescriptor) md; |
| 346 | } |
| 347 | |
| 348 | DefaultModuleDescriptor dmd = new DefaultModuleDescriptor(this, res); |
| 349 | |
| 350 | dmd.setModuleRevisionId(md.getModuleRevisionId()); |
| 351 | dmd.setPublicationDate(md.getPublicationDate()); |
| 352 | |
| 353 | for (Configuration c : md.getConfigurations()) { |
| 354 | String conf = c.getName(); |
| 355 | |
| 356 | dmd.addConfiguration(c); |
| 357 | |
| 358 | for (Artifact a : md.getArtifacts(conf)) { |
| 359 | dmd.addArtifact(conf, a); |
| 360 | } |
| 361 | } |
| 362 | |
| 363 | if (keepDependencyPattern != null) { |
| 364 | for (DependencyDescriptor dependency : md.getDependencies()) { |
| 365 | String name = dependency.getDependencyId().getName(); |
| 366 | if (keepDependencyPattern.matcher(name).matches()) { |
| 367 | dmd.addDependency(dependency); |
| 368 | } |
| 369 | } |
| 370 | } |
| 371 | |
| 372 | return dmd; |
| 373 | } |
| 374 | |
| 375 | /* |
| 376 | * find URI to Sigil project file. This assumes that it is in the same |
| 377 | * directory as the ivy file. |
| 378 | */ |
| 379 | private URI getSigilURI(Resource res) { |
| 380 | URI uri = null; |
| 381 | |
| 382 | if (res instanceof URLResource) { |
| 383 | URL url = ((URLResource) res).getURL(); |
| 384 | uri = URI.create(url.toString()).resolve(IBldProject.PROJECT_FILE); |
| 385 | try { |
| 386 | InputStream stream = uri.toURL().openStream(); // check file |
| 387 | // exists |
| 388 | stream.close(); |
| 389 | } catch (IOException e) { |
| 390 | uri = null; |
| 391 | } |
| 392 | } else if (res instanceof FileResource) { |
| 393 | uri = ((FileResource) res).getFile().toURI().resolve(IBldProject.PROJECT_FILE); |
| 394 | if (!(new File(uri).exists())) |
| 395 | uri = null; |
| 396 | } |
| 397 | |
| 398 | return uri; |
| 399 | } |
| 400 | |
| 401 | /* |
| 402 | * add sigil dependencies to ModuleDescriptor. |
| 403 | */ |
| 404 | private void addDependenciesToDescriptor(Resource res, DefaultModuleDescriptor md) throws IOException { |
| 405 | // FIXME: transitive should be configurable |
| 406 | final boolean transitive = true; // ivy default is true |
| 407 | final boolean changing = false; |
| 408 | final boolean force = false; |
| 409 | |
| 410 | URI uri = getSigilURI(res); |
| 411 | if (uri == null) |
| 412 | return; |
| 413 | |
| 414 | IBldProject project; |
| 415 | |
| 416 | project = BldFactory.getProject(uri); |
| 417 | |
| 418 | IBundleModelElement requirements = project.getDependencies(); |
| 419 | Log.verbose("requirements: " + Arrays.asList(requirements.children())); |
| 420 | |
| 421 | // preserve version range for Require-Bundle |
| 422 | // XXX: synthesise bundle version range corresponding to package version ranges? |
| 423 | HashMap<String, VersionRange> versions = new HashMap<String, VersionRange>(); |
| 424 | for (IModelElement child : requirements.children()) { |
| 425 | if (child instanceof IRequiredBundle) { |
| 426 | IRequiredBundle bundle = (IRequiredBundle) child; |
| 427 | versions.put(bundle.getSymbolicName(), bundle.getVersions()); |
| 428 | } |
| 429 | } |
| 430 | |
| 431 | IBldResolver resolver = findResolver(); |
| 432 | if (resolver == null) { |
| 433 | // this can happen in IvyDE, but it retries and is OK next time. |
| 434 | Log.warn("failed to find resolver - IvyContext not yet available."); |
| 435 | return; |
| 436 | } |
| 437 | |
| 438 | IResolution resolution = resolver.resolve(requirements, false); |
| 439 | Log.verbose("resolution: " + resolution.getBundles()); |
| 440 | |
| 441 | ModuleRevisionId masterMrid = md.getModuleRevisionId(); |
| 442 | DefaultDependencyDescriptor dd; |
| 443 | ModuleRevisionId mrid; |
| 444 | |
| 445 | for (ISigilBundle bundle : resolution.getBundles()) { |
| 446 | IBundleModelElement info = bundle.getBundleInfo(); |
| 447 | String name = info.getSymbolicName(); |
| 448 | |
| 449 | if (name == null) { |
| 450 | // e.g. SystemProvider with framework=null |
| 451 | continue; |
| 452 | } |
| 453 | |
| 454 | if (bundle instanceof ProjectRepository.ProjectBundle) { |
| 455 | ProjectRepository.ProjectBundle pb = (ProjectRepository.ProjectBundle) bundle; |
| 456 | String org = pb.getOrg(); |
| 457 | if (org == null) |
| 458 | org = masterMrid.getOrganisation(); |
| 459 | String id = pb.getId(); |
| 460 | String module = pb.getModule(); |
| 461 | String rev = pb.getRevision(); |
| 462 | |
| 463 | mrid = ModuleRevisionId.newInstance(org, module, rev); |
| 464 | dd = new SigilDependencyDescriptor(md, mrid, force, changing, transitive); |
| 465 | |
| 466 | if (!id.equals(module)) { // non-default artifact |
| 467 | dd.addDependencyArtifact(module, |
| 468 | new DefaultDependencyArtifactDescriptor(dd, id, "jar", "jar", null, null)); |
| 469 | } |
| 470 | } else { |
| 471 | VersionRange version = versions.get(name); |
| 472 | String rev = version != null ? version.toString() : info.getVersion().toString(); |
| 473 | mrid = ModuleRevisionId.newInstance(SigilResolver.ORG_SIGIL, name, rev); |
| 474 | dd = new SigilDependencyDescriptor(md, mrid, force, changing, transitive); |
| 475 | } |
| 476 | |
| 477 | int nDeps = 0; |
| 478 | boolean foundDefault = false; |
| 479 | |
| 480 | // TODO: make dependency configurations configurable SIGIL-176 |
| 481 | for (String conf : md.getConfigurationsNames()) { |
| 482 | if (conf.equals("default")) { |
| 483 | foundDefault = true; |
| 484 | } else if (md.getArtifacts(conf).length == 0) { |
| 485 | dd.addDependencyConfiguration(conf, conf + "(default)"); |
| 486 | nDeps++; |
| 487 | } |
| 488 | } |
| 489 | |
| 490 | if (nDeps > 0) { |
| 491 | if (foundDefault) |
| 492 | dd.addDependencyConfiguration("default", "default"); |
| 493 | } else { |
| 494 | dd.addDependencyConfiguration("*", "*"); // all configurations |
| 495 | } |
| 496 | |
| 497 | md.addDependency(dd); |
| 498 | } |
| 499 | |
| 500 | boolean resolved = true; |
| 501 | for (IModelElement child : requirements.children()) { |
| 502 | ISigilBundle provider = resolution.getProvider(child); |
| 503 | if (provider == null) { |
| 504 | resolved = false; |
| 505 | // this is parse phase, so only log verbose message. |
| 506 | // error is produced during resolution phase. |
| 507 | Log.verbose("WARN: can't resolve: " + child); |
| 508 | |
| 509 | String name; |
| 510 | String version; |
| 511 | if (child instanceof IRequiredBundle) { |
| 512 | IRequiredBundle rb = (IRequiredBundle) child; |
| 513 | name = rb.getSymbolicName(); |
| 514 | version = rb.getVersions().toString(); |
| 515 | } else { |
| 516 | IPackageImport pi = (IPackageImport) child; |
| 517 | name = "import!" + pi.getPackageName(); |
| 518 | version = pi.getVersions().toString(); |
| 519 | } |
| 520 | |
| 521 | mrid = ModuleRevisionId.newInstance("!" + SigilResolver.ORG_SIGIL, name, version); |
| 522 | dd = new SigilDependencyDescriptor(md, mrid, force, changing, transitive); |
| 523 | dd.addDependencyConfiguration("*", "*"); // all |
| 524 | // configurations |
| 525 | md.addDependency(dd); |
| 526 | } |
| 527 | } |
| 528 | |
| 529 | if (!resolved) { |
| 530 | // Ivy does not show warnings or errors logged from parse phase, until after resolution. |
| 531 | // but <buildlist> ant task doesn't do resolution, so errors would be silently ignored. |
| 532 | // Hence, we must use Message.info to ensure this failure is seen. |
| 533 | if (!quiet) |
| 534 | Log.info("WARN: resolution failed in: " + masterMrid.getName() + ". Use -v for details."); |
| 535 | } |
| 536 | } |
| 537 | |
| 538 | /* |
| 539 | * find named resolver, or first resolver that implements IBldResolver. |
| 540 | */ |
| 541 | private IBldResolver findResolver() { |
| 542 | if (resolver == null) { |
| 543 | Ivy ivy = IvyContext.getContext().peekIvy(); |
| 544 | if (ivy != null) { |
| 545 | if (resolverName != null) { |
| 546 | DependencyResolver r = ivy.getSettings().getResolver(resolverName); |
| 547 | if (r == null) { |
| 548 | throw new Error("SigilParser: resolver \"" + resolverName + "\" not defined."); |
| 549 | } else if (r instanceof IBldResolver) { |
| 550 | resolver = (IBldResolver) r; |
| 551 | } else { |
| 552 | throw new Error("SigilParser: resolver \"" + resolverName + "\" is not a SigilResolver."); |
| 553 | } |
| 554 | } else { |
| 555 | for (Object r : ivy.getSettings().getResolvers()) { |
| 556 | if (r instanceof IBldResolver) { |
| 557 | resolver = (IBldResolver) r; |
| 558 | break; |
| 559 | } |
| 560 | } |
| 561 | } |
| 562 | |
| 563 | if (resolver == null) { |
| 564 | throw new Error("SigilParser: can't find SigilResolver. Check ivysettings.xml."); |
| 565 | } |
| 566 | } else if (config != null) { |
| 567 | Log.warn("creating duplicate resolver to support IvyDE."); |
| 568 | resolver = new SigilResolver(); |
| 569 | ((SigilResolver)resolver).setConfig(config); |
| 570 | } |
| 571 | } |
| 572 | return resolver; |
| 573 | } |
| 574 | } |
| 575 | |
| 576 | } |
| 577 | |
| 578 | /* |
| 579 | * this is only needed so that we can distinguish sigil-added dependencies from |
| 580 | * existing ones. |
| 581 | */ |
| 582 | class SigilDependencyDescriptor extends DefaultDependencyDescriptor { |
| 583 | public SigilDependencyDescriptor(DefaultModuleDescriptor md, ModuleRevisionId mrid, boolean force, |
| 584 | boolean changing, boolean transitive) { |
| 585 | super(md, mrid, force, changing, transitive); |
| 586 | } |
| 587 | } |