/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIESOR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.aries.application.deployment.management.impl; import static org.apache.aries.application.utils.AppConstants.LOG_ENTRY; import static org.apache.aries.application.utils.AppConstants.LOG_EXIT; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.URL; import java.net.URLConnection; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import java.util.jar.Attributes; import java.util.jar.Manifest; import org.apache.aries.application.ApplicationMetadata; import org.apache.aries.application.Content; import org.apache.aries.application.InvalidAttributeException; import org.apache.aries.application.ServiceDeclaration; import org.apache.aries.application.management.AriesApplication; import org.apache.aries.application.management.BundleInfo; import org.apache.aries.application.management.ResolveConstraint; import org.apache.aries.application.management.ResolverException; import org.apache.aries.application.management.spi.resolve.AriesApplicationResolver; import org.apache.aries.application.management.spi.resolve.DeploymentManifestManager; import org.apache.aries.application.management.spi.resolve.PostResolveTransformer; import org.apache.aries.application.management.spi.resolve.PreResolveHook; import org.apache.aries.application.management.spi.runtime.LocalPlatform; import org.apache.aries.application.modelling.DeployedBundles; import org.apache.aries.application.modelling.ExportedPackage; import org.apache.aries.application.modelling.ExportedService; import org.apache.aries.application.modelling.ImportedBundle; import org.apache.aries.application.modelling.ImportedPackage; import org.apache.aries.application.modelling.ModelledResource; import org.apache.aries.application.modelling.ModelledResourceManager; import org.apache.aries.application.modelling.ModellerException; import org.apache.aries.application.modelling.ModellingManager; import org.apache.aries.application.modelling.utils.ModellingHelper; import org.apache.aries.application.utils.AppConstants; import org.apache.aries.application.utils.manifest.ContentFactory; import org.apache.aries.util.filesystem.FileSystem; import org.apache.aries.util.io.IOUtils; import org.apache.aries.util.manifest.ManifestHeaderProcessor; import org.osgi.framework.Constants; import org.osgi.framework.Filter; import org.osgi.service.blueprint.container.ServiceUnavailableException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class DeploymentManifestManagerImpl implements DeploymentManifestManager { private final Logger _logger = LoggerFactory.getLogger(DeploymentManifestManagerImpl.class); private AriesApplicationResolver resolver; private PostResolveTransformer postResolveTransformer = null; private ModelledResourceManager modelledResourceManager; private LocalPlatform localPlatform; private ModellingManager modellingManager; private ModellingHelper modellingHelper; private List<PreResolveHook> preResolveHooks; public void setModellingManager (ModellingManager m) { modellingManager = m; } public void setModellingHelper (ModellingHelper mh) { modellingHelper = mh; } public LocalPlatform getLocalPlatform() { return localPlatform; } public void setLocalPlatform(LocalPlatform localPlatform) { this.localPlatform = localPlatform; } public void setPreResolveHooks(List<PreResolveHook> hooks) { preResolveHooks = hooks; } public ModelledResourceManager getModelledResourceManager() { return modelledResourceManager; } public void setModelledResourceManager(ModelledResourceManager modelledResourceManager) { this.modelledResourceManager = modelledResourceManager; } public void setPostResolveTransformer(PostResolveTransformer transformer) { postResolveTransformer = transformer; } public void setResolver(AriesApplicationResolver resolver) { this.resolver = resolver; } /** * Perform provisioning to work out the 'freeze dried list' of the eba * @param app - Aries application * @param ResolveConstraint - resolver constraint for limiting the resolving results * @return manifest the generated deployment manifest * @throws ResolverException */ @Override public Manifest generateDeploymentManifest(AriesApplication app, ResolveConstraint... constraints ) throws ResolverException { _logger.debug(LOG_ENTRY, "generateDeploymentManifest", new Object[]{app, constraints}); ApplicationMetadata appMetadata = app.getApplicationMetadata(); Collection<ModelledResource> byValueBundles = null; try { // find out blueprint information byValueBundles = getByValueBundles(app); // find out by value bundles and then by reference bundles } catch (Exception e) { throw new ResolverException (e); } Collection<Content> bundlesToResolve = new ArrayList<Content>(); bundlesToResolve.addAll(appMetadata.getApplicationContents()); bundlesToResolve.addAll(app.getApplicationMetadata().getUseBundles()); //If we pass in provision bundles (e.g. import deployment manifest sanity check), we add them into our bundlesToResolve set. // This is because we want to make sure all bundles we passed into resolver the same as what we are going to get from resolver. List<Content> restrictedReqs = new ArrayList<Content>(); for (ResolveConstraint constraint : constraints ) { Content content = ContentFactory.parseContent(constraint.getBundleName(), constraint.getVersionRange().toString()); restrictedReqs.add(content); } DeployedBundles deployedBundles = generateDeployedBundles (appMetadata, byValueBundles, restrictedReqs); Manifest man = generateDeploymentManifest(appMetadata.getApplicationSymbolicName(), appMetadata.getApplicationVersion().toString(), deployedBundles); _logger.debug(LOG_EXIT, "generateDeploymentManifest", new Object[] {man}); return man; } /** * Perform provisioning to work out the 'freeze dried list' of the eba * @param appContent - the application content in the application.mf * @param useBundleContent - use bundle entry in the application.mf * @param providedByValueBundles - bundles contained in the eba * @return * @throws ResolverException */ @Override public DeployedBundles generateDeployedBundles(ApplicationMetadata appMetadata, Collection<ModelledResource> provideByValueBundles, Collection<Content> otherBundles) throws ResolverException { Collection<Content> useBundleSet = appMetadata.getUseBundles(); Collection<Content> appContent = appMetadata.getApplicationContents(); Collection<Content> bundlesToResolve = new ArrayList<Content>(); Set<ImportedBundle> appContentIB = toImportedBundle(appContent); Set<ImportedBundle> useBundleIB = toImportedBundle(useBundleSet); bundlesToResolve.addAll(useBundleSet); bundlesToResolve.addAll(appContent); bundlesToResolve.addAll(otherBundles); Collection<ModelledResource> byValueBundles = new ArrayList<ModelledResource>(provideByValueBundles); ModelledResource fakeBundleResource; try { fakeBundleResource = createFakeBundle(appMetadata.getApplicationImportServices()); } catch (InvalidAttributeException iax) { ResolverException rx = new ResolverException (iax); _logger.debug(LOG_EXIT, "generateDeploymentManifest", new Object[] {rx}); throw rx; } byValueBundles.add(fakeBundleResource); Collection<ModelledResource> fakeResources = new ArrayList<ModelledResource>(); for (PreResolveHook hook : preResolveHooks) { hook.collectFakeResources(fakeResources); } byValueBundles.addAll(fakeResources); String appSymbolicName = appMetadata.getApplicationSymbolicName(); String appVersion = appMetadata.getApplicationVersion().toString(); String uniqueName = appSymbolicName + "_" + appVersion; DeployedBundles deployedBundles = modellingHelper.createDeployedBundles(appSymbolicName, appContentIB, useBundleIB, Arrays.asList(fakeBundleResource)); Collection<ModelledResource> bundlesToBeProvisioned = resolver.resolve( appSymbolicName, appVersion, byValueBundles, bundlesToResolve); pruneFakeBundlesFromResults (bundlesToBeProvisioned, fakeResources); if (bundlesToBeProvisioned.isEmpty()) { throw new ResolverException(MessageUtil.getMessage("EMPTY_DEPLOYMENT_CONTENT",uniqueName)); } for (ModelledResource rbm : bundlesToBeProvisioned) { deployedBundles.addBundle(rbm); } Collection<ModelledResource> requiredUseBundle = deployedBundles.getRequiredUseBundle(); if (requiredUseBundle.size() < useBundleSet.size()) { // Some of the use-bundle entries were redundant so resolve again with just the good ones. deployedBundles = modellingHelper.createDeployedBundles(appSymbolicName, appContentIB, useBundleIB, Arrays.asList(fakeBundleResource)); bundlesToResolve.clear(); bundlesToResolve.addAll(appContent); Collection<ImportedBundle> slimmedDownUseBundle = narrowUseBundles(useBundleIB, requiredUseBundle); bundlesToResolve.addAll(toContent(slimmedDownUseBundle)); bundlesToBeProvisioned = resolver.resolve(appSymbolicName, appVersion, byValueBundles, bundlesToResolve); pruneFakeBundlesFromResults (bundlesToBeProvisioned, fakeResources); for (ModelledResource rbm : bundlesToBeProvisioned) { deployedBundles.addBundle(rbm); } requiredUseBundle = deployedBundles.getRequiredUseBundle(); } // Check for circular dependencies. No shared bundle can depend on any // isolated bundle. Collection<ModelledResource> sharedBundles = new HashSet<ModelledResource>(); sharedBundles.addAll (deployedBundles.getDeployedProvisionBundle()); sharedBundles.addAll (requiredUseBundle); Collection<ModelledResource> appContentBundles = deployedBundles.getDeployedContent(); Collection<Content> requiredSharedBundles = new ArrayList<Content>(); for (ModelledResource mr : sharedBundles) { String version = mr.getExportedBundle().getVersion(); String exactVersion = "[" + version + "," + version + "]"; Content ib = ContentFactory.parseContent(mr.getExportedBundle().getSymbolicName(), exactVersion); requiredSharedBundles.add(ib); } // This will throw a ResolverException if the shared content does not resolve Collection<ModelledResource> resolvedSharedBundles = resolver.resolve(appSymbolicName, appVersion , byValueBundles, requiredSharedBundles); // we need to find out whether any shared bundles depend on the isolated bundles List<String> suspects = findSuspects (resolvedSharedBundles, sharedBundles, appContentBundles); // If we have differences, it means that we have shared bundles trying to import packages // from isolated bundles. We need to build up the error message and throw a ResolverException if (!suspects.isEmpty()) { StringBuilder msgs = new StringBuilder(); List<String> unsatisfiedRequirements = new ArrayList<String>(); Map<String, List<String>> isolatedBundles = new HashMap<String, List<String>>(); // Find the isolated bundles and store all the packages that they export in a map. for (ModelledResource mr : resolvedSharedBundles) { String mrName = mr.getSymbolicName() + "_" + mr.getExportedBundle().getVersion(); if (suspects.contains(mrName)) { List<String> exportedPackages = new ArrayList<String>(); isolatedBundles.put(mrName, exportedPackages); for (ExportedPackage ep : mr.getExportedPackages()) { exportedPackages.add(ep.getPackageName()); } } } // Now loop through the shared bundles, reading the imported packages, and find which ones // are exported from the isolated bundles. for (ModelledResource mr : resolvedSharedBundles) { String mrName = mr.getSymbolicName() + "_" + mr.getExportedBundle().getVersion(); // if current resource isn't an isolated bundle check it's requirements if (!!! suspects.contains(mrName)) { // Iterate through the imported packages of the current shared bundle. for (ImportedPackage ip : mr.getImportedPackages()) { String packageName = ip.getPackageName(); List<String> bundlesExportingPackage = new ArrayList<String>(); // Loop through each exported package of each isolated bundle, and if we // get a match store the info away. for (Map.Entry<String, List<String>> currBundle : isolatedBundles.entrySet()) { List<String> exportedPackages = currBundle.getValue(); if (exportedPackages != null && exportedPackages.contains(packageName)) { bundlesExportingPackage.add(currBundle.getKey()); } } // If we have found at least one matching entry, we construct the sub message for the // exception. if (!!! bundlesExportingPackage.isEmpty()) { String newMsg; if (bundlesExportingPackage.size() > 1) { newMsg = MessageUtil.getMessage("SHARED_BUNDLE_IMPORTING_FROM_ISOLATED_BUNDLES", new Object[] {mrName, packageName, bundlesExportingPackage}); } else { newMsg = MessageUtil.getMessage("SHARED_BUNDLE_IMPORTING_FROM_ISOLATED_BUNDLE", new Object[] {mrName, packageName, bundlesExportingPackage}); } msgs.append("\n"); msgs.append(newMsg); unsatisfiedRequirements.add(newMsg); } } } } // Once we have iterated over all bundles and have got our translated submessages, // throw the exception. // Well! if the msgs is empty, no need to throw an exception if (msgs.length() !=0) { String message = MessageUtil.getMessage( "SUSPECTED_CIRCULAR_DEPENDENCIES", new Object[] {appSymbolicName, msgs}); ResolverException rx = new ResolverException (message); rx.setUnsatisfiedRequirements(unsatisfiedRequirements); _logger.debug(LOG_EXIT, "generateDeploymentManifest", new Object[] {rx}); throw (rx); } } checkForIsolatedContentInProvisionBundle(appSymbolicName, deployedBundles); if (postResolveTransformer != null) try { deployedBundles = postResolveTransformer.postResolveProcess (appMetadata, deployedBundles); } catch (ServiceUnavailableException e) { _logger.debug(MessageUtil.getMessage("POST_RESOLVE_TRANSFORMER_UNAVAILABLE",e)); } return deployedBundles; } @Override public Manifest generateDeploymentManifest(String appSymbolicName, String appVersion, DeployedBundles deployedBundles) throws ResolverException { _logger.debug (LOG_ENTRY, "generateDeploymentManifest", new Object[]{appSymbolicName, appVersion, deployedBundles}); Map<String, String> deploymentManifestMap = generateDeploymentAttributes(appSymbolicName, appVersion, deployedBundles); Manifest man = convertMapToManifest(deploymentManifestMap); _logger.debug (LOG_EXIT, "generateDeploymentManifest", man); return man; } /** * Returns a Collection of the {@link ImportedBundle} objects that are * satisfied by the contents of the Collection of requiredUseBundles. * * @param useBundleSet * @param requiredUseBundle * @return the collection of ImportedBundle objects */ private Collection<ImportedBundle> narrowUseBundles( Collection<ImportedBundle> useBundleSet, Collection<ModelledResource> requiredUseBundle) { _logger.debug(LOG_ENTRY, "narrowUseBundles", new Object[] {useBundleSet,requiredUseBundle}); Collection<ImportedBundle> result = new HashSet<ImportedBundle>(); outer : for(ImportedBundle ib : useBundleSet) { for(ModelledResource mb : requiredUseBundle) { if(ib.isSatisfied(mb.getExportedBundle())) { result.add(ib); continue outer; } } } _logger.debug(LOG_EXIT, "narrowUseBundles", result); return result; } private Map<String,String> generateDeploymentAttributes(String appSymbolicName, String version, DeployedBundles deployedBundles) throws ResolverException { _logger.debug(LOG_ENTRY, "generateDeploymentAttributes", new Object[] {appSymbolicName, version}); Map<String,String> result = new HashMap<String, String>(); String content = deployedBundles.getContent(); if (!content.isEmpty()) { result.put(AppConstants.DEPLOYMENT_CONTENT, content); } else { throw new ResolverException(MessageUtil.getMessage("EMPTY_DEPLOYMENT_CONTENT", appSymbolicName)); } String useBundle = deployedBundles.getUseBundle(); if (!useBundle.isEmpty()) { result.put(AppConstants.DEPLOYMENT_USE_BUNDLE, useBundle); } String provisionBundle = deployedBundles.getProvisionBundle(); if (!provisionBundle.isEmpty()) { result.put(AppConstants.DEPLOYMENT_PROVISION_BUNDLE, provisionBundle); } String importServices = deployedBundles.getDeployedImportService(); if (!importServices.isEmpty()) { result.put(AppConstants.DEPLOYMENTSERVICE_IMPORT, importServices); } String importPackages = deployedBundles.getImportPackage(); if (!importPackages.isEmpty()) { result.put(Constants.IMPORT_PACKAGE, importPackages); } result.put(AppConstants.APPLICATION_VERSION, version); result.put(AppConstants.APPLICATION_SYMBOLIC_NAME, appSymbolicName); result.putAll(deployedBundles.getExtraHeaders()); _logger.debug(LOG_EXIT, "generateDeploymentAttributes", result); return result; } private Manifest convertMapToManifest(Map<String,String> attributes) { _logger.debug(LOG_ENTRY, "convertMapToManifest", new Object[]{attributes}); Manifest man = new Manifest(); Attributes att = man.getMainAttributes(); att.putValue(Attributes.Name.MANIFEST_VERSION.toString(), AppConstants.MANIFEST_VERSION); for (Map.Entry<String, String> entry : attributes.entrySet()) { att.putValue(entry.getKey(), entry.getValue()); } _logger.debug(LOG_EXIT, "convertMapToManifest", new Object[]{man}); return man; } private static final String FAKE_BUNDLE_NAME = "aries.internal.fake.service.bundle"; // create a 'mock' bundle that does nothing but export services required by // Application-ImportService private ModelledResource createFakeBundle (Collection<ServiceDeclaration> appImportServices) throws InvalidAttributeException { _logger.debug(LOG_ENTRY, "createFakeBundle", new Object[]{appImportServices}); Attributes attrs = new Attributes(); attrs.putValue(Constants.BUNDLE_SYMBOLICNAME, FAKE_BUNDLE_NAME); attrs.putValue(Constants.BUNDLE_VERSION_ATTRIBUTE, "1.0"); attrs.putValue(Constants.BUNDLE_MANIFESTVERSION, "2"); // Build an ExportedService for every Application-ImportService entry Collection<ExportedService> exportedServices = new ArrayList<ExportedService>(); for (ServiceDeclaration sDec : appImportServices) { Collection<String> ifaces = Arrays.asList(sDec.getInterfaceName()); Filter filter = sDec.getFilter(); Map<String, String> serviceProperties; if (filter != null) { serviceProperties = ManifestHeaderProcessor.parseFilter(filter.toString()); } else { serviceProperties = new HashMap<String, String>(); } serviceProperties.put("service.imported", ""); exportedServices.add (modellingManager.getExportedService("", 0, ifaces, new HashMap<String, Object>(serviceProperties))); } ModelledResource fakeBundle = modellingManager.getModelledResource(null, attrs, null, exportedServices); _logger.debug(LOG_EXIT, "createFakeBundle", new Object[]{fakeBundle}); return fakeBundle; } private void pruneFakeBundlesFromResults (Collection<ModelledResource> results, Collection<ModelledResource> fakeResources) { _logger.debug(LOG_ENTRY, "pruneFakeBundleFromResults", new Object[]{results}); List<String> fakeBundles = new ArrayList<String>(); fakeBundles.add(FAKE_BUNDLE_NAME); for (ModelledResource resource : fakeResources) { fakeBundles.add(resource.getSymbolicName()); } Iterator<ModelledResource> it = results.iterator(); while (it.hasNext()) { ModelledResource mr = it.next(); if (fakeBundles.contains(mr.getSymbolicName())) { it.remove(); } } _logger.debug(LOG_EXIT, "pruneFakeBundleFromResults"); } /** * We've done a sanity check resolve on our sharedBundles and received back * resolvedSharedBundles. The resolvedSharedBundles should not contain any bundles listed in the isolated bundle list. * If this is not true, we've found a case of shared bundles depending on isolated bundles. * This method extracts the name_versions of those bundles in resolvedSharedBundles * that do not appear in sharedBundles. * @param resolvedSharedBundles What we got back from the resolver * @param sharedBundles What we expected to get back from the resolver * @param appContentBundles The isolated bundles * @return The isolated bundles depended by the shared bundles */ private List<String> findSuspects (Collection<ModelledResource> resolvedSharedBundles, Collection<ModelledResource> sharedBundles, Collection<ModelledResource> appContentBundles){ _logger.debug(LOG_ENTRY, "findSuspects", new Object[]{resolvedSharedBundles,sharedBundles, appContentBundles }); Set<String> expectedBundles = new HashSet<String>(); Set<String> isolatedBundles = new HashSet<String>(); for (ModelledResource sb : sharedBundles) { expectedBundles.add(sb.getExportedBundle().getSymbolicName() + "_" + sb.getExportedBundle().getVersion()); } for (ModelledResource sb : appContentBundles) { isolatedBundles.add(sb.getExportedBundle().getSymbolicName() + "_" + sb.getExportedBundle().getVersion()); } List<String> suspects = new ArrayList<String>(); for (ModelledResource mr : resolvedSharedBundles) { String thisBundle = mr.getExportedBundle().getSymbolicName() + "_" + mr.getExportedBundle().getVersion(); if (!expectedBundles.contains(thisBundle) && (isolatedBundles.contains(thisBundle))) { suspects.add(thisBundle); } } _logger.debug(LOG_EXIT, "findSuspects", new Object[]{suspects}); return suspects; } /** * Check whether there are isolated bundles deployed into both deployed content and provision bundles. This almost * always indicates a resolution problem hence we throw a ResolverException. * Note that we check provision bundles rather than provision bundles and deployed use bundles. So in any corner case * where the rejected deployment is actually intended, it can still be achieved by introducing a use bundle clause. * * @param applicationSymbolicName * @param appContentBundles * @param provisionBundles * @throws ResolverException */ private void checkForIsolatedContentInProvisionBundle(String applicationSymbolicName, DeployedBundles db) throws ResolverException { for (ModelledResource isolatedBundle : db.getDeployedContent()) { for (ModelledResource provisionBundle : db.getDeployedProvisionBundle()) { if (isolatedBundle.getSymbolicName().equals(provisionBundle.getSymbolicName()) && providesPackage(provisionBundle, db.getImportPackage())) { throw new ResolverException( MessageUtil.getMessage("ISOLATED_CONTENT_PROVISIONED", applicationSymbolicName, isolatedBundle.getSymbolicName(), isolatedBundle.getVersion(), provisionBundle.getVersion())); } } } } /** * Can the modelled resource provide a package against the given import specificiation * @param bundle * @param importPackages * @return */ private boolean providesPackage(ModelledResource bundle, String importPackages) { Map<String, Map<String, String>> imports = ManifestHeaderProcessor.parseImportString(importPackages); try { for (Map.Entry<String, Map<String,String>> e : imports.entrySet()) { ImportedPackage importPackage = modellingManager.getImportedPackage(e.getKey(), e.getValue()); for (ExportedPackage export : bundle.getExportedPackages()) { if (importPackage.isSatisfied(export)) return true; } } } catch (InvalidAttributeException iae) { _logger.error(MessageUtil.getMessage("UNEXPECTED_EXCEPTION_PARSING_IMPORTS", iae, importPackages), iae); } return false; } /** * Covert a collection of contents to a collection of ImportedBundle objects * @param content a collection of content * @return a collection of ImportedBundle objects * @throws ResolverException */ private Set<ImportedBundle> toImportedBundle(Collection<Content> content) throws ResolverException { _logger.debug(LOG_ENTRY, "toImportedBundle", new Object[]{content}); Set<ImportedBundle> result = new HashSet<ImportedBundle>(); for (Content c : content) { try { result.add(modellingManager.getImportedBundle(c.getContentName(), c.getVersion().toString())); } catch (InvalidAttributeException iax) { ResolverException rx = new ResolverException (iax); _logger.debug(LOG_EXIT, "toImportedBundle", new Object[]{rx}); throw rx; } } _logger.debug(LOG_EXIT, "toImportedBundle", new Object[]{result}); return result; } private Collection<Content> toContent(Collection<ImportedBundle> ibs) { Collection<Content> contents = new ArrayList<Content>(); for (ImportedBundle ib : ibs) { contents.add(ContentFactory.parseContent(ib.getSymbolicName(), ib.getVersionRange())); } return contents; } /** * Get a list of bundles included by value in this application. * @param app The Aries Application * @return a list of by value bundles * @throws IOException * @throws InvalidAttributeException * @throws ModellerException */ private Collection<ModelledResource> getByValueBundles(AriesApplication app) throws IOException, InvalidAttributeException, ModellerException { _logger.debug(LOG_ENTRY, "getByValueBundles", new Object[]{app}); Collection<BundleInfo> bundles = app.getBundleInfo(); Collection<ModelledResource> result = new ArrayList<ModelledResource>(); for (BundleInfo bundleInfo: bundles) { // find out the eba directory String bundleLocation = bundleInfo.getLocation(); String bundleFileName = bundleLocation.substring(bundleLocation.lastIndexOf('/') + 1); // just the portion of root directory excluding ! URL jarUrl = new URL(bundleLocation); URLConnection jarCon = jarUrl.openConnection(); jarCon.connect(); InputStream in = jarCon.getInputStream(); File dir = getLocalPlatform().getTemporaryDirectory(); File temp = new File(dir, bundleFileName); OutputStream out = new FileOutputStream(temp); IOUtils.copy(in, out); IOUtils.close(out); result.add(modelledResourceManager.getModelledResource(null, FileSystem.getFSRoot(temp))); // delete the temp file temp.delete(); IOUtils.deleteRecursive(dir); } _logger.debug(LOG_EXIT, "getByValueBundles", new Object[]{result}); return result; } }