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
10 * http://www.apache.org/licenses/LICENSE-2.0
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
19 package org.apache.karaf.tooling;
22 import java.io.FileReader;
23 import java.io.IOException;
24 import java.io.InputStream;
25 import java.io.Reader;
26 import java.lang.reflect.Field;
27 import java.lang.reflect.InvocationHandler;
28 import java.lang.reflect.Method;
29 import java.lang.reflect.Proxy;
31 import java.util.ArrayList;
32 import java.util.Collection;
33 import java.util.Collections;
34 import java.util.EnumSet;
35 import java.util.Enumeration;
36 import java.util.HashMap;
37 import java.util.HashSet;
38 import java.util.Hashtable;
39 import java.util.Iterator;
40 import java.util.LinkedHashSet;
41 import java.util.List;
43 import java.util.Properties;
45 import java.util.TreeSet;
46 import java.util.concurrent.Executors;
47 import java.util.concurrent.ScheduledExecutorService;
48 import java.util.concurrent.atomic.AtomicLong;
49 import java.util.jar.Attributes;
50 import java.util.jar.Manifest;
51 import java.util.regex.Pattern;
52 import java.util.zip.ZipEntry;
53 import java.util.zip.ZipInputStream;
55 import aQute.bnd.osgi.Macro;
56 import aQute.bnd.osgi.Processor;
57 import org.apache.felix.resolver.Logger;
58 import org.apache.felix.resolver.ResolverImpl;
59 import org.apache.felix.utils.version.VersionRange;
60 import org.apache.felix.utils.version.VersionTable;
61 import org.apache.karaf.features.FeatureEvent;
62 import org.apache.karaf.features.FeaturesService;
63 import org.apache.karaf.features.internal.download.DownloadCallback;
64 import org.apache.karaf.features.internal.download.DownloadManager;
65 import org.apache.karaf.features.internal.download.Downloader;
66 import org.apache.karaf.features.internal.download.StreamProvider;
67 import org.apache.karaf.features.internal.model.Conditional;
68 import org.apache.karaf.features.internal.model.ConfigFile;
69 import org.apache.karaf.features.internal.model.Feature;
70 import org.apache.karaf.features.internal.model.Features;
71 import org.apache.karaf.features.internal.model.JaxbUtil;
72 import org.apache.karaf.features.internal.resolver.ResourceBuilder;
73 import org.apache.karaf.features.internal.resolver.ResourceImpl;
74 import org.apache.karaf.features.internal.resolver.ResourceUtils;
75 import org.apache.karaf.features.internal.service.Deployer;
76 import org.apache.karaf.features.internal.service.State;
77 import org.apache.karaf.features.internal.util.MapUtils;
78 import org.apache.karaf.features.internal.util.MultiException;
79 import org.apache.karaf.profile.assembly.CustomDownloadManager;
80 import org.apache.karaf.tooling.utils.MojoSupport;
81 import org.apache.karaf.util.config.PropertiesLoader;
82 import org.apache.maven.artifact.Artifact;
83 import org.apache.maven.plugin.MojoExecutionException;
84 import org.apache.maven.plugin.MojoFailureException;
85 import org.apache.maven.plugins.annotations.Component;
86 import org.apache.maven.plugins.annotations.Mojo;
87 import org.apache.maven.plugins.annotations.Parameter;
88 import org.apache.maven.plugins.annotations.ResolutionScope;
89 import org.apache.maven.project.MavenProject;
90 import org.apache.maven.settings.Settings;
91 import org.ops4j.pax.url.mvn.MavenResolver;
92 import org.ops4j.pax.url.mvn.MavenResolvers;
93 import org.osgi.framework.Bundle;
94 import org.osgi.framework.BundleException;
95 import org.osgi.framework.Constants;
96 import org.osgi.framework.InvalidSyntaxException;
97 import org.osgi.framework.Version;
98 import org.osgi.framework.namespace.IdentityNamespace;
99 import org.osgi.framework.startlevel.BundleStartLevel;
100 import org.osgi.framework.wiring.BundleCapability;
101 import org.osgi.framework.wiring.BundleRequirement;
102 import org.osgi.framework.wiring.BundleRevision;
103 import org.osgi.framework.wiring.BundleWiring;
104 import org.osgi.resource.Requirement;
105 import org.osgi.resource.Resource;
106 import org.osgi.resource.Wire;
107 import org.osgi.service.resolver.ResolutionException;
109 import static java.util.jar.JarFile.MANIFEST_NAME;
111 @Mojo(name = "verify", requiresDependencyResolution = ResolutionScope.COMPILE_PLUS_RUNTIME, threadSafe = true)
112 public class VerifyMojo extends MojoSupport {
114 @Parameter(property = "descriptors")
115 protected Set<String> descriptors;
117 @Parameter(property = "features")
118 protected Set<String> features;
120 @Parameter(property = "framework")
121 protected Set<String> framework;
123 @Parameter(property = "configuration")
124 protected String configuration;
126 @Parameter(property = "distribution", defaultValue = "org.apache.karaf:apache-karaf")
127 protected String distribution;
129 @Parameter(property = "javase")
130 protected String javase;
132 @Parameter(property = "dist-dir")
133 protected String distDir;
135 @Parameter(property = "additional-metadata")
136 protected File additionalMetadata;
138 @Parameter(property = "ignore-missing-conditions")
139 protected boolean ignoreMissingConditions;
141 @Parameter(property = "fail")
142 protected String fail = "end";
144 @Parameter(property = "verify-transitive")
145 protected boolean verifyTransitive = false;
147 @Parameter(defaultValue = "${project}", readonly = true)
148 protected MavenProject project;
150 protected MavenResolver resolver;
153 public void execute() throws MojoExecutionException, MojoFailureException {
154 Hashtable<String, String> config = new Hashtable<>();
155 StringBuilder remote = new StringBuilder();
156 for (Object obj : project.getRemoteProjectRepositories()) {
157 if (remote.length() > 0) {
160 remote.append(invoke(obj, "getUrl"));
161 remote.append("@id=").append(invoke(obj, "getId"));
162 if (!((Boolean) invoke(getPolicy(obj, false), "isEnabled"))) {
163 remote.append("@noreleases");
165 if ((Boolean) invoke(getPolicy(obj, true), "isEnabled")) {
166 remote.append("@snapshots");
169 getLog().info("Using repositories: " + remote.toString());
170 config.put("maven.repositories", remote.toString());
171 config.put("maven.localRepository", localRepo.getBasedir());
172 config.put("maven.settings", mavenSession.getRequest().getUserSettingsFile().toString());
173 // TODO: add more configuration bits ?
174 resolver = MavenResolvers.createMavenResolver(config, "maven");
178 private Object invoke(Object object, String getter) throws MojoExecutionException {
180 return object.getClass().getMethod(getter).invoke(object);
181 } catch (Exception e) {
182 throw new MojoExecutionException("Unable to build remote repository from " + object.toString(), e);
186 private Object getPolicy(Object object, boolean snapshots) throws MojoExecutionException {
187 return invoke(object, "getPolicy", new Class[] { Boolean.TYPE }, new Object[] { snapshots });
190 private Object invoke(Object object, String getter, Class[] types, Object[] params) throws MojoExecutionException {
192 return object.getClass().getMethod(getter, types).invoke(object, params);
193 } catch (Exception e) {
194 throw new MojoExecutionException("Unable to build remote repository from " + object.toString(), e);
198 protected void doExecute() throws MojoExecutionException, MojoFailureException {
199 System.setProperty("karaf.home", "target/karaf");
200 System.setProperty("karaf.data", "target/karaf/data");
202 Hashtable<String, String> properties = new Hashtable<>();
204 if (additionalMetadata != null) {
205 try (Reader reader = new FileReader(additionalMetadata)) {
206 Properties metadata = new Properties();
207 metadata.load(reader);
208 for (Enumeration<?> e = metadata.propertyNames(); e.hasMoreElements(); ) {
209 Object key = e.nextElement();
210 Object val = metadata.get(key);
211 properties.put(key.toString(), val.toString());
213 } catch (IOException e) {
214 throw new MojoExecutionException("Unable to load additional metadata from " + additionalMetadata, e);
218 // TODO: allow using external configuration ?
219 ScheduledExecutorService executor = Executors.newScheduledThreadPool(8);
220 DownloadManager manager = new CustomDownloadManager(resolver, executor);
221 final Map<String, Features> repositories;
222 Map<String, List<Feature>> allFeatures = new HashMap<>();
224 repositories = loadRepositories(manager, descriptors);
225 for (String repoUri : repositories.keySet()) {
226 List<Feature> features = repositories.get(repoUri).getFeature();
227 // Ack features to inline configuration files urls
228 for (Feature feature : features) {
229 for (org.apache.karaf.features.internal.model.Bundle bi : feature.getBundle()) {
230 String loc = bi.getLocation();
232 if (loc.contains("file:")) {
233 for (ConfigFile cfi : feature.getConfigfile()) {
234 if (cfi.getFinalname().substring(1)
235 .equals(loc.substring(loc.indexOf("file:") + "file:".length()))) {
236 nloc = cfi.getLocation();
241 Field field = bi.getClass().getDeclaredField("location");
242 field.setAccessible(true);
243 field.set(bi, loc.substring(0, loc.indexOf("file:")) + nloc);
247 allFeatures.put(repoUri, features);
249 } catch (Exception e) {
250 throw new MojoExecutionException("Unable to load features descriptors", e);
253 List<Feature> featuresToTest = new ArrayList<>();
254 if (verifyTransitive) {
255 for (List<Feature> features : allFeatures.values()) {
256 featuresToTest.addAll(features);
259 for (String uri : descriptors) {
260 featuresToTest.addAll(allFeatures.get(uri));
263 if (features != null && !features.isEmpty()) {
264 StringBuilder sb = new StringBuilder();
265 for (String feature : features) {
266 if (sb.length() > 0) {
269 String p = feature.replaceAll("\\.", "\\\\.").replaceAll("\\*", ".*");
271 if (!feature.contains("/")) {
275 Pattern pattern = Pattern.compile(sb.toString());
276 for (Iterator<Feature> iterator = featuresToTest.iterator(); iterator.hasNext();) {
277 Feature feature = iterator.next();
278 String id = feature.getName() + "/" + feature.getVersion();
279 if (!pattern.matcher(id).matches()) {
285 for (String fmk : framework) {
286 properties.put("feature.framework." + fmk, fmk);
288 List<Exception> failures = new ArrayList<>();
289 for (Feature feature : featuresToTest) {
291 String id = feature.getName() + "/" + feature.getVersion();
292 verifyResolution(new CustomDownloadManager(resolver, executor),
293 repositories, Collections.singleton(id), properties);
294 getLog().info("Verification of feature " + id + " succeeded");
295 } catch (Exception e) {
296 if (e.getCause() instanceof ResolutionException) {
297 getLog().warn(e.getMessage());
302 if ("first".equals(fail)) {
306 for (Conditional cond : feature.getConditional()) {
307 Set<String> ids = new LinkedHashSet<>();
308 ids.add(feature.getId());
309 ids.addAll(cond.getCondition());
311 verifyResolution(manager, repositories, ids, properties);
312 getLog().info("Verification of feature " + ids + " succeeded");
313 } catch (Exception e) {
314 if (ignoreMissingConditions && e.getCause() instanceof ResolutionException) {
315 boolean ignore = true;
316 Collection<Requirement> requirements = ((ResolutionException) e.getCause()).getUnresolvedRequirements();
317 for (Requirement req : requirements) {
318 ignore &= (IdentityNamespace.IDENTITY_NAMESPACE.equals(req.getNamespace())
319 && ResourceUtils.TYPE_FEATURE.equals(req.getAttributes().get("type"))
320 && cond.getCondition().contains(req.getAttributes().get(IdentityNamespace.IDENTITY_NAMESPACE).toString()));
323 getLog().warn("Feature resolution failed for " + ids
324 + "\nMessage: " + e.getCause().getMessage());
328 if (e.getCause() instanceof ResolutionException) {
329 getLog().warn(e.getMessage());
334 if ("first".equals(fail)) {
340 if ("end".equals(fail) && !failures.isEmpty()) {
341 throw new MojoExecutionException("Verification failures", new MultiException("Verification failures", failures));
345 private void verifyResolution(DownloadManager manager, final Map<String, Features> repositories, Set<String> features, Hashtable<String, String> properties) throws MojoExecutionException {
347 Bundle systemBundle = getSystemBundle(getMetadata(properties, "metadata#"));
348 DummyDeployCallback callback = new DummyDeployCallback(systemBundle, repositories.values());
349 Deployer deployer = new Deployer(manager, new ResolverImpl(new MavenResolverLog()), callback);
353 Deployer.DeploymentRequest request = createDeploymentRequest();
355 for (String fmwk : framework) {
356 MapUtils.addToMapSet(request.requirements, FeaturesService.ROOT_REGION, fmwk);
359 deployer.deploy(callback.getDeploymentState(), request);
360 } catch (Exception e) {
361 throw new MojoExecutionException("Unable to resolve framework features", e);
366 boolean resolveOptionalImports = getResolveOptionalImports(properties);
368 DeploymentBuilder builder = new DeploymentBuilder(
371 repositories.values(),
372 -1 // Disable url handlers
374 Map<String, Resource> downloadedResources = builder.download(
375 getPrefixedProperties(properties, "feature."),
376 getPrefixedProperties(properties, "bundle."),
377 getPrefixedProperties(properties, "fab."),
378 getPrefixedProperties(properties, "req."),
379 getPrefixedProperties(properties, "override."),
380 getPrefixedProperties(properties, "optional."),
381 getMetadata(properties, "metadata#")
384 for (String uri : getPrefixedProperties(properties, "resources.")) {
385 builder.addResourceRepository(new MetadataRepository(new HttpMetadataProvider(uri)));
391 for (String feature : features) {
392 MapUtils.addToMapSet(request.requirements, FeaturesService.ROOT_REGION, feature);
395 Set<String> prereqs = new HashSet<>();
398 deployer.deploy(callback.getDeploymentState(), request);
400 } catch (Deployer.PartialDeploymentException e) {
401 if (!prereqs.containsAll(e.getMissing())) {
402 prereqs.addAll(e.getMissing());
404 throw new Exception("Deployment aborted due to loop in missing prerequisites: " + e.getMissing());
408 // TODO: find unused resources ?
409 } catch (Exception e) {
410 throw new MojoExecutionException("Feature resolution failed for " + features
411 + "\nMessage: " + e.getMessage()
412 + "\nRepositories: " + toString(new TreeSet<>(repositories.keySet()))
413 + "\nResources: " + toString(new TreeSet<>(manager.getProviders().keySet())), e);
417 } catch (MojoExecutionException e) {
419 } catch (Exception e) {
420 throw new MojoExecutionException("Error verifying feature " + features + "\nMessage: " + e.getMessage(), e);
424 private Deployer.DeploymentRequest createDeploymentRequest() {
425 Deployer.DeploymentRequest request = new Deployer.DeploymentRequest();
426 request.bundleUpdateRange = FeaturesService.DEFAULT_BUNDLE_UPDATE_RANGE;
427 request.featureResolutionRange = FeaturesService.DEFAULT_FEATURE_RESOLUTION_RANGE;
428 request.serviceRequirements = FeaturesService.SERVICE_REQUIREMENTS_DEFAULT;
429 request.overrides = new HashSet<>();
430 request.requirements = new HashMap<>();
431 request.stateChanges = new HashMap<>();
432 request.options = EnumSet.noneOf(FeaturesService.Option.class);
436 private String toString(Collection<String> collection) {
437 StringBuilder sb = new StringBuilder();
439 for (String s : collection) {
440 sb.append("\t").append(s).append("\n");
443 return sb.toString();
446 private Bundle getSystemBundle(Map<String, Map<VersionRange, Map<String, String>>> metadata) throws Exception {
448 if (configuration != null) {
449 configPropURL = new URL(configuration);
451 Artifact karafDistro = project.getArtifactMap().get(distribution);
452 if (karafDistro == null) {
453 throw new MojoFailureException("The karaf distribution " + distribution + " is not a dependency");
455 if ("kar".equals(karafDistro.getType()) && distDir == null) {
456 distDir = "resources";
458 String dir = distDir;
460 dir = karafDistro.getArtifactId() + "-" + karafDistro.getBaseVersion();
462 configPropURL = new URL("jar:file:" + karafDistro.getFile() + "!/" + dir + "/etc/config.properties");
464 org.apache.felix.utils.properties.Properties configProps = PropertiesLoader.loadPropertiesFile(configPropURL, true);
465 // copySystemProperties(configProps);
466 if (javase == null) {
467 configProps.put("java.specification.version", System.getProperty("java.specification.version"));
469 configProps.put("java.specification.version", javase);
471 configProps.substitute();
473 Attributes attributes = new Attributes();
474 attributes.putValue(Constants.BUNDLE_MANIFESTVERSION, "2");
475 attributes.putValue(Constants.BUNDLE_SYMBOLICNAME, "system.bundle");
476 attributes.putValue(Constants.BUNDLE_VERSION, "0.0.0");
478 String exportPackages = configProps.getProperty("org.osgi.framework.system.packages");
479 if (configProps.containsKey("org.osgi.framework.system.packages.extra")) {
480 exportPackages += "," + configProps.getProperty("org.osgi.framework.system.packages.extra");
482 exportPackages = exportPackages.replaceAll(",\\s*,", ",");
483 attributes.putValue(Constants.EXPORT_PACKAGE, exportPackages);
485 String systemCaps = configProps.getProperty("org.osgi.framework.system.capabilities");
486 attributes.putValue(Constants.PROVIDE_CAPABILITY, systemCaps);
488 // TODO: support metadata overrides on system bundle
489 // attributes = DeploymentBuilder.overrideAttributes(attributes, metadata);
491 final Hashtable<String, String> headers = new Hashtable<>();
492 for (Map.Entry attr : attributes.entrySet()) {
493 headers.put(attr.getKey().toString(), attr.getValue().toString());
496 final FakeBundleRevision resource = new FakeBundleRevision(headers, "system-bundle", 0l);
497 return resource.getBundle();
501 public static Map<String, Features> loadRepositories(DownloadManager manager, Set<String> uris) throws Exception {
502 final Map<String, Features> loaded = new HashMap<>();
503 final Downloader downloader = manager.createDownloader();
504 for (String repository : uris) {
505 downloader.download(repository, new DownloadCallback() {
507 public void downloaded(final StreamProvider provider) throws Exception {
508 try (InputStream is = provider.open()) {
509 Features featuresModel = JaxbUtil.unmarshal(provider.getUrl(), is, false);
510 synchronized (loaded) {
511 loaded.put(provider.getUrl(), featuresModel);
512 for (String innerRepository : featuresModel.getRepository()) {
513 downloader.download(innerRepository, this);
524 public static Set<String> getPrefixedProperties(Map<String, String> properties, String prefix) {
525 Set<String> result = new HashSet<>();
526 for (String key : properties.keySet()) {
527 if (key.startsWith(prefix)) {
528 String url = properties.get(key);
529 if (url == null || url.length() == 0) {
530 url = key.substring(prefix.length());
532 if (!url.isEmpty()) {
540 public static Map<String, Map<VersionRange, Map<String, String>>> getMetadata(Map<String, String> properties, String prefix) {
541 Map<String, Map<VersionRange, Map<String, String>>> result = new HashMap<>();
542 for (String key : properties.keySet()) {
543 if (key.startsWith(prefix)) {
544 String val = properties.get(key);
545 key = key.substring(prefix.length());
546 String[] parts = key.split("#");
547 if (parts.length == 3) {
548 Map<VersionRange, Map<String, String>> ranges = result.get(parts[0]);
549 if (ranges == null) {
550 ranges = new HashMap<>();
551 result.put(parts[0], ranges);
553 String version = parts[1];
554 if (!version.startsWith("[") && !version.startsWith("(")) {
555 Processor processor = new Processor();
556 processor.setProperty("@", VersionTable.getVersion(version).toString());
557 Macro macro = new Macro(processor);
558 version = macro.process("${range;[==,=+)}");
560 VersionRange range = new VersionRange(version);
561 Map<String, String> hdrs = ranges.get(range);
563 hdrs = new HashMap<>();
564 ranges.put(range, hdrs);
566 hdrs.put(parts[2], val);
573 public static class FakeBundleRevision extends ResourceImpl implements BundleRevision, BundleStartLevel {
575 private final Bundle bundle;
576 private int startLevel;
578 public FakeBundleRevision(final Hashtable<String, String> headers, final String location, final long bundleId) throws BundleException {
579 ResourceBuilder.build(this, location, headers);
580 this.bundle = (Bundle) Proxy.newProxyInstance(
581 getClass().getClassLoader(),
582 new Class[] { Bundle.class },
583 new InvocationHandler() {
585 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
586 if (method.getName().equals("hashCode")) {
587 return FakeBundleRevision.this.hashCode();
588 } else if (method.getName().equals("equals")) {
589 return proxy == args[0];
590 } else if (method.getName().equals("toString")) {
591 return bundle.getSymbolicName() + "/" + bundle.getVersion();
592 } else if (method.getName().equals("adapt")) {
593 if (args.length == 1 && args[0] == BundleRevision.class) {
594 return FakeBundleRevision.this;
595 } else if (args.length == 1 && args[0] == BundleStartLevel.class) {
596 return FakeBundleRevision.this;
598 } else if (method.getName().equals("getHeaders")) {
600 } else if (method.getName().equals("getBundleId")) {
602 } else if (method.getName().equals("getLocation")) {
604 } else if (method.getName().equals("getSymbolicName")) {
605 String name = headers.get(Constants.BUNDLE_SYMBOLICNAME);
606 int idx = name.indexOf(';');
608 name = name.substring(0, idx).trim();
611 } else if (method.getName().equals("getVersion")) {
612 return new Version(headers.get(Constants.BUNDLE_VERSION));
613 } else if (method.getName().equals("getState")) {
614 return Bundle.ACTIVE;
615 } else if (method.getName().equals("getLastModified")) {
624 public int getStartLevel() {
629 public void setStartLevel(int startLevel) {
630 this.startLevel = startLevel;
634 public boolean isPersistentlyStarted() {
639 public boolean isActivationPolicyUsed() {
644 public String getSymbolicName() {
645 return bundle.getSymbolicName();
649 public Version getVersion() {
650 return bundle.getVersion();
654 public List<BundleCapability> getDeclaredCapabilities(String namespace) {
655 throw new UnsupportedOperationException();
659 public List<BundleRequirement> getDeclaredRequirements(String namespace) {
660 throw new UnsupportedOperationException();
664 public int getTypes() {
665 throw new UnsupportedOperationException();
669 public BundleWiring getWiring() {
670 throw new UnsupportedOperationException();
674 public Bundle getBundle() {
679 public static class DummyDeployCallback implements Deployer.DeployCallback {
681 private final Bundle systemBundle;
682 private final Deployer.DeploymentState dstate;
683 private final AtomicLong nextBundleId = new AtomicLong(0);
685 public DummyDeployCallback(Bundle sysBundle, Collection<Features> repositories) throws Exception {
686 systemBundle = sysBundle;
687 dstate = new Deployer.DeploymentState();
688 dstate.bundles = new HashMap<>();
689 dstate.features = new HashMap<>();
690 dstate.bundlesPerRegion = new HashMap<>();
691 dstate.filtersPerRegion = new HashMap<>();
692 dstate.state = new State();
694 MapUtils.addToMapSet(dstate.bundlesPerRegion, FeaturesService.ROOT_REGION, 0l);
695 dstate.bundles.put(0l, systemBundle);
696 for (Features repo : repositories) {
697 for (Feature f : repo.getFeature()) {
698 dstate.features.put(f.getId(), f);
703 public Deployer.DeploymentState getDeploymentState() {
708 public void print(String message, boolean verbose) {
712 public void saveState(State state) {
713 dstate.state.replace(state);
717 public void persistResolveRequest(Deployer.DeploymentRequest request) throws IOException {
721 public void installFeature(org.apache.karaf.features.Feature feature) throws IOException, InvalidSyntaxException {
725 public void callListeners(FeatureEvent featureEvent) {
729 public Bundle installBundle(String region, String uri, InputStream is) throws BundleException {
731 Hashtable<String, String> headers = new Hashtable<>();
732 ZipInputStream zis = new ZipInputStream(is);
734 while ((entry = zis.getNextEntry()) != null) {
735 if (MANIFEST_NAME.equals(entry.getName())) {
736 Attributes attributes = new Manifest(zis).getMainAttributes();
737 for (Map.Entry attr : attributes.entrySet()) {
738 headers.put(attr.getKey().toString(), attr.getValue().toString());
742 BundleRevision revision = new FakeBundleRevision(headers, uri, nextBundleId.incrementAndGet());
743 Bundle bundle = revision.getBundle();
744 MapUtils.addToMapSet(dstate.bundlesPerRegion, region, bundle.getBundleId());
745 dstate.bundles.put(bundle.getBundleId(), bundle);
747 } catch (IOException e) {
748 throw new BundleException("Unable to install bundle", e);
753 public void updateBundle(Bundle bundle, String uri, InputStream is) throws BundleException {
754 throw new UnsupportedOperationException();
758 public void uninstall(Bundle bundle) throws BundleException {
759 throw new UnsupportedOperationException();
763 public void startBundle(Bundle bundle) throws BundleException {
767 public void stopBundle(Bundle bundle, int options) throws BundleException {
771 public void setBundleStartLevel(Bundle bundle, int startLevel) {
775 public void refreshPackages(Collection<Bundle> bundles) throws InterruptedException {
779 public void resolveBundles(Set<Bundle> bundles, Map<Resource, List<Wire>> wiring, Map<Resource, Bundle> resToBnd) {
783 public void replaceDigraph(Map<String, Map<String, Map<String, Set<String>>>> policies, Map<String, Set<Long>> bundles) throws BundleException, InvalidSyntaxException {
787 public class MavenResolverLog extends org.apache.felix.resolver.Logger {
789 public MavenResolverLog() {
790 super(Logger.LOG_DEBUG);
794 protected void doLog(int level, String msg, Throwable throwable) {
797 getLog().debug(msg, throwable);
800 getLog().info(msg, throwable);
803 getLog().warn(msg, throwable);
806 getLog().error(msg, throwable);