aries-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From z..@apache.org
Subject svn commit: r1075132 [12/18] - in /aries/tags/application-0.3: ./ application-api/ application-api/src/ application-api/src/main/ application-api/src/main/java/ application-api/src/main/java/org/ application-api/src/main/java/org/apache/ application-ap...
Date Sun, 27 Feb 2011 20:20:30 GMT
Added: aries/tags/application-0.3/application-obr-resolver/src/main/java/org/apache/aries/application/resolver/obr/OBRAriesResolver.java
URL: http://svn.apache.org/viewvc/aries/tags/application-0.3/application-obr-resolver/src/main/java/org/apache/aries/application/resolver/obr/OBRAriesResolver.java?rev=1075132&view=auto
==============================================================================
--- aries/tags/application-0.3/application-obr-resolver/src/main/java/org/apache/aries/application/resolver/obr/OBRAriesResolver.java (added)
+++ aries/tags/application-0.3/application-obr-resolver/src/main/java/org/apache/aries/application/resolver/obr/OBRAriesResolver.java Sun Feb 27 20:20:13 2011
@@ -0,0 +1,712 @@
+/*
+ * 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 WARRANTIES OR 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.resolver.obr;
+
+import static org.apache.aries.application.utils.AppConstants.LOG_ENTRY;
+import static org.apache.aries.application.utils.AppConstants.LOG_EXIT;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.aries.application.ApplicationMetadata;
+import org.apache.aries.application.Content;
+import org.apache.aries.application.InvalidAttributeException;
+import org.apache.aries.application.VersionRange;
+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.repository.PlatformRepository;
+import org.apache.aries.application.management.spi.resolve.AriesApplicationResolver;
+import org.apache.aries.application.modelling.ImportedBundle;
+import org.apache.aries.application.modelling.ModelledResource;
+import org.apache.aries.application.modelling.ModellingConstants;
+import org.apache.aries.application.modelling.ModellingManager;
+import org.apache.aries.application.modelling.utils.ModellingHelper;
+import org.apache.aries.application.resolver.internal.MessageUtil;
+import org.apache.aries.application.resolver.obr.impl.ApplicationResourceImpl;
+import org.apache.aries.application.resolver.obr.impl.ModelledBundleResource;
+import org.apache.aries.application.resolver.obr.impl.OBRBundleInfo;
+import org.apache.aries.application.resolver.obr.impl.RepositoryGeneratorImpl;
+import org.apache.aries.application.resolver.obr.impl.ResourceWrapper;
+import org.apache.aries.application.utils.AppConstants;
+import org.apache.aries.application.utils.filesystem.IOUtils;
+import org.apache.aries.application.utils.manifest.ManifestHeaderProcessor;
+import org.apache.aries.application.utils.manifest.ManifestHeaderProcessor.NameValueMap;
+import org.apache.felix.bundlerepository.Capability;
+import org.apache.felix.bundlerepository.DataModelHelper;
+import org.apache.felix.bundlerepository.Reason;
+import org.apache.felix.bundlerepository.Repository;
+import org.apache.felix.bundlerepository.RepositoryAdmin;
+import org.apache.felix.bundlerepository.Requirement;
+import org.apache.felix.bundlerepository.Resolver;
+import org.apache.felix.bundlerepository.Resource;
+import org.osgi.framework.Constants;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.Version;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @version $Rev: 1059320 $ $Date: 2011-01-15 12:58:13 +0000 (Sat, 15 Jan 2011) $
+ */
+public class OBRAriesResolver implements AriesApplicationResolver
+{
+  private static Logger log = LoggerFactory.getLogger(OBRAriesResolver.class);
+
+  private final RepositoryAdmin repositoryAdmin;  
+  private boolean returnOptionalResources = true;
+  private PlatformRepository platformRepository;
+  private ModellingManager modellingManager;
+  private ModellingHelper modellingHelper;
+  
+  public void setModellingManager (ModellingManager m) { 
+    modellingManager = m;
+  }
+  
+  public void setModellingHelper (ModellingHelper mh) { 
+    modellingHelper = mh;
+  }
+  
+  public PlatformRepository getPlatformRepository()
+  {
+    return platformRepository;
+  }
+
+ 
+  
+  public  RepositoryAdmin getRepositoryAdmin() {
+    return this.repositoryAdmin;
+  }
+  public void setPlatformRepository(PlatformRepository platformRepository)
+  {
+    this.platformRepository = platformRepository;
+  }
+
+  public OBRAriesResolver(RepositoryAdmin repositoryAdmin)
+  {
+    this.repositoryAdmin = repositoryAdmin;
+  }
+
+  public void setReturnOptionalResources(boolean optional) 
+  {
+    this.returnOptionalResources = optional;
+  }
+  
+  public boolean getReturnOptionalResources() 
+  {
+    return returnOptionalResources;
+  }
+  
+	public Collection<ModelledResource> resolve(String appName,
+			String appVersion, Collection<ModelledResource> byValueBundles,
+			Collection<Content> inputs) throws ResolverException {
+		return resolve(appName, appVersion, byValueBundles,
+				inputs, this.platformRepository);
+	}
+
+/**
+   * Resolve a list of resources from the OBR bundle repositories by OBR
+   * resolver.
+   * 
+   * @param appName - application name
+   * @param appVersion - application version
+   * @param byValueBundles - by value bundles
+   * @param inputs - other constraints
+   * @param platformRepository - a platform repository to use instead of the one provided as a service
+   * @return a collection of modelled resources required by this application
+   * @throws ResolverException
+   */
+  @Override
+  public Collection<ModelledResource> resolve(String appName, String appVersion,
+			Collection<ModelledResource> byValueBundles, Collection<Content> inputs, PlatformRepository platformRepository)
+			throws ResolverException {
+     log.debug(LOG_ENTRY, "resolve", new Object[]{appName, appVersion,byValueBundles, inputs});
+    Collection<ImportedBundle> importedBundles = toImportedBundle(inputs);
+    Collection<ModelledResource> toReturn = new ArrayList<ModelledResource>();
+    
+    Resolver obrResolver = getConfiguredObrResolver(appName, appVersion, byValueBundles, platformRepository);
+    // add a resource describing the requirements of the application metadata.
+    obrResolver.add(createApplicationResource( appName, appVersion, importedBundles));
+    
+    if (obrResolver.resolve()) {
+      
+      List<Resource> requiredResources = retrieveRequiredResources(obrResolver);
+
+      if (requiredResources == null) {
+        log.debug("resolver.getRequiredResources() returned null");
+      } else {
+
+        for (Resource r : requiredResources) {
+          NameValueMap<String, String> attribs = new NameValueMap<String, String>();
+          attribs.put(Constants.VERSION_ATTRIBUTE, "[" + r.getVersion() + ',' + r.getVersion()
+              + "]");
+          ModelledResource modelledResourceForThisMatch = null; 
+          // OBR may give us back the global capabilities. Typically these do not have a bundle symbolic name - they're a 
+          // list of packages available in the target runtime environment. If the resource has no symbolic name, we can ignore it
+          if (r.getSymbolicName() != null) { 
+            try { 
+              modelledResourceForThisMatch = new ModelledBundleResource (r, modellingManager, modellingHelper);
+            } catch (InvalidAttributeException iax) { 
+              
+              ResolverException re = new ResolverException("Internal error occurred: " + iax.toString());
+              log.debug(LOG_EXIT, "resolve", re);
+              
+              throw re;
+            }
+            toReturn.add(modelledResourceForThisMatch);
+          }
+        }
+      }
+      log.debug(LOG_EXIT, "resolve", toReturn); 
+      return toReturn;
+    } else {
+      Reason[] reasons = obrResolver.getUnsatisfiedRequirements();
+      // let's refine the list by removing the indirect unsatisfied bundles that are caused by unsatisfied packages or other bundles
+      Map<String,Set<String>> refinedReqs = refineUnsatisfiedRequirements(obrResolver, reasons);
+      StringBuffer reqList = new StringBuffer();
+      List<String> unsatisfiedRequirements = new LinkedList<String>();
+
+      for (Map.Entry<String, Set<String>> filterEntry : refinedReqs.entrySet()) {
+        log.debug("unable to satisfy the filter , filter = " + filterEntry.getKey() + "required by "+filterEntry.getValue());
+       
+        String reason = extractConsumableMessageInfo(filterEntry.getKey(),filterEntry.getValue());
+
+        reqList.append('\n');
+        reqList.append(reason);
+        unsatisfiedRequirements.add(reason);
+      }
+
+      ResolverException re = new ResolverException(MessageUtil.getMessage("RESOLVER_UNABLE_TO_RESOLVE", 
+          new Object[] { appName, reqList }));
+      re.setUnsatisfiedRequirements(unsatisfiedRequirements);
+      log.debug(LOG_EXIT, "resolve", re);
+      
+      throw re;
+    }
+    
+  }
+
+  private Resolver getConfiguredObrResolver(String appName, String appVersion,
+	      Collection<ModelledResource> byValueBundles) throws ResolverException
+	      {
+	 
+	  return getConfiguredObrResolver(appName, appVersion, byValueBundles, platformRepository);
+	      }
+
+  private Resolver getConfiguredObrResolver(String appName, String appVersion,
+      Collection<ModelledResource> byValueBundles, PlatformRepository platformRepository) throws ResolverException
+  {
+    log.debug(LOG_ENTRY, "getConfiguredObrResolver", new Object[]{appName, appVersion,byValueBundles });
+    DataModelHelper helper = repositoryAdmin.getHelper();
+    Repository appRepo;
+    try {      
+      ByteArrayOutputStream bytesOut = new ByteArrayOutputStream();
+      RepositoryGeneratorImpl.generateRepository(repositoryAdmin, appName + "_" + appVersion, byValueBundles, bytesOut);
+      appRepo = helper.readRepository(new InputStreamReader(new ByteArrayInputStream(bytesOut.toByteArray())));
+    } catch (Exception e) {
+      throw new ResolverException(e);
+    } 
+        
+    List<Repository> resolveRepos = new ArrayList<Repository>();
+    // add system repository
+    resolveRepos.add(repositoryAdmin.getSystemRepository());
+    // add local repository if configured
+    if (!(excludeLocalRuntime())) {
+      resolveRepos.add(getLocalRepository(repositoryAdmin));
+    }
+    // add application repository
+    resolveRepos.add(appRepo);
+    // Need to refresh the repositories added to repository admin 
+    // add user-defined repositories
+    Repository[] repos = repositoryAdmin.listRepositories();
+    for (Repository r : repos) {
+      resolveRepos.add(r);      
+    }     
+    Resolver obrResolver = repositoryAdmin.resolver(resolveRepos.toArray(new Repository[resolveRepos.size()]));
+    addPlatformRepositories (obrResolver, appName, platformRepository);
+    log.debug(LOG_EXIT, "getConfiguredObrResolver", obrResolver);
+    return obrResolver;
+  }
+ 
+  
+  @Deprecated
+  @Override
+  public Set<BundleInfo> resolve(AriesApplication app, ResolveConstraint... constraints) throws ResolverException
+  {
+    log.trace("resolving {}", app);
+    ApplicationMetadata appMeta = app.getApplicationMetadata();
+
+    String appName = appMeta.getApplicationSymbolicName();
+    Version appVersion = appMeta.getApplicationVersion();
+    List<Content> appContent = appMeta.getApplicationContents();
+
+    Collection<Content> useBundleContent = appMeta.getUseBundles();
+    List<Content> contents = new ArrayList<Content>();
+    contents.addAll(appContent);
+    contents.addAll(useBundleContent);
+    if ((constraints != null ) && (constraints.length > 0 )) {
+      for (ResolveConstraint con: constraints) {
+        contents.add(ManifestHeaderProcessor.parseContent(con.getBundleName(), con.getVersionRange().toString()));
+      }
+    }
+
+    Resolver obrResolver = getConfiguredObrResolver(appName, appVersion.toString(), toModelledResource(app.getBundleInfo()));
+    // add a resource describing the requirements of the application metadata.
+    obrResolver.add(createApplicationResource( appName, appVersion, contents));
+    if (obrResolver.resolve()) {
+     Set<BundleInfo> result = new HashSet<BundleInfo>();
+      List<Resource> requiredResources = retrieveRequiredResources(obrResolver);
+      
+      for (Resource resource: requiredResources) {
+        BundleInfo bundleInfo = toBundleInfo(resource, false);
+        result.add(bundleInfo);
+      }
+      if (returnOptionalResources) {
+        for (Resource resource: obrResolver.getOptionalResources()) {
+          BundleInfo bundleInfo = toBundleInfo(resource, true);
+          result.add(bundleInfo);
+        }
+      }
+            
+      return result;
+    } else {
+      Reason[] reasons = obrResolver.getUnsatisfiedRequirements();
+      //refine the list by removing the indirect unsatisfied bundles that are caused by unsatisfied packages or other bundles
+      Map<String,Set<String>> refinedReqs = refineUnsatisfiedRequirements(obrResolver, reasons);
+      StringBuffer reqList = new StringBuffer();
+      List<String> unsatisfiedRequirements = new LinkedList<String>();
+
+      for (Map.Entry<String, Set<String>> filterEntry : refinedReqs.entrySet()) {
+        log.debug("unable to satisfied the filter , filter = " + filterEntry.getKey() + "required by "+filterEntry.getValue());
+       
+        String reason = extractConsumableMessageInfo(filterEntry.getKey(),filterEntry.getValue());
+
+        reqList.append('\n');
+        reqList.append(reason);
+        unsatisfiedRequirements.add(reason);
+      }
+
+      ResolverException re = new ResolverException(MessageUtil.getMessage("RESOLVER_UNABLE_TO_RESOLVE", 
+          new Object[] { app.getApplicationMetadata().getApplicationName(), reqList }));
+      re.setUnsatisfiedRequirements(unsatisfiedRequirements);
+      log.debug(LOG_EXIT, "resolve", re);
+      
+      throw re;
+    }
+  }
+
+  
+  
+  @Override
+  public BundleInfo getBundleInfo(String bundleSymbolicName, Version bundleVersion)
+  {
+    Map<String, String> attribs = new HashMap<String, String>();
+    attribs.put(Resource.VERSION, bundleVersion.toString());
+    String filterString = ManifestHeaderProcessor.generateFilter(Resource.SYMBOLIC_NAME, bundleSymbolicName, attribs);
+    Resource[] resources;
+    try {
+      resources = repositoryAdmin.discoverResources(filterString);
+      if (resources != null && resources.length > 0) {
+        return toBundleInfo(resources[0], false);
+      } else {
+        return null;
+      }
+    } catch (InvalidSyntaxException e) {
+      log.error("Invalid filter", e);
+      return null;
+    }
+  }
+
+  /* A 'platform repository' describes capabilities of the target runtime environment
+   * These should be added to the resolver without being listed as coming from a particular 
+   * repository or bundle.  
+   */
+  private void addPlatformRepositories (Resolver obrResolver, String appName, PlatformRepository platformRepository)
+  { 
+    log.debug(LOG_ENTRY, "addPlatformRepositories", new Object[]{obrResolver, appName});
+    DataModelHelper helper = repositoryAdmin.getHelper();
+    if (platformRepository != null) {
+      Collection<URI> uris = platformRepository.getPlatformRepositoryURLs();
+      if ((uris != null) && (!uris.isEmpty())) {
+        for (URI uri : uris) {
+          InputStream is = null;
+          try {
+            is = uri.toURL().openStream();
+            Reader repoReader = new InputStreamReader(is);
+            Repository aPlatformRepo = helper.readRepository(repoReader);
+            Resource resources[] = aPlatformRepo.getResources();
+            for (Resource r : resources) { 
+              Capability[] caps = r.getCapabilities();
+              for (Capability c : caps) { 
+                obrResolver.addGlobalCapability(c);
+              }
+            }
+          } catch (Exception e) {
+            // not a big problem
+            log.error(MessageUtil.getMessage("RESOLVER_UNABLE_TO_READ_REPOSITORY_EXCEPTION", new Object[]{appName, uri}) );
+          } finally { 
+            IOUtils.close(is);
+          }
+        }
+      }
+    }
+    log.debug(LOG_EXIT, "addPlatformRepositories");
+  }
+  
+  private Resource createApplicationResource( String appName, Version appVersion,
+      List<Content> appContent)
+  {
+    return new ApplicationResourceImpl(appName, appVersion, appContent);
+  }
+  
+  private Resource createApplicationResource( String appName, String appVersion,
+      Collection<ImportedBundle> inputs)
+  {
+    return new ApplicationResourceImpl(appName, Version.parseVersion(appVersion), inputs);
+  }
+  
+  private BundleInfo toBundleInfo(Resource resource, boolean optional) 
+  {
+    Map<String, String> directives = null;
+    if (optional) {
+      directives = new HashMap<String, String>();
+      directives.put(Constants.RESOLUTION_DIRECTIVE, Constants.RESOLUTION_OPTIONAL);
+    }
+    
+
+    return new OBRBundleInfo(resource.getSymbolicName(),
+                             resource.getVersion(),
+                             resource.getURI(),
+                             null,
+                             null,
+                             null,
+                             null,
+                             null, 
+                             null,
+                             directives,
+                             null);
+    
+  }
+  
+  /**
+   * Get the list of resources returned by the resolver
+   * @param resolver OBR resolver
+   * @return a list of required resources
+   */
+  protected List<Resource> retrieveRequiredResources(Resolver resolver)
+  {
+    log.debug(LOG_ENTRY,"retrieveRequiredResources", resolver);
+    Map<String, List<Resource>> resourcesByName = new HashMap<String, List<Resource>>();
+
+    for (Resource r : resolver.getRequiredResources()) {
+      resourcesByName.put(r.getSymbolicName(), mergeResource(resolver, r, resourcesByName.get(r
+          .getSymbolicName())));
+    }
+
+    List<Resource> result = new ArrayList<Resource>();
+    for (List<Resource> res : resourcesByName.values()) {
+      result.addAll(res);
+    }
+
+    log.debug(LOG_EXIT,  "retrieveRequiredResources", result);
+    return result;
+  }
+
+  
+/**
+ * Get rid of the redundant resources
+ * @param resolver OBR resolver
+ * @param r a resource
+ * @param list similar resources
+ * @return the list of minimum resources
+ */
+  protected List<Resource> mergeResource(Resolver resolver, Resource r,
+      List<Resource> list)
+  {
+    log.debug(LOG_ENTRY, "mergeResource", new Object[]{resolver, r, list});
+    
+    if (list == null) {
+      log.debug(LOG_EXIT, "mergeResource", Arrays.asList(r));
+      return Arrays.asList(r);
+    } else {
+      List<Resource> result = new ArrayList<Resource>();
+
+      for (Resource old : list) {
+        boolean oldRedundant = satisfiesAll(r, resolver.getReason(old));
+        boolean newRedundant = satisfiesAll(old, resolver.getReason(r));
+        if (oldRedundant && newRedundant) {
+          int comp = old.getVersion().compareTo(r.getVersion());
+          oldRedundant = comp < 0;
+          newRedundant = comp >= 0;
+        }
+        
+        if (newRedundant) {
+          log.debug(LOG_EXIT, "mergeResource", list);
+          return list;
+        } else if (oldRedundant) {
+          // do nothing -> so don't add the old resource to the new list
+        } else {
+          result.add(old);
+        }
+      }
+
+      result.add(r);
+
+      log.debug(LOG_EXIT, "mergeResource", result);
+      
+      return result;
+    }
+  }
+  protected boolean satisfiesAll(Resource res, Reason[] reasons)
+  {
+    log.debug(LOG_ENTRY,"satisfiesAll", new Object[] {res, Arrays.toString(reasons)});
+    //Let's convert the reason to requirement
+    List<Requirement> reqs = new ArrayList<Requirement>();
+    for (Reason reason : reasons) {
+      reqs.add(reason.getRequirement());
+    }
+    boolean result = true;
+    
+    outer: for (Requirement r : reqs) {
+      boolean found = false;
+      inner: for (Capability c : res.getCapabilities()) {
+        if (r.isSatisfied(c)) {
+          found = true;
+          break inner;
+        }
+      }
+      
+      if (!!!found && !!!r.isOptional()) {
+        result = false;
+        break outer;
+      }
+    }
+    log.debug(LOG_EXIT, "satisfiesAll", result);
+    return result;
+  }
+
+  private static final Set<String> SPECIAL_FILTER_ATTRS = Collections
+  .unmodifiableSet(new HashSet<String>(Arrays.asList(ModellingConstants.OBR_PACKAGE,
+      ModellingConstants.OBR_SYMBOLIC_NAME, ModellingConstants.OBR_SERVICE, Constants.VERSION_ATTRIBUTE)));
+
+  /**
+   * Turn a requirement into a human readable String for debug.
+   * @param filter The filter that is failing
+   * @param bundlesFailing For problems with a bundle, the set of bundles that have a problem
+   * @return human readable form
+   */
+  private String extractConsumableMessageInfo(String filter, Set<String> bundlesFailing)
+  {
+    log.debug(LOG_ENTRY, "extractConsumableMessageInfo", new Object[] {filter, bundlesFailing});
+    
+    Map<String, String> attrs = ManifestHeaderProcessor.parseFilter(filter);
+    Map<String, String> customAttrs = new HashMap<String, String>();
+    for (Map.Entry<String, String> e : attrs.entrySet()) {
+      if (!SPECIAL_FILTER_ATTRS.contains(e.getKey())) {
+        customAttrs.put(e.getKey(), e.getValue());
+      }
+    }
+
+    StringBuilder msgKey = new StringBuilder();
+    List<Object> inserts = new ArrayList<Object>();
+
+    boolean unknownType = false;
+    if (attrs.containsKey(ModellingConstants.OBR_PACKAGE)) {
+      msgKey.append("RESOLVER_UNABLE_TO_RESOLVE_PACKAGE");
+      inserts.add(attrs.get(ModellingConstants.OBR_PACKAGE));
+    } else if (attrs.containsKey(ModellingConstants.OBR_SYMBOLIC_NAME)) {
+      msgKey.append("RESOLVER_UNABLE_TO_RESOLVE_BUNDLE");
+      inserts.add(attrs.get(ModellingConstants.OBR_SYMBOLIC_NAME));
+    } else if (attrs.containsKey(ModellingConstants.OBR_SERVICE)) {
+      msgKey.append("RESOLVER_UNABLE_TO_RESOLVE_SERVICE");
+      //No insert for service name as the name must be "*" to match any Service capability
+    } else {
+      unknownType = true;
+      msgKey.append("RESOLVER_UNABLE_TO_RESOLVE_FILTER");
+      inserts.add(filter);
+    }
+
+    if (bundlesFailing != null && bundlesFailing.size() != 0) {
+      msgKey.append("_REQUIRED_BY_BUNDLE");
+      if (bundlesFailing.size() == 1)
+        inserts.add(bundlesFailing.iterator().next()); // Just take the string if there's only one of them
+      else
+        inserts.add(bundlesFailing.toString()); // Add the whole set if there isn't exactly one
+    }
+    if (!unknownType && !customAttrs.isEmpty()) {
+      msgKey.append("_WITH_ATTRS");
+      inserts.add(customAttrs);
+    }
+
+    if (!unknownType && attrs.containsKey(Constants.VERSION_ATTRIBUTE)) {
+      msgKey.append("_WITH_VERSION");
+      VersionRange vr = ManifestHeaderProcessor.parseVersionRange(attrs
+          .get(Constants.VERSION_ATTRIBUTE));
+      inserts.add(vr.getMinimumVersion());
+
+      if (!!!vr.isExactVersion()) {
+        msgKey.append(vr.isMinimumExclusive() ? "_LOWEX" : "_LOW");
+        if (vr.getMaximumVersion() != null) {
+          msgKey.append(vr.isMaximumExclusive() ? "_UPEX" : "_UP");
+          inserts.add(vr.getMaximumVersion());
+        }
+      }
+    }
+
+    String msgKeyStr = msgKey.toString();
+    
+    String msg = MessageUtil.getMessage(msgKeyStr, inserts.toArray());
+
+    log.debug(LOG_EXIT, "extractConsumableMessageInfo", msg);
+    
+    return msg;
+  }
+  
+  /**
+   * Refine the unsatisfied requirements ready for later human comsumption
+   * 
+   * @param resolver The resolver to be used to refine the requirements
+   * @param reasons The reasons
+   * @return A map of the unsatifiedRequirement to the set of bundles that have that requirement unsatisfied (values associated with the keys can be null) 
+   */
+  private Map<String,Set<String>> refineUnsatisfiedRequirements(Resolver resolver, Reason[] reasons) {
+    log.debug(LOG_ENTRY, "refineUnsatisfiedRequirements", new Object[]{resolver, Arrays.toString(reasons)});
+    
+    Map<Requirement,Set<String>> req_resources = new HashMap<Requirement,Set<String>>();
+    // add the reasons to the map, use the requirement as the key, the resources required the requirement as the values
+    Set<Resource> resources = new HashSet<Resource>();
+    for (Reason reason: reasons) {
+      resources.add(reason.getResource());
+      Requirement key = reason.getRequirement();
+      String value = reason.getResource().getSymbolicName()+"_" + reason.getResource().getVersion().toString();
+      Set<String> values = req_resources.get(key);
+      if (values == null) {
+        values = new HashSet<String>();
+      }
+      values.add(value);
+      req_resources.put(key, values);
+    }
+    
+    // remove the requirements that can be satisifed by the resources. It is listed because the resources are not satisfied by other requirements.
+    // For an instance, the unsatisfied reasons are [package a, required by bundle aa], [package b, required by bundle bb] and [package c, required by bundle cc], 
+    // If the bundle aa exports the package a and c. In our error message, we only want to display package a is needed by bundle aa.
+    // Go through each requirement and find out whether the requirement can be satisfied by the reasons.
+    Set<Capability> caps = new HashSet<Capability>();
+    for (Resource res : resources) {
+      if ((res !=null) && (res.getCapabilities() != null)) {
+        
+      List<Capability> capList = Arrays.asList(res.getCapabilities());
+      if (capList != null) {
+      caps.addAll(capList);
+      }
+      }
+    }
+    Iterator<Map.Entry<Requirement, Set<String>>> iterator = req_resources.entrySet().iterator();
+    while (iterator.hasNext()) {
+      Map.Entry<Requirement, Set<String>> entry = iterator.next();
+      Requirement req = entry.getKey();
+      for (Capability cap :caps) {
+        if (req.isSatisfied(cap)){ // remove the key from the map
+          iterator.remove();
+          break;
+        }
+      }
+    }
+    //Now the map only contains the necessary missing requirements
+    
+      Map<String,Set<String>> result = new HashMap<String, Set<String>>();
+      for (Map.Entry<Requirement, Set<String>> req_res : req_resources.entrySet()) {
+        result.put(req_res.getKey().getFilter(), req_res.getValue());
+      }
+      log.debug(LOG_EXIT, "refineUnsatisfiedRequirements", new Object[]{result});
+      
+    return result;
+    }
+  
+ 
+   
+   private Collection<ImportedBundle> toImportedBundle(Collection<Content> content) throws ResolverException
+   {
+     log.debug(LOG_ENTRY, "toImportedBundle", content);
+
+     List<ImportedBundle> result = new ArrayList<ImportedBundle>();
+     for (Content c : content) {
+       try {
+       result.add(modellingManager.getImportedBundle(c.getContentName(), c.getVersion().toString()));
+       } catch (InvalidAttributeException iae) {
+         throw new ResolverException(iae);
+       }
+     }
+     log.debug(LOG_EXIT, "toImportedBundle", result);
+     return result;
+   }
+   
+   private Collection<ModelledResource> toModelledResource(Collection<BundleInfo> bundleInfos) throws ResolverException{
+
+     Collection<ModelledResource> result = new ArrayList<ModelledResource>();
+    
+     if ((bundleInfos != null) && (!!!bundleInfos.isEmpty())) {
+       for (BundleInfo bi : bundleInfos) {
+         try {
+         result.add(modellingManager.getModelledResource(null, bi, null, null));
+         } catch (InvalidAttributeException iae) {
+           throw new ResolverException(iae);
+         }
+       }
+     }
+     return result;
+   }
+  
+   private Repository getLocalRepository(RepositoryAdmin admin) 
+   {
+       Repository localRepository = repositoryAdmin.getLocalRepository();
+       
+       Resource[] resources = localRepository.getResources();
+
+       Resource[] newResources = new Resource[resources.length];
+       for (int i = 0; i < resources.length; i++) {
+           newResources[i] = new ResourceWrapper(resources[i]); 
+       }
+       
+       return repositoryAdmin.getHelper().repository(newResources);
+   }
+   
+
+   private boolean excludeLocalRuntime() {   
+     return Boolean.parseBoolean(System.getProperty(AppConstants.PROVISON_EXCLUDE_LOCAL_REPO_SYSPROP));     
+   }
+
+}

Added: aries/tags/application-0.3/application-obr-resolver/src/main/java/org/apache/aries/application/resolver/obr/ext/BundleResource.java
URL: http://svn.apache.org/viewvc/aries/tags/application-0.3/application-obr-resolver/src/main/java/org/apache/aries/application/resolver/obr/ext/BundleResource.java?rev=1075132&view=auto
==============================================================================
--- aries/tags/application-0.3/application-obr-resolver/src/main/java/org/apache/aries/application/resolver/obr/ext/BundleResource.java (added)
+++ aries/tags/application-0.3/application-obr-resolver/src/main/java/org/apache/aries/application/resolver/obr/ext/BundleResource.java Sun Feb 27 20:20:13 2011
@@ -0,0 +1,228 @@
+/*
+ * 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 WARRANTIES OR 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.resolver.obr.ext;
+
+import static org.apache.aries.application.utils.AppConstants.LOG_ENTRY;
+import static org.apache.aries.application.utils.AppConstants.LOG_EXIT;
+
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Map;
+
+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.ImportedService;
+import org.apache.aries.application.modelling.ModelledResource;
+import org.apache.aries.application.modelling.ModellingConstants;
+import org.apache.aries.application.resolver.obr.impl.OBRCapability;
+import org.apache.aries.application.resolver.obr.impl.RequirementImpl;
+import org.apache.felix.bundlerepository.Capability;
+import org.apache.felix.bundlerepository.RepositoryAdmin;
+import org.apache.felix.bundlerepository.Requirement;
+import org.apache.felix.bundlerepository.Resource;
+import org.osgi.framework.Version;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class BundleResource implements Resource
+{
+  
+  private final ModelledResource _modelledBundle;
+  private final Collection<Capability> _capabilities;
+  private final Collection<Requirement> _requirements;
+  private final String _displayName;
+  private Logger logger = LoggerFactory.getLogger(BundleResource.class);
+  
+  /**
+   * Build a BundleResource from another BundleResource and some optional extra capabilities and requirements
+   * @param br
+   * @param extraCapabilities can be null
+   * @param extraRequirements can be null
+   */
+  public BundleResource (BundleResource br, Collection<Capability> extraCapabilities, Collection<Requirement> extraRequirements) { 
+    _modelledBundle = br._modelledBundle;
+    _capabilities = new ArrayList<Capability> (br._capabilities);
+    _requirements = new ArrayList<Requirement> (br._requirements);
+    _displayName = new String (br._displayName);
+    if (extraCapabilities != null) _capabilities.addAll(extraCapabilities);
+    if (extraRequirements != null) _requirements.addAll(extraRequirements);
+  }
+  
+  public BundleResource (ModelledResource mb, RepositoryAdmin repositoryAdmin) { 
+    logger.debug(LOG_ENTRY,"BundleResource", mb);
+    _modelledBundle = mb;
+    
+    _capabilities = new ArrayList<Capability>();
+    _capabilities.add(new OBRCapability(_modelledBundle.getExportedBundle(), repositoryAdmin));
+
+    for (ExportedPackage pkg : _modelledBundle.getExportedPackages()) {
+      _capabilities.add(new OBRCapability(pkg, repositoryAdmin));
+    }
+
+    for (ExportedService svc : _modelledBundle.getExportedServices()) {
+      _capabilities.add(new OBRCapability(svc, repositoryAdmin));
+    }
+
+    _requirements = new ArrayList<Requirement>();
+    for (ImportedPackage pkg : _modelledBundle.getImportedPackages()) {
+      _requirements.add(new RequirementImpl(pkg));
+    }
+    
+    for (ImportedService svc : _modelledBundle.getImportedServices()) { 
+      _requirements.add(new RequirementImpl(svc));
+    }
+    
+    for (ImportedBundle requiredBundle : _modelledBundle.getRequiredBundles()) { 
+      _requirements.add(new RequirementImpl(requiredBundle));
+    }
+    
+    if(mb.isFragment())
+      _requirements.add(new RequirementImpl(mb.getFragmentHost()));
+
+    String possibleDisplayName = (String) mb.getExportedBundle().getAttributes().get(
+        ModellingConstants.OBR_PRESENTATION_NAME);
+    if (possibleDisplayName == null) {
+      _displayName = mb.getSymbolicName();
+    } else {
+      _displayName = possibleDisplayName;
+    }
+    
+    
+    
+    logger.debug(LOG_EXIT,"BundleResource");
+    
+  }
+
+  public ModelledResource getModelledResource() { 
+    return _modelledBundle;
+  }
+  
+  public Capability[] getCapabilities() {
+   
+    logger.debug(LOG_ENTRY,"getCapabilities");
+    Capability [] result = _capabilities.toArray(new Capability[_capabilities.size()]);
+    logger.debug(LOG_EXIT,"getCapabilities", result);
+    return result;
+  }
+
+
+  public String[] getCategories() {
+    logger.debug(LOG_ENTRY,"getCategories");
+    logger.debug(LOG_EXIT,"getCategories", null);
+    return null;
+  }
+
+
+  public String getId() {   
+    logger.debug(LOG_ENTRY,"getId");
+    String id = _modelledBundle.getSymbolicName() + '/' + _modelledBundle.getVersion();
+    logger.debug(LOG_EXIT,"getId", id);
+    return id;
+  }
+
+
+  public String getPresentationName() {
+    
+    logger.debug(LOG_ENTRY,"getPresentationName");
+    logger.debug(LOG_EXIT,"getPresentationName", _displayName);
+    return _displayName;
+  }
+
+
+  @SuppressWarnings("unchecked")
+  public Map getProperties() {
+    logger.debug(LOG_ENTRY,"getProperties");
+    logger.debug(LOG_EXIT,"getProperties", null);
+    
+    return null;
+  }
+
+
+
+
+  public Requirement[] getRequirements() {
+    logger.debug(LOG_ENTRY,"getRequirements");
+    Requirement [] result = _requirements.toArray(new Requirement[_requirements.size()]);
+    logger.debug(LOG_EXIT,"getRequirements", result);
+    return result;
+  }
+
+
+  public String getSymbolicName() {
+    logger.debug(LOG_ENTRY,"getSymbolicName");
+    String result = _modelledBundle.getSymbolicName();
+    logger.debug(LOG_EXIT,"getSymbolicName", result);
+    return result;
+  }
+
+
+  public URL getURL() {
+    
+    logger.debug(LOG_ENTRY,"getURL");
+    URL url = null;
+    try {
+      URI uri = new URI(_modelledBundle.getLocation());
+      url = uri.toURL();
+    } catch (URISyntaxException e) {
+      logger.error(e.getMessage());
+    } catch (MalformedURLException e) {
+      logger.error(e.getMessage());
+    }
+    logger.debug(LOG_EXIT,"getURL", url);
+    return url;
+  }
+
+
+  public Version getVersion() {
+    logger.debug(LOG_ENTRY,"getVersion");
+    Version v = new Version(_modelledBundle.getVersion()); 
+    logger.debug(LOG_EXIT,"getVersion", v);
+    return v;
+  }
+
+  public Long getSize()
+  {
+    logger.debug(LOG_ENTRY,"getSize");
+    logger.debug(LOG_EXIT,"getSize", 5l);
+    return 5l;
+  }
+
+  public String getURI()
+  {
+    logger.debug(LOG_ENTRY,"getURI");
+    String uri = _modelledBundle.getLocation();
+    logger.debug(LOG_EXIT,"getURI", uri);
+    return uri;
+  }
+
+  public boolean isLocal()
+  {
+    logger.debug(LOG_ENTRY,"isLocal");
+    logger.debug(LOG_EXIT,"isLocal", false);
+    return false;
+  }
+
+}

Added: aries/tags/application-0.3/application-obr-resolver/src/main/java/org/apache/aries/application/resolver/obr/ext/BundleResourceTransformer.java
URL: http://svn.apache.org/viewvc/aries/tags/application-0.3/application-obr-resolver/src/main/java/org/apache/aries/application/resolver/obr/ext/BundleResourceTransformer.java?rev=1075132&view=auto
==============================================================================
--- aries/tags/application-0.3/application-obr-resolver/src/main/java/org/apache/aries/application/resolver/obr/ext/BundleResourceTransformer.java (added)
+++ aries/tags/application-0.3/application-obr-resolver/src/main/java/org/apache/aries/application/resolver/obr/ext/BundleResourceTransformer.java Sun Feb 27 20:20:13 2011
@@ -0,0 +1,27 @@
+/**
+ * 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 WARRANTIES OR 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.resolver.obr.ext;
+
+
+public interface BundleResourceTransformer {
+
+  BundleResource transform (BundleResource b);
+}
+
+

Added: aries/tags/application-0.3/application-obr-resolver/src/main/java/org/apache/aries/application/resolver/obr/impl/ApplicationResourceImpl.java
URL: http://svn.apache.org/viewvc/aries/tags/application-0.3/application-obr-resolver/src/main/java/org/apache/aries/application/resolver/obr/impl/ApplicationResourceImpl.java?rev=1075132&view=auto
==============================================================================
--- aries/tags/application-0.3/application-obr-resolver/src/main/java/org/apache/aries/application/resolver/obr/impl/ApplicationResourceImpl.java (added)
+++ aries/tags/application-0.3/application-obr-resolver/src/main/java/org/apache/aries/application/resolver/obr/impl/ApplicationResourceImpl.java Sun Feb 27 20:20:13 2011
@@ -0,0 +1,180 @@
+/*
+ * 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 WARRANTIES OR 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.resolver.obr.impl;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Dictionary;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.aries.application.Content;
+import org.apache.aries.application.modelling.ImportedBundle;
+import org.apache.aries.application.utils.manifest.ManifestHeaderProcessor;
+import org.apache.felix.bundlerepository.Capability;
+import org.apache.felix.bundlerepository.Requirement;
+import org.apache.felix.bundlerepository.Resource;
+import org.osgi.framework.Filter;
+import org.osgi.framework.FrameworkUtil;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.Version;
+
+public class ApplicationResourceImpl implements Resource
+{
+  private String _symbolicName;
+  private Version _version;
+  private List<Requirement> _requirements = new ArrayList<Requirement>();
+  
+  private static class FilterWrapper implements Filter
+  {
+    private Filter delgate;
+    
+    public FilterWrapper(Filter f)
+    {
+      delgate = f;
+    }
+    
+    public boolean match(ServiceReference reference)
+    {
+      return delgate.match(reference);
+    }
+
+    public boolean match(Dictionary dictionary)
+    {
+      boolean result = delgate.match(dictionary);
+      return result;
+    }
+
+    public boolean matchCase(Dictionary dictionary)
+    {
+      return delgate.matchCase(dictionary);
+    }
+    
+    public String toString()
+    {
+      return delgate.toString();
+    }
+  }
+  
+  public ApplicationResourceImpl(String appName, Version appVersion, List<Content> appContent)
+  {
+    _symbolicName = appName;
+    _version = appVersion;
+    
+ 
+    for (int i = 0; i < appContent.size(); i++) {
+      Content c = appContent.get(i);
+      
+      String comment = "Requires " + Resource.SYMBOLIC_NAME + " " + c.getContentName() + " with attributes " + c.getAttributes();
+      
+      String resolution = c.getDirective("resolution");
+
+      boolean optional = Boolean.valueOf(resolution);
+      
+      String f = ManifestHeaderProcessor.generateFilter(Resource.SYMBOLIC_NAME, c.getContentName(), c.getAttributes());
+      Filter filter;
+      try {
+        filter = FrameworkUtil.createFilter(f);
+        _requirements.add(new RequirementImpl("bundle", new FilterWrapper(filter), false, optional, false, comment));
+      } catch (InvalidSyntaxException e) {
+        // TODO work out what to do if this happens. If it does our filter generation code is bust.
+      }
+    }
+  }
+  
+  public ApplicationResourceImpl(String appName, Version appVersion, Collection<ImportedBundle> inputs)
+  {
+    _symbolicName = appName;
+    _version = appVersion;
+    
+    for (ImportedBundle match : inputs) {
+      _requirements.add(new RequirementImpl(match));
+    }
+  }
+  public Capability[] getCapabilities()
+  {
+    return null;
+  }
+
+  public String[] getCategories()
+  {
+    return null;
+  }
+
+  public String getId()
+  {
+    return _symbolicName;
+  }
+
+  public String getPresentationName()
+  {
+    return _symbolicName;
+  }
+
+  public Map getProperties()
+  {
+    return null;
+  }
+
+  public Requirement[] getRequirements()
+  {
+    if (_requirements!= null) {
+    Requirement[] reqs = new Requirement[_requirements.size()];
+    int index =0;
+    for (Requirement req: _requirements) {
+      reqs[index++] = req;
+    }
+    return reqs;
+    } else {
+      return null;
+    }
+      
+  }
+
+  public String getSymbolicName()
+  {
+    return _symbolicName;
+  }
+
+  public java.net.URL getURL()
+  {
+    return null;
+  }
+
+  public Version getVersion()
+  {
+    return _version;
+  }
+
+  public Long getSize()
+  {
+    return 0l;
+  }
+
+  public String getURI()
+  {
+    return null;
+  }
+
+  public boolean isLocal()
+  {
+    return false;
+  }
+}
\ No newline at end of file

Added: aries/tags/application-0.3/application-obr-resolver/src/main/java/org/apache/aries/application/resolver/obr/impl/MapToDictionary.java
URL: http://svn.apache.org/viewvc/aries/tags/application-0.3/application-obr-resolver/src/main/java/org/apache/aries/application/resolver/obr/impl/MapToDictionary.java?rev=1075132&view=auto
==============================================================================
--- aries/tags/application-0.3/application-obr-resolver/src/main/java/org/apache/aries/application/resolver/obr/impl/MapToDictionary.java (added)
+++ aries/tags/application-0.3/application-obr-resolver/src/main/java/org/apache/aries/application/resolver/obr/impl/MapToDictionary.java Sun Feb 27 20:20:13 2011
@@ -0,0 +1,123 @@
+/*
+ * 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 WARRANTIES OR 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.resolver.obr.impl;
+
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.Map;
+
+/**
+ * @version $Rev: 911397 $ $Date: 2010-02-18 13:41:27 +0000 (Thu, 18 Feb 2010) $
+ */
+public class MapToDictionary extends Dictionary
+{
+  /**
+   * Map source.
+   */
+  private final Map m_map;
+
+  public MapToDictionary(Map map)
+  {
+    m_map = map;
+  }
+
+  public Enumeration elements()
+  {
+    if (m_map == null) {
+      return null;
+    }
+    return new IteratorToEnumeration(m_map.values().iterator());
+  }
+
+  public Object get(Object key)
+  {
+    if (m_map == null) {
+      return null;
+    }
+    return m_map.get(key);
+  }
+
+  public boolean isEmpty()
+  {
+    if (m_map == null) {
+      return true;
+    }
+    return m_map.isEmpty();
+  }
+
+  public Enumeration keys()
+  {
+    if (m_map == null) {
+      return null;
+    }
+    return new IteratorToEnumeration(m_map.keySet().iterator());
+  }
+
+  public Object put(Object key, Object value)
+  {
+    throw new UnsupportedOperationException();
+  }
+
+  public Object remove(Object key)
+  {
+    throw new UnsupportedOperationException();
+  }
+
+  public int size()
+  {
+    if (m_map == null) {
+      return 0;
+    }
+    return m_map.size();
+  }
+
+  @Override
+  public String toString()
+  {
+    return m_map != null ? m_map.toString() : "null";
+  }
+
+  private static class IteratorToEnumeration implements Enumeration
+  {
+    private final Iterator m_iter;
+
+    public IteratorToEnumeration(Iterator iter)
+    {
+      m_iter = iter;
+    }
+
+    public boolean hasMoreElements()
+    {
+      if (m_iter == null)
+        return false;
+      return m_iter.hasNext();
+    }
+
+    public Object nextElement()
+    {
+      if (m_iter == null)
+        return null;
+      return m_iter.next();
+    }
+  }
+
+}

Added: aries/tags/application-0.3/application-obr-resolver/src/main/java/org/apache/aries/application/resolver/obr/impl/ModelledBundleResource.java
URL: http://svn.apache.org/viewvc/aries/tags/application-0.3/application-obr-resolver/src/main/java/org/apache/aries/application/resolver/obr/impl/ModelledBundleResource.java?rev=1075132&view=auto
==============================================================================
--- aries/tags/application-0.3/application-obr-resolver/src/main/java/org/apache/aries/application/resolver/obr/impl/ModelledBundleResource.java (added)
+++ aries/tags/application-0.3/application-obr-resolver/src/main/java/org/apache/aries/application/resolver/obr/impl/ModelledBundleResource.java Sun Feb 27 20:20:13 2011
@@ -0,0 +1,313 @@
+/*
+ * 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.resolver.obr.impl;
+
+import static org.apache.aries.application.utils.AppConstants.LOG_ENTRY;
+import static org.apache.aries.application.utils.AppConstants.LOG_EXIT;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.aries.application.InvalidAttributeException;
+import org.apache.aries.application.modelling.ExportedBundle;
+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.ImportedService;
+import org.apache.aries.application.modelling.ModelledResource;
+import org.apache.aries.application.modelling.ModellingConstants;
+import org.apache.aries.application.modelling.ModellingManager;
+import org.apache.aries.application.modelling.ResourceType;
+import org.apache.aries.application.modelling.utils.ModellingHelper;
+import org.apache.aries.application.resolver.internal.MessageUtil;
+import org.apache.aries.application.utils.AppConstants;
+import org.apache.aries.application.utils.manifest.ManifestHeaderProcessor;
+import org.apache.felix.bundlerepository.Capability;
+import org.apache.felix.bundlerepository.Property;
+import org.apache.felix.bundlerepository.Requirement;
+import org.apache.felix.bundlerepository.Resource;
+import org.osgi.framework.Constants;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ModelledBundleResource implements ModelledResource {  
+  private final Resource resource;
+  private final ExportedBundle exportedBundle;
+  private final Collection<ImportedPackage> packageRequirements;
+  private final Collection<ImportedService> serviceRequirements;
+  private final Collection<ExportedPackage> packageCapabilities;
+  private final Collection<ExportedService> serviceCapabilties;
+  private final Collection<ImportedBundle> bundleRequirements;
+  private final ResourceType type;
+  private final ModellingManager modellingManager;
+  private final ModellingHelper modellingHelper;
+  private final Logger logger = LoggerFactory.getLogger(ModelledBundleResource.class);
+
+  public ModelledBundleResource (Resource r, ModellingManager mm, ModellingHelper mh) throws InvalidAttributeException { 
+
+    logger.debug(LOG_ENTRY, "ModelledBundleResource", new Object[]{r, mm, mh});
+    resource = r;
+    modellingManager = mm;
+    modellingHelper = mh;
+    List<ExportedBundle> exportedBundles = new ArrayList<ExportedBundle>();
+    ResourceType thisResourceType = ResourceType.BUNDLE;
+
+    // We'll iterate through our Capabilities a second time below. We do this since we later
+    // build an ExportedPackageImpl for which 'this' is the ModelledResource. 
+    for (Capability cap : r.getCapabilities()) { 
+      String capName = cap.getName();
+      if (capName.equals(ResourceType.BUNDLE.toString())) { 
+        @SuppressWarnings("unchecked")
+        Property[] props = cap.getProperties();
+
+        Map<String,String> sanitizedMap = new HashMap<String, String>();
+        for(Property entry : props) {
+          sanitizedMap.put(entry.getName(), entry.getValue());
+        }
+        exportedBundles.add (modellingManager.getExportedBundle(sanitizedMap, modellingHelper.buildFragmentHost(
+            sanitizedMap.get(Constants.FRAGMENT_HOST))));
+      } else if (cap.getName().equals(ResourceType.COMPOSITE.toString())) { 
+        thisResourceType = ResourceType.COMPOSITE;
+      }
+    }
+    type = thisResourceType;
+
+
+    if (exportedBundles.size() == 0) {
+      throw new InvalidAttributeException(MessageUtil.getMessage("NO_EXPORTED_BUNDLE", new Object[0]));
+    } else if (exportedBundles.size() == 1) { 
+      exportedBundle = exportedBundles.get(0);
+    } else {  
+      throw new InvalidAttributeException(MessageUtil.getMessage("TOO_MANY_EXPORTED_BUNDLES",
+          new Object[0]));
+    }   
+
+    packageCapabilities = new HashSet<ExportedPackage>();
+    packageRequirements = new HashSet<ImportedPackage>();
+    serviceCapabilties = new HashSet<ExportedService>();
+    serviceRequirements = new HashSet<ImportedService>();
+    bundleRequirements = new HashSet<ImportedBundle>();
+
+    for (Requirement requirement : r.getRequirements())
+    {
+      String reqName = requirement.getName();
+      // Build ImportedPackageImpl, ImportedServiceImpl objects from the Resource's requirments. 
+      // Parse the Requirement's filter and remove from the parsed Map all the entries
+      // that we will pass in as explicit parameters to the ImportedServiceImpl or ImportedPackageImpl
+      // constructor. 
+      // (This does mean that we remove 'package=package.name' entries but not 'service=service' - 
+      // the latter is not very useful :)
+      if (ResourceType.PACKAGE.toString().equals(reqName))
+      {
+        Map<String, String> filter = ManifestHeaderProcessor.parseFilter(requirement.getFilter());
+        // Grab and remove the package name, leaving only additional attributes.
+        String name = filter.remove(ResourceType.PACKAGE.toString());
+        if (requirement.isOptional()) { 
+          filter.put(Constants.RESOLUTION_DIRECTIVE + ":", Constants.RESOLUTION_OPTIONAL);
+        }
+        ImportedPackage info = modellingManager.getImportedPackage(name, filter);
+        packageRequirements.add(info);
+      } else if (ResourceType.SERVICE.toString().equals(requirement.getName())) {
+        boolean optional = requirement.isOptional();
+        String iface;
+        String componentName;
+        String blueprintFilter;
+        String id = null;
+        boolean isMultiple = requirement.isMultiple();
+
+        /* It would be much better to pull these keys out of ImportedServiceImpl, 
+         * or even values via static methods
+         */
+        Map<String, String> attrs = ManifestHeaderProcessor.parseFilter(requirement.getFilter());
+        iface = attrs.get(Constants.OBJECTCLASS);
+        componentName = attrs.get ("osgi.service.blueprint.compname");
+        blueprintFilter = requirement.getFilter();
+
+        ImportedService svc = modellingManager.getImportedService(optional, iface, componentName,
+            blueprintFilter, id, isMultiple);
+        serviceRequirements.add(svc);
+      } else if (ResourceType.BUNDLE.toString().equals(requirement.getName())) {
+        String filter =requirement.getFilter();
+        Map<String,String> atts = ManifestHeaderProcessor.parseFilter(filter);
+        if (requirement.isOptional()) { 
+          atts.put(Constants.RESOLUTION_DIRECTIVE + ":", Constants.RESOLUTION_OPTIONAL);
+        }
+        bundleRequirements.add(modellingManager.getImportedBundle(filter, atts));
+      }
+    }
+
+    for (Capability capability : r.getCapabilities())
+    {
+      Map<String, Object> props = new HashMap<String, Object>();
+      Property[] properties = capability.getProperties();
+      for (Property prop : properties) {
+        props.put(prop.getName(), prop.getValue());
+      }
+      if (ResourceType.PACKAGE.toString().equals(capability.getName())) 
+      {
+        // Grab and remove the package name, leaving only additional attributes.
+        Object pkg = props.remove(ResourceType.PACKAGE.toString());
+        // bundle symbolic name and version will be in additionalProps, so do not 
+        // need to be passed in separately. 
+        ExportedPackage info = modellingManager.getExportedPackage(this, pkg.toString(), props);
+        packageCapabilities.add(info);
+      } else if (ResourceType.SERVICE.toString().equals(capability.getName())) { 
+        String name = null;   // we've lost this irretrievably
+        int ranking = 0;
+        Collection<String> ifaces;
+        String rankingText = (String) props.remove(Constants.SERVICE_RANKING);
+        if (rankingText != null) ranking = Integer.parseInt(rankingText);
+        // objectClass may come out as a String or String[]
+        Object rawObjectClass = props.remove (Constants.OBJECTCLASS);
+        if (rawObjectClass == null) {
+        	// get it from service
+        	ifaces = Arrays.asList((String)props.get(ModellingConstants.OBR_SERVICE));
+        } else {
+        	if (rawObjectClass.getClass().isArray()) { 
+        		ifaces = Arrays.asList((String[])rawObjectClass);
+        	} else { 
+        		ifaces = Arrays.asList((String)rawObjectClass);
+        	}
+        }
+
+        ExportedService svc = modellingManager.getExportedService(name, ranking, ifaces, props);
+        serviceCapabilties.add(svc);
+
+      }
+    }
+    logger.debug(LOG_EXIT, "ModelledBundleResource");
+
+  }
+
+
+  public ExportedBundle getExportedBundle() {
+    logger.debug(LOG_ENTRY, "AbstractExportedBundle");
+    logger.debug(LOG_EXIT, "AbstractExportedBundle",exportedBundle );
+    return exportedBundle;
+  }
+
+
+  public Collection<? extends ExportedPackage> getExportedPackages() {
+    logger.debug(LOG_ENTRY, "getExportedPackages");
+    logger.debug(LOG_EXIT,  "getExportedPackages", packageCapabilities );
+    return Collections.unmodifiableCollection(packageCapabilities);
+  }
+
+
+  public Collection<? extends ExportedService> getExportedServices() {
+    logger.debug(LOG_ENTRY, "getExportedServices");
+    logger.debug(LOG_EXIT,  "getExportedServices", serviceCapabilties );
+
+    return Collections.unmodifiableCollection(serviceCapabilties);
+  }
+
+
+  public Collection<? extends ImportedPackage> getImportedPackages() {
+    logger.debug(LOG_ENTRY, "getImportedPackages");
+    logger.debug(LOG_EXIT,  "getImportedPackages", packageRequirements );
+    return Collections.unmodifiableCollection(packageRequirements);
+  }
+
+
+  public Collection<? extends ImportedService> getImportedServices() {
+    logger.debug(LOG_ENTRY, "getImportedServices");
+    logger.debug(LOG_EXIT,  "getImportedServices", serviceRequirements );    
+    return Collections.unmodifiableCollection(serviceRequirements);
+  }
+
+
+  public Collection<? extends ImportedBundle> getRequiredBundles() {
+    logger.debug(LOG_ENTRY, "getRequiredBundles");
+    logger.debug(LOG_EXIT,  "getRequiredBundles", bundleRequirements );    
+    return Collections.unmodifiableCollection(bundleRequirements);
+  }
+
+
+  public String getSymbolicName() {
+    logger.debug(LOG_ENTRY, "getSymbolicName");   
+    String result = resource.getSymbolicName();
+    logger.debug(LOG_EXIT,  "getSymbolicName", result );
+
+    return result;
+  }
+
+
+  public String getLocation() {
+    logger.debug(LOG_ENTRY, "getLocation");   
+    logger.debug(LOG_EXIT,  "getLocation", resource.getURI());
+    return resource.getURI();
+
+  }
+
+
+  public String getVersion() {
+    logger.debug(LOG_ENTRY, "getVersion");
+    String result = resource.getVersion().toString();
+    logger.debug(LOG_EXIT,  "getVersion", result);
+    return result;
+  }
+
+
+  public String toDeploymentString() {
+    logger.debug(LOG_ENTRY, "toDeploymentString");   
+    String result = getSymbolicName() + ";" + AppConstants.DEPLOYMENT_BUNDLE_VERSION + "=" + getVersion();
+    logger.debug(LOG_EXIT,  "toDeploymentString", result);
+    return result;
+  }
+
+
+  public String toString() { 
+    logger.debug(LOG_ENTRY, "toString");
+    String result = toDeploymentString() + " uri=" + getLocation();
+    logger.debug(LOG_EXIT,  "toString", result);
+    return result;
+  }
+
+
+  public ResourceType getType() {
+    logger.debug(LOG_ENTRY, "getType");   
+    logger.debug(LOG_EXIT,  "getType", type);
+    return type;
+  }
+
+
+  public ImportedBundle getFragmentHost() {
+    logger.debug(LOG_ENTRY, "getFragmentHost");
+    ImportedBundle result = exportedBundle.getFragmentHost();
+    logger.debug(LOG_EXIT,  "getFragmentHost", result);
+    return result;
+  }
+
+
+  public boolean isFragment() {
+    logger.debug(LOG_ENTRY, "isFragment");
+    boolean result = exportedBundle.isFragment();
+    logger.debug(LOG_EXIT,  "isFragment", result);
+    return result;
+  }
+
+
+}
\ No newline at end of file

Added: aries/tags/application-0.3/application-obr-resolver/src/main/java/org/apache/aries/application/resolver/obr/impl/OBRBundleInfo.java
URL: http://svn.apache.org/viewvc/aries/tags/application-0.3/application-obr-resolver/src/main/java/org/apache/aries/application/resolver/obr/impl/OBRBundleInfo.java?rev=1075132&view=auto
==============================================================================
--- aries/tags/application-0.3/application-obr-resolver/src/main/java/org/apache/aries/application/resolver/obr/impl/OBRBundleInfo.java (added)
+++ aries/tags/application-0.3/application-obr-resolver/src/main/java/org/apache/aries/application/resolver/obr/impl/OBRBundleInfo.java Sun Feb 27 20:20:13 2011
@@ -0,0 +1,152 @@
+/*
+ * 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 WARRANTIES OR 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.resolver.obr.impl;
+
+import java.util.Map;
+import java.util.Set;
+import java.util.jar.Attributes;
+
+import org.apache.aries.application.Content;
+import org.apache.aries.application.management.BundleInfo;
+import org.osgi.framework.Version;
+
+public class OBRBundleInfo implements BundleInfo
+{
+
+  private final String symbolicName;
+  private final Version version;
+  private final String location;
+  private final Set<Content> importPackage;
+  private final Set<Content> exportPackage;
+  private final Set<Content> importService;
+  private final Set<Content> exportService;
+  private final Map<String, String> headers;
+  private final Set<Content> requireBundle;
+  private final Map<String, String> attributes;
+  private final Map<String, String> directives;
+
+  public OBRBundleInfo(String symbolicName, Version version, String location,
+                       Set<Content> importPackage, Set<Content> exportPackage,
+                       Set<Content> importService, Set<Content> exportService,
+                       Set<Content> requireBundle, Map<String, String> attributes,
+                       Map<String, String> directives, Map<String, String> headers)
+  {
+    this.symbolicName = symbolicName;
+    this.version = version;
+    this.location = location;
+    this.importPackage = importPackage;
+    this.exportPackage = exportPackage;
+    this.importService = importService;
+    this.exportService = exportService;
+    this.headers = headers;
+    this.requireBundle = requireBundle;
+    this.attributes = attributes;
+    this.directives = directives;
+  }
+
+  public String getSymbolicName()
+  {
+    return symbolicName;
+  }
+
+  public Version getVersion()
+  {
+    return version;
+  }
+
+  public String getLocation()
+  {
+    return location;
+  }
+
+  public Set<Content> getImportPackage()
+  {
+    return importPackage;
+  }
+
+  public Set<Content> getExportPackage()
+  {
+    return exportPackage;
+  }
+
+  public Set<Content> getImportService()
+  {
+    return importService;
+  }
+
+  public Set<Content> getExportService()
+  {
+    return exportService;
+  }
+
+  public Map<String, String> getHeaders()
+  {
+    return headers;
+  }
+
+  public Map<String, String> getBundleAttributes()
+  {
+    return attributes;
+  }
+
+  public Map<String, String> getBundleDirectives()
+  {
+    return directives;
+  }
+
+  public Set<Content> getRequireBundle()
+  {
+    return requireBundle;
+  }
+    
+  public String toString()
+  {
+    return symbolicName + "_" + version;
+  }
+
+  public int hashCode() 
+  {
+    final int prime = 31;
+    int result = 1;
+    result = prime * result + symbolicName.hashCode();
+    result = prime * result + version.hashCode();
+    return result;
+  }
+
+  public boolean equals(Object obj) {
+    if (this == obj) return true;
+    if (obj == null) return false;
+    if (getClass() != obj.getClass()) {
+        return false;
+    }
+    OBRBundleInfo other = (OBRBundleInfo) obj;
+    return (symbolicName.equals(other.symbolicName)
+            && version.equals(other.version));
+  }
+  
+  public Attributes getRawAttributes()
+  {
+
+    Attributes _attributes = new Attributes();
+    _attributes.putAll(attributes);
+    _attributes.putAll(directives);
+    return _attributes;
+  }
+}

Added: aries/tags/application-0.3/application-obr-resolver/src/main/java/org/apache/aries/application/resolver/obr/impl/OBRCapability.java
URL: http://svn.apache.org/viewvc/aries/tags/application-0.3/application-obr-resolver/src/main/java/org/apache/aries/application/resolver/obr/impl/OBRCapability.java?rev=1075132&view=auto
==============================================================================
--- aries/tags/application-0.3/application-obr-resolver/src/main/java/org/apache/aries/application/resolver/obr/impl/OBRCapability.java (added)
+++ aries/tags/application-0.3/application-obr-resolver/src/main/java/org/apache/aries/application/resolver/obr/impl/OBRCapability.java Sun Feb 27 20:20:13 2011
@@ -0,0 +1,90 @@
+/*
+ * 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 WARRANTIES OR 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.resolver.obr.impl;
+
+
+import static org.apache.aries.application.utils.AppConstants.LOG_ENTRY;
+import static org.apache.aries.application.utils.AppConstants.LOG_EXIT;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.aries.application.modelling.Provider;
+import org.apache.felix.bundlerepository.Capability;
+import org.apache.felix.bundlerepository.Property;
+import org.apache.felix.bundlerepository.RepositoryAdmin;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Common code for handling OBR Capabilities. 
+ */
+public class OBRCapability implements Capability
+{
+
+  private Logger logger = LoggerFactory.getLogger(OBRCapability.class);
+  private final Provider _provider;
+
+  private final RepositoryAdmin repositoryAdmin;
+  /**
+   * Property map for this Capability.
+   */
+  private final Map<String, Object> _props;
+  
+  /**
+   * Construct a Capability specifying the OBR name to use.
+   * @param type the value to be used for the Capability name in OBR.
+   */
+  public OBRCapability(Provider provider, RepositoryAdmin repositoryAdmin){
+
+    logger.debug(LOG_ENTRY, "OBRCapability", provider);
+    _provider = provider;
+    _props = new HashMap<String, Object>(provider.getAttributes());
+    this.repositoryAdmin = repositoryAdmin;
+    logger.debug(LOG_EXIT, "OBRCapability");
+    
+  }
+  
+ 
+  public String getName()
+  {
+    logger.debug(LOG_ENTRY, "getName");
+    String name = _provider.getType().toString();  
+    logger.debug(LOG_EXIT, "getName", name);
+    return name;
+  }
+
+ 
+  public Property[] getProperties()
+  {
+    logger.debug(LOG_ENTRY, "getProperties");
+    Property[] props = repositoryAdmin.getHelper().capability(getName(), _props).getProperties();
+    logger.debug(LOG_EXIT, "getProperties", props);
+    return props;
+  }
+
+  public Map getPropertiesAsMap()
+  {
+    logger.debug(LOG_ENTRY, "getPropertiesAsMap");
+    logger.debug(LOG_ENTRY, "getPropertiesAsMap", new Object[]{_props});
+    return _props;
+  }
+
+}

Added: aries/tags/application-0.3/application-obr-resolver/src/main/java/org/apache/aries/application/resolver/obr/impl/RepositoryGeneratorImpl.java
URL: http://svn.apache.org/viewvc/aries/tags/application-0.3/application-obr-resolver/src/main/java/org/apache/aries/application/resolver/obr/impl/RepositoryGeneratorImpl.java?rev=1075132&view=auto
==============================================================================
--- aries/tags/application-0.3/application-obr-resolver/src/main/java/org/apache/aries/application/resolver/obr/impl/RepositoryGeneratorImpl.java (added)
+++ aries/tags/application-0.3/application-obr-resolver/src/main/java/org/apache/aries/application/resolver/obr/impl/RepositoryGeneratorImpl.java Sun Feb 27 20:20:13 2011
@@ -0,0 +1,226 @@
+/*
+ * 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 WARRANTIES OR 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.resolver.obr.impl;
+
+import static org.apache.aries.application.utils.AppConstants.LOG_ENTRY;
+import static org.apache.aries.application.utils.AppConstants.LOG_EXIT;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+
+import org.apache.aries.application.management.ResolverException;
+import org.apache.aries.application.management.spi.repository.RepositoryGenerator;
+import org.apache.aries.application.modelling.ModelledResource;
+import org.apache.aries.application.resolver.obr.ext.BundleResource;
+import org.apache.aries.application.resolver.obr.ext.BundleResourceTransformer;
+import org.apache.felix.bundlerepository.Capability;
+import org.apache.felix.bundlerepository.Property;
+import org.apache.felix.bundlerepository.RepositoryAdmin;
+import org.apache.felix.bundlerepository.Requirement;
+import org.apache.felix.bundlerepository.Resource;
+import org.osgi.framework.Constants;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+public final class RepositoryGeneratorImpl implements RepositoryGenerator
+{
+  private RepositoryAdmin repositoryAdmin;
+  private static Logger logger = LoggerFactory.getLogger(RepositoryGeneratorImpl.class);
+  private static Collection<BundleResourceTransformer> bundleResourceTransformers = new ArrayList<BundleResourceTransformer>();
+  private static final String MANDATORY_DIRECTIVE = Constants.MANDATORY_DIRECTIVE + ":";
+  
+  
+  public void setBundleResourceTransformers (List<BundleResourceTransformer> brts) { 
+    bundleResourceTransformers = brts;
+  }
+  
+  public RepositoryGeneratorImpl(RepositoryAdmin repositoryAdmin) {
+    this.repositoryAdmin = repositoryAdmin;
+  }
+  private static void addProperty(Document doc, Element capability, String name,
+      String value, String type)
+  {
+    logger.debug(LOG_ENTRY, "addProperty", new Object[]{doc, capability, name, value, type});
+    Element p = doc.createElement("p");
+    p.setAttribute("n", name);
+    p.setAttribute("v", value);
+    if (type != null) p.setAttribute("t", type);
+    capability.appendChild(p);
+    logger.debug(LOG_ENTRY, "addProperty", new Object[]{});
+  }
+  
+  
+
+  /**
+   * Write out the resource element
+   * 
+   * @param r
+   *          resource
+   * @param writer
+   *          buffer writer
+   * @throws IOException
+   */
+  private  static void writeResource(Resource r, String uri, Document doc, Element root) throws IOException
+  {
+    logger.debug(LOG_ENTRY, "writeResource", new Object[]{r, uri, doc, root});
+    Element resource = doc.createElement("resource");
+    resource.setAttribute(Resource.VERSION, r.getVersion().toString());
+    resource.setAttribute("uri", r.getURI());
+    resource.setAttribute(Resource.SYMBOLIC_NAME, r.getSymbolicName());
+    resource.setAttribute(Resource.ID, r.getSymbolicName() + "/" + r.getVersion());
+    resource.setAttribute(Resource.PRESENTATION_NAME, r.getPresentationName());
+    root.appendChild(resource);
+
+
+    for (Capability c : r.getCapabilities())
+      writeCapability(c, doc, resource);
+
+    for (Requirement req : r.getRequirements()) {
+      writeRequirement(req, doc, resource);
+
+    }
+    logger.debug(LOG_EXIT, "writeResource");
+
+  }
+
+  /**
+   * Write out the capability
+   * 
+   * @param c capability
+   * @param writer buffer writer
+   * @throws IOException
+   */
+  private  static void writeCapability(Capability c, Document doc, Element resource) throws IOException
+  {
+    logger.debug(LOG_ENTRY, "writeCapability", new Object[]{c, doc, resource});
+    Element capability = doc.createElement("capability");
+    capability.setAttribute("name", c.getName());
+    resource.appendChild(capability);
+
+    Property[] props = c.getProperties();
+
+    for (Property entry : props) {
+
+      String name = (String) entry.getName();
+      String objectAttrs = entry.getValue();
+      
+      String type = getType(name);
+
+      // remove the beginning " and tailing "
+      if (objectAttrs.startsWith("\"") && objectAttrs.endsWith("\""))
+        objectAttrs = objectAttrs.substring(1, objectAttrs.length() - 1);
+      addProperty(doc, capability, name, objectAttrs, type);
+    }
+
+    logger.debug(LOG_EXIT, "writeCapability");
+  }
+
+  /**
+   * write the requirement
+   * 
+   * @param req
+   *          requirement
+   * @param writer
+   *          buffer writer
+   * @throws IOException
+   */
+  private static void  writeRequirement(Requirement req, Document doc, Element resource) throws IOException
+  {
+    logger.debug(LOG_ENTRY, "writeRequirement", new Object[]{req, doc, resource});
+    Element requirement = doc.createElement("require");
+    requirement.setAttribute("name", req.getName());
+    requirement.setAttribute("extend", String.valueOf(req.isExtend()));
+    requirement.setAttribute("multiple", String.valueOf(req.isMultiple()));
+    requirement.setAttribute("optional", String.valueOf(req.isOptional()));
+    requirement.setAttribute("filter", req.getFilter());
+    requirement.setTextContent(req.getComment());
+    resource.appendChild(requirement);
+    logger.debug(LOG_EXIT, "writeRequirement");
+  }
+
+
+  public void generateRepository(String repositoryName,
+      Collection<? extends ModelledResource> byValueBundles, OutputStream os)
+  throws ResolverException, IOException
+  {
+    logger.debug(LOG_ENTRY, "generateRepository", new Object[]{repositoryName, byValueBundles, os});
+    generateRepository(repositoryAdmin, repositoryName, byValueBundles, os);
+    logger.debug(LOG_EXIT, "generateRepository");
+  }
+
+  public static void generateRepository (RepositoryAdmin repositoryAdmin, String repositoryName,
+      Collection<? extends ModelledResource> byValueBundles, OutputStream os)
+  throws ResolverException, IOException {
+	  logger.debug(LOG_ENTRY, "generateRepository", new Object[]{repositoryAdmin, repositoryName, byValueBundles, os});
+	    Document doc;
+	    try {
+	      doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
+
+	    } catch (ParserConfigurationException pce) {
+	      throw new ResolverException(pce);
+	    }
+	    Element root = doc.createElement("repository");
+
+	    root.setAttribute("name", repositoryName);
+	    doc.appendChild(root);
+	    for (ModelledResource mr : byValueBundles) {
+	      BundleResource bundleResource = new BundleResource(mr, repositoryAdmin);
+	      if (bundleResourceTransformers.size() > 0) { 
+	        for (BundleResourceTransformer brt : bundleResourceTransformers) { 
+	          bundleResource = brt.transform (bundleResource);
+	        }
+	      }
+	      writeResource (bundleResource, mr.getLocation(), doc, root);
+	    }
+
+	    try {
+	      Transformer trans = TransformerFactory.newInstance().newTransformer();
+	      trans.setOutputProperty(OutputKeys.INDENT, "yes");
+	      trans.transform(new DOMSource(doc), new StreamResult(os));
+	    } catch (TransformerException te) {
+	      logger.debug(LOG_EXIT, "generateRepository", te);
+	      throw new ResolverException(te);
+	    }
+	    logger.debug(LOG_EXIT, "generateRepository");
+  }
+  private static String getType(String name) {
+    logger.debug(LOG_ENTRY, "getType", new Object[]{name});
+    String type = null;
+    if (Constants.VERSION_ATTRIBUTE.equals(name) || (Constants.BUNDLE_VERSION_ATTRIBUTE.equals(name))) {
+      type =  "version";
+    } else if (Constants.OBJECTCLASS.equals(name) || MANDATORY_DIRECTIVE.equals(name))
+      type = "set";
+    logger.debug(LOG_EXIT, "getType", new Object[]{type});
+    return type;
+  }
+
+}
\ No newline at end of file

Added: aries/tags/application-0.3/application-obr-resolver/src/main/java/org/apache/aries/application/resolver/obr/impl/RequirementImpl.java
URL: http://svn.apache.org/viewvc/aries/tags/application-0.3/application-obr-resolver/src/main/java/org/apache/aries/application/resolver/obr/impl/RequirementImpl.java?rev=1075132&view=auto
==============================================================================
--- aries/tags/application-0.3/application-obr-resolver/src/main/java/org/apache/aries/application/resolver/obr/impl/RequirementImpl.java (added)
+++ aries/tags/application-0.3/application-obr-resolver/src/main/java/org/apache/aries/application/resolver/obr/impl/RequirementImpl.java Sun Feb 27 20:20:13 2011
@@ -0,0 +1,178 @@
+/*
+ * 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 WARRANTIES OR 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.resolver.obr.impl;
+
+import static org.apache.aries.application.utils.AppConstants.LOG_ENTRY;
+import static org.apache.aries.application.utils.AppConstants.LOG_EXIT;
+
+import java.util.Hashtable;
+import java.util.Map;
+
+import org.apache.aries.application.modelling.Consumer;
+import org.apache.aries.application.utils.FilterUtils;
+import org.apache.aries.application.utils.manifest.ManifestHeaderProcessor;
+import org.apache.felix.bundlerepository.Capability;
+import org.apache.felix.bundlerepository.Requirement;
+import org.osgi.framework.Filter;
+import org.osgi.framework.FrameworkUtil;
+import org.osgi.framework.InvalidSyntaxException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class RequirementImpl implements Requirement
+{
+
+
+  private final Logger logger = LoggerFactory.getLogger(RequirementImpl.class);
+  private final Consumer consumer;
+
+  private final String name;
+  private final String filter;
+  private final boolean multiple;
+  private final boolean optional;
+  private final boolean extend;
+  private final String comment;
+
+  public RequirementImpl(String name, Filter filter, boolean multiple, boolean optional, boolean extend, String comment)
+  {
+    this.name = name;
+    this.filter = filter.toString();
+    this.multiple = multiple;
+    this.optional = optional;
+    this.extend = extend;
+    this.comment = comment;
+    this.consumer = null;
+  }
+
+  public RequirementImpl(Consumer consumer) {
+    this.consumer = consumer;
+    this.name = getName();
+    this.filter= getFilter();
+    this.multiple= isMultiple();
+    this.optional= isOptional();
+    this.extend = false;
+    this.comment = getComment();
+
+  }
+
+
+
+  public String getComment()
+  {
+
+    logger.debug(LOG_ENTRY,"getComment" );
+    if (consumer!= null) {
+      String cleanFilter = FilterUtils.removeMandatoryFilterToken(consumer.getAttributeFilter());
+      Map<String, String> atts = ManifestHeaderProcessor.parseFilter(cleanFilter);
+      String comment = "Requires " + consumer.getType().toString() + " with attributes " + atts;
+      logger.debug(LOG_EXIT,"getComment", comment );
+      return comment;
+    } else {
+      logger.debug(LOG_EXIT,"getComment", this.comment );
+      return this.comment;
+    }
+  }
+
+
+  public String getFilter()
+  {
+    String result;
+    if (consumer != null) {
+      result = consumer.getAttributeFilter();
+    } else {
+      result = this.filter;
+    }
+    return result;
+  }
+
+
+  public String getName()
+  {
+
+    String result;
+    if (consumer != null) {
+      result = consumer.getType().toString();
+    } else {
+      result = this.name;
+    }
+    return result;
+  }
+
+
+  public boolean isExtend()
+  {
+    return this.extend;
+  }
+
+
+  public boolean isMultiple()
+  {
+    boolean result;
+    if (consumer != null ) {
+      result = consumer.isMultiple();
+    } else {
+      result = this.multiple;
+    }
+    return result;
+  }
+
+
+  public boolean isOptional()
+  {
+    boolean result;
+    if (consumer != null) {
+      result = consumer.isOptional();
+    } else {
+      result = this.optional;
+    }
+    return result;
+  }
+
+  @SuppressWarnings("unchecked")
+
+  public boolean isSatisfied(Capability cap)
+  {
+   
+    logger.debug(LOG_ENTRY,"isSatisfied", cap );
+    boolean result = false;
+
+    String name = getName();
+    if (name.equals(cap.getName())) {
+      String filterToCreate = getFilter();
+      try {
+        Filter f = FrameworkUtil.createFilter(FilterUtils.removeMandatoryFilterToken(filterToCreate));
+        Hashtable<String, Object> hash = new Hashtable<String, Object>();
+        Map<String, String> props = cap.getPropertiesAsMap();
+        if ((props != null) && (!!!props.isEmpty())) {
+          for (Map.Entry<String, String> propertyPair : props.entrySet()) {
+            hash.put(propertyPair.getKey(), propertyPair.getValue());
+          }
+        }
+
+        result = f.match(hash);
+      } catch (InvalidSyntaxException e) {
+        logger.error(e.getMessage());
+      }
+    }
+    logger.debug(LOG_EXIT,"isSatisfied", result );
+    return result;
+  }
+}

Added: aries/tags/application-0.3/application-obr-resolver/src/main/java/org/apache/aries/application/resolver/obr/impl/ResourceWrapper.java
URL: http://svn.apache.org/viewvc/aries/tags/application-0.3/application-obr-resolver/src/main/java/org/apache/aries/application/resolver/obr/impl/ResourceWrapper.java?rev=1075132&view=auto
==============================================================================
--- aries/tags/application-0.3/application-obr-resolver/src/main/java/org/apache/aries/application/resolver/obr/impl/ResourceWrapper.java (added)
+++ aries/tags/application-0.3/application-obr-resolver/src/main/java/org/apache/aries/application/resolver/obr/impl/ResourceWrapper.java Sun Feb 27 20:20:13 2011
@@ -0,0 +1,84 @@
+/*
+ * 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 WARRANTIES OR 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.resolver.obr.impl;
+
+import java.util.Map;
+
+import org.apache.felix.bundlerepository.Capability;
+import org.apache.felix.bundlerepository.Requirement;
+import org.apache.felix.bundlerepository.Resource;
+import org.osgi.framework.Version;
+
+/**
+ * @version $Rev: 964138 $ $Date: 2010-07-14 20:03:40 +0100 (Wed, 14 Jul 2010) $
+ */
+public class ResourceWrapper implements Resource {
+
+    private final Resource resource;
+    
+    public ResourceWrapper(Resource resource) {
+        this.resource = resource;
+    }
+    
+    public Capability[] getCapabilities() {
+        return resource.getCapabilities();
+    }
+
+    public String[] getCategories() {
+        return resource.getCategories();
+    }
+
+    public String getId() {
+        return resource.getId();
+    }
+
+    public String getPresentationName() {
+        return resource.getPresentationName();
+    }
+
+    public Map getProperties() {
+        return resource.getProperties();
+    }
+
+    public Requirement[] getRequirements() {
+        return resource.getRequirements();
+    }
+
+    public Long getSize() {
+        return resource.getSize();
+    }
+
+    public String getSymbolicName() {
+        return resource.getSymbolicName();
+    }
+
+    public String getURI() {
+        return resource.getURI();
+    }
+
+    public Version getVersion() {
+        return resource.getVersion();
+    }
+
+    public boolean isLocal() {
+        return false;
+    }
+
+}



Mime
View raw message